diff --git a/src/Sourcefile b/src/Sourcefile index 65122a55a..b423fecb2 100644 --- a/src/Sourcefile +++ b/src/Sourcefile @@ -113,3 +113,4 @@ k_hud.c k_menudef.c k_menufunc.c k_menudraw.c +k_brightmap.c diff --git a/src/d_clisrv.c b/src/d_clisrv.c index cd404a685..b4055042e 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -795,10 +795,14 @@ static boolean CL_SendJoin(void) sizeof netbuffer->u.clientcfg.application); for (i = 0; i <= splitscreen; i++) - CleanupPlayerName(g_localplayers[i], cv_playername[i].zstring); - - for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + // the MAXPLAYERS addition is necessary to communicate that g_localplayers is not yet safe to reference + CleanupPlayerName(MAXPLAYERS+i, cv_playername[i].zstring); strncpy(netbuffer->u.clientcfg.names[i], cv_playername[i].zstring, MAXPLAYERNAME); + } + // privacy shield for the local players not joining this session + for (; i < MAXSPLITSCREENPLAYERS; i++) + strncpy(netbuffer->u.clientcfg.names[i], va("Player %c", 'A' + i), MAXPLAYERNAME); return HSendPacket(servernode, false, 0, sizeof (clientconfig_pak)); } @@ -1334,7 +1338,7 @@ static void CL_ReloadReceivedSavegame(void) for (i = 0; i < MAXPLAYERS; i++) { LUA_InvalidatePlayer(&players[i]); - sprintf(player_names[i], "Player %d", i + 1); + sprintf(player_names[i], "Player %c", 'A' + i); } CL_LoadReceivedSavegame(true); @@ -2424,7 +2428,7 @@ void CL_RemovePlayer(INT32 playernum, kickreason_t reason) doomcom->numslots--; // Reset the name - sprintf(player_names[playernum], "Player %d", playernum+1); + sprintf(player_names[playernum], "Player %c", 'A' + playernum); player_name_changes[playernum] = 0; @@ -3236,7 +3240,7 @@ void SV_ResetServer(void) playeringame[i] = false; playernode[i] = UINT8_MAX; memset(playeraddress[i], 0, sizeof(*playeraddress)); - sprintf(player_names[i], "Player %d", i + 1); + sprintf(player_names[i], "Player %c", 'A' + i); adminplayers[i] = -1; // Populate the entire adminplayers array with -1. K_ClearClientPowerLevels(); splitscreen_invitations[i] = -1; @@ -3435,7 +3439,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) P_ForceLocalAngle(newplayer, newplayer->angleturn); - D_SendPlayerConfig(); + D_SendPlayerConfig(splitscreenplayer); addedtogame = true; if (rejoined) @@ -3581,14 +3585,13 @@ static void Got_AddBot(UINT8 **p, INT32 playernum) LUAh_PlayerJoin(newplayernum); } -static boolean SV_AddWaitingPlayers(const char *name, const char *name2, const char *name3, const char *name4) +static boolean SV_AddWaitingPlayers(SINT8 node, const char *name, const char *name2, const char *name3, const char *name4) { - INT32 node, n, newplayer = false; + INT32 n, newplayernum; UINT8 buf[4 + MAXPLAYERNAME]; UINT8 *buf_p = buf; - INT32 newplayernum; + boolean newplayer = false; - for (node = 0; node < MAXNETNODES; node++) { // splitscreen can allow 2+ players in one node for (; nodewaiting[node] > 0; nodewaiting[node]--) @@ -3707,6 +3710,7 @@ boolean SV_SpawnServer(void) I_Error("What do you think you're doing?"); return false; #else + boolean result = false; if (demo.playback) G_StopDemo(); // reset engine parameter if (metalplayback) @@ -3733,7 +3737,14 @@ boolean SV_SpawnServer(void) else doomcom->numslots = 1; } - return SV_AddWaitingPlayers(cv_playername[0].zstring, cv_playername[1].zstring, cv_playername[2].zstring, cv_playername[3].zstring); + // strictly speaking, i'm not convinced the following is necessary + // but I'm not confident enough to remove it entirely in case it breaks something + { + SINT8 node = 0; + for (; node < MAXNETNODES; node++) + result |= SV_AddWaitingPlayers(node, cv_playername[0].zstring, cv_playername[1].zstring, cv_playername[2].zstring, cv_playername[3].zstring); + } + return result; #endif } @@ -3906,7 +3917,7 @@ static void HandleConnect(SINT8 node) SV_SendSaveGame(node, false); // send a complete game state DEBFILE("send savegame\n"); } - SV_AddWaitingPlayers(names[0], names[1], names[2], names[3]); + SV_AddWaitingPlayers(node, names[0], names[1], names[2], names[3]); joindelay += cv_joindelay.value * TICRATE; player_joining = true; } diff --git a/src/d_main.c b/src/d_main.c index 9bb6c678d..fc17a5334 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -776,7 +776,7 @@ void D_SRB2Loop(void) // process tics (but maybe not if realtic == 0) TryRunTics(realtics); - if (cv_frameinterpolation.value == 1) + if (cv_frameinterpolation.value == 1 && !(paused || P_AutoPause() || hu_stopped)) { fixed_t entertimefrac = I_GetTimeFrac(); // renderdeltatics is a bit awkard to evaluate, since the system time interface is whole tic-based @@ -815,20 +815,6 @@ void D_SRB2Loop(void) } else if (rendertimeout < entertic) // in case the server hang or netsplit { -#if 0 - // Lagless camera! Yay! - if (gamestate == GS_LEVEL && netgame) - { - INT32 i; - - for (i = 0; i <= r_splitscreen; i++) - { - if (camera[i].chase) - P_MoveChaseCamera(&players[displayplayers[i]], &camera[i], false); - } - } -#endif - // (Only display if not already done for frame interp) cv_frameinterpolation.value == 0 ? D_Display() : 0; @@ -1424,6 +1410,9 @@ void D_SRB2Main(void) // setup loading screen SCR_Startup(); + // Do this in background; lots of number crunching + R_InitTranslucencyTables(); + CON_SetLoadingProgress(LOADED_ISTARTUPGRAPHICS); CONS_Printf("HU_Init()...\n"); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 0f91028ff..775cf8598 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -222,8 +222,6 @@ static void Command_KartGiveItem_f(void); // CLIENT VARIABLES // ========================================================================= -void SendWeaponPref(UINT8 n); - static CV_PossibleValue_t usemouse_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Force"}, {0, NULL}}; #ifdef LJOYSTICK @@ -1102,6 +1100,7 @@ boolean EnsurePlayerNameIsGood(char *name, INT32 playernum) * is restored to what it was before. * * We assume that if playernum is in ::g_localplayers + * (unless clientjoin is true, a necessary evil) * the console variable ::cv_playername[n] is * already set to newname. However, the player name table is assumed to * contain the old name. @@ -1120,6 +1119,10 @@ void CleanupPlayerName(INT32 playernum, const char *newname) char *tmpname = NULL; INT32 i; boolean namefailed = true; + boolean clientjoin = !!(playernum >= MAXPLAYERS); + + if (clientjoin) + playernum -= MAXPLAYERS; buf = Z_StrDup(newname); @@ -1177,17 +1180,20 @@ void CleanupPlayerName(INT32 playernum, const char *newname) } // no stealing another player's name - for (i = 0; i < MAXPLAYERS; i++) + if (!clientjoin) { - if (i != playernum && playeringame[i] - && strcasecmp(tmpname, player_names[i]) == 0) + for (i = 0; i < MAXPLAYERS; i++) { - break; + if (i != playernum && playeringame[i] + && strcasecmp(tmpname, player_names[i]) == 0) + { + break; + } } - } - if (i < MAXPLAYERS) - break; + if (i < MAXPLAYERS) + break; + } // name is okay then namefailed = false; @@ -1198,18 +1204,23 @@ void CleanupPlayerName(INT32 playernum, const char *newname) // set consvars whether namefailed or not, because even if it succeeded, // spaces may have been removed - for (i = 0; i <= splitscreen; i++) + if (clientjoin) + CV_StealthSet(&cv_playername[playernum], tmpname); + else { - if (playernum == g_localplayers[i]) + for (i = 0; i <= splitscreen; i++) { - CV_StealthSet(&cv_playername[i], tmpname); - break; + if (playernum == g_localplayers[i]) + { + CV_StealthSet(&cv_playername[i], tmpname); + break; + } } - } - if (i > splitscreen) - { - I_Assert(((void)"CleanupPlayerName used on non-local player", 0)); + if (i > splitscreen) + { + I_Assert(((void)"CleanupPlayerName used on non-local player", 0)); + } } Z_Free(buf); @@ -1805,33 +1816,28 @@ static void Got_LeaveParty(UINT8 **cp,INT32 playernum) } } -void D_SendPlayerConfig(void) +void D_SendPlayerConfig(UINT8 n) { - UINT8 i; + UINT8 buf[4]; + UINT8 *p = buf; - for (i = 0; i <= splitscreen; i++) + SendNameAndColor(n); + SendWeaponPref(n); + + if (n == 0) { - UINT8 buf[4]; - UINT8 *p = buf; - - SendNameAndColor(i); - SendWeaponPref(i); - - if (i == 0) - { - // Send it over - WRITEUINT16(p, vspowerlevel[PWRLV_RACE]); - WRITEUINT16(p, vspowerlevel[PWRLV_BATTLE]); - } - else - { - // Splitscreen players have invalid powerlevel - WRITEUINT16(p, 0); - WRITEUINT16(p, 0); - } - - SendNetXCmdForPlayer(i, XD_POWERLEVEL, buf, p-buf); + // Send it over + WRITEUINT16(p, vspowerlevel[PWRLV_RACE]); + WRITEUINT16(p, vspowerlevel[PWRLV_BATTLE]); } + else + { + // Splitscreen players have invalid powerlevel + WRITEUINT16(p, 0); + WRITEUINT16(p, 0); + } + + SendNetXCmdForPlayer(n, XD_POWERLEVEL, buf, p-buf); } // Only works for displayplayer, sorry! diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 41dc3fdf7..0e8ef25e2 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -207,7 +207,8 @@ void D_RegisterServerCommands(void); void D_RegisterClientCommands(void); void CleanupPlayerName(INT32 playernum, const char *newname); boolean EnsurePlayerNameIsGood(char *name, INT32 playernum); -void D_SendPlayerConfig(void); +void SendWeaponPref(UINT8 n); +void D_SendPlayerConfig(UINT8 n); void Command_ExitGame_f(void); void Command_Retry_f(void); void D_GameTypeChanged(INT32 lastgametype); // not a real _OnChange function anymore diff --git a/src/d_netfil.c b/src/d_netfil.c index b3c93efa2..930662cfa 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -161,10 +161,16 @@ UINT8 *PutFileNeeded(UINT16 firstfile) char wadfilename[MAX_WADPATH] = ""; UINT8 filestatus; - for (i = mainwads+1; i < numwadfiles; i++) //mainwads+1, otherwise we start on the first mainwad +#ifdef DEVELOP + i = 0; +#else + i = mainwads + 1; +#endif + + for (; i < numwadfiles; i++) //mainwads+1, otherwise we start on the first mainwad { // If it has only music/sound lumps, don't put it in the list - if (!wadfiles[i]->important) + if (i > mainwads && !wadfiles[i]->important) continue; if (firstfile) @@ -276,11 +282,16 @@ boolean CL_CheckDownloadable(void) } // Downloading locally disabled +#if 0 if (!dlstatus && M_CheckParm("-nodownload")) dlstatus = 3; if (!dlstatus) return true; +#else + if (!dlstatus) + dlstatus = 3; +#endif // not downloadable, put reason in console CONS_Alert(CONS_NOTICE, M_GetText("You need additional files to connect to this server:\n")); @@ -489,7 +500,12 @@ INT32 CL_CheckFiles(void) CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename); // Check in already loaded files - for (j = mainwads+1; wadfiles[j]; j++) +#ifdef DEVELOP + j = 0; +#else + j = mainwads + 1; +#endif + for (; wadfiles[j]; j++) { nameonly(strcpy(wadfilename, wadfiles[j]->filename)); if (!stricmp(wadfilename, fileneeded[i].filename) && diff --git a/src/d_player.h b/src/d_player.h index 0a406f785..738f8240b 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -312,6 +312,7 @@ typedef struct player_s fixed_t bob; angle_t viewrollangle; + angle_t old_viewrollangle; // camera tilt // TODO: expose to lua angle_t tilt; @@ -325,6 +326,7 @@ typedef struct player_s // fun thing for player sprite angle_t drawangle; + angle_t old_drawangle; // interp // Bit flags. // See pflags_t, above. @@ -394,6 +396,8 @@ typedef struct player_s INT32 aizdrifttilt; INT32 aizdriftturn; + INT32 underwatertilt; + fixed_t offroad; // In Super Mario Kart, going offroad has lee-way of about 1 second before you start losing speed UINT8 waterskip; // Water skipping counter diff --git a/src/deh_tables.c b/src/deh_tables.c index c2eb54691..d36221b31 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -323,6 +323,7 @@ actionpointer_t actionpointers[] = {{A_SPBChase}, "A_SPBCHASE"}, {{A_SSMineSearch}, "A_SSMINESEARCH"}, {{A_SSMineExplode}, "A_SSMINEEXPLODE"}, + {{A_LandMineExplode}, "A_LANDMINEEXPLODE"}, {{A_BallhogExplode}, "A_BALLHOGEXPLODE"}, {{A_LightningFollowPlayer}, "A_LIGHTNINGFOLLOWPLAYER"}, {{A_FZBoomFlash}, "A_FZBOOMFLASH"}, @@ -3475,6 +3476,21 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_RANDOMITEM12", "S_DEADRANDOMITEM", + // Sphere Box (for Battle) + "S_SPHEREBOX1", + "S_SPHEREBOX2", + "S_SPHEREBOX3", + "S_SPHEREBOX4", + "S_SPHEREBOX5", + "S_SPHEREBOX6", + "S_SPHEREBOX7", + "S_SPHEREBOX8", + "S_SPHEREBOX9", + "S_SPHEREBOX10", + "S_SPHEREBOX11", + "S_SPHEREBOX12", + "S_DEADSPHEREBOX", + // Random Item Pop "S_RANDOMITEMPOP1", "S_RANDOMITEMPOP2", diff --git a/src/f_finale.c b/src/f_finale.c index d5450f2c7..6749d259b 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -109,8 +109,12 @@ static patch_t *ttcheckers; // *vroom* KART static patch_t *ttkflash; // flash screen */ +#define NOWAY + +#ifdef NOWAY static patch_t *driver[2]; // Driving character on the waiting screen static UINT8 *waitcolormap; // colormap for the spinning character +#endif // ttmode user static patch_t *ttuser[TTMAX_USER]; @@ -2145,14 +2149,17 @@ void F_TitleDemoTicker(void) void F_StartWaitingPlayers(void) { +#ifdef NOWAY INT32 i; INT32 randskin; spritedef_t *sprdef; spriteframe_t *sprframe; +#endif wipegamestate = GS_TITLESCREEN; // technically wiping from title screen finalecount = 0; +#ifdef NOWAY randskin = M_RandomKey(numskins); if (waitcolormap) @@ -2165,8 +2172,9 @@ void F_StartWaitingPlayers(void) for (i = 0; i < 2; i++) { sprframe = &sprdef->spriteframes[i]; - driver[i] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); + driver[i] = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); } +#endif } void F_WaitingPlayersTicker(void) @@ -2183,14 +2191,17 @@ void F_WaitingPlayersTicker(void) void F_WaitingPlayersDrawer(void) { +#ifdef NOWAY UINT32 frame = (finalecount % 8) / 4; // The game only tics every other frame while waitingplayers - INT32 flags = V_FLIP; +#endif const char *waittext1 = "You will join"; const char *waittext2 = "the next race..."; V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); V_DrawCreditString((160 - (V_CreditStringWidth(waittext1)>>1))<>1))<width / 2, 150<width / 2, 150<mipmap.height = (UINT16)texture->height; grtex->mipmap.format = textureformat; +#ifdef GLENCORE if (encoremap) colormap += COLORMAP_REMAPOFFSET; grtex->mipmap.colormap = Z_Calloc(sizeof(*grtex->mipmap.colormap), PU_HWRPATCHCOLMIPMAP, NULL); grtex->mipmap.colormap->source = colormap; M_Memcpy(grtex->mipmap.colormap->data, colormap, 256 * sizeof(UINT8)); +#endif blockwidth = texture->width; blockheight = texture->height; @@ -891,7 +895,9 @@ void HWR_GetRawFlat(lumpnum_t flatlumpnum, boolean noencoremap) GLMipmap_t *grmip; patch_t *patch; +#ifdef GLENCORE UINT8 *colormap = colormaps; +#endif if (flatlumpnum == LUMPERROR) return; @@ -899,12 +905,16 @@ void HWR_GetRawFlat(lumpnum_t flatlumpnum, boolean noencoremap) patch = HWR_GetCachedGLPatch(flatlumpnum); grmip = ((GLPatch_t *)Patch_AllocateHardwarePatch(patch))->mipmap; +#ifdef GLENCORE if (!noencoremap && encoremap) colormap += COLORMAP_REMAPOFFSET; grmip->colormap = Z_Calloc(sizeof(*grmip->colormap), PU_HWRPATCHCOLMIPMAP, NULL); grmip->colormap->source = colormap; M_Memcpy(grmip->colormap->data, colormap, 256 * sizeof(UINT8)); +#else + (void)noencoremap; +#endif if (!grmip->downloaded && !grmip->data) HWR_CacheFlat(grmip, flatlumpnum); diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 3f6ad01e5..2cdbd02c3 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -113,7 +113,7 @@ typedef struct UINT8 splitscreen; boolean flip; // screenflip boolean shearing; // 14042019 - angle_t viewaiming; // 17052019 + float viewaiming; // 17052019 boolean roll; FLOAT rollangle; // done to not override USE_FTRANSFORM_ANGLEZ FLOAT centerx, centery; @@ -284,7 +284,7 @@ struct FSurfaceInfo typedef struct FSurfaceInfo FSurfaceInfo; #define GL_DEFAULTMIX 0x00000000 -#define GL_DEFAULTFOG 0xFF000000 +#define GL_DEFAULTFOG 0x19000000 //Hurdler: added for backward compatibility enum hwdsetspecialstate diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index b48d39b9c..4f6046123 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -51,7 +51,7 @@ EXPORT void HWRAPI(ClearMipMapCache) (void); EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value); //Hurdler: added for new development -EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface); +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface); EXPORT void HWRAPI(CreateModelVBOs) (model_t *model); EXPORT void HWRAPI(SetTransform) (FTransform *stransform); EXPORT INT32 HWRAPI(GetTextureUsed) (void); @@ -136,4 +136,4 @@ extern struct hwdriver_s hwdriver; #endif //not defined _CREATE_DLL_ -#endif //__HWR_DRV_H__ \ No newline at end of file +#endif //__HWR_DRV_H__ diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index aafef9eb4..79cdba4f3 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -26,7 +26,7 @@ //#define HWR_LOADING_SCREEN // SRB2Kart -#define GLENCORE +//#define GLENCORE // ----------- // structures diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index fd98f7898..7f6eed52a 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -40,6 +40,7 @@ #include "../r_things.h" // R_GetShadowZ #include "../d_main.h" #include "../p_slopes.h" +#include "../k_kart.h" // HITLAGJITTERS #include "hw_md2.h" #ifdef NEWCLIP @@ -3628,14 +3629,14 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) FOutVector shadowVerts[4]; FSurfaceInfo sSurf; float fscale; float fx; float fy; float offset; + float ph; extracolormap_t *colormap = NULL; UINT8 i; SINT8 flip = P_MobjFlip(thing); + UINT32 tFlag = PF_ReverseSubtract; INT32 light; fixed_t scalemul; - UINT16 alpha; - fixed_t floordiff; fixed_t groundz; fixed_t slopez; pslope_t *groundslope; @@ -3645,7 +3646,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) fixed_t interpz = thing->z; // do interpolation - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); @@ -3655,7 +3656,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) // hitlag vibrating (todo: interp somehow?) if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG)) { - fixed_t mul = thing->hitlag * (FRACUNIT / 10); + fixed_t mul = thing->hitlag * HITLAGJITTERS; if (leveltime & 1) { @@ -3674,33 +3675,32 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) groundz = R_GetShadowZ(thing, &groundslope); - floordiff = abs((flip < 0 ? thing->height : 0) + interpz - groundz); - - alpha = floordiff / (4*FRACUNIT) + 75; - if (alpha >= 255) return; - alpha = 255 - alpha; - gpatch = (patch_t *)W_CachePatchName("DSHADOW", PU_SPRITE); if (!(gpatch && ((GLPatch_t *)gpatch->hardware)->mipmap->format)) return; HWR_GetPatch(gpatch); - scalemul = FixedMul(FRACUNIT - floordiff/640, scale); - scalemul = FixedMul(scalemul, (thing->radius*2) / gpatch->height); + scalemul = FixedMul(scale, (thing->radius * 2) / gpatch->height); + + ph = (float)gpatch->height; fscale = FIXED_TO_FLOAT(scalemul); fx = FIXED_TO_FLOAT(interpx); fy = FIXED_TO_FLOAT(interpy); + if (fscale > 0.0) + { + offset = (ph / 2) * fscale; + } + else + { + return; + } + // 3--2 // | /| // |/ | // 0--1 - if (thing && fabsf(fscale - 1.0f) > 1.0E-36f) - offset = ((gpatch->height)/2) * fscale; - else - offset = (float)((gpatch->height)/2); - shadowVerts[2].x = shadowVerts[3].x = fx + offset; shadowVerts[1].x = shadowVerts[0].x = fx - offset; shadowVerts[1].z = shadowVerts[2].z = fy - offset; @@ -3748,10 +3748,15 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) colormap = thing->subsector->sector->extra_colormap; } - HWR_Lighting(&sSurf, 0, colormap); - sSurf.PolyColor.s.alpha = alpha; + HWR_Lighting(&sSurf, 255, colormap); + sSurf.PolyColor.s.alpha = 255; - HWR_ProcessPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated, SHADER_SPRITE, false); // sprite shader + if (thing->whiteshadow == true) + { + tFlag = PF_Additive; + } + + HWR_ProcessPolygon(&sSurf, shadowVerts, 4, tFlag|PF_Modulated, SHADER_SPRITE, false); // sprite shader } // This is expecting a pointer to an array containing 4 wallVerts for a sprite @@ -5055,7 +5060,6 @@ static void HWR_ProjectSprite(mobj_t *thing) INT32 heightsec, phs; const boolean splat = R_ThingIsFloorSprite(thing); const boolean papersprite = (R_ThingIsPaperSprite(thing) && !splat); - angle_t mobjangle = (thing->player ? thing->player->drawangle : thing->angle); float z1, z2; fixed_t spr_width, spr_height; @@ -5083,20 +5087,28 @@ static void HWR_ProjectSprite(mobj_t *thing) interpx = thing->x; interpy = thing->y; interpz = thing->z; - interpangle = mobjangle; + interpangle = (thing->player ? thing->player->drawangle : thing->angle); - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z); - interpangle = mobjangle; + + if (thing->player) + { + interpangle = thing->player->old_drawangle + FixedMul(rendertimefrac, thing->player->drawangle - thing->player->old_drawangle); + } + else + { + interpangle = thing->old_angle + FixedMul(rendertimefrac, thing->angle - thing->old_angle); + } } // hitlag vibrating (todo: interp somehow?) if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG)) { - fixed_t mul = thing->hitlag * (FRACUNIT / 10); + fixed_t mul = thing->hitlag * HITLAGJITTERS; if (leveltime & 1) { @@ -5237,6 +5249,8 @@ static void HWR_ProjectSprite(mobj_t *thing) spr_topoffset = spritecachedinfo[lumpoff].topoffset; #ifdef ROTSPRITE + spriterotangle = R_SpriteRotationAngle(thing, NULL); + if (spriterotangle != 0 && !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE))) { @@ -5276,8 +5290,8 @@ static void HWR_ProjectSprite(mobj_t *thing) if (papersprite) { - rightsin = FIXED_TO_FLOAT(FINESINE((mobjangle)>>ANGLETOFINESHIFT)); - rightcos = FIXED_TO_FLOAT(FINECOSINE((mobjangle)>>ANGLETOFINESHIFT)); + rightsin = FIXED_TO_FLOAT(FINESINE((interpangle)>>ANGLETOFINESHIFT)); + rightcos = FIXED_TO_FLOAT(FINECOSINE((interpangle)>>ANGLETOFINESHIFT)); } else { @@ -5470,8 +5484,10 @@ static void HWR_ProjectSprite(mobj_t *thing) { vis->colormap = colormaps; +#ifdef GLENCORE if (encoremap && (thing->flags & (MF_SCENERY|MF_NOTHINK)) && !(thing->flags & MF_DONTENCOREMAP)) vis->colormap += COLORMAP_REMAPOFFSET; +#endif } // set top/bottom coords @@ -5515,7 +5531,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) interpz = thing->z; // do interpolation - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); @@ -5803,8 +5819,7 @@ static void HWR_DrawSkyBackground(player_t *player) dometransform.scalez = 1; dometransform.fovxangle = fpov; // Tails dometransform.fovyangle = fpov; // Tails - HWR_RollTransform(&dometransform, - R_ViewRollAngle(player)); + HWR_RollTransform(&dometransform, viewroll); dometransform.splitscreen = r_splitscreen; HWR_GetTexture(texturetranslation[skytexture]); @@ -6096,7 +6111,7 @@ void HWR_RenderSkyboxView(player_t *player) atransform.fovxangle = fpov; // Tails atransform.fovyangle = fpov; // Tails - HWR_RollTransform(&atransform, R_ViewRollAngle(player)); + HWR_RollTransform(&atransform, viewroll); atransform.splitscreen = r_splitscreen; gl_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l))); @@ -6308,7 +6323,7 @@ void HWR_RenderPlayerView(void) atransform.fovxangle = fpov; // Tails atransform.fovyangle = fpov; // Tails - HWR_RollTransform(&atransform, R_ViewRollAngle(player)); + HWR_RollTransform(&atransform, viewroll); atransform.splitscreen = r_splitscreen; gl_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l))); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 70c064081..95077a54a 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -45,6 +45,7 @@ // SRB2Kart #include "../k_color.h" +#include "../k_kart.h" // HITLAGJITTERS #ifdef HAVE_PNG @@ -1372,7 +1373,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) fixed_t interpz = spr->mobj->z; // do interpolation - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = spr->mobj->old_x + FixedMul(rendertimefrac, spr->mobj->x - spr->mobj->old_x); interpy = spr->mobj->old_y + FixedMul(rendertimefrac, spr->mobj->y - spr->mobj->old_y); @@ -1382,7 +1383,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) // hitlag vibrating if (spr->mobj->hitlag > 0 && (spr->mobj->eflags & MFE_DAMAGEHITLAG)) { - fixed_t mul = spr->mobj->hitlag * (FRACUNIT / 10); + fixed_t mul = spr->mobj->hitlag * HITLAGJITTERS; if (leveltime & 1) { @@ -1648,23 +1649,26 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) p.angley = FIXED_TO_FLOAT(anglef); } - p.rollangle = 0.0f; - - if (spr->mobj->rollangle) { - fixed_t camAngleDiff = AngleFixed(viewangle) - FLOAT_TO_FIXED(p.angley); // dumb reconversion back, I know - fixed_t anglef = AngleFixed(spr->mobj->rollangle); + fixed_t anglef = AngleFixed(R_ModelRotationAngle(spr->mobj, NULL)); - p.rollangle = FIXED_TO_FLOAT(anglef); - p.roll = true; + p.rollangle = 0.0f; - // rotation pivot - p.centerx = FIXED_TO_FLOAT(spr->mobj->radius / 2); - p.centery = FIXED_TO_FLOAT(spr->mobj->height / 2); + if (anglef) + { + fixed_t camAngleDiff = AngleFixed(viewangle) - FLOAT_TO_FIXED(p.angley); // dumb reconversion back, I know - // rotation axes relative to camera - p.rollx = FIXED_TO_FLOAT(FINECOSINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT)); - p.rollz = FIXED_TO_FLOAT(FINESINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT)); + p.rollangle = FIXED_TO_FLOAT(anglef); + p.roll = true; + + // rotation pivot + p.centerx = FIXED_TO_FLOAT(spr->mobj->radius / 2); + p.centery = FIXED_TO_FLOAT(spr->mobj->height / 2); + + // rotation axes relative to camera + p.rollx = FIXED_TO_FLOAT(FINECOSINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT)); + p.rollz = FIXED_TO_FLOAT(FINESINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT)); + } } p.anglez = FIXED_TO_FLOAT(AngleFixed(spr->mobj->pitch)); @@ -1677,7 +1681,11 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) p.mirror = atransform.mirror; HWD.pfnSetShader(SHADER_MODEL); // model shader - HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, hflip, &Surf); + { + float xs = finalscale * FIXED_TO_FLOAT(spr->mobj->spritexscale); + float ys = finalscale * FIXED_TO_FLOAT(spr->mobj->spriteyscale); + HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, xs, ys, flip, hflip, &Surf); + } } return true; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 367ce8331..b2762dcbf 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -715,14 +715,15 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "float colorBrightness = sqrt((final_color.r * final_color.r) + (final_color.g * final_color.g) + (final_color.b * final_color.b));\n" \ "float fogBrightness = sqrt((fade_color.r * fade_color.r) + (fade_color.g * fade_color.g) + (fade_color.b * fade_color.b));\n" \ "float colorIntensity = 0.0;\n" \ - "if (fogBrightness > colorBrightness) {\n" \ + "if (colorBrightness < fogBrightness) {\n" \ "colorIntensity = 1.0 - min(final_color.r, min(final_color.g, final_color.b));\n" \ - "colorIntensity = abs(colorIntensity - (1.0 - fogBrightness));\n" \ + "colorIntensity = abs(colorIntensity - (1.0 - max(fade_color.r, max(fade_color.g, fade_color.b))));\n" \ "} else {\n" \ "colorIntensity = max(final_color.r, max(final_color.g, final_color.b));\n" \ - "colorIntensity = abs(colorIntensity - (fogBrightness));\n" \ + "colorIntensity = abs(colorIntensity - min(fade_color.r, min(fade_color.g, fade_color.b)));\n" \ "}\n" \ "colorIntensity *= darkness;\n" \ + "colorIntensity *= fade_color.a * 10.0;\n" \ "if (abs(final_color.r - fade_color.r) <= colorIntensity) {\n" \ "final_color.r = fade_color.r;\n" \ "} else if (final_color.r < fade_color.r) {\n" \ @@ -2687,7 +2688,7 @@ EXPORT void HWRAPI(CreateModelVBOs) (model_t *model) #define BUFFER_OFFSET(i) ((void*)(i)) -static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) +static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) { static GLRGBAFloat poly = {0,0,0,0}; static GLRGBAFloat tint = {0,0,0,0}; @@ -2711,10 +2712,11 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 #endif // Affect input model scaling - scale *= 0.5f; - scalex = scale; - scaley = scale; - scalez = scale; + hscale *= 0.5f; + vscale *= 0.5f; + scalex = hscale; + scaley = vscale; + scalez = hscale; if (duration != 0 && duration != -1 && tics != -1) // don't interpolate if instantaneous or infinite in length { @@ -2972,9 +2974,9 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 // -----------------+ // HWRAPI DrawModel : Draw a model // -----------------+ -EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) { - DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, hflipped, Surface); + DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, hscale, vscale, flipped, hflipped, Surface); } // -----------------+ diff --git a/src/i_system.h b/src/i_system.h index 4bc0e73da..789117eaa 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -56,7 +56,7 @@ precise_t I_GetPreciseTime(void); /** \brief Returns the difference between precise times as microseconds. */ -int I_PreciseToMicros(precise_t); +int I_PreciseToMicros(precise_t d); /** \brief The I_Sleep function diff --git a/src/info.c b/src/info.c index 915702380..062d1fbb2 100644 --- a/src/info.c +++ b/src/info.c @@ -526,6 +526,7 @@ char sprnames[NUMSPRITES + 1][5] = //SRB2kart Sprites (sort later) "RNDM", // Random Item Box + "SBOX", // Sphere Box (for Battle) "RPOP", // Random Item Box Pop "SGNS", // Signpost sparkle "FAST", // Speed boost trail @@ -4061,6 +4062,20 @@ state_t states[NUMSTATES] = {SPR_RNDM, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM1}, // S_RANDOMITEM12 {SPR_NULL, 0, 0, {A_ItemPop}, 0, 0, S_NULL}, // S_DEADRANDOMITEM + {SPR_SBOX, FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX2}, // S_SPHEREBOX1 + {SPR_SBOX, 2|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX3}, // S_SPHEREBOX2 + {SPR_SBOX, 4|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX4}, // S_SPHEREBOX3 + {SPR_SBOX, 6|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX5}, // S_SPHEREBOX4 + {SPR_SBOX, 8|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX6}, // S_SPHEREBOX5 + {SPR_SBOX, 10|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX7}, // S_SPHEREBOX6 + {SPR_SBOX, 12|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX8}, // S_SPHEREBOX7 + {SPR_SBOX, 14|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX9}, // S_SPHEREBOX8 + {SPR_SBOX, 16|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX10}, // S_SPHEREBOX9 + {SPR_SBOX, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX11}, // S_SPHEREBOX10 + {SPR_SBOX, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX12}, // S_SPHEREBOX11 + {SPR_SBOX, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX1}, // S_SPHEREBOX12 + {SPR_NULL, 0, 0, {A_ItemPop}, 1, 0, S_NULL}, // S_DEADSPHEREBOX + {SPR_RPOP, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_RANDOMITEMPOP2}, // S_RANDOMITEMPOP1 {SPR_RPOP, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_RANDOMITEMPOP3}, // S_RANDOMITEMPOP2 {SPR_RPOP, FF_FULLBRIGHT|2, 5, {NULL}, 0, 0, S_RANDOMITEMPOP4}, // S_RANDOMITEMPOP3 @@ -4076,17 +4091,17 @@ state_t states[NUMSTATES] = //{SPR_ICAP, FF_FLOORSPRITE|4, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMCAPSULE_BOTTOM //{SPR_ICAP, FF_FLOORSPRITE|5, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMCAPSULE_INSIDE - {SPR_SGNS, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SIGNSPARK2}, // S_SIGNSPARK1 - {SPR_SGNS, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_SIGNSPARK3}, // S_SIGNSPARK2 - {SPR_SGNS, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_SIGNSPARK4}, // S_SIGNSPARK3 - {SPR_SGNS, FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_SIGNSPARK5}, // S_SIGNSPARK4 - {SPR_SGNS, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_SIGNSPARK6}, // S_SIGNSPARK5 - {SPR_SGNS, FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_SIGNSPARK7}, // S_SIGNSPARK6 - {SPR_SGNS, FF_FULLBRIGHT|6, 1, {NULL}, 0, 0, S_SIGNSPARK8}, // S_SIGNSPARK7 - {SPR_SGNS, FF_FULLBRIGHT|7, 1, {NULL}, 0, 0, S_SIGNSPARK9}, // S_SIGNSPARK8 - {SPR_SGNS, FF_FULLBRIGHT|8, 1, {NULL}, 0, 0, S_SIGNSPARK10}, // S_SIGNSPARK9 - {SPR_SGNS, FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_SIGNSPARK11}, // S_SIGNSPARK10 - {SPR_SGNS, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_NULL}, // S_SIGNSPARK11 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SIGNSPARK2}, // S_SIGNSPARK1 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_SIGNSPARK3}, // S_SIGNSPARK2 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_SIGNSPARK4}, // S_SIGNSPARK3 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_SIGNSPARK5}, // S_SIGNSPARK4 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_SIGNSPARK6}, // S_SIGNSPARK5 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_SIGNSPARK7}, // S_SIGNSPARK6 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|6, 1, {NULL}, 0, 0, S_SIGNSPARK8}, // S_SIGNSPARK7 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|7, 1, {NULL}, 0, 0, S_SIGNSPARK9}, // S_SIGNSPARK8 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|8, 1, {NULL}, 0, 0, S_SIGNSPARK10}, // S_SIGNSPARK9 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_SIGNSPARK11}, // S_SIGNSPARK10 + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_NULL}, // S_SIGNSPARK11 {SPR_DRIF, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_DRIFTSPARK_A2}, // S_DRIFTSPARK_A1 {SPR_DRIF, FF_FULLBRIGHT|FF_TRANS20|1, 1, {NULL}, 0, 0, S_DRIFTSPARK_A3}, // S_DRIFTSPARK_A2 @@ -4358,7 +4373,7 @@ state_t states[NUMSTATES] = {SPR_KRBM, FF_FULLBRIGHT|9, 5, {NULL}, 0, 0, S_NULL}, // S_SLOWBOOM10 {SPR_LNDM, 0, -1, {NULL}, 0, 0, S_LANDMINE}, // S_LANDMINE - {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_LANDMINE_EXPLODE + {SPR_NULL, 0, 1, {A_LandMineExplode}, 0, 0, S_NULL}, // S_LANDMINE_EXPLODE {SPR_BHOG, 0, 3, {A_PlaySound}, sfx_s1bd, 1, S_BALLHOG2}, // S_BALLHOG1 {SPR_BHOG, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_BALLHOG3}, // S_BALLHOG2 @@ -23017,6 +23032,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_SPHEREBOX + -1, // doomednum + S_SPHEREBOX1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_DEADSPHEREBOX, // deathstate + S_NULL, // xdeathstate + sfx_kc2e, // deathsound + 60*FRACUNIT, // speed + 48*FRACUNIT, // radius + 48*FRACUNIT, // height + 0, // display offset + 100, // mass + MT_RANDOMITEMPOP, // damage + sfx_None, // activesound + MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + { // MT_RANDOMITEMPOP -1, // doomednum S_INVISIBLE, // spawnstate diff --git a/src/info.h b/src/info.h index c9998c498..dfb0d3c43 100644 --- a/src/info.h +++ b/src/info.h @@ -276,6 +276,7 @@ enum actionnum A_SPBCHASE, A_SSMINESEARCH, A_SSMINEEXPLODE, + A_LANDMINEEXPLODE, A_BALLHOGEXPLODE, A_LIGHTNINGFOLLOWPLAYER, A_FZBOOMFLASH, @@ -546,6 +547,8 @@ void A_JawzExplode(); void A_SPBChase(); void A_SSMineSearch(); void A_SSMineExplode(); +void A_LandMineExplode(); +void A_LandMineExplode(); void A_BallhogExplode(); void A_LightningFollowPlayer(); void A_FZBoomFlash(); @@ -1067,6 +1070,7 @@ typedef enum sprite // SRB2Kart SPR_RNDM, // Random Item Box + SPR_SBOX, // Sphere Box (for Battle) SPR_RPOP, // Random Item Box Pop SPR_SGNS, // Signpost sparkle SPR_FAST, // Speed boost trail @@ -4450,6 +4454,21 @@ typedef enum state S_RANDOMITEM12, S_DEADRANDOMITEM, + // Sphere Box (for Battle) + S_SPHEREBOX1, + S_SPHEREBOX2, + S_SPHEREBOX3, + S_SPHEREBOX4, + S_SPHEREBOX5, + S_SPHEREBOX6, + S_SPHEREBOX7, + S_SPHEREBOX8, + S_SPHEREBOX9, + S_SPHEREBOX10, + S_SPHEREBOX11, + S_SPHEREBOX12, + S_DEADSPHEREBOX, + // Random Item Pop S_RANDOMITEMPOP1, S_RANDOMITEMPOP2, @@ -6462,6 +6481,7 @@ typedef enum mobj_type // SRB2kart MT_RANDOMITEM, + MT_SPHEREBOX, MT_RANDOMITEMPOP, MT_FLOATINGITEM, MT_ITEMCAPSULE, diff --git a/src/k_battle.c b/src/k_battle.c index c33ea6bcc..8a5257206 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -229,6 +229,28 @@ mobj_t *K_SpawnChaosEmerald(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT return emerald; } +mobj_t *K_SpawnSphereBox(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 amount) +{ + mobj_t *drop = P_SpawnMobj(x, y, z, MT_SPHEREBOX); + + (void)amount; + + drop->angle = angle; + P_Thrust(drop, + FixedAngle(P_RandomFixed() * 180) + angle, + P_RandomRange(4, 12) * mapobjectscale); + + drop->momz = flip * 12 * mapobjectscale; + if (drop->eflags & MFE_UNDERWATER) + drop->momz = (117 * drop->momz) / 200; + + drop->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); + + drop->extravalue1 = amount; + + return drop; +} + void K_DropEmeraldsFromPlayer(player_t *player, UINT32 emeraldType) { UINT8 i; @@ -359,6 +381,12 @@ void K_RunPaperItemSpawners(void) FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip, 0, 0 ); + + K_SpawnSphereBox( + battleovertime.x, battleovertime.y, battleovertime.z + (128 * mapobjectscale * flip), + FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip, + 10 + ); } } else @@ -441,6 +469,14 @@ void K_RunPaperItemSpawners(void) firstUnspawnedEmerald ); } + else if (P_RandomChance(FRACUNIT/3)) + { + drop = K_SpawnSphereBox( + spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip), + FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip, + 10 + ); + } else { drop = K_CreatePaperItem( diff --git a/src/k_battle.h b/src/k_battle.h index 221873b04..c56c576d6 100644 --- a/src/k_battle.h +++ b/src/k_battle.h @@ -22,6 +22,7 @@ void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount); void K_CheckBumpers(void); void K_CheckEmeralds(player_t *player); mobj_t *K_SpawnChaosEmerald(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT32 emeraldType); +mobj_t *K_SpawnSphereBox(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 amount); void K_DropEmeraldsFromPlayer(player_t *player, UINT32 emeraldType); UINT8 K_NumEmeralds(player_t *player); void K_RunPaperItemSpawners(void); diff --git a/src/k_bot.c b/src/k_bot.c index 29aa4f177..24f3517a2 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -273,16 +273,94 @@ boolean K_PlayerUsesBotMovement(player_t *player) --------------------------------------------------*/ boolean K_BotCanTakeCut(player_t *player) { - if (!K_ApplyOffroad(player) + if ( +#if 1 + K_TripwirePass(player) == true +#else + K_ApplyOffroad(player) == false +#endif || player->itemtype == KITEM_SNEAKER || player->itemtype == KITEM_ROCKETSNEAKER || player->itemtype == KITEM_INVINCIBILITY - || player->itemtype == KITEM_HYUDORO) + ) + { return true; + } return false; } +/*-------------------------------------------------- + static line_t *K_FindBotController(mobj_t *mo) + + Finds if any bot controller linedefs are tagged to the bot's sector. + + Input Arguments:- + mo - The bot player's mobj. + + Return:- + Linedef of the bot controller. NULL if it doesn't exist. +--------------------------------------------------*/ +static line_t *K_FindBotController(mobj_t *mo) +{ + msecnode_t *node; + ffloor_t *rover; + INT16 lineNum = -1; + mtag_t tag; + + I_Assert(mo != NULL); + I_Assert(!P_MobjWasRemoved(mo)); + + for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + if (!node->m_sector) + { + continue; + } + + tag = Tag_FGet(&node->m_sector->tags); + lineNum = P_FindSpecialLineFromTag(2004, tag, -1); // todo: needs to not use P_FindSpecialLineFromTag + + if (lineNum != -1) + { + break; + } + + for (rover = node->m_sector->ffloors; rover; rover = rover->next) + { + sector_t *rs = NULL; + + if (!(rover->flags & FF_EXISTS)) + { + continue; + } + + if (mo->z > *rover->topheight || mo->z + mo->height < *rover->bottomheight) + { + continue; + } + + rs = §ors[rover->secnum]; + tag = Tag_FGet(&rs->tags); + lineNum = P_FindSpecialLineFromTag(2004, tag, -1); + + if (lineNum != -1) + { + break; + } + } + } + + if (lineNum != -1) + { + return &lines[lineNum]; + } + else + { + return NULL; + } +} + /*-------------------------------------------------- static UINT32 K_BotRubberbandDistance(player_t *player) @@ -346,6 +424,7 @@ fixed_t K_BotRubberband(player_t *player) fixed_t rubberband = FRACUNIT; fixed_t max, min; player_t *firstplace = NULL; + line_t *botController = NULL; UINT8 i; if (player->exiting) @@ -354,6 +433,17 @@ fixed_t K_BotRubberband(player_t *player) return FRACUNIT; } + botController = K_FindBotController(player->mo); + + if (botController != NULL) + { + // No Climb Flag: Disable rubberbanding + if (botController->flags & ML_NOCLIMB) + { + return FRACUNIT; + } + } + for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i] || players[i].spectator) @@ -430,8 +520,8 @@ fixed_t K_BotTopSpeedRubberband(player_t *player) } else { - // Max at +10% for level 9 bots - rubberband = FRACUNIT + ((rubberband - FRACUNIT) / 10); + // Max at +20% for level 9 bots + rubberband = FRACUNIT + ((rubberband - FRACUNIT) / 5); } // Only allow you to go faster than your regular top speed if you're facing the right direction @@ -488,6 +578,14 @@ fixed_t K_BotFrictionRubberband(player_t *player, fixed_t frict) return frict; } + if (player->tiregrease > 0) + { + // This isn't great -- it means rubberbanding will slow down when they hit a spring + // But it's better than the opposite where they accelerate into hyperspace :V + // (would appreciate an actual fix though ... could try being additive instead of multiplicative) + return frict; + } + origFrict = FixedDiv(ORIG_FRICTION, FRACUNIT + (rubberband / 2)); if (frict == ORIG_FRICTION) @@ -567,14 +665,11 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) const INT16 handling = K_GetKartTurnValue(player, KART_FULLTURN); // Reduce prediction based on how fast you can turn const INT16 normal = KART_FULLTURN; // "Standard" handling to compare to - const fixed_t distreduce = K_BotReducePrediction(player); - const fixed_t radreduce = min(distreduce + FRACUNIT/4, FRACUNIT); - const tic_t futuresight = (TICRATE * normal) / max(1, handling); // How far ahead into the future to try and predict - const fixed_t speed = max(P_AproxDistance(player->mo->momx, player->mo->momy), K_GetKartSpeed(player, false) / 4); + const fixed_t speed = P_AproxDistance(player->mo->momx, player->mo->momy); const INT32 startDist = (768 * mapobjectscale) / FRACUNIT; - const INT32 distance = ((FixedMul(speed, distreduce) / FRACUNIT) * futuresight) + startDist; + const INT32 distance = ((speed / FRACUNIT) * futuresight) + startDist; botprediction_t *predict = Z_Calloc(sizeof(botprediction_t), PU_STATIC, NULL); waypoint_t *wp = player->nextwaypoint; @@ -583,6 +678,9 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) fixed_t smallestradius = INT32_MAX; angle_t angletonext = ANGLE_MAX; + // Halves radius when encountering a wall on your way to your destination. + fixed_t radreduce = FRACUNIT; + size_t nwp; size_t i; @@ -595,7 +693,7 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) { predict->x = wp->mobj->x; predict->y = wp->mobj->y; - predict->radius = FixedMul(wp->mobj->radius, radreduce); + predict->radius = wp->mobj->radius; return predict; } @@ -635,12 +733,12 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) for (i = 0; i < wp->numnextwaypoints; i++) { - if (!K_GetWaypointIsEnabled(wp->nextwaypoints[i])) + if (K_GetWaypointIsEnabled(wp->nextwaypoints[i]) == false) { continue; } - if (K_GetWaypointIsShortcut(wp->nextwaypoints[i]) && !K_BotCanTakeCut(player)) + if (K_GetWaypointIsShortcut(wp->nextwaypoints[i]) == true && K_BotCanTakeCut(player) == false) { continue; } @@ -673,6 +771,13 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) disttonext = (INT32)wp->nextwaypointdistances[nwp]; + if (P_TraceBotTraversal(player->mo, wp->nextwaypoints[nwp]->mobj) == false) + { + // If we can't get a direct path to this waypoint, we don't want to check much further... + disttonext *= 2; + radreduce = FRACUNIT/2; + } + if (disttonext > distanceleft) { break; @@ -761,7 +866,7 @@ static UINT8 K_TrySpindash(player_t *player) return 0; } - if (speedDiff < (3 * baseAccel / 4)) + if (speedDiff < (baseAccel / 4)) { if (player->botvars.spindashconfirm < BOTSPINDASHCONFIRM) { @@ -797,70 +902,6 @@ static UINT8 K_TrySpindash(player_t *player) return 0; } -/*-------------------------------------------------- - static INT16 K_FindBotController(mobj_t *mo) - - Finds if any bot controller linedefs are tagged to the bot's sector. - - Input Arguments:- - mo - The bot player's mobj. - - Return:- - Line number of the bot controller. -1 if it doesn't exist. ---------------------------------------------------*/ -static INT16 K_FindBotController(mobj_t *mo) -{ - msecnode_t *node; - ffloor_t *rover; - INT16 lineNum = -1; - mtag_t tag; - - I_Assert(mo != NULL); - I_Assert(!P_MobjWasRemoved(mo)); - - for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - if (!node->m_sector) - { - continue; - } - - tag = Tag_FGet(&node->m_sector->tags); - lineNum = P_FindSpecialLineFromTag(2004, tag, -1); // todo: needs to not use P_FindSpecialLineFromTag - - if (lineNum != -1) - { - return lineNum; - } - - for (rover = node->m_sector->ffloors; rover; rover = rover->next) - { - sector_t *rs = NULL; - - if (!(rover->flags & FF_EXISTS)) - { - continue; - } - - if (mo->z > *rover->topheight || mo->z + mo->height < *rover->bottomheight) - { - continue; - } - - rs = §ors[rover->secnum]; - tag = Tag_FGet(&rs->tags); - lineNum = P_FindSpecialLineFromTag(2004, tag, -1); - - if (lineNum != -1) - { - return lineNum; - } - } - } - - return -1; -} - /*-------------------------------------------------- static void K_DrawPredictionDebug(botprediction_t *predict, player_t *player) @@ -925,6 +966,50 @@ static void K_DrawPredictionDebug(botprediction_t *predict, player_t *player) } } +/*-------------------------------------------------- + static void K_BotTrick(player_t *player, ticcmd_t *cmd, line_t *botController) + + Determines inputs for trick panels. + + Input Arguments:- + player - Player to generate the ticcmd for. + cmd - The player's ticcmd to modify. + botController - Linedef for the bot controller. + + Return:- + None +--------------------------------------------------*/ +static void K_BotTrick(player_t *player, ticcmd_t *cmd, line_t *botController) +{ + // Trick panel state -- do nothing until a controller line is found, in which case do a trick. + if (botController == NULL) + { + return; + } + + if (player->trickpanel == 1) + { + INT32 type = (sides[botController->sidenum[0]].rowoffset / FRACUNIT); + + // Y Offset: Trick type + switch (type) + { + case 1: + cmd->turning = KART_FULLTURN; + break; + case 2: + cmd->turning = -KART_FULLTURN; + break; + case 3: + cmd->buttons |= BT_FORWARD; + break; + case 4: + cmd->buttons |= BT_BACKWARD; + break; + } + } +} + /*-------------------------------------------------- void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) @@ -936,7 +1021,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) boolean trySpindash = true; UINT8 spindash = 0; INT32 turnamt = 0; - INT16 botController = -1; + line_t *botController = NULL; // Can't build a ticcmd if we aren't spawned... if (!player->mo) @@ -959,7 +1044,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) } // Complete override of all ticcmd functionality - if (LUAh_BotTiccmd(player, cmd)) + if (LUAh_BotTiccmd(player, cmd) == true) { return; } @@ -968,30 +1053,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) if (player->trickpanel != 0) { - // Trick panel state -- do nothing until a controller line is found, in which case do a trick. - - if (player->trickpanel == 1 && botController != -1) - { - line_t *controllerLine = &lines[botController]; - INT32 type = (sides[controllerLine->sidenum[0]].rowoffset / FRACUNIT); - - // Y Offset: Trick type - switch (type) - { - case 1: - cmd->turning = KART_FULLTURN; - break; - case 2: - cmd->turning = -KART_FULLTURN; - break; - case 3: - cmd->buttons |= BT_FORWARD; - break; - case 4: - cmd->buttons |= BT_BACKWARD; - break; - } - } + K_BotTrick(player, cmd, botController); // Don't do anything else. return; @@ -1000,20 +1062,19 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) if ((player->nextwaypoint != NULL && player->nextwaypoint->mobj != NULL && !P_MobjWasRemoved(player->nextwaypoint->mobj)) - || (botController != -1)) + || (botController != NULL)) { // Handle steering towards waypoints! SINT8 turnsign = 0; angle_t destangle, moveangle, angle; INT16 anglediff; - if (botController != -1) + if (botController != NULL && (botController->flags & ML_EFFECT1)) { const fixed_t dist = (player->mo->radius * 4); - line_t *controllerLine = &lines[botController]; // X Offset: Movement direction - destangle = FixedAngle(sides[controllerLine->sidenum[0]].textureoffset); + destangle = FixedAngle(sides[botController->sidenum[0]].textureoffset); // Overwritten prediction predict = Z_Calloc(sizeof(botprediction_t), PU_STATIC, NULL); @@ -1112,18 +1173,6 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) // Don't turn at all turnamt = 0; } - else - { - // Make minor adjustments - turnamt /= 4; - } - } - - if (anglediff > 60) - { - // Actually, don't go too fast... - cmd->forwardmove /= 2; - cmd->buttons |= BT_BRAKE; } } } diff --git a/src/k_bot.h b/src/k_bot.h index 94694c2dd..a04d5c174 100644 --- a/src/k_bot.h +++ b/src/k_bot.h @@ -15,6 +15,7 @@ #include "k_waypoint.h" #include "d_player.h" +#include "r_defs.h" // Maximum value of botvars.difficulty #define MAXBOTDIFFICULTY 9 @@ -185,19 +186,22 @@ UINT8 K_EggboxStealth(fixed_t x, fixed_t y); /*-------------------------------------------------- - fixed_t K_BotReducePrediction(player_t *player); + boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y) - Finds walls nearby the specified player, to create a multiplier - to pull bot predictions back by. + Tells us if a bot will play more careful around + this sector. Checks FOFs in the sector, as well. Input Arguments:- - player - Player to compare. + player - Player to check against. + sec - Sector to check against. + x - Linedef cross X position, for slopes + y - Linedef cross Y position, for slopes Return:- - Multiplier in fixed point scale. + true if avoiding this sector, false otherwise. --------------------------------------------------*/ -fixed_t K_BotReducePrediction(player_t *player); +boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y); /*-------------------------------------------------- @@ -219,8 +223,8 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) /*-------------------------------------------------- void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd); - Gives a multiplier for a bot's rubberbanding. Meant to be used for top speed, - acceleration, and handling. + Creates a bot's ticcmd, looking at its surroundings to + try and figure out what it should do. Input Arguments:- player - Player to generate the ticcmd for. diff --git a/src/k_botitem.c b/src/k_botitem.c index 212a84929..4bb83931c 100644 --- a/src/k_botitem.c +++ b/src/k_botitem.c @@ -86,7 +86,7 @@ static boolean K_BotUseItemNearPlayer(player_t *player, ticcmd_t *cmd, fixed_t r } /*-------------------------------------------------- - static boolean K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t radius) + static player_t *K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t radius) Looks for players around a specified x/y coordinate. @@ -97,9 +97,9 @@ static boolean K_BotUseItemNearPlayer(player_t *player, ticcmd_t *cmd, fixed_t r radius - The radius to look for players in. Return:- - true if a player was found around the coordinate, otherwise false. + The player we found, NULL if nothing was found. --------------------------------------------------*/ -static boolean K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t radius) +static player_t *K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t radius) { UINT8 i; @@ -129,15 +129,15 @@ static boolean K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t if (dist <= radius) { - return true; + return target; } } - return false; + return NULL; } /*-------------------------------------------------- - static boolean K_PlayerPredictThrow(player_t *player, UINT8 extra) + static player_t *K_PlayerPredictThrow(player_t *player, UINT8 extra) Looks for players around the predicted coordinates of their thrown item. @@ -146,9 +146,9 @@ static boolean K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t extra - Extra throwing distance, for aim forward on mines. Return:- - true if a player was found around the coordinate, otherwise false. + The player we're trying to throw at, NULL if none was found. --------------------------------------------------*/ -static boolean K_PlayerPredictThrow(player_t *player, UINT8 extra) +static player_t *K_PlayerPredictThrow(player_t *player, UINT8 extra) { const fixed_t dist = (30 + (extra * 10)) * player->mo->scale; const UINT32 airtime = FixedDiv(dist + player->mo->momz, gravity); @@ -159,7 +159,7 @@ static boolean K_PlayerPredictThrow(player_t *player, UINT8 extra) } /*-------------------------------------------------- - static boolean K_PlayerInCone(player_t *player, UINT16 cone, boolean flip) + static player_t *K_PlayerInCone(player_t *player, UINT16 cone, boolean flip) Looks for players in the . @@ -172,7 +172,7 @@ static boolean K_PlayerPredictThrow(player_t *player, UINT8 extra) Return:- true if a player was found in the cone, otherwise false. --------------------------------------------------*/ -static boolean K_PlayerInCone(player_t *player, fixed_t radius, UINT16 cone, boolean flip) +static player_t *K_PlayerInCone(player_t *player, fixed_t radius, UINT16 cone, boolean flip) { UINT8 i; @@ -222,22 +222,96 @@ static boolean K_PlayerInCone(player_t *player, fixed_t radius, UINT16 cone, boo { if (ad >= 180-cone) { - return true; + return target; } } else { if (ad <= cone) { - return true; + return target; } } } } + return NULL; +} + +/*-------------------------------------------------- + static boolean K_RivalBotAggression(player_t *bot, player_t *target) + + Returns if a bot is a rival & wants to be aggressive to a player. + + Input Arguments:- + bot - Bot to check. + target - Who the bot wants to attack. + + Return:- + false if not the rival. false if the target is another bot. Otherwise, true. +--------------------------------------------------*/ +static boolean K_RivalBotAggression(player_t *bot, player_t *target) +{ + if (bot == NULL || target == NULL) + { + // Invalid. + return false; + } + + if (bot->bot == false) + { + // lol + return false; + } + + if (bot->botvars.rival == false) + { + // Not the rival, we aren't self-aware. + return false; + } + + if (target->bot == false) + { + // This bot knows that the real threat is the player. + return true; + } + + // Calling them your friends is misleading, but you'll at least spare them. return false; } +/*-------------------------------------------------- + static void K_ItemConfirmForTarget(player_t *bot, player_t *target, UINT16 amount) + + Handles updating item confirm values for offense items. + + Input Arguments:- + bot - Bot to check. + target - Who the bot wants to attack. + amount - Amount to increase item confirm time by. + + Return:- + None +--------------------------------------------------*/ +static void K_ItemConfirmForTarget(player_t *bot, player_t *target, UINT16 amount) +{ + if (bot == NULL || target == NULL) + { + return; + } + + if (K_RivalBotAggression(bot, target) == true) + { + // Double the rate when you're aggressive. + bot->botvars.itemconfirm += amount << 1; + } + else + { + // Do as normal. + bot->botvars.itemconfirm += amount; + } +} + /*-------------------------------------------------- static boolean K_BotGenericPressItem(player_t *player, ticcmd_t *cmd, SINT8 dir) @@ -316,21 +390,21 @@ static boolean K_BotRevealsGenericTrap(player_t *player, INT16 turnamt, boolean } // Check the predicted throws. - if (K_PlayerPredictThrow(player, 0)) + if (K_PlayerPredictThrow(player, 0) != NULL) { return true; } if (mine) { - if (K_PlayerPredictThrow(player, 1)) + if (K_PlayerPredictThrow(player, 1) != NULL) { return true; } } // Check your behind. - if (K_PlayerInCone(player, player->mo->radius * 16, 10, true)) + if (K_PlayerInCone(player, player->mo->radius * 16, 10, true) != NULL) { return true; } @@ -447,7 +521,6 @@ static void K_BotItemRocketSneaker(player_t *player, ticcmd_t *cmd) } } - /*-------------------------------------------------- static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt) @@ -464,9 +537,17 @@ static void K_BotItemRocketSneaker(player_t *player, ticcmd_t *cmd) static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt) { SINT8 throwdir = -1; + player_t *target = NULL; player->botvars.itemconfirm++; + target = K_PlayerInCone(player, player->mo->radius * 16, 10, true); + if (target != NULL) + { + K_ItemConfirmForTarget(player, target, player->botvars.difficulty); + throwdir = -1; + } + if (abs(turnamt) >= KART_FULLTURN/2) { player->botvars.itemconfirm += player->botvars.difficulty / 2; @@ -474,19 +555,15 @@ static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt) } else { - if (K_PlayerPredictThrow(player, 0)) + target = K_PlayerPredictThrow(player, 0); + + if (target != NULL) { - player->botvars.itemconfirm += player->botvars.difficulty * 2; + K_ItemConfirmForTarget(player, target, player->botvars.difficulty * 2); throwdir = 1; } } - if (K_PlayerInCone(player, player->mo->radius * 16, 10, true)) - { - player->botvars.itemconfirm += player->botvars.difficulty; - throwdir = -1; - } - if (player->botvars.itemconfirm > 2*TICRATE || player->bananadrag >= TICRATE) { K_BotGenericPressItem(player, cmd, throwdir); @@ -509,12 +586,14 @@ static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt) static void K_BotItemMine(player_t *player, ticcmd_t *cmd, INT16 turnamt) { SINT8 throwdir = 0; + player_t *target = NULL; player->botvars.itemconfirm++; - if (K_PlayerInCone(player, player->mo->radius * 16, 10, true)) + target = K_PlayerInCone(player, player->mo->radius * 16, 10, true); + if (target != NULL) { - player->botvars.itemconfirm += player->botvars.difficulty; + K_ItemConfirmForTarget(player, target, player->botvars.difficulty); throwdir = -1; } @@ -525,27 +604,63 @@ static void K_BotItemMine(player_t *player, ticcmd_t *cmd, INT16 turnamt) } else { - if (K_PlayerPredictThrow(player, 0)) + target = K_PlayerPredictThrow(player, 0); + if (target != NULL) { - player->botvars.itemconfirm += player->botvars.difficulty * 2; + K_ItemConfirmForTarget(player, target, player->botvars.difficulty * 2); throwdir = 0; } - if (K_PlayerPredictThrow(player, 1)) + target = K_PlayerPredictThrow(player, 1); + if (target != NULL) { - player->botvars.itemconfirm += player->botvars.difficulty * 2; + K_ItemConfirmForTarget(player, target, player->botvars.difficulty * 2); throwdir = 1; } } - - if (player->botvars.itemconfirm > 2*TICRATE || player->bananadrag >= TICRATE) { K_BotGenericPressItem(player, cmd, throwdir); } } +/*-------------------------------------------------- + static void K_BotItemLandmine(player_t *player, ticcmd_t *cmd, INT16 turnamt) + + Item usage for landmine tossing. + + Input Arguments:- + player - Bot to do this for. + cmd - Bot's ticcmd to edit. + turnamt - How hard they currently are turning. + + Return:- + None +--------------------------------------------------*/ +static void K_BotItemLandmine(player_t *player, ticcmd_t *cmd, INT16 turnamt) +{ + player_t *target = NULL; + + player->botvars.itemconfirm++; + + if (abs(turnamt) >= KART_FULLTURN/2) + { + player->botvars.itemconfirm += player->botvars.difficulty / 2; + } + + target = K_PlayerInCone(player, player->mo->radius * 16, 10, true); + if (target != NULL) + { + K_ItemConfirmForTarget(player, target, player->botvars.difficulty); + } + + if (player->botvars.itemconfirm > 2*TICRATE) + { + K_BotGenericPressItem(player, cmd, -1); + } +} + /*-------------------------------------------------- static void K_BotItemEggman(player_t *player, ticcmd_t *cmd) @@ -562,18 +677,21 @@ static void K_BotItemEggman(player_t *player, ticcmd_t *cmd) { const UINT8 stealth = K_EggboxStealth(player->mo->x, player->mo->y); SINT8 throwdir = -1; + player_t *target = NULL; player->botvars.itemconfirm++; - if (K_PlayerPredictThrow(player, 0)) + target = K_PlayerPredictThrow(player, 0); + if (target != NULL) { - player->botvars.itemconfirm += player->botvars.difficulty / 2; + K_ItemConfirmForTarget(player, target, player->botvars.difficulty / 2); throwdir = 1; } - if (K_PlayerInCone(player, player->mo->radius * 16, 10, true)) + target = K_PlayerInCone(player, player->mo->radius * 16, 10, true); + if (target != NULL) { - player->botvars.itemconfirm += player->botvars.difficulty; + K_ItemConfirmForTarget(player, target, player->botvars.difficulty); throwdir = -1; } @@ -603,6 +721,7 @@ static void K_BotItemEggman(player_t *player, ticcmd_t *cmd) static boolean K_BotRevealsEggbox(player_t *player) { const UINT8 stealth = K_EggboxStealth(player->mo->x, player->mo->y); + player_t *target = NULL; // This is a stealthy spot for an eggbox, lets reveal it! if (stealth > 1) @@ -611,13 +730,15 @@ static boolean K_BotRevealsEggbox(player_t *player) } // Check the predicted throws. - if (K_PlayerPredictThrow(player, 0)) + target = K_PlayerPredictThrow(player, 0); + if (target != NULL) { return true; } // Check your behind. - if (K_PlayerInCone(player, player->mo->radius * 16, 10, true)) + target = K_PlayerInCone(player, player->mo->radius * 16, 10, true); + if (target != NULL) { return true; } @@ -644,7 +765,7 @@ static void K_BotItemEggmanShield(player_t *player, ticcmd_t *cmd) return; } - if (K_BotRevealsEggbox(player) || (player->botvars.itemconfirm++ > 20*TICRATE)) + if (K_BotRevealsEggbox(player) == true || (player->botvars.itemconfirm++ > 20*TICRATE)) { K_BotGenericPressItem(player, cmd, 0); } @@ -666,8 +787,9 @@ static void K_BotItemEggmanExplosion(player_t *player, ticcmd_t *cmd) { if (player->position == 1) { + // Hey, we aren't gonna find anyone up here... + // why don't we slow down a bit? :) cmd->forwardmove /= 2; - cmd->buttons |= BT_BRAKE; } K_BotUseItemNearPlayer(player, cmd, 128*player->mo->scale); @@ -690,23 +812,32 @@ static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd) const fixed_t topspeed = K_GetKartSpeed(player, false); fixed_t radius = (player->mo->radius * 32); SINT8 throwdir = -1; + UINT8 snipeMul = 2; + player_t *target = NULL; if (player->speed > topspeed) { radius = FixedMul(radius, FixedDiv(player->speed, topspeed)); + snipeMul = 3; // Confirm faster when you'll throw it with a bunch of extra speed!! } player->botvars.itemconfirm++; - if (K_PlayerInCone(player, radius, 10, false)) + target = K_PlayerInCone(player, radius, 10, false); + if (target != NULL) { - player->botvars.itemconfirm += player->botvars.difficulty * 2; + K_ItemConfirmForTarget(player, target, player->botvars.difficulty * snipeMul); throwdir = 1; } else if (K_PlayerInCone(player, radius, 10, true)) { - player->botvars.itemconfirm += player->botvars.difficulty; - throwdir = -1; + target = K_PlayerInCone(player, radius, 10, true); + + if (target != NULL) + { + K_ItemConfirmForTarget(player, target, player->botvars.difficulty); + throwdir = -1; + } } if (player->botvars.itemconfirm > 5*TICRATE) @@ -732,24 +863,54 @@ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd) const fixed_t topspeed = K_GetKartSpeed(player, false); fixed_t radius = (player->mo->radius * 32); SINT8 throwdir = 1; + UINT8 snipeMul = 2; + INT32 lastTarg = player->lastjawztarget; + player_t *target = NULL; if (player->speed > topspeed) { radius = FixedMul(radius, FixedDiv(player->speed, topspeed)); + snipeMul = 3; // Confirm faster when you'll throw it with a bunch of extra speed!! } player->botvars.itemconfirm++; - if (K_PlayerInCone(player, radius, 10, true)) + target = K_PlayerInCone(player, radius, 10, true); + if (target != NULL) { - player->botvars.itemconfirm += player->botvars.difficulty; + K_ItemConfirmForTarget(player, target, player->botvars.difficulty); throwdir = -1; } - if (player->lastjawztarget != -1) + if (lastTarg != -1 + && playeringame[lastTarg] == true + && players[lastTarg].spectator == false + && players[lastTarg].mo != NULL + && P_MobjWasRemoved(players[lastTarg].mo) == false) { - player->botvars.itemconfirm += player->botvars.difficulty * 2; - throwdir = 1; + mobj_t *targMo = players[lastTarg].mo; + mobj_t *mobj = NULL, *next = NULL; + boolean targettedAlready = false; + + target = &players[lastTarg]; + + // Make sure no other Jawz are targetting this player. + for (mobj = kitemcap; mobj; mobj = next) + { + next = mobj->itnext; + + if (mobj->type == MT_JAWZ && mobj->target == targMo) + { + targettedAlready = true; + break; + } + } + + if (targettedAlready == false) + { + K_ItemConfirmForTarget(player, target, player->botvars.difficulty * snipeMul); + throwdir = 1; + } } if (player->botvars.itemconfirm > 5*TICRATE) @@ -772,7 +933,7 @@ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd) --------------------------------------------------*/ static void K_BotItemThunder(player_t *player, ticcmd_t *cmd) { - if (!K_BotUseItemNearPlayer(player, cmd, 192*player->mo->scale)) + if (K_BotUseItemNearPlayer(player, cmd, 192*player->mo->scale) == false) { if (player->botvars.itemconfirm > 10*TICRATE) { @@ -1036,7 +1197,6 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) K_BotItemSneaker(player, cmd); break; case KITEM_BANANA: - case KITEM_LANDMINE: if (!(player->pflags & PF_ITEMOUT)) { K_BotItemGenericTrapShield(player, cmd, turnamt, false); @@ -1081,6 +1241,9 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) K_BotItemMine(player, cmd, turnamt); } break; + case KITEM_LANDMINE: + K_BotItemLandmine(player, cmd, turnamt); + break; case KITEM_THUNDERSHIELD: K_BotItemThunder(player, cmd); break; diff --git a/src/k_botsearch.c b/src/k_botsearch.c index 55533d02a..846521e6f 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -122,7 +122,7 @@ UINT8 K_EggboxStealth(fixed_t x, fixed_t y) } } - return (globalsmuggle.randomitems * globalsmuggle.eggboxes); + return (globalsmuggle.randomitems * (globalsmuggle.eggboxes + 1)); } /*-------------------------------------------------- @@ -162,21 +162,11 @@ static boolean K_BotHatesThisSectorsSpecial(player_t *player, sector_t *sec) } /*-------------------------------------------------- - static boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y) + boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y) - Tells us if a bot will play more careful around - this sector. Checks FOFs in the sector, as well. - - Input Arguments:- - player - Player to check against. - sec - Sector to check against. - x - Linedef cross X position, for slopes - y - Linedef cross Y position, for slopes - - Return:- - true if avoiding this sector, false otherwise. + See header file for description. --------------------------------------------------*/ -static boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y) +boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y) { const boolean flip = (player->mo->eflags & MFE_VERTICALFLIP); INT32 specialflag = 0; @@ -257,171 +247,6 @@ static boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, return K_BotHatesThisSectorsSpecial(player, bestsector); } -/*-------------------------------------------------- - static boolean K_FindBlockingWalls(line_t *line) - - Blockmap search function. - Reels the bot prediction back in based on solid walls - or other obstacles surrounding the bot. - - Input Arguments:- - line - Linedef passed in from iteration. - - Return:- - true continues searching, false ends the search early. ---------------------------------------------------*/ -static boolean K_FindBlockingWalls(line_t *line) -{ - // Condensed version of PIT_CheckLine - const fixed_t maxstepmove = FixedMul(MAXSTEPMOVE, mapobjectscale); - fixed_t maxstep = maxstepmove; - fixed_t linedist = INT32_MAX; - INT32 lineside = 0; - vertex_t pos; - - if (!globalsmuggle.botmo || P_MobjWasRemoved(globalsmuggle.botmo) || !globalsmuggle.botmo->player) - { - return false; - } - - if (line->polyobj && !(line->polyobj->flags & POF_SOLID)) - { - return true; - } - - if (tmbbox[BOXRIGHT] <= line->bbox[BOXLEFT] || tmbbox[BOXLEFT] >= line->bbox[BOXRIGHT] - || tmbbox[BOXTOP] <= line->bbox[BOXBOTTOM] || tmbbox[BOXBOTTOM] >= line->bbox[BOXTOP]) - { - return true; - } - - if (P_BoxOnLineSide(tmbbox, line) != -1) - { - return true; - } - - lineside = P_PointOnLineSide(globalsmuggle.botmo->x, globalsmuggle.botmo->y, line); - - // one sided line - if (!line->backsector) - { - if (lineside) - { - // don't hit the back side - return true; - } - - goto blocked; - } - - if ((line->flags & ML_IMPASSABLE) || (line->flags & ML_BLOCKPLAYERS)) - { - goto blocked; - } - - // set openrange, opentop, openbottom - P_LineOpening(line, globalsmuggle.botmo); - - if (globalsmuggle.botmo->player->waterskip) - maxstep += maxstepmove; - - if (P_MobjTouchingSectorSpecial(globalsmuggle.botmo, 1, 13, false)) - maxstep <<= 1; - else if (P_MobjTouchingSectorSpecial(globalsmuggle.botmo, 1, 12, false)) - maxstep = 0; - - if ((openrange < globalsmuggle.botmo->height) // doesn't fit - || (opentop - globalsmuggle.botmo->z < globalsmuggle.botmo->height) // mobj is too high - || (openbottom - globalsmuggle.botmo->z > maxstep)) // too big a step up - { - goto blocked; - } - - // Treat damage sectors like walls - P_ClosestPointOnLine(globalsmuggle.botmo->x, globalsmuggle.botmo->y, line, &pos); - - if (lineside) - { - if (K_BotHatesThisSector(globalsmuggle.botmo->player, line->frontsector, pos.x, pos.y)) - goto blocked; - } - else - { - if (K_BotHatesThisSector(globalsmuggle.botmo->player, line->backsector, pos.x, pos.y)) - goto blocked; - } - - // We weren't blocked! - return true; - -blocked: - linedist = K_DistanceOfLineFromPoint(line->v1->x, line->v1->y, line->v2->x, line->v2->y, globalsmuggle.botmo->x, globalsmuggle.botmo->y); - linedist -= (globalsmuggle.botmo->radius * 8); // Maintain a reasonable distance away from it - - if (linedist > globalsmuggle.distancetocheck) - { - return true; - } - - if (linedist <= 0) - { - globalsmuggle.closestlinedist = 0; - return false; - } - - if (linedist < globalsmuggle.closestlinedist) - { - globalsmuggle.closestlinedist = linedist; - } - - return true; -} - -/*-------------------------------------------------- - fixed_t K_BotReducePrediction(player_t *player) - - See header file for description. ---------------------------------------------------*/ -fixed_t K_BotReducePrediction(player_t *player) -{ - INT32 xl, xh, yl, yh, bx, by; - - globalsmuggle.botmo = player->mo; - globalsmuggle.distancetocheck = (player->mo->radius * 32); - globalsmuggle.closestlinedist = INT32_MAX; - - tmx = player->mo->x; - tmy = player->mo->y; - - xl = (unsigned)(tmx - globalsmuggle.distancetocheck - bmaporgx)>>MAPBLOCKSHIFT; - xh = (unsigned)(tmx + globalsmuggle.distancetocheck - bmaporgx)>>MAPBLOCKSHIFT; - yl = (unsigned)(tmy - globalsmuggle.distancetocheck - bmaporgy)>>MAPBLOCKSHIFT; - yh = (unsigned)(tmy + globalsmuggle.distancetocheck - bmaporgy)>>MAPBLOCKSHIFT; - - BMBOUNDFIX(xl, xh, yl, yh); - - tmbbox[BOXTOP] = tmy + globalsmuggle.distancetocheck; - tmbbox[BOXBOTTOM] = tmy - globalsmuggle.distancetocheck; - tmbbox[BOXRIGHT] = tmx + globalsmuggle.distancetocheck; - tmbbox[BOXLEFT] = tmx - globalsmuggle.distancetocheck; - - // Check for lines that the bot might collide with - for (bx = xl; bx <= xh; bx++) - { - for (by = yl; by <= yh; by++) - { - P_BlockLinesIterator(bx, by, K_FindBlockingWalls); - } - } - - if (globalsmuggle.closestlinedist == INT32_MAX) - { - return FRACUNIT; - } - - return (FRACUNIT/2) + (FixedDiv(globalsmuggle.closestlinedist, globalsmuggle.distancetocheck) / 2); -} - /*-------------------------------------------------- static void K_AddAttackObject(mobj_t *thing, UINT8 side, UINT8 weight) diff --git a/src/k_brightmap.c b/src/k_brightmap.c new file mode 100644 index 000000000..f481938f2 --- /dev/null +++ b/src/k_brightmap.c @@ -0,0 +1,256 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2021 by Sally "TehRealSalt" Cochenour +// Copyright (C) 2021 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file k_brightmap.c +/// \brief Brightmap texture loading. + +#include "k_brightmap.h" + +#include "doomdata.h" +#include "doomdef.h" +#include "doomtype.h" +#include "fastcmp.h" +#include "r_textures.h" +#include "w_wad.h" +#include "z_zone.h" + +static brightmapStorage_t *brightmapStorage = NULL; +static size_t maxBrightmapStorage = 0; + +/*-------------------------------------------------- + static brightmapStorage_t *K_NewBrightmap(void) + + Increases the size of maxBrightmapStorage by 1. + + Input Arguments:- + None + + Return:- + The new brightmap storage struct. +--------------------------------------------------*/ +static brightmapStorage_t *K_NewBrightmap(void) +{ + maxBrightmapStorage++; + brightmapStorage = (brightmapStorage_t *)Z_Realloc(brightmapStorage, sizeof(brightmapStorage_t) * (maxBrightmapStorage + 1), PU_STATIC, NULL); + return &brightmapStorage[ maxBrightmapStorage - 1 ]; +} + +/*-------------------------------------------------- + static brightmapStorage_t *K_GetBrightmapStorageByIndex(size_t checkIndex) + + See header file for description. +--------------------------------------------------*/ +static brightmapStorage_t *K_GetBrightmapStorageByIndex(size_t checkIndex) +{ + if (checkIndex >= maxBrightmapStorage) + { + return NULL; + } + + return &brightmapStorage[checkIndex]; +} + +/*-------------------------------------------------- + static brightmapStorage_t *K_GetBrightmapStorageByTextureName(const char *checkName) + + See header file for description. +--------------------------------------------------*/ +static brightmapStorage_t *K_GetBrightmapStorageByTextureName(const char *checkName) +{ + size_t i; + + if (maxBrightmapStorage == 0) + { + return NULL; + } + + for (i = 0; i < maxBrightmapStorage; i++) + { + brightmapStorage_t *bms = &brightmapStorage[i]; + + if (stricmp(checkName, bms->textureName) == 0) + { + // Name matches. + return bms; + } + } + + return NULL; +} + +/*-------------------------------------------------- + static boolean K_BRIGHTLumpParser(UINT8 *data, size_t size) + + Parses inputted lump data as a BRIGHT lump. + + Input Arguments:- + data - Pointer to lump data. + size - The length of the lump data. + + Return:- + false if any errors occured, otherwise true. +--------------------------------------------------*/ +static boolean K_BRIGHTLumpParser(UINT8 *data, size_t size) +{ + char *tkn = M_GetToken((char *)data); + size_t pos = 0; + + while (tkn && (pos = M_GetTokenPos()) < size) + { + boolean valid = true; + + if (stricmp(tkn, "texture") == 0) + { + Z_Free(tkn); + tkn = M_GetToken(NULL); + pos = M_GetTokenPos(); + + if (tkn && pos < size) + { + brightmapStorage_t *bms = K_GetBrightmapStorageByTextureName(tkn); + + if (bms == NULL) + { + bms = K_NewBrightmap(); + strncpy(bms->textureName, tkn, 9); + } + + Z_Free(tkn); + tkn = M_GetToken(NULL); + pos = M_GetTokenPos(); + + if (tkn && pos < size) + { + strncpy(bms->brightmapName, tkn, 9); + } + else + { + CONS_Alert(CONS_ERROR, "No brightmap for brightmap definition.\n"); + valid = false; + } + } + else + { + CONS_Alert(CONS_ERROR, "No texture for brightmap definition.\n"); + valid = false; + } + } + // todo: SPRITE brightmaps?! + else + { + CONS_Alert(CONS_ERROR, "Unknown keyword '%s' found in BRIGHT lump.\n", tkn); + valid = false; + } + + Z_Free(tkn); + + if (valid == false) + { + return false; + } + + tkn = M_GetToken(NULL); + } + + Z_Free(tkn); + return true; +} + +/*-------------------------------------------------- + void K_InitBrightmaps(void) + + See header file for description. +--------------------------------------------------*/ +void K_InitBrightmaps(void) +{ + INT32 wadNum; + size_t i; + + I_Assert(brightmapStorage == NULL); + maxBrightmapStorage = 0; + + for (wadNum = 0; wadNum < numwadfiles; wadNum++) + { + UINT16 lumpNum; + + // Find BRIGHT lump in the WAD + lumpNum = W_CheckNumForNamePwad("BRIGHT", wadNum, 0); + + while (lumpNum != INT16_MAX) + { + UINT8 *data; + data = (UINT8 *)W_CacheLumpNumPwad(wadNum, lumpNum, PU_STATIC); + + // If that didn't exist, we have nothing to do here. + if (data == NULL) + { + lumpNum = W_CheckNumForNamePwad("BRIGHT", (UINT16)wadNum, lumpNum + 1); + continue; + } + else + { + lumpinfo_t *lump_p = &wadfiles[wadNum]->lumpinfo[lumpNum]; + size_t size = W_LumpLengthPwad(wadNum, lumpNum); + + size_t nameLength = strlen(wadfiles[wadNum]->filename) + 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name + char *name = malloc(nameLength + 1); + + sprintf(name, "%s|%s", wadfiles[wadNum]->filename, lump_p->fullname); + name[nameLength] = '\0'; + + size = W_LumpLengthPwad(wadNum, lumpNum); + + CONS_Printf(M_GetText("Loading BRIGHT from %s\n"), name); + K_BRIGHTLumpParser(data, size); + + free(name); + } + + lumpNum = W_CheckNumForNamePwad("BRIGHT", (UINT16)wadNum, lumpNum + 1); + } + } + + if (maxBrightmapStorage == 0) + { + // No brightmaps were defined. + return; + } + + for (i = 0; i < maxBrightmapStorage; i++) + { + brightmapStorage_t *bms = K_GetBrightmapStorageByIndex(i); + INT32 texNum, bmNum; + + if (bms == NULL) + { + // Shouldn't happen. + break; + } + + texNum = R_CheckTextureNumForName(bms->textureName); + if (texNum != -1) + { + bmNum = R_CheckTextureNumForName(bms->brightmapName); + if (bmNum == -1) + { + texturebrightmaps[texNum] = 0; + } + else + { + texturebrightmaps[texNum] = bmNum; + } + } + } + + R_ClearTextureNumCache(false); + + // Clear brightmapStorage now that we're done with it. + Z_Free(brightmapStorage); + brightmapStorage = NULL; +} diff --git a/src/k_brightmap.h b/src/k_brightmap.h new file mode 100644 index 000000000..8d33ae5cb --- /dev/null +++ b/src/k_brightmap.h @@ -0,0 +1,38 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2021 by Sally "TehRealSalt" Cochenour +// Copyright (C) 2021 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file k_brightmap.h +/// \brief Brightmap texture loading. + +#ifndef __K_BRIGHTMAP_H__ +#define __K_BRIGHTMAP_H__ + +#include "doomdata.h" +#include "doomdef.h" +#include "doomtype.h" + +typedef struct brightmapStorage_s +{ + // Brightmap storage struct. + // Stores data for brightmap definitions, + // before putting them into texturebrightmaps. + + char textureName[9]; // The texture's name. + char brightmapName[9]; // The brightmap's name. +} brightmapStorage_t; + +/*-------------------------------------------------- + void K_InitBrightmaps(void); + + Finds all BRIGHT lumps and processes them. +--------------------------------------------------*/ + +void K_InitBrightmaps(void); + +#endif // __K_BRIGHTMAP_H__ diff --git a/src/k_hud.c b/src/k_hud.c index 589467bd6..7f54abd49 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -801,7 +801,7 @@ void K_ObjectTracking(trackingResult_t *result, vector3_t *point, UINT8 cameraNu player_t *player; fixed_t viewpointX, viewpointY, viewpointZ; - angle_t viewpointAngle, viewpointAiming; + angle_t viewpointAngle, viewpointAiming, viewpointRoll; INT32 screenWidth, screenHeight; fixed_t screenHalfW, screenHalfH; @@ -829,12 +829,13 @@ void K_ObjectTracking(trackingResult_t *result, vector3_t *point, UINT8 cameraNu cam = &camera[cameraNum]; player = &players[displayplayers[cameraNum]]; - if (cam == NULL || player == NULL) + if (cam == NULL || player == NULL || player->mo == NULL || P_MobjWasRemoved(player->mo) == true) { // Shouldn't be possible? return; } + // TODO: needs da interp if (cam->chase == true && !player->spectator) { // Use the camera's properties. @@ -843,26 +844,45 @@ void K_ObjectTracking(trackingResult_t *result, vector3_t *point, UINT8 cameraNu viewpointZ = cam->z - point->z; viewpointAngle = (INT32)cam->angle; viewpointAiming = (INT32)cam->aiming; + viewpointRoll = (INT32)player->viewrollangle; + + if (cv_frameinterpolation.value == 1) + { + viewpointX = cam->old_x + FixedMul(rendertimefrac, cam->x - cam->old_x); + viewpointY = cam->old_y + FixedMul(rendertimefrac, cam->y - cam->old_y); + viewpointZ = (cam->old_z + FixedMul(rendertimefrac, cam->z - cam->old_z)) - point->z; + + viewpointAngle = (INT32)(cam->old_angle + FixedMul(rendertimefrac, cam->angle - cam->old_angle)); + viewpointAiming = (INT32)(cam->old_aiming + FixedMul(rendertimefrac, cam->aiming - cam->old_aiming)); + viewpointRoll = (INT32)(player->old_viewrollangle + FixedMul(rendertimefrac, player->viewrollangle - player->old_viewrollangle)); + } } else { // Use player properties. - - if (player->mo == NULL || P_MobjWasRemoved(player->mo) == true) - { - // This shouldn't happen. - return; - } - viewpointX = player->mo->x; viewpointY = player->mo->y; viewpointZ = player->viewz - point->z; viewpointAngle = (INT32)player->mo->angle; viewpointAiming = (INT32)player->aiming; + viewpointRoll = (INT32)player->viewrollangle; + + if (cv_frameinterpolation.value == 1) + { + viewpointX = player->mo->old_x + FixedMul(rendertimefrac, player->mo->x - player->mo->old_x); + viewpointY = player->mo->old_y + FixedMul(rendertimefrac, player->mo->y - player->mo->old_y); + viewpointZ = (player->mo->old_z + FixedMul(rendertimefrac, player->viewz - player->mo->old_z)) - point->z; //player->old_viewz + + viewpointAngle = (INT32)(player->mo->old_angle + FixedMul(rendertimefrac, player->mo->angle - player->mo->old_angle)); + //viewpointAiming = (INT32)(player->mo->old_aiming + FixedMul(rendertimefrac, player->mo->aiming - player->mo->old_aiming)); + viewpointRoll = (INT32)(player->old_viewrollangle + FixedMul(rendertimefrac, player->viewrollangle - player->old_viewrollangle)); + } } viewpointAngle += (INT32)angleOffset; + (void)viewpointRoll; // will be used later... + // Calculate screen size adjustments. // TODO: Anyone want to make this support non-green resolutions somehow? :V screenWidth = BASEVIDWIDTH; @@ -2590,6 +2610,7 @@ static void K_drawKartPlayerCheck(void) UINT8 *colormap = NULL; UINT8 pnum = 0; vector3_t v; + vector3_t pPos; trackingResult_t result; if (!playeringame[i] || checkplayer->spectator) @@ -2614,7 +2635,22 @@ static void K_drawKartPlayerCheck(void) v.y = checkplayer->mo->y; v.z = checkplayer->mo->z; - distance = R_PointToDist2(stplyr->mo->x, stplyr->mo->y, v.x, v.y); + pPos.x = stplyr->mo->x; + pPos.y = stplyr->mo->y; + pPos.z = stplyr->mo->z; + + if (cv_frameinterpolation.value == 1) + { + v.x = checkplayer->mo->old_x + FixedMul(rendertimefrac, checkplayer->mo->x - checkplayer->mo->old_x); + v.y = checkplayer->mo->old_y + FixedMul(rendertimefrac, checkplayer->mo->y - checkplayer->mo->old_y); + v.z = checkplayer->mo->old_z + FixedMul(rendertimefrac, checkplayer->mo->z - checkplayer->mo->old_z); + + pPos.x = stplyr->mo->old_x + FixedMul(rendertimefrac, stplyr->mo->x - stplyr->mo->old_x); + pPos.y = stplyr->mo->old_y + FixedMul(rendertimefrac, stplyr->mo->y - stplyr->mo->old_y); + pPos.z = stplyr->mo->old_z + FixedMul(rendertimefrac, stplyr->mo->z - stplyr->mo->old_z); + } + + distance = R_PointToDist2(pPos.x, pPos.y, v.x, v.y); if (distance > maxdistance) { @@ -2801,12 +2837,26 @@ static void K_drawKartNameTags(void) c.x = thiscam->x; c.y = thiscam->y; c.z = thiscam->z; + + if (cv_frameinterpolation.value == 1) + { + c.x = thiscam->old_x + FixedMul(rendertimefrac, thiscam->x - thiscam->old_x); + c.y = thiscam->old_y + FixedMul(rendertimefrac, thiscam->y - thiscam->old_y); + c.z = thiscam->old_z + FixedMul(rendertimefrac, thiscam->z - thiscam->old_z); + } } else { c.x = stplyr->mo->x; c.y = stplyr->mo->y; c.z = stplyr->mo->z; + + if (cv_frameinterpolation.value == 1) + { + c.x = stplyr->mo->old_x + FixedMul(rendertimefrac, stplyr->mo->x - stplyr->mo->old_x); + c.y = stplyr->mo->old_y + FixedMul(rendertimefrac, stplyr->mo->y - stplyr->mo->old_y); + c.z = stplyr->mo->old_z + FixedMul(rendertimefrac, stplyr->mo->z - stplyr->mo->old_z); + } } for (i = 0; i < MAXPLAYERS; i++) @@ -2849,6 +2899,13 @@ static void K_drawKartNameTags(void) v.y = ntplayer->mo->y; v.z = ntplayer->mo->z; + if (cv_frameinterpolation.value == 1) + { + v.x = ntplayer->mo->old_x + FixedMul(rendertimefrac, ntplayer->mo->x - ntplayer->mo->old_x); + v.y = ntplayer->mo->old_y + FixedMul(rendertimefrac, ntplayer->mo->y - ntplayer->mo->old_y); + v.z = ntplayer->mo->old_z + FixedMul(rendertimefrac, ntplayer->mo->z - ntplayer->mo->old_z); + } + if (!(ntplayer->mo->eflags & MFE_VERTICALFLIP)) { v.z += ntplayer->mo->height; @@ -2904,7 +2961,16 @@ static void K_drawKartNameTags(void) v.x = ntplayer->mo->x; v.y = ntplayer->mo->y; - v.z = ntplayer->mo->z + (ntplayer->mo->height / 2); + v.z = ntplayer->mo->z; + + if (cv_frameinterpolation.value == 1) + { + v.x = ntplayer->mo->old_x + FixedMul(rendertimefrac, ntplayer->mo->x - ntplayer->mo->old_x); + v.y = ntplayer->mo->old_y + FixedMul(rendertimefrac, ntplayer->mo->y - ntplayer->mo->old_y); + v.z = ntplayer->mo->old_z + FixedMul(rendertimefrac, ntplayer->mo->z - ntplayer->mo->old_z); + } + + v.z += (ntplayer->mo->height / 2); if (stplyr->mo->eflags & MFE_VERTICALFLIP) { @@ -3145,7 +3211,7 @@ static void K_drawKartMinimap(void) interpx = g->mo->x; interpy = g->mo->y; - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = g->mo->old_x + FixedMul(rendertimefrac, g->mo->x - g->mo->old_x); interpy = g->mo->old_y + FixedMul(rendertimefrac, g->mo->y - g->mo->old_y); @@ -3210,7 +3276,7 @@ static void K_drawKartMinimap(void) interpx = players[i].mo->x; interpy = players[i].mo->y; - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = players[i].mo->old_x + FixedMul(rendertimefrac, players[i].mo->x - players[i].mo->old_x); interpy = players[i].mo->old_y + FixedMul(rendertimefrac, players[i].mo->y - players[i].mo->old_y); @@ -3245,7 +3311,7 @@ static void K_drawKartMinimap(void) interpx = mobj->x; interpy = mobj->y; - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = mobj->old_x + FixedMul(rendertimefrac, mobj->x - mobj->old_x); interpy = mobj->old_y + FixedMul(rendertimefrac, mobj->y - mobj->old_y); @@ -3282,7 +3348,7 @@ static void K_drawKartMinimap(void) interpx = players[localplayers[i]].mo->x; interpy = players[localplayers[i]].mo->y; - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = players[localplayers[i]].mo->old_x + FixedMul(rendertimefrac, players[localplayers[i]].mo->x - players[localplayers[i]].mo->old_x); interpy = players[localplayers[i]].mo->old_y + FixedMul(rendertimefrac, players[localplayers[i]].mo->y - players[localplayers[i]].mo->old_y); @@ -3795,7 +3861,7 @@ static void K_drawKartFirstPerson(void) // hitlag vibrating if (stplyr->mo->hitlag > 0 && (stplyr->mo->eflags & MFE_DAMAGEHITLAG)) { - fixed_t mul = stplyr->mo->hitlag * (FRACUNIT / 10); + fixed_t mul = stplyr->mo->hitlag * HITLAGJITTERS; if (r_splitscreen && mul > FRACUNIT) mul = FRACUNIT; diff --git a/src/k_kart.c b/src/k_kart.c index 73661c018..822e103be 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2682,7 +2682,7 @@ boolean K_ApplyOffroad(player_t *player) boolean K_SlopeResistance(player_t *player) { - if (player->invincibilitytimer || player->sneakertimer || player->tiregrease) + if (player->invincibilitytimer || player->sneakertimer || player->tiregrease || player->flamedash) return true; return false; } @@ -2700,6 +2700,19 @@ boolean K_TripwirePass(player_t *player) return false; } +boolean K_WaterRun(player_t *player) +{ + if ( + player->invincibilitytimer || + player->sneakertimer || + player->tiregrease || + player->flamedash || + player->speed > 2 * K_GetKartSpeed(player, false) + ) + return true; + return false; +} + static fixed_t K_FlameShieldDashVar(INT32 val) { // 1 second = 75% + 50% top speed @@ -3623,14 +3636,9 @@ void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 #define MINEQUAKEDIST 4096 -// Spawns the purely visual explosion -void K_SpawnMineExplosion(mobj_t *source, UINT8 color) +// Does the proximity screen flash and quake for explosions +void K_MineFlashScreen(mobj_t *source) { - INT32 i, radius, height; - mobj_t *smoldering = P_SpawnMobj(source->x, source->y, source->z, MT_SMOLDERING); - mobj_t *dust; - mobj_t *truc; - INT32 speed, speed2; INT32 pnum; player_t *p; @@ -3653,6 +3661,18 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) break; // we can break right now because quakes are global to all split players somehow. } } +} + +// Spawns the purely visual explosion +void K_SpawnMineExplosion(mobj_t *source, UINT8 color) +{ + INT32 i, radius, height; + mobj_t *smoldering = P_SpawnMobj(source->x, source->y, source->z, MT_SMOLDERING); + mobj_t *dust; + mobj_t *truc; + INT32 speed, speed2; + + K_MineFlashScreen(source); K_MatchGenericExtraFlags(smoldering, source); smoldering->tics = TICRATE*3; @@ -4525,13 +4545,18 @@ void K_DriftDustHandling(mobj_t *spawner) void K_Squish(mobj_t *mo) { const fixed_t maxstretch = 4*FRACUNIT; - const fixed_t factor = 3 * mo->height / 2; + const fixed_t factor = 5 * mo->height / 4; const fixed_t threshold = factor / 6; - const fixed_t old3dspeed = abs(mo->lastmomz); - const fixed_t new3dspeed = abs(mo->momz); + fixed_t old3dspeed = abs(mo->lastmomz); + fixed_t new3dspeed = abs(mo->momz); - const fixed_t delta = abs(old3dspeed - new3dspeed); + fixed_t delta = abs(old3dspeed - new3dspeed); + fixed_t grav = mo->height/3; + fixed_t add = abs(grav - new3dspeed); + + if (delta < 2 * add && new3dspeed > grav) + delta += add; if (delta > threshold) { @@ -4541,7 +4566,7 @@ void K_Squish(mobj_t *mo) if (mo->spritexscale > maxstretch) mo->spritexscale = maxstretch; - if (abs(new3dspeed) > abs(old3dspeed)) + if (new3dspeed > old3dspeed || new3dspeed > grav) { mo->spritexscale = FixedDiv(FRACUNIT, mo->spritexscale); @@ -4551,7 +4576,7 @@ void K_Squish(mobj_t *mo) { mo->spritexscale -= (mo->spritexscale - FRACUNIT) - / (mo->spritexscale < FRACUNIT ? 8 : 2); + / (mo->spritexscale < FRACUNIT ? 8 : 3); } mo->spriteyscale = @@ -7565,10 +7590,12 @@ static INT16 K_GetKartDriftValue(player_t *player, fixed_t countersteer) basedrift += (basedrift / greasetics) * player->tiregrease; } - if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) +#if 0 + if (player->mo->eflags & MFE_UNDERWATER) { countersteer = FixedMul(countersteer, 3*FRACUNIT/2); } +#endif return basedrift + (FixedMul(driftadjust * FRACUNIT, countersteer) / FRACUNIT); } @@ -7672,9 +7699,10 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) turnfixed = FixedMul(turnfixed, FRACUNIT + player->handleboost); } - if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) + if ((player->mo->eflags & MFE_UNDERWATER) && + player->speed > 11 * player->mo->scale) { - turnfixed = FixedMul(turnfixed, 3*FRACUNIT/2); + turnfixed /= 2; } // Weight has a small effect on turning @@ -7683,6 +7711,24 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) return (turnfixed / FRACUNIT); } +INT32 K_GetUnderwaterTurnAdjust(player_t *player) +{ + if ((player->mo->eflags & MFE_UNDERWATER) && + player->speed > 11 * player->mo->scale) + { + INT32 steer = (K_GetKartTurnValue(player, + player->steering) << TICCMD_REDUCE); + + if (!player->drift) + steer = 9 * steer / 5; + + return FixedMul(steer, 8 * FixedDiv(player->speed, + 2 * K_GetKartSpeed(player, false) / 3)); + } + else + return 0; +} + INT32 K_GetKartDriftSparkValue(player_t *player) { return (26*4 + player->kartspeed*2 + (9 - player->kartweight))*8; @@ -8449,10 +8495,15 @@ void K_AdjustPlayerFriction(player_t *player) */ // Water gets ice physics too - if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) + if ((player->mo->eflags & MFE_TOUCHWATER) && + !player->offroad) { player->mo->friction += 614; } + else if (player->mo->eflags & MFE_UNDERWATER) + { + player->mo->friction += 312; + } // Wipeout slowdown if (player->spinouttimer && player->wipeoutslow) @@ -8583,8 +8634,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) boolean HOLDING_ITEM = (player->pflags & (PF_ITEMOUT|PF_EGGMANOUT)); boolean NO_HYUDORO = (player->stealingtimer == 0); - player->pflags &= ~PF_HITFINISHLINE; - if (!player->exiting) { if (player->oldposition < player->position) // But first, if you lost a place, diff --git a/src/k_kart.h b/src/k_kart.h index 8b0f755d6..dffc1cedf 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -20,6 +20,7 @@ Make sure this matches the actual number of states #define KART_NUMINVSPARKLESANIM 12 #define MAXHITLAGTICS 18 //12 +#define HITLAGJITTERS (FRACUNIT / 20) player_t *K_GetItemBoxPlayer(mobj_t *mobj); angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t yourspeed); @@ -69,6 +70,7 @@ void K_HandleBumperChanges(player_t *player, UINT8 prevBumpers); void K_DestroyBumpers(player_t *player, UINT8 amount); void K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount); void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source); +void K_MineFlashScreen(mobj_t *source); void K_SpawnMineExplosion(mobj_t *source, UINT8 color); void K_RunFinishLineBeam(void); UINT16 K_DriftSparkColor(player_t *player, INT32 charge); @@ -92,6 +94,7 @@ void K_UpdateDistanceFromFinishLine(player_t *const player); boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y); void K_UpdateSteeringValue(player_t *player, INT16 destSteering); INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue); +INT32 K_GetUnderwaterTurnAdjust(player_t *player); INT32 K_GetKartDriftSparkValue(player_t *player); INT32 K_StairJankFlip(INT32 value); INT32 K_GetKartDriftSparkValueForStage(player_t *player, UINT8 stage); @@ -108,6 +111,7 @@ void K_MomentumToFacing(player_t *player); boolean K_ApplyOffroad(player_t *player); boolean K_SlopeResistance(player_t *player); boolean K_TripwirePass(player_t *player); +boolean K_WaterRun(player_t *player); void K_ApplyTripWire(player_t *player, tripwirestate_t state); INT16 K_GetSpindashChargeTime(player_t *player); fixed_t K_GetSpindashChargeSpeed(player_t *player); diff --git a/src/k_menu.h b/src/k_menu.h index dfef52055..3280eba8a 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -18,6 +18,7 @@ #include "d_event.h" #include "command.h" #include "doomstat.h" // MAXSPLITSCREENPLAYERS +#include "g_demo.h" //menudemo_t // flags for items in the menu // menu handle (what we do when key is pressed @@ -173,6 +174,9 @@ extern menu_t PLAY_GamemodesDef; extern menuitem_t PLAY_RaceGamemodesMenu[]; extern menu_t PLAY_RaceGamemodesDef; +extern menuitem_t PLAY_RaceDifficulty[]; +extern menu_t PLAY_RaceDifficultyDef; + extern menuitem_t PLAY_CupSelect[]; extern menu_t PLAY_CupSelectDef; @@ -268,6 +272,16 @@ extern menu_t OPTIONS_DataDiscordDef; extern menuitem_t OPTIONS_DataErase[]; extern menu_t OPTIONS_DataEraseDef; +// EXTRAS +extern menuitem_t EXTRAS_Main[]; +extern menu_t EXTRAS_MainDef; + +extern menuitem_t EXTRAS_ReplayHut[]; +extern menu_t EXTRAS_ReplayHutDef; + +extern menuitem_t EXTRAS_ReplayStart[]; +extern menu_t EXTRAS_ReplayStartDef; + // PAUSE extern menuitem_t PAUSE_Main[]; extern menu_t PAUSE_MainDef; @@ -499,6 +513,16 @@ void M_CupSelectTick(void); void M_LevelSelectHandler(INT32 choice); void M_LevelSelectTick(void); +// dummy consvars for GP & match race setup +extern consvar_t cv_dummygpdifficulty; +extern consvar_t cv_dummykartspeed; +extern consvar_t cv_dummygpencore; +extern consvar_t cv_dummymatchbots; + +void M_SetupDifficultySelect(INT32 choice); +void M_SetupDifficultySelectMP(INT32 choice); +void M_DifficultySelectInputs(INT32 choice); + // Multiplayer menu stuff // Keep track of multiplayer menu related data @@ -597,6 +621,46 @@ void M_EraseData(INT32 choice); // For data erasing void M_VideoModeMenu(INT32 choice); void M_HandleVideoModes(INT32 ch); + +// Extras menu: +#define DF_ENCORE 0x40 + +extern struct extrasmenu_s { + + tic_t ticker; // How long the menu's been open for + INT16 offset; // To make the icons move smoothly when we transition! + + // For moving the button when we get into a submenu. it's smooth and cool! (normal x/y and target x/y.) + // this is only used during menu transitions. (and will probably remain unused until we get the statistics menu + INT16 extx; + INT16 exty; + INT16 textx; + INT16 texty; + + + // The replay vars...... oh no...... + menudemo_t *demolist; + + INT16 replayScrollTitle; + SINT8 replayScrollDelay; + SINT8 replayScrollDir; + + + +} extrasmenu; + +void M_InitExtras(INT32 choice); // init for the struct +void M_ExtrasTick(void); +boolean M_ExtrasInputs(INT32 ch); +boolean M_ExtrasQuit(void); // resets buttons when you quit + +// Extras: Replay Hut +void M_HandleReplayHutList(INT32 choice); +boolean M_QuitReplayHut(void); +void M_HutStartReplay(INT32 choice); +void M_PrepReplayList(void); + + // Pause menu: // Keep track of some pause menu data for visual goodness. @@ -673,6 +737,8 @@ void M_DrawCupSelect(void); void M_DrawLevelSelect(void); void M_DrawTimeAttack(void); +void M_DrawRaceDifficulty(void); + // Multiplayer menu stuff void M_DrawMPOptSelect(void); void M_DrawMPHost(void); @@ -692,6 +758,13 @@ void M_DrawGenericOptions(void); void M_DrawVideoModes(void); void M_DrawItemToggles(void); +// Extras menu: +void M_DrawExtrasMovingButton(void); +void M_DrawExtras(void); +void M_DrawReplayHut(void); +void M_DrawReplayStartMenu(void); +void M_DrawReplayHutReplayInfo(void); + // Misc menus: #define LOCATIONSTRING1 "Visit \x83SRB2.ORG/MODS\x80 to get & make addons!" #define LOCATIONSTRING2 "Visit \x88SRB2.ORG/MODS\x80 to get & make addons!" diff --git a/src/k_menudef.c b/src/k_menudef.c index f1925ef94..b2ef70cff 100644 --- a/src/k_menudef.c +++ b/src/k_menudef.c @@ -31,9 +31,9 @@ menuitem_t MainMenu[] = "Cut to the chase and start the race!", NULL, M_CharacterSelectInit, 0, 0}, - {IT_STRING, "Extra", + {IT_STRING | IT_CALL, "Extras", "Check out some bonus features.", "MENUI001", - NULL, 0, 0}, + M_InitExtras, 0, 0}, {IT_STRING, "Options", "Configure your controls, settings, and preferences.", NULL, @@ -100,10 +100,10 @@ menu_t PLAY_GamemodesDef = KARTGAMEMODEMENU(PLAY_GamemodesMenu, &PLAY_MainDef); menuitem_t PLAY_RaceGamemodesMenu[] = { {IT_STRING | IT_CALL, "Grand Prix", "Compete for the best rank over five races!", - NULL, M_LevelSelectInit, 2, GT_RACE}, + NULL, M_SetupDifficultySelect, 0, 0}, {IT_STRING | IT_CALL, "Match Race", "Play by your own rules in a specialized, single race!", - "MENIMG01", M_LevelSelectInit, 0, GT_RACE}, + "MENIMG01", M_SetupDifficultySelect, 1, 0}, {IT_STRING | IT_CALL, "Time Attack", "Record your best time on any track!", NULL, M_LevelSelectInit, 1, GT_RACE}, @@ -113,6 +113,52 @@ menuitem_t PLAY_RaceGamemodesMenu[] = menu_t PLAY_RaceGamemodesDef = KARTGAMEMODEMENU(PLAY_RaceGamemodesMenu, &PLAY_GamemodesDef); + +// difficulty selection: +menuitem_t PLAY_RaceDifficulty[] = +{ + // local play + {IT_STRING | IT_CVAR, "Difficulty", "Select the game difficulty", + NULL, &cv_dummygpdifficulty, 0, 0}, + + // netgames + {IT_STRING | IT_CVAR, "Difficulty", "Select the game speed", + NULL, &cv_dummykartspeed, 0, 0}, + + // DISABLE THAT OPTION OUTSIDE OF MATCH RACE + {IT_STRING2 | IT_CVAR, "CPU Players", "Enable or disable CPU players.", // 2 whitestring is used by the drawer to know to draw shitstring + NULL, &cv_dummymatchbots, 0, 0}, + + {IT_STRING2 | IT_CVAR, "Encore", "Enable or disable Encore mode", // 3 + NULL, &cv_dummygpencore, 0, 0}, + + // For GP: + {IT_STRING | IT_CALL, "Cup Select", "Go on and select a cup!", NULL, M_LevelSelectInit, 2, GT_RACE}, // 4 + + // For Match Race: + {IT_STRING | IT_CALL, "Map Select", "Go on and select a race track!", NULL, M_LevelSelectInit, 0, GT_RACE}, // 5 + + // For Match Race in NETGAMES: + {IT_STRING | IT_CALL, "Map Select", "Go on and select a race track!", NULL, M_MPSetupNetgameMapSelect, 0, GT_RACE}, // 6 + + {IT_STRING | IT_CALL, "Back", NULL, NULL, M_GoBack, 0, 0}, +}; + +menu_t PLAY_RaceDifficultyDef = { + sizeof(PLAY_RaceDifficulty) / sizeof(menuitem_t), + &PLAY_RaceGamemodesDef, + 0, + PLAY_RaceDifficulty, + 0, 0, + 0, 0, + 1, 10, + M_DrawRaceDifficulty, + NULL, + NULL, + NULL +}; + + menuitem_t PLAY_CupSelect[] = { {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, M_CupSelectHandler, 0, 0}, @@ -234,7 +280,7 @@ menuitem_t PLAY_MP_Host[] = NULL, &cv_dummygametype, 0, 0}, {IT_STRING | IT_CALL, "GO", "Select a map with the currently selected gamemode", - NULL, M_MPSetupNetgameMapSelect, 0, 0}, + NULL, M_SetupDifficultySelectMP, 0, 0}, }; @@ -1103,6 +1149,96 @@ menu_t OPTIONS_DataEraseDef = { NULL, }; + + +// extras menu +menuitem_t EXTRAS_Main[] = +{ + + {IT_STRING | IT_CALL, "Addons", "Add files to customize your experience.", + NULL, M_Addons, 0, 0}, + + {IT_STRING | IT_CALL, "Replay Hut", "Play the replays you've saved throughout your many races & battles!", + NULL, M_ReplayHut, 0, 0}, + + {IT_STRING | IT_CALL, "Statistics", "Look back on some of your greatest achievements such as your playtime and wins!", + NULL, NULL, 0, 0}, + + {IT_STRING | IT_TRANSTEXT, "Extras Checklist", "View the requirement for some of the secret content you can unlock!", + NULL, NULL, 0, 0}, +}; + +// the extras menu essentially reuses the options menu stuff +menu_t EXTRAS_MainDef = { + sizeof (EXTRAS_Main) / sizeof (menuitem_t), + &MainDef, + 0, + EXTRAS_Main, + 0, 0, + 0, 0, + 2, 10, + M_DrawExtras, + M_ExtrasTick, + NULL, + M_ExtrasInputs +}; + +// extras menu: replay hut +menuitem_t EXTRAS_ReplayHut[] = +{ + {IT_KEYHANDLER|IT_NOTHING, "", "", // Dummy menuitem for the replay list + NULL, M_HandleReplayHutList, 0, 0}, + + {IT_NOTHING, "", "", // Dummy for handling wrapping to the top of the menu.. + NULL, NULL, 0, 0}, +}; + +menu_t EXTRAS_ReplayHutDef = +{ + sizeof (EXTRAS_ReplayHut)/sizeof (menuitem_t), + &EXTRAS_MainDef, + 0, + EXTRAS_ReplayHut, + 30, 80, + 0, 0, + 0, 0, + M_DrawReplayHut, + NULL, + M_QuitReplayHut, + NULL +}; + +menuitem_t EXTRAS_ReplayStart[] = +{ + {IT_CALL |IT_STRING, "Load Addons and Watch", NULL, + NULL, M_HutStartReplay, 0, 0}, + + {IT_CALL |IT_STRING, "Load Without Addons", NULL, + NULL, M_HutStartReplay, 10, 0}, + + {IT_CALL |IT_STRING, "Watch Replay", NULL, + NULL, M_HutStartReplay, 10, 0}, + + {IT_SUBMENU |IT_STRING, "Go Back", NULL, + NULL, &EXTRAS_ReplayHutDef, 30, 0}, +}; + + +menu_t EXTRAS_ReplayStartDef = +{ + sizeof (EXTRAS_ReplayStart)/sizeof (menuitem_t), + &EXTRAS_ReplayHutDef, + 0, + EXTRAS_ReplayStart, + 27, 80, + 0, 0, + 0, 0, + M_DrawReplayStartMenu, + NULL, + NULL, + NULL +}; + // ------------------- // In-game/pause menus // ------------------- diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 2f4a29d15..8bab9160c 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -245,7 +245,10 @@ void M_Drawer(void) } else if (!WipeInAction && currentMenu != &PAUSE_PlaybackMenuDef) { - V_DrawCustomFadeScreen("FADEMAP0", 4); // now that's more readable with a faded background (yeah like Quake...) + if (rendermode == render_opengl) // OGL can't handle what SW is doing so let's fake it; + V_DrawFadeScreen(122, 3); // palette index aproximation... + else // Software can keep its unique fade + V_DrawCustomFadeScreen("FADEMAP0", 4); // now that's more readable with a faded background (yeah like Quake...) } if (currentMenu->drawroutine) @@ -342,7 +345,7 @@ static const char *M_CreateSecretMenuOption(const char *str) // void M_DrawGenericMenu(void) { - INT32 x = 0, y = 0, w, i, cursory = 0; + INT32 x = currentMenu->x, y = currentMenu->y, w, i, cursory = 0; M_DrawMenuTooltips(); @@ -1022,6 +1025,135 @@ void M_DrawCharacterSelect(void) M_DrawCharSelectCursor(priority); } +// DIFFICULTY SELECT +// This is a mix of K_DrawKartGamemodeMenu and the generic menu drawer depending on what we need. +// This is only ever used here (I hope because this is starting to pile up on hacks to look like the old m_menu.c lol...) + +void M_DrawRaceDifficulty(void) +{ + UINT8 n = currentMenu->numitems-4; + patch_t *box = W_CachePatchName("M_DBOX", PU_CACHE); + + INT32 i; + INT32 x = 120; + INT32 y = 48; + + M_DrawMenuTooltips(); + + // Draw the box for difficulty... + V_DrawFixedPatch((111 + 24*menutransition.tics)*FRACUNIT, 33*FRACUNIT, FRACUNIT, 0, box, NULL); + + if (menutransition.tics) + { + x += 24 * menutransition.tics; + } + + for (i = 0; i < currentMenu->numitems; i++) + { + if (i >= n) + { + + x = GM_STARTX + (GM_XOFFSET * 5 / 2); + y = GM_STARTY + (GM_YOFFSET * 5 / 2); + + if (i < currentMenu->numitems-1) + { + x -= GM_XOFFSET; + y -= GM_YOFFSET; + } + + + if (menutransition.tics) + { + x += 24 * menutransition.tics; + } + } + + switch (currentMenu->menuitems[i].status & IT_DISPLAY) + { + // This is HACKY...... + + case IT_STRING2: + { + + INT32 f = (i == itemOn) ? highlightflags : 0; + + V_DrawString(140 + 24*menutransition.tics, y, f, currentMenu->menuitems[i].text); + + if (currentMenu->menuitems[i].status & IT_CVAR) + { + // implicitely we'll only take care of normal cvars + INT32 cx = 260 + 24*menutransition.tics; + consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction; + + V_DrawCenteredString(cx, y, f, cv->string); + + if (i == itemOn) + { + + INT32 w = V_StringWidth(cv->string, 0)/2; + + V_DrawCharacter(cx - 10 - w - (skullAnimCounter/5), y, '\x1C' | highlightflags, false); // left arrow + V_DrawCharacter(cx + w + 2 + (skullAnimCounter/5), y, '\x1D' | highlightflags, false); // right arrow + } + } + + y += 12; + + break; + } + + case IT_STRING: + { + + UINT8 *colormap = NULL; + + if (i == itemOn) + { + colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_PLAGUE, GTC_CACHE); + } + else + { + colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_MOSS, GTC_CACHE); + } + + + if (currentMenu->menuitems[i].status & IT_CVAR) + { + + INT32 fx = (x - 24*menutransition.tics); + INT32 centx = fx + (320-fx)/2 + (menutransition.tics*24); // undo the menutransition movement to redo it here otherwise the text won't move at the same speed lole. + + // implicitely we'll only take care of normal consvars + consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction; + + V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT, 0, W_CachePatchName("MENUSHRT", PU_CACHE), colormap); + V_DrawCenteredGamemodeString(centx, y - 3, V_ALLOWLOWERCASE, colormap, cv->string); + + if (i == itemOn) + { + patch_t *arr_r = W_CachePatchName("GM_ARRL", PU_CACHE); + patch_t *arr_l = W_CachePatchName("GM_ARRR", PU_CACHE); + + V_DrawFixedPatch((centx-54 - arr_r->width - (skullAnimCounter/5))*FRACUNIT, (y-3)*FRACUNIT, FRACUNIT, 0, arr_r, colormap); + V_DrawFixedPatch((centx+54 + (skullAnimCounter/5))*FRACUNIT, (y-3)*FRACUNIT, FRACUNIT, 0, arr_l, colormap); + } + + } + else // not a cvar + { + V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT, 0, W_CachePatchName("MENUPLTR", PU_CACHE), colormap); + V_DrawGamemodeString(x + 16, y - 3, V_ALLOWLOWERCASE, colormap, currentMenu->menuitems[i].text); + } + x += GM_XOFFSET; + y += GM_YOFFSET; + + break; + } + } + } +} + // LEVEL SELECT static void M_DrawCupPreview(INT16 y, cupheader_t *cup) @@ -2113,6 +2245,60 @@ void M_DrawItemToggles(void) } +// EXTRAS: +// Copypasted from options but separate either way in case we want it to look more unique later down the line. +void M_DrawExtrasMovingButton(void) +{ + patch_t *butt = W_CachePatchName("OPT_BUTT", PU_CACHE); + UINT8 *c = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_PLAGUE, GTC_CACHE); + + V_DrawFixedPatch((extrasmenu.extx)*FRACUNIT, (extrasmenu.exty)*FRACUNIT, FRACUNIT, 0, butt, c); + V_DrawCenteredGamemodeString((extrasmenu.extx)-3, (extrasmenu.exty) - 16, V_ALLOWLOWERCASE, c, EXTRAS_MainDef.menuitems[EXTRAS_MainDef.lastOn].text); +} + +void M_DrawExtras(void) +{ + UINT8 i; + INT32 x = 140 - (48*itemOn) + extrasmenu.offset; + INT32 y = 70 + extrasmenu.offset; + patch_t *buttback = W_CachePatchName("OPT_BUTT", PU_CACHE); + patch_t *bg = W_CachePatchName("M_XTRABG", PU_CACHE); + + UINT8 *c = NULL; + + V_DrawFixedPatch(0, 0, FRACUNIT, 0, bg, NULL); + + for (i=0; i < currentMenu->numitems; i++) + { + INT32 py = y - (itemOn*48); + INT32 px = x - menutransition.tics*64; + INT32 tflag = 0; + + if (i == itemOn) + c = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_PLAGUE, GTC_CACHE); + else + c = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_BLACK, GTC_CACHE); + + if (currentMenu->menuitems[i].status & IT_TRANSTEXT) + tflag = V_TRANSLUCENT; + + if (!(menutransition.tics && i == itemOn)) + { + V_DrawFixedPatch(px*FRACUNIT, py*FRACUNIT, FRACUNIT, 0, buttback, c); + V_DrawCenteredGamemodeString(px-3, py - 16, V_ALLOWLOWERCASE|tflag, (i == itemOn ? c : NULL), currentMenu->menuitems[i].text); + } + + y += 48; + x += 48; + } + + M_DrawMenuTooltips(); + + if (menutransition.tics) + M_DrawExtrasMovingButton(); + +} + // // INGAME / PAUSE MENUS // @@ -2407,6 +2593,385 @@ void M_DrawPlaybackMenu(void) } +// replay hut... +// ...dear lord this is messy, but Ima be real I ain't fixing this. + +#define SCALEDVIEWWIDTH (vid.width/vid.dupx) +#define SCALEDVIEWHEIGHT (vid.height/vid.dupy) +void M_DrawReplayHutReplayInfo(void) +{ + lumpnum_t lumpnum; + patch_t *patch; + UINT8 *colormap; + INT32 x, y, w, h; + + switch (extrasmenu.demolist[dir_on[menudepthleft]].type) + { + case MD_NOTLOADED: + V_DrawCenteredString(160, 40, V_SNAPTOTOP, "Loading replay information..."); + break; + + case MD_INVALID: + V_DrawCenteredString(160, 40, V_SNAPTOTOP|warningflags, "This replay cannot be played."); + break; + + case MD_SUBDIR: + break; // Can't think of anything to draw here right now + + case MD_OUTDATED: + V_DrawThinString(17, 64, V_SNAPTOTOP|V_ALLOWLOWERCASE|V_TRANSLUCENT|highlightflags, "Recorded on an outdated version."); + /* FALLTHRU */ + default: + // Draw level stuff + x = 15; y = 15; + + // A 160x100 image of the level as entry MAPxxP + //CONS_Printf("%d %s\n", extrasmenu.demolist[dir_on[menudepthleft]].map, G_BuildMapName(extrasmenu.demolist[dir_on[menudepthleft]].map)); + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(extrasmenu.demolist[dir_on[menudepthleft]].map))); + if (lumpnum != LUMPERROR) + patch = W_CachePatchNum(lumpnum, PU_CACHE); + else + patch = W_CachePatchName("M_NOLVL", PU_CACHE); + + if (!(extrasmenu.demolist[dir_on[menudepthleft]].kartspeed & DF_ENCORE)) + V_DrawSmallScaledPatch(x, y, V_SNAPTOTOP, patch); + else + { + w = SHORT(patch->width); + h = SHORT(patch->height); + V_DrawSmallScaledPatch(x+(w>>1), y, V_SNAPTOTOP|V_FLIP, patch); + + { + static angle_t rubyfloattime = 0; + const fixed_t rubyheight = FINESINE(rubyfloattime>>ANGLETOFINESHIFT); + V_DrawFixedPatch((x+(w>>2))<>2))<width), y+20, V_SNAPTOTOP, patch, colormap); + + break; + } +} + +void M_DrawReplayHut(void) +{ + INT32 x, y, cursory = 0; + INT16 i; + INT16 replaylistitem = currentMenu->numitems-2; + boolean processed_one_this_frame = false; + + static UINT16 replayhutmenuy = 0; + + M_DrawEggaChannel(); + + // Draw menu choices + x = currentMenu->x; + y = currentMenu->y; + + if (itemOn > replaylistitem) + { + itemOn = replaylistitem; + dir_on[menudepthleft] = sizedirmenu-1; + extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; + } + else if (itemOn < replaylistitem) + { + dir_on[menudepthleft] = 0; + extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; + } + + if (itemOn == replaylistitem) + { + INT32 maxy; + // Scroll menu items if needed + cursory = y + currentMenu->menuitems[replaylistitem].mvar1 + dir_on[menudepthleft]*10; + maxy = y + currentMenu->menuitems[replaylistitem].mvar1 + sizedirmenu*10; + + if (cursory > maxy - 20) + cursory = maxy - 20; + + if (cursory - replayhutmenuy > SCALEDVIEWHEIGHT-50) + replayhutmenuy += (cursory-SCALEDVIEWHEIGHT-replayhutmenuy + 51)/2; + else if (cursory - replayhutmenuy < 110) + replayhutmenuy += (max(0, cursory-110)-replayhutmenuy - 1)/2; + } + else + replayhutmenuy /= 2; + + y -= replayhutmenuy; + + // Draw static menu items + for (i = 0; i < replaylistitem; i++) + { + INT32 localy = y + currentMenu->menuitems[i].mvar1; + + if (localy < 65) + continue; + + if (i == itemOn) + cursory = localy; + + if ((currentMenu->menuitems[i].status & IT_DISPLAY)==IT_STRING) + V_DrawString(x, localy, V_SNAPTOTOP|V_SNAPTOLEFT, currentMenu->menuitems[i].text); + else + V_DrawString(x, localy, V_SNAPTOTOP|V_SNAPTOLEFT|highlightflags, currentMenu->menuitems[i].text); + } + + y += currentMenu->menuitems[replaylistitem].mvar1; + + for (i = 0; i < (INT16)sizedirmenu; i++) + { + INT32 localy = y+i*10; + INT32 localx = x; + + if (localy < 65) + continue; + if (localy >= SCALEDVIEWHEIGHT) + break; + + if (extrasmenu.demolist[i].type == MD_NOTLOADED && !processed_one_this_frame) + { + processed_one_this_frame = true; + G_LoadDemoInfo(&extrasmenu.demolist[i]); + } + + if (extrasmenu.demolist[i].type == MD_SUBDIR) + { + localx += 8; + V_DrawScaledPatch(x - 4, localy, V_SNAPTOTOP|V_SNAPTOLEFT, W_CachePatchName(dirmenu[i][DIR_TYPE] == EXT_UP ? "M_RBACK" : "M_RFLDR", PU_CACHE)); + } + + if (itemOn == replaylistitem && i == (INT16)dir_on[menudepthleft]) + { + cursory = localy; + + if (extrasmenu.replayScrollDelay) + extrasmenu.replayScrollDelay--; + else if (extrasmenu.replayScrollDir > 0) + { + if (extrasmenu.replayScrollTitle < (V_StringWidth(extrasmenu.demolist[i].title, 0) - (SCALEDVIEWWIDTH - (x<<1)))<<1) + extrasmenu.replayScrollTitle++; + else + { + extrasmenu.replayScrollDelay = TICRATE; + extrasmenu.replayScrollDir = -1; + } + } + else + { + if (extrasmenu.replayScrollTitle > 0) + extrasmenu.replayScrollTitle--; + else + { + extrasmenu.replayScrollDelay = TICRATE; + extrasmenu.replayScrollDir = 1; + } + } + + V_DrawString(localx - (extrasmenu.replayScrollTitle>>1), localy, V_SNAPTOTOP|V_SNAPTOLEFT|highlightflags|V_ALLOWLOWERCASE, extrasmenu.demolist[i].title); + } + else + V_DrawString(localx, localy, V_SNAPTOTOP|V_SNAPTOLEFT|V_ALLOWLOWERCASE, extrasmenu.demolist[i].title); + } + + // Draw scrollbar + y = sizedirmenu*10 + currentMenu->menuitems[replaylistitem].mvar1 + 30; + if (y > SCALEDVIEWHEIGHT-80) + { + V_DrawFill(BASEVIDWIDTH-4, 75, 4, SCALEDVIEWHEIGHT-80, V_SNAPTOTOP|V_SNAPTORIGHT|159); + V_DrawFill(BASEVIDWIDTH-3, 76 + (SCALEDVIEWHEIGHT-80) * replayhutmenuy / y, 2, (((SCALEDVIEWHEIGHT-80) * (SCALEDVIEWHEIGHT-80))-1) / y - 1, V_SNAPTOTOP|V_SNAPTORIGHT|149); + } + + // Draw the cursor + V_DrawScaledPatch(currentMenu->x - 24, cursory, V_SNAPTOTOP|V_SNAPTOLEFT, + W_CachePatchName("M_CURSOR", PU_CACHE)); + V_DrawString(currentMenu->x, cursory, V_SNAPTOTOP|V_SNAPTOLEFT|highlightflags, currentMenu->menuitems[itemOn].text); + + // Now draw some replay info! + V_DrawFill(10, 10, 300, 60, V_SNAPTOTOP|159); + + if (itemOn == replaylistitem) + { + M_DrawReplayHutReplayInfo(); + } +} + +void M_DrawReplayStartMenu(void) +{ + const char *warning; + UINT8 i; + + M_DrawEggaChannel(); + M_DrawGenericMenu(); + +#define STARTY 62-(extrasmenu.replayScrollTitle>>1) + // Draw rankings beyond first + for (i = 1; i < MAXPLAYERS && extrasmenu.demolist[dir_on[menudepthleft]].standings[i].ranking; i++) + { + patch_t *patch; + UINT8 *colormap; + + V_DrawRightAlignedString(BASEVIDWIDTH-100, STARTY + i*20, V_SNAPTOTOP|highlightflags, va("%2d", extrasmenu.demolist[dir_on[menudepthleft]].standings[i].ranking)); + V_DrawThinString(BASEVIDWIDTH-96, STARTY + i*20, V_SNAPTOTOP|V_ALLOWLOWERCASE, extrasmenu.demolist[dir_on[menudepthleft]].standings[i].name); + + if (extrasmenu.demolist[dir_on[menudepthleft]].standings[i].timeorscore == UINT32_MAX-1) + V_DrawThinString(BASEVIDWIDTH-92, STARTY + i*20 + 9, V_SNAPTOTOP, "NO CONTEST"); + else if (extrasmenu.demolist[dir_on[menudepthleft]].gametype == GT_RACE) + V_DrawRightAlignedString(BASEVIDWIDTH-40, STARTY + i*20 + 9, V_SNAPTOTOP, va("%d'%02d\"%02d", + G_TicsToMinutes(extrasmenu.demolist[dir_on[menudepthleft]].standings[i].timeorscore, true), + G_TicsToSeconds(extrasmenu.demolist[dir_on[menudepthleft]].standings[i].timeorscore), + G_TicsToCentiseconds(extrasmenu.demolist[dir_on[menudepthleft]].standings[i].timeorscore) + )); + else + V_DrawString(BASEVIDWIDTH-92, STARTY + i*20 + 9, V_SNAPTOTOP, va("%d", extrasmenu.demolist[dir_on[menudepthleft]].standings[i].timeorscore)); + + // Character face! + + // Lat: 08/06/2020: For some reason missing skins have their value set to 255 (don't even ask me why I didn't write this) + // and for an even STRANGER reason this passes the first check below, so we're going to make sure that the skin here ISN'T 255 before we do anything stupid. + + if (extrasmenu.demolist[dir_on[menudepthleft]].standings[i].skin != 0xFF) + { + patch = faceprefix[extrasmenu.demolist[dir_on[menudepthleft]].standings[i].skin][FACE_RANK]; + colormap = R_GetTranslationColormap( + extrasmenu.demolist[dir_on[menudepthleft]].standings[i].skin, + extrasmenu.demolist[dir_on[menudepthleft]].standings[i].color, + GTC_MENUCACHE); + } + else + { + patch = W_CachePatchName("M_NORANK", PU_CACHE); + colormap = R_GetTranslationColormap( + TC_RAINBOW, + extrasmenu.demolist[dir_on[menudepthleft]].standings[i].color, + GTC_MENUCACHE); + } + + V_DrawMappedPatch(BASEVIDWIDTH-5 - SHORT(patch->width), STARTY + i*20, V_SNAPTOTOP, patch, colormap); + } +#undef STARTY + + // Handle scrolling rankings + if (extrasmenu.replayScrollDelay) + extrasmenu.replayScrollDelay--; + else if (extrasmenu.replayScrollDir > 0) + { + if (extrasmenu.replayScrollTitle < (i*20 - SCALEDVIEWHEIGHT + 100)<<1) + extrasmenu.replayScrollTitle++; + else + { + extrasmenu.replayScrollDelay = TICRATE; + extrasmenu.replayScrollDir = -1; + } + } + else + { + if (extrasmenu.replayScrollTitle > 0) + extrasmenu.replayScrollTitle--; + else + { + extrasmenu.replayScrollDelay = TICRATE; + extrasmenu.replayScrollDir = 1; + } + } + + V_DrawFill(10, 10, 300, 60, V_SNAPTOTOP|159); + M_DrawReplayHutReplayInfo(); + + V_DrawString(10, 72, V_SNAPTOTOP|highlightflags|V_ALLOWLOWERCASE, extrasmenu.demolist[dir_on[menudepthleft]].title); + + // Draw a warning prompt if needed + switch (extrasmenu.demolist[dir_on[menudepthleft]].addonstatus) + { + case DFILE_ERROR_CANNOTLOAD: + warning = "Some addons in this replay cannot be loaded.\nYou can watch anyway, but desyncs may occur."; + break; + + case DFILE_ERROR_NOTLOADED: + case DFILE_ERROR_INCOMPLETEOUTOFORDER: + warning = "Loading addons will mark your game as modified, and Record Attack may be unavailable.\nYou can watch without loading addons, but desyncs may occur."; + break; + + case DFILE_ERROR_EXTRAFILES: + warning = "You have addons loaded that were not present in this replay.\nYou can watch anyway, but desyncs may occur."; + break; + + case DFILE_ERROR_OUTOFORDER: + warning = "You have this replay's addons loaded, but they are out of order.\nYou can watch anyway, but desyncs may occur."; + break; + + default: + return; + } + + V_DrawSmallString(4, BASEVIDHEIGHT-14, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, warning); +} + // Draw misc menus: // Addons (this is merely copypasted, original code by toaster) @@ -2494,6 +3059,14 @@ void M_DrawAddons(void) M_CacheAddonPatches(); + // hack: If we're calling this from GS_MENU, that means we're in the extras menu! + // so draw the apropriate background + if (gamestate == GS_MENU) + { + patch_t *bg = W_CachePatchName("M_XTRABG", PU_CACHE); + V_DrawFixedPatch(0, 0, FRACUNIT, 0, bg, NULL); + } + // hack - need to refresh at end of frame to handle addfile... if (refreshdirmenu & M_AddonsRefresh()) { diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 824c0050c..d46064bb9 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -169,6 +169,9 @@ static CV_PossibleValue_t dummyscramble_cons_t[] = {{0, "Random"}, {1, "Points"} static CV_PossibleValue_t dummystaff_cons_t[] = {{0, "MIN"}, {100, "MAX"}, {0, NULL}}; static CV_PossibleValue_t dummygametype_cons_t[] = {{0, "Race"}, {1, "Battle"}, {0, NULL}}; +static CV_PossibleValue_t dummygpdifficulty_cons_t[] = {{0, "Easy"}, {1, "Normal"}, {2, "Hard"}, {3, "Master"}, {0, NULL}}; +static CV_PossibleValue_t dummykartspeed_cons_t[] = {{-1, "Auto"}, {0, "Easy"}, {1, "Normal"}, {2, "Hard"}, {0, NULL}}; + //static consvar_t cv_dummymenuplayer = CVAR_INIT ("dummymenuplayer", "P1", CV_HIDDEN|CV_CALL, dummymenuplayer_cons_t, Dummymenuplayer_OnChange); static consvar_t cv_dummyteam = CVAR_INIT ("dummyteam", "Spectator", CV_HIDDEN, dummyteam_cons_t, NULL); //static cv_dummyspectate = CVAR_INITconsvar_t ("dummyspectate", "Spectator", CV_HIDDEN, dummyspectate_cons_t, NULL); @@ -179,6 +182,26 @@ consvar_t cv_dummyip = CVAR_INIT ("dummyip", "", CV_HIDDEN, NULL, NULL); consvar_t cv_dummymenuplayer = CVAR_INIT ("dummymenuplayer", "P1", CV_HIDDEN|CV_CALL, dummymenuplayer_cons_t, Dummymenuplayer_OnChange); consvar_t cv_dummyspectate = CVAR_INIT ("dummyspectate", "Spectator", CV_HIDDEN, dummyspectate_cons_t, NULL); +consvar_t cv_dummygpdifficulty = CVAR_INIT ("dummygpdifficulty", "Normal", CV_HIDDEN, dummygpdifficulty_cons_t, NULL); +consvar_t cv_dummykartspeed = CVAR_INIT ("dummykartspeed", "Auto", CV_HIDDEN, dummykartspeed_cons_t, NULL); +consvar_t cv_dummygpencore = CVAR_INIT ("dummygpdifficulty", "No", CV_HIDDEN, CV_YesNo, NULL); + +static CV_PossibleValue_t dummymatchbots_cons_t[] = { + {0, "Off"}, + {1, "Lv.1"}, + {2, "Lv.2"}, + {3, "Lv.3"}, + {4, "Lv.4"}, + {5, "Lv.5"}, + {6, "Lv.6"}, + {7, "Lv.7"}, + {8, "Lv.8"}, + {9, "Lv.9"}, + {0, NULL} +}; + +consvar_t cv_dummymatchbots = CVAR_INIT ("dummymatchbots", "Off", CV_HIDDEN|CV_SAVE, dummymatchbots_cons_t, NULL); // Save this one if you wanna test your stuff without bots for instance + // ========================================================================== // CVAR ONCHANGE EVENTS GO HERE // ========================================================================== @@ -1563,6 +1586,11 @@ void M_Init(void) CV_RegisterVar(&cv_dummygametype); CV_RegisterVar(&cv_dummyip); + CV_RegisterVar(&cv_dummygpdifficulty); + CV_RegisterVar(&cv_dummykartspeed); + CV_RegisterVar(&cv_dummygpencore); + CV_RegisterVar(&cv_dummymatchbots); + M_UpdateMenuBGImage(true); #if 0 @@ -2372,6 +2400,63 @@ boolean M_CharacterSelectQuit(void) return true; } +// DIFFICULTY SELECT + +void M_SetupDifficultySelect(INT32 choice) +{ + // check what we picked. + choice = currentMenu->menuitems[itemOn].mvar1; + + // setup the difficulty menu and then remove choices depending on choice + PLAY_RaceDifficultyDef.prevMenu = currentMenu; + M_SetupNextMenu(&PLAY_RaceDifficultyDef, false); + + PLAY_RaceDifficulty[0].status = IT_STRING|IT_CVAR; + PLAY_RaceDifficulty[1].status = IT_DISABLED; + PLAY_RaceDifficulty[2].status = IT_DISABLED; + PLAY_RaceDifficulty[3].status = IT_DISABLED; + PLAY_RaceDifficulty[4].status = IT_DISABLED; + PLAY_RaceDifficulty[5].status = IT_DISABLED; + PLAY_RaceDifficulty[6].status = IT_DISABLED; + + if (choice) // Match Race + { + PLAY_RaceDifficulty[2].status = IT_STRING2|IT_CVAR; // CPUs on/off use string2 to signify not to use the normal gm font drawer + PLAY_RaceDifficulty[3].status = IT_STRING2|IT_CVAR; // Encore on/off use string2 to signify not to use the normal gm font drawer + PLAY_RaceDifficulty[5].status = IT_STRING|IT_CALL; // Level Select (Match Race) + itemOn = 5; // Select cup select by default. + + } + else // GP + { + PLAY_RaceDifficulty[3].status = IT_STRING2|IT_CVAR; // Encore on/off use string2 to signify not to use the normal gm font drawer + PLAY_RaceDifficulty[4].status = IT_STRING|IT_CALL; // Level Select (GP) + itemOn = 4; // Select cup select by default. + } +} + +// calls the above but changes the cvar we set +void M_SetupDifficultySelectMP(INT32 choice) +{ + (void) choice; + + PLAY_RaceDifficultyDef.prevMenu = currentMenu; + M_SetupNextMenu(&PLAY_RaceDifficultyDef, false); + + PLAY_RaceDifficulty[0].status = IT_DISABLED; + PLAY_RaceDifficulty[1].status = IT_STRING|IT_CVAR; + PLAY_RaceDifficulty[2].status = IT_STRING2|IT_CVAR; // CPUs on/off use string2 to signify not to use the normal gm font drawer + PLAY_RaceDifficulty[3].status = IT_STRING2|IT_CVAR; // Encore on/off use string2 to signify not to use the normal gm font drawer + PLAY_RaceDifficulty[4].status = IT_DISABLED; + PLAY_RaceDifficulty[5].status = IT_DISABLED; + PLAY_RaceDifficulty[6].status = IT_STRING|IT_CALL; + + itemOn = 6; // Select cup select by default. + + // okay this is REALLY stupid but this fixes the host menu re-folding on itself when we go back. + mpmenu.modewinextend[0][0] = 1; +} + // LEVEL SELECT // @@ -2610,10 +2695,11 @@ void M_CupSelectHandler(INT32 choice) memset(&grandprixinfo, 0, sizeof(struct grandprixinfo)); - // TODO: game settings screen - grandprixinfo.gamespeed = KARTSPEED_NORMAL; - grandprixinfo.masterbots = false; - grandprixinfo.encore = false; + // read our dummy cvars + + grandprixinfo.gamespeed = min(KARTSPEED_HARD, cv_dummygpdifficulty.value); + grandprixinfo.masterbots = (cv_dummygpdifficulty.value == 3); + grandprixinfo.encore = (boolean)cv_dummygpencore.value; grandprixinfo.cup = newcup; @@ -2769,9 +2855,18 @@ void M_LevelSelectHandler(INT32 choice) SV_StartSinglePlayerServer(); multiplayer = true; // yeah, SV_StartSinglePlayerServer clobbers this... netgame = levellist.netgame; // ^ ditto. - } - D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false); + // this is considered to be CV_CHEAT however... + CV_StealthSet(&cv_kartbot, cv_dummymatchbots.string); // Match the kartbot value to the dummy match bots value. + + if (netgame) // check for the dummy kartspeed value + CV_StealthSet(&cv_kartspeed, cv_dummykartspeed.string); + + + D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_dummygpencore.value == 1), 1, 1, false, false); + } + else // directly do the map change + D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false); M_ClearMenus(true); } @@ -3403,6 +3498,103 @@ void M_HandleItemToggles(INT32 choice) } +// Extras menu; +// this is copypasted from the options menu but all of these are different functions in case we ever want it to look more unique + +struct extrasmenu_s extrasmenu; + +void M_InitExtras(INT32 choice) +{ + (void)choice; + + extrasmenu.ticker = 0; + extrasmenu.offset = 0; + + extrasmenu.extx = 0; + extrasmenu.exty = 0; + extrasmenu.textx = 0; + extrasmenu.texty = 0; + + M_SetupNextMenu(&EXTRAS_MainDef, false); +} + +// For statistics, will maybe remain unused for a while +boolean M_ExtrasQuit(void) +{ + extrasmenu.textx = 140-1; + extrasmenu.texty = 70+1; + + return true; // Always allow quitting, duh. +} + +void M_ExtrasTick(void) +{ + extrasmenu.offset /= 2; + extrasmenu.ticker++; + + extrasmenu.extx += (extrasmenu.textx - extrasmenu.extx)/2; + extrasmenu.exty += (extrasmenu.texty - extrasmenu.exty)/2; + + if (abs(extrasmenu.extx - extrasmenu.exty) < 2) + { + extrasmenu.extx = extrasmenu.textx; + extrasmenu.exty = extrasmenu.texty; // Avoid awkward 1 px errors. + } + + // Move the button for cool animations + if (currentMenu == &EXTRAS_MainDef) + { + M_ExtrasQuit(); // reset the options button. + } + else + { + extrasmenu.textx = 160; + extrasmenu.texty = 50; + } +} + +boolean M_ExtrasInputs(INT32 ch) +{ + + switch (ch) + { + case KEY_DOWNARROW: + { + extrasmenu.offset += 48; + M_NextOpt(); + S_StartSound(NULL, sfx_menu1); + + if (itemOn == 0) + extrasmenu.offset -= currentMenu->numitems*48; + + return true; + } + case KEY_UPARROW: + { + extrasmenu.offset -= 48; + M_PrevOpt(); + S_StartSound(NULL, sfx_menu1); + + if (itemOn == currentMenu->numitems-1) + extrasmenu.offset += currentMenu->numitems*48; + + return true; + } + case KEY_ENTER: + { + + if (currentMenu->menuitems[itemOn].status & IT_TRANSTEXT) + return true; // No. + + extrasmenu.extx = 140; + extrasmenu.exty = 70; // Default position for the currently selected option. + + return false; // Don't eat. + } + } + return false; +} + // ===================== // PAUSE / IN-GAME MENUS // ===================== @@ -3711,12 +3903,223 @@ void M_PlaybackQuit(INT32 choice) D_StartTitle(); } +void M_PrepReplayList(void) +{ + size_t i; + + if (extrasmenu.demolist) + Z_Free(extrasmenu.demolist); + + extrasmenu.demolist = Z_Calloc(sizeof(menudemo_t) * sizedirmenu, PU_STATIC, NULL); + + for (i = 0; i < sizedirmenu; i++) + { + if (dirmenu[i][DIR_TYPE] == EXT_UP) + { + extrasmenu.demolist[i].type = MD_SUBDIR; + sprintf(extrasmenu.demolist[i].title, "UP"); + } + else if (dirmenu[i][DIR_TYPE] == EXT_FOLDER) + { + extrasmenu.demolist[i].type = MD_SUBDIR; + strncpy(extrasmenu.demolist[i].title, dirmenu[i] + DIR_STRING, 64); + } + else + { + extrasmenu.demolist[i].type = MD_NOTLOADED; + snprintf(extrasmenu.demolist[i].filepath, 255, "%s%s", menupath, dirmenu[i] + DIR_STRING); + sprintf(extrasmenu.demolist[i].title, "....."); + } + } +} + void M_ReplayHut(INT32 choice) { (void)choice; + + extrasmenu.replayScrollTitle = 0; + extrasmenu.replayScrollDelay = TICRATE; + extrasmenu.replayScrollDir = 1; + + if (!demo.inreplayhut) + { + snprintf(menupath, 1024, "%s"PATHSEP"media"PATHSEP"replay"PATHSEP"online"PATHSEP, srb2home); + menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath); + } + if (!preparefilemenu(false, true)) + { + M_StartMessage("No replays found.\n\n(Press a key)\n", NULL, MM_NOTHING); + return; + } + else if (!demo.inreplayhut) + dir_on[menudepthleft] = 0; + demo.inreplayhut = true; + + extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; + + M_PrepReplayList(); + + menuactive = true; + M_SetupNextMenu(&EXTRAS_ReplayHutDef, false); + //G_SetGamestate(GS_TIMEATTACK); + //titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please + + demo.rewinding = false; + CL_ClearRewinds(); + + //S_ChangeMusicInternal("replst", true); } +// key handler +void M_HandleReplayHutList(INT32 choice) +{ + switch (choice) + { + case KEY_UPARROW: + if (dir_on[menudepthleft]) + dir_on[menudepthleft]--; + else + return; + //M_PrevOpt(); + + S_StartSound(NULL, sfx_menu1); + extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; + break; + + case KEY_DOWNARROW: + if (dir_on[menudepthleft] < sizedirmenu-1) + dir_on[menudepthleft]++; + else + return; + //itemOn = 0; // Not M_NextOpt because that would take us to the extra dummy item + + S_StartSound(NULL, sfx_menu1); + extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; + break; + + case KEY_ESCAPE: + M_QuitReplayHut(); + break; + + case KEY_ENTER: + switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE]) + { + case EXT_FOLDER: + strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING); + if (menudepthleft) + { + menupathindex[--menudepthleft] = strlen(menupath); + menupath[menupathindex[menudepthleft]] = 0; + + if (!preparefilemenu(false, true)) + { + S_StartSound(NULL, sfx_s224); + M_StartMessage(va("%c%s\x80\nThis folder is empty.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); + menupath[menupathindex[++menudepthleft]] = 0; + + if (!preparefilemenu(true, true)) + { + M_QuitReplayHut(); + return; + } + } + else + { + S_StartSound(NULL, sfx_menu1); + dir_on[menudepthleft] = 1; + M_PrepReplayList(); + } + } + else + { + S_StartSound(NULL, sfx_s26d); + M_StartMessage(va("%c%s\x80\nThis folder is too deep to navigate to!\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); + menupath[menupathindex[menudepthleft]] = 0; + } + break; + case EXT_UP: + S_StartSound(NULL, sfx_menu1); + menupath[menupathindex[++menudepthleft]] = 0; + if (!preparefilemenu(false, true)) + { + M_QuitReplayHut(); + return; + } + M_PrepReplayList(); + break; + default: + // We can't just use M_SetupNextMenu because that'll run ReplayDef's quitroutine and boot us back to the title screen! + currentMenu->lastOn = itemOn; + currentMenu = &EXTRAS_ReplayStartDef; + + extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; + + switch (extrasmenu.demolist[dir_on[menudepthleft]].addonstatus) + { + case DFILE_ERROR_CANNOTLOAD: + // Only show "Watch Replay Without Addons" + EXTRAS_ReplayStart[0].status = IT_DISABLED; + EXTRAS_ReplayStart[1].status = IT_CALL|IT_STRING; + //EXTRAS_ReplayStart[1].alphaKey = 0; + EXTRAS_ReplayStart[2].status = IT_DISABLED; + itemOn = 1; + break; + + case DFILE_ERROR_NOTLOADED: + case DFILE_ERROR_INCOMPLETEOUTOFORDER: + // Show "Load Addons and Watch Replay" and "Watch Replay Without Addons" + EXTRAS_ReplayStart[0].status = IT_CALL|IT_STRING; + EXTRAS_ReplayStart[1].status = IT_CALL|IT_STRING; + //EXTRAS_ReplayStart[1].alphaKey = 10; + EXTRAS_ReplayStart[2].status = IT_DISABLED; + itemOn = 0; + break; + + case DFILE_ERROR_EXTRAFILES: + case DFILE_ERROR_OUTOFORDER: + default: + // Show "Watch Replay" + EXTRAS_ReplayStart[0].status = IT_DISABLED; + EXTRAS_ReplayStart[1].status = IT_DISABLED; + EXTRAS_ReplayStart[2].status = IT_CALL|IT_STRING; + //EXTRAS_ReplayStart[2].alphaKey = 0; + itemOn = 2; + break; + } + } + + break; + } +} + +boolean M_QuitReplayHut(void) +{ + // D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate. + menuactive = false; + D_StartTitle(); + + if (extrasmenu.demolist) + Z_Free(extrasmenu.demolist); + extrasmenu.demolist = NULL; + + demo.inreplayhut = false; + + return true; +} + +void M_HutStartReplay(INT32 choice) +{ + (void)choice; + + M_ClearMenus(false); + demo.loadfiles = (itemOn == 0); + demo.ignorefiles = (itemOn != 0); + + G_DoPlayDemo(extrasmenu.demolist[dir_on[menudepthleft]].filepath); +} + + static void Splitplayers_OnChange(void) { #if 0 diff --git a/src/p_enemy.c b/src/p_enemy.c index 5417d3293..749d0dc09 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -310,6 +310,7 @@ void A_JawzExplode(mobj_t *actor); void A_SPBChase(mobj_t *actor); void A_SSMineSearch(mobj_t *actor); void A_SSMineExplode(mobj_t *actor); +void A_LandMineExplode(mobj_t *actor); void A_BallhogExplode(mobj_t *actor); void A_LightningFollowPlayer(mobj_t *actor); void A_FZBoomFlash(mobj_t *actor); @@ -11194,10 +11195,13 @@ void A_MineExplode(mobj_t *actor) A_Scream(actor); actor->flags = MF_NOGRAVITY|MF_NOCLIP; + /* quake.epicenter = NULL; quake.radius = 512*FRACUNIT; quake.intensity = 8*FRACUNIT; quake.time = TICRATE/3; + */ + P_StartQuake(8<tracer, 192*FRACUNIT, 0, true); P_MobjCheckWater(actor); @@ -12204,9 +12208,9 @@ void A_Boss5BombExplode(mobj_t *actor) P_DustRing(locvar1, 4, actor->x, actor->y, actor->z+actor->height, 2*actor->radius, 0, FRACUNIT, actor->scale); P_DustRing(locvar1, 6, actor->x, actor->y, actor->z+actor->height/2, 3*actor->radius, FRACUNIT, FRACUNIT, actor->scale); - //P_StartQuake(9*actor->scale, TICRATE/6, {actor->x, actor->y, actor->z}, 20*actor->radius); + //P_StartQuake(9*FRACUNIT, TICRATE/6, {actor->x, actor->y, actor->z}, 20*actor->radius); // the above does not exist, so we set the quake values directly instead - quake.intensity = 9*actor->scale; + quake.intensity = 9*FRACUNIT; quake.time = TICRATE/6; // the following quake values have no effect atm? ah well, may as well set them anyway { @@ -13250,6 +13254,8 @@ void A_ChangeHeight(mobj_t *actor) void A_ItemPop(mobj_t *actor) { + INT32 locvar1 = var1; + mobj_t *remains; mobjtype_t explode; @@ -13304,7 +13310,9 @@ void A_ItemPop(mobj_t *actor) if (actor->info->deathsound) S_StartSound(remains, actor->info->deathsound); - if (!((gametyperules & GTR_BUMPERS) && actor->target->player->bumpers <= 0)) + if (locvar1 == 1) + P_GivePlayerSpheres(actor->target->player, actor->extravalue1); + else if (locvar1 == 0) actor->target->player->itemroulette = 1; remains->flags2 &= ~MF2_AMBUSH; @@ -14132,6 +14140,50 @@ void A_SSMineExplode(mobj_t *actor) actor->flags2 |= MF2_DEBRIS; // Set this flag to ensure that the explosion won't be effective more than 1 frame. } +void A_LandMineExplode(mobj_t *actor) +{ + + mobj_t *expl; + INT32 colour = SKINCOLOR_KETCHUP; // we spell words properly here + INT32 i; + mobj_t *smoldering; + + if (LUA_CallAction(A_LANDMINEEXPLODE, actor)) + return; + + // we'll base the explosion "timer" off of some stupid variable like uh... cvmem! + // Yeah let's use cvmem since nobody uses that + + if (actor->target && !P_MobjWasRemoved(actor->target)) + colour = actor->target->color; + + K_MineFlashScreen(actor); + + // Spawn smoke remains: + smoldering = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMOLDERING); + P_SetScale(smoldering, actor->scale); + smoldering->tics = TICRATE*3; + + actor->fuse = actor->tics; // disappear when this state ends. + + // spawn a few physics explosions + for (i = 0; i < 15; i++) + { + expl = P_SpawnMobj(actor->x, actor->y, actor->z + actor->scale, MT_BOOMEXPLODE); + expl->color = colour; + expl->tics = (i+1); + + //K_MatchGenericExtraFlags(expl, actor); + P_SetScale(expl, actor->scale*4); + + expl->momx = P_RandomRange(-3, 3)*actor->scale/2; + expl->momy = P_RandomRange(-3, 3)*actor->scale/2; + + // 100/45 = 2.22 fu/t + expl->momz = ((i+1)*actor->scale*5/2)*P_MobjFlip(expl); + } +} + void A_BallhogExplode(mobj_t *actor) { mobj_t *mo2; diff --git a/src/p_inter.c b/src/p_inter.c index 0a2bb4e13..4dafa91c2 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -268,12 +268,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (!P_CanPickupItem(player, 1)) return; - if ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0) - { - return; - } - special->momx = special->momy = special->momz = 0; + P_SetTarget(&special->target, toucher); + P_KillMobj(special, toucher, toucher, DMG_NORMAL); + break; + case MT_SPHEREBOX: + if (player->bumpers <= 0) + return; + P_SetTarget(&special->target, toucher); P_KillMobj(special, toucher, toucher, DMG_NORMAL); break; @@ -510,16 +512,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (!(P_CanPickupItem(player, 0))) return; - // Reached the cap, don't waste 'em! - if (player->spheres >= 40) - return; - - // Not alive - if ((gametyperules & GTR_BUMPERS) && (player->bumpers <= 0)) - return; - - special->momx = special->momy = special->momz = 0; - player->spheres++; + P_GivePlayerSpheres(player, 1); break; // Secret emblem thingy diff --git a/src/p_local.h b/src/p_local.h index 631920bb6..227d915f8 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -112,6 +112,10 @@ typedef struct camera_s fixed_t pan; // SRB2Kart: camera pitches on slopes angle_t pitch; + + // Interpolation data + fixed_t old_x, old_y, old_z; + angle_t old_angle, old_aiming; } camera_t; // demo freecam or something before i commit die @@ -171,7 +175,7 @@ void P_RestoreMusic(player_t *player); boolean P_EndingMusic(player_t *player); mobj_t *P_SpawnGhostMobj(mobj_t *mobj); INT32 P_GivePlayerRings(player_t *player, INT32 num_rings); -void P_GivePlayerSpheres(player_t *player, INT32 num_spheres); +INT32 P_GivePlayerSpheres(player_t *player, INT32 num_spheres); void P_GivePlayerLives(player_t *player, INT32 numlives); UINT8 P_GetNextEmerald(void); void P_GiveEmerald(boolean spawnObj); @@ -329,6 +333,7 @@ void P_Attract(mobj_t *source, mobj_t *enemy, boolean nightsgrab); mobj_t *P_GetClosestAxis(mobj_t *source); boolean P_CanRunOnWater(player_t *player, ffloor_t *rover); +boolean P_CheckSolidFFloorSurface(player_t *player, ffloor_t *rover); void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot); @@ -399,6 +404,8 @@ boolean P_IsLineBlocking(const line_t *ld, const mobj_t *thing); boolean P_IsLineTripWire(const line_t *ld); boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y); boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam); +fixed_t P_BaseStepUp(void); +fixed_t P_GetThingStepUp(mobj_t *thing); boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff); boolean P_Move(mobj_t *actor, fixed_t speed); boolean P_SetOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z); @@ -408,6 +415,7 @@ void P_BouncePlayerMove(mobj_t *mo); void P_BounceMove(mobj_t *mo); boolean P_CheckSight(mobj_t *t1, mobj_t *t2); boolean P_TraceBlockingLines(mobj_t *t1, mobj_t *t2); +boolean P_TraceBotTraversal(mobj_t *t1, mobj_t *t2); void P_CheckHoopPosition(mobj_t *hoopthing, fixed_t x, fixed_t y, fixed_t z, fixed_t radius); boolean P_CheckSector(sector_t *sector, boolean crunch); diff --git a/src/p_map.c b/src/p_map.c index d0716790b..28487e2e3 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -310,6 +310,9 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) if (spring->eflags & MFE_VERTICALFLIP) vertispeed *= -1; + if ((spring->eflags ^ object->eflags) & MFE_VERTICALFLIP) + vertispeed *= 2; + // Vertical springs teleport you on TOP of them. if (vertispeed > 0) { @@ -1848,7 +1851,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) continue; } - if (thing->player && P_CheckSolidLava(rover)) + if (thing->player && P_CheckSolidFFloorSurface(thing->player, rover)) ; else if (thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE)) ; @@ -2414,6 +2417,56 @@ boolean PIT_PushableMoved(mobj_t *thing) return true; } +static boolean P_WaterRunning(mobj_t *thing) +{ + ffloor_t *rover = thing->floorrover; + return rover && (rover->flags & FF_SWIMMABLE) && + P_IsObjectOnGround(thing); +} + +static boolean P_WaterStepUp(mobj_t *thing) +{ + player_t *player = thing->player; + return (player && player->waterskip) || + P_WaterRunning(thing); +} + +fixed_t P_BaseStepUp(void) +{ + return FixedMul(MAXSTEPMOVE, mapobjectscale); +} + +fixed_t P_GetThingStepUp(mobj_t *thing) +{ + const fixed_t maxstepmove = P_BaseStepUp(); + fixed_t maxstep = maxstepmove; + + if (thing->type == MT_SKIM) + { + // Skim special (not needed for kart?) + return 0; + } + + if (P_WaterStepUp(thing) == true) + { + // Add some extra stepmove when waterskipping + maxstep += maxstepmove; + } + + if (P_MobjTouchingSectorSpecial(thing, 1, 13, false)) + { + // If using type Section1:13, double the maxstep. + maxstep <<= 1; + } + else if (P_MobjTouchingSectorSpecial(thing, 1, 12, false)) + { + // If using type Section1:12, no maxstep. For short walls, like Egg Zeppelin + maxstep = 0; + } + + return maxstep; +} + // // P_TryMove // Attempt to move to a new position. @@ -2475,21 +2528,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (!(thing->flags & MF_NOCLIP)) { //All things are affected by their scale. - const fixed_t maxstepmove = FixedMul(MAXSTEPMOVE, mapobjectscale); - fixed_t maxstep = maxstepmove; - - if (thing->player && thing->player->waterskip) - maxstep += maxstepmove; // Add some extra stepmove when waterskipping - - // If using type Section1:13, double the maxstep. - if (P_MobjTouchingSectorSpecial(thing, 1, 13, false)) - maxstep <<= 1; - // If using type Section1:12, no maxstep. For short walls, like Egg Zeppelin - else if (P_MobjTouchingSectorSpecial(thing, 1, 12, false)) - maxstep = 0; - - if (thing->type == MT_SKIM) - maxstep = 0; + fixed_t maxstep = P_GetThingStepUp(thing); if (tmceilingz - tmfloorz < thing->height) { @@ -2726,7 +2765,7 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y) if (!(thing->flags & MF_NOCLIP)) { - const fixed_t maxstep = FixedMul(MAXSTEPMOVE, mapobjectscale); + const fixed_t maxstep = P_BaseStepUp(); if (tmceilingz - tmfloorz < thing->height) return false; // doesn't fit @@ -3188,7 +3227,7 @@ static boolean PTR_LineIsBlocking(line_t *li) if (opentop - slidemo->z < slidemo->height) return true; // mobj is too high - if (openbottom - slidemo->z > FixedMul(MAXSTEPMOVE, mapobjectscale)) + if (openbottom - slidemo->z > P_GetThingStepUp(slidemo)) return true; // too big a step up return false; diff --git a/src/p_maputl.c b/src/p_maputl.c index 2e21f5ee3..5acddf09c 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -730,7 +730,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (!(rover->flags & FF_EXISTS)) continue; - if (mobj->player && P_CheckSolidLava(rover)) + if (mobj->player && P_CheckSolidFFloorSurface(mobj->player, rover)) ; else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) @@ -772,7 +772,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (!(rover->flags & FF_EXISTS)) continue; - if (mobj->player && P_CheckSolidLava(rover)) + if (mobj->player && P_CheckSolidFFloorSurface(mobj->player, rover)) ; else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) diff --git a/src/p_mobj.c b/src/p_mobj.c index 491b371b3..afcc87c3e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1879,7 +1879,7 @@ void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype) topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL); bottomheight = P_GetFOFBottomZ(mo, sector, rover, mo->x, mo->y, NULL); - if (mo->player && P_CheckSolidLava(rover)) // only the player should stand on lava + if (mo->player && P_CheckSolidFFloorSurface(mo->player, rover)) // only the player should stand on lava or run on water ; else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only continue; @@ -2940,6 +2940,33 @@ boolean P_SceneryZMovement(mobj_t *mo) return true; } +// P_CanRunOnWater +// +// Returns true if player can waterrun on the 3D floor +// +boolean P_CanRunOnWater(player_t *player, ffloor_t *rover) +{ + boolean flip = player->mo->eflags & MFE_VERTICALFLIP; + fixed_t surfaceheight = flip ? player->mo->waterbottom : player->mo->watertop; + fixed_t playerbottom = flip ? (player->mo->z + player->mo->height) : player->mo->z; + fixed_t clip = flip ? (surfaceheight - playerbottom) : (playerbottom - surfaceheight); + fixed_t span = player->mo->watertop - player->mo->waterbottom; + + return + clip > -(player->mo->height / 2) && + span > player->mo->height && + player->speed / 5 > abs(player->mo->momz) && + player->speed > K_GetKartSpeed(player, false) && + K_WaterRun(player) && + (rover->flags & FF_SWIMMABLE); +} + +boolean P_CheckSolidFFloorSurface(player_t *player, ffloor_t *rover) +{ + return P_CheckSolidLava(rover) || + P_CanRunOnWater(player, rover); +} + // // P_MobjCheckWater // @@ -2955,7 +2982,10 @@ void P_MobjCheckWater(mobj_t *mobj) ffloor_t *rover; player_t *p = mobj->player; // Will just be null if not a player. fixed_t height = mobj->height; + fixed_t halfheight = height / 2; boolean wasgroundpounding = false; + fixed_t top2 = P_GetSectorCeilingZAt(sector, mobj->x, mobj->y); + fixed_t bot2 = P_GetSectorFloorZAt(sector, mobj->x, mobj->y); // Default if no water exists. mobj->watertop = mobj->waterbottom = mobj->z - 1000*FRACUNIT; @@ -2966,24 +2996,31 @@ void P_MobjCheckWater(mobj_t *mobj) for (rover = sector->ffloors; rover; rover = rover->next) { fixed_t topheight, bottomheight; - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) - || (((rover->flags & FF_BLOCKPLAYER) && mobj->player) - || ((rover->flags & FF_BLOCKOTHERS) && !mobj->player))) - continue; topheight = P_GetFFloorTopZAt (rover, mobj->x, mobj->y); bottomheight = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y); + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) + || (((rover->flags & FF_BLOCKPLAYER) && mobj->player) + || ((rover->flags & FF_BLOCKOTHERS) && !mobj->player))) + { + if (topheight < top2 && topheight > thingtop) + top2 = topheight; + if (bottomheight > bot2 && bottomheight < mobj->z) + bot2 = bottomheight; + continue; + } + if (mobj->eflags & MFE_VERTICALFLIP) { - if (topheight < (thingtop - (height>>1)) - || bottomheight > thingtop) + if (topheight < (thingtop - halfheight) + || bottomheight > (thingtop + halfheight)) continue; } else { - if (topheight < mobj->z - || bottomheight > (mobj->z + (height>>1))) + if (topheight < (mobj->z - halfheight) + || bottomheight > (mobj->z + halfheight)) continue; } @@ -3011,19 +3048,87 @@ void P_MobjCheckWater(mobj_t *mobj) } } + if (mobj->watertop > top2) + mobj->watertop = top2; + + if (mobj->waterbottom < bot2) + mobj->waterbottom = bot2; + // Spectators and dead players don't get to do any of the things after this. if (p && (p->spectator || p->playerstate != PST_LIVE)) return; // The rest of this code only executes on a water state change. - if (waterwasnotset || !!(mobj->eflags & MFE_UNDERWATER) == wasinwater) + if (!!(mobj->eflags & MFE_UNDERWATER) == wasinwater) return; + if (p && !p->waterskip && + p->curshield != KSHIELD_BUBBLE && wasinwater) + { + S_StartSound(mobj, sfx_s3k38); + } + if ((p) // Players || (mobj->flags & MF_PUSHABLE) // Pushables || ((mobj->info->flags & MF_PUSHABLE) && mobj->fuse) // Previously pushable, might be moving still ) { + // Time to spawn the bubbles! + { + INT32 i; + INT32 bubblecount; + UINT8 prandom[4]; + mobj_t *bubble; + mobjtype_t bubbletype; + + if (mobj->eflags & MFE_GOOWATER || wasingoo) + S_StartSound(mobj, sfx_ghit); + else if (mobj->eflags & MFE_TOUCHLAVA) + S_StartSound(mobj, sfx_splash); + else + S_StartSound(mobj, sfx_splish); // And make a sound! + + bubblecount = FixedDiv(abs(mobj->momz), mobj->scale)>>(FRACBITS-1); + // Max bubble count + if (bubblecount > 128) + bubblecount = 128; + + // Create tons of bubbles + for (i = 0; i < bubblecount; i++) + { + // P_RandomByte()s are called individually to allow consistency + // across various compilers, since the order of function calls + // in C is not part of the ANSI specification. + prandom[0] = P_RandomByte(); + prandom[1] = P_RandomByte(); + prandom[2] = P_RandomByte(); + prandom[3] = P_RandomByte(); + + bubbletype = MT_SMALLBUBBLE; + if (!(prandom[0] & 0x3)) // medium bubble chance up to 64 from 32 + bubbletype = MT_MEDIUMBUBBLE; + + bubble = P_SpawnMobj( + mobj->x + FixedMul((prandom[1]<<(FRACBITS-3)) * (prandom[0]&0x80 ? 1 : -1), mobj->scale), + mobj->y + FixedMul((prandom[2]<<(FRACBITS-3)) * (prandom[0]&0x40 ? 1 : -1), mobj->scale), + mobj->z + FixedMul((prandom[3]<<(FRACBITS-2)), mobj->scale), bubbletype); + + if (bubble) + { + if (P_MobjFlip(mobj)*mobj->momz < 0) + bubble->momz = mobj->momz >> 4; + else + bubble->momz = 0; + + bubble->destscale = mobj->scale; + P_SetScale(bubble, mobj->scale); + } + } + } + + if (waterwasnotset) + return; + // Check to make sure you didn't just cross into a sector to jump out of // that has shallower water than the block you were originally in. if ((!(mobj->eflags & MFE_VERTICALFLIP) && mobj->watertop-mobj->floorz <= height>>1) @@ -3108,59 +3213,6 @@ void P_MobjCheckWater(mobj_t *mobj) P_SetScale(splish, mobj->scale); } } - - // Time to spawn the bubbles! - { - INT32 i; - INT32 bubblecount; - UINT8 prandom[4]; - mobj_t *bubble; - mobjtype_t bubbletype; - - if (mobj->eflags & MFE_GOOWATER || wasingoo) - S_StartSound(mobj, sfx_ghit); - else if (mobj->eflags & MFE_TOUCHLAVA) - S_StartSound(mobj, sfx_splash); - else - S_StartSound(mobj, sfx_splish); // And make a sound! - - bubblecount = FixedDiv(abs(mobj->momz), mobj->scale)>>(FRACBITS-1); - // Max bubble count - if (bubblecount > 128) - bubblecount = 128; - - // Create tons of bubbles - for (i = 0; i < bubblecount; i++) - { - // P_RandomByte()s are called individually to allow consistency - // across various compilers, since the order of function calls - // in C is not part of the ANSI specification. - prandom[0] = P_RandomByte(); - prandom[1] = P_RandomByte(); - prandom[2] = P_RandomByte(); - prandom[3] = P_RandomByte(); - - bubbletype = MT_SMALLBUBBLE; - if (!(prandom[0] & 0x3)) // medium bubble chance up to 64 from 32 - bubbletype = MT_MEDIUMBUBBLE; - - bubble = P_SpawnMobj( - mobj->x + FixedMul((prandom[1]<<(FRACBITS-3)) * (prandom[0]&0x80 ? 1 : -1), mobj->scale), - mobj->y + FixedMul((prandom[2]<<(FRACBITS-3)) * (prandom[0]&0x40 ? 1 : -1), mobj->scale), - mobj->z + FixedMul((prandom[3]<<(FRACBITS-2)), mobj->scale), bubbletype); - - if (bubble) - { - if (P_MobjFlip(mobj)*mobj->momz < 0) - bubble->momz = mobj->momz >> 4; - else - bubble->momz = 0; - - bubble->destscale = mobj->scale; - P_SetScale(bubble, mobj->scale); - } - } - } } } @@ -3661,6 +3713,9 @@ void P_PrecipThinker(precipmobj_t *mobj) mobj->old_x = mobj->x; mobj->old_y = mobj->y; mobj->old_z = mobj->z; + mobj->old_angle = mobj->angle; + mobj->old_pitch = mobj->pitch; + mobj->old_roll = mobj->roll; P_CycleStateAnimation((mobj_t *)mobj); @@ -4049,7 +4104,7 @@ boolean P_BossTargetPlayer(mobj_t *actor, boolean closest) player = &players[actor->lastlook]; - if (player->bot || player->spectator) + if (player->spectator) continue; // ignore notarget if (!player->mo || P_MobjWasRemoved(player->mo)) @@ -8551,6 +8606,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) } break; case MT_RANDOMITEM: + case MT_SPHEREBOX: if (gametype == GT_BATTLE && mobj->threshold == 70) { mobj->color = K_RainbowColor(leveltime); @@ -8822,6 +8878,9 @@ void P_MobjThinker(mobj_t *mobj) mobj->old_x = mobj->x; mobj->old_y = mobj->y; mobj->old_z = mobj->z; + mobj->old_angle = mobj->angle; + mobj->old_pitch = mobj->pitch; + mobj->old_roll = mobj->roll; // Remove dead target/tracer. if (mobj->target && P_MobjWasRemoved(mobj->target)) @@ -9328,6 +9387,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing) thing->shadowscale = 12*FRACUNIT/5; break; case MT_RANDOMITEM: + case MT_SPHEREBOX: thing->shadowscale = FRACUNIT/2; thing->whiteshadow = false; break; @@ -9930,7 +9990,13 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) } } + // OK so we kind of need NOTHINK objects to still think + // because otherwise they can never update their + // interpolation values. They might need some other kind + // of system, so consider this temporary... +#if 0 if (!(mobj->flags & MF_NOTHINK)) +#endif P_AddThinker(THINK_MOBJ, &mobj->thinker); if (mobj->skin) // correct inadequecies above. @@ -9970,6 +10036,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->old_x = mobj->x; mobj->old_y = mobj->y; mobj->old_z = mobj->z; + mobj->old_angle = mobj->angle; + mobj->old_pitch = mobj->pitch; + mobj->old_roll = mobj->roll; return mobj; } @@ -10026,6 +10095,9 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype mobj->old_x = mobj->x; mobj->old_y = mobj->y; mobj->old_z = mobj->z; + mobj->old_angle = mobj->angle; + mobj->old_pitch = mobj->pitch; + mobj->old_roll = mobj->roll; return mobj; } diff --git a/src/p_mobj.h b/src/p_mobj.h index 3c7ab4367..2373bdca4 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -285,6 +285,7 @@ typedef struct mobj_s // More drawing info: to determine current sprite. angle_t angle, pitch, roll; // orientation + angle_t old_angle, old_pitch, old_roll; // orientation interpolation angle_t rollangle; spritenum_t sprite; // used to find patch_t and flip value UINT32 frame; // frame number, plus bits see p_pspr.h @@ -424,6 +425,7 @@ typedef struct precipmobj_s // More drawing info: to determine current sprite. angle_t angle, pitch, roll; // orientation + angle_t old_angle, old_pitch, old_roll; // orientation interpolation angle_t rollangle; spritenum_t sprite; // used to find patch_t and flip value UINT32 frame; // frame number, plus bits see p_pspr.h diff --git a/src/p_saveg.c b/src/p_saveg.c index 83625026d..39a4fec28 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -239,6 +239,8 @@ static void P_NetArchivePlayers(void) WRITEINT32(save_p, players[i].aizdrifttilt); WRITEINT32(save_p, players[i].aizdriftturn); + WRITEINT32(save_p, players[i].underwatertilt); + WRITEFIXED(save_p, players[i].offroad); WRITEUINT8(save_p, players[i].waterskip); @@ -495,6 +497,8 @@ static void P_NetUnArchivePlayers(void) players[i].aizdrifttilt = READINT32(save_p); players[i].aizdriftturn = READINT32(save_p); + players[i].underwatertilt = READINT32(save_p); + players[i].offroad = READFIXED(save_p); players[i].waterskip = READUINT8(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index 830059ee3..a60c4399d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -91,6 +91,7 @@ #include "k_waypoint.h" #include "k_bot.h" #include "k_grandprix.h" +#include "k_brightmap.h" // Replay names have time #if !defined (UNDER_CE) @@ -4457,6 +4458,9 @@ boolean P_AddWadFile(const char *wadfilename) // Reload ANIMDEFS P_InitPicAnims(); + // Reload BRIGHT + K_InitBrightmaps(); + // Flush and reload HUD graphics ST_UnloadGraphics(); HU_LoadGraphics(); diff --git a/src/p_sight.c b/src/p_sight.c index 38a50df36..cdc8df864 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -18,6 +18,9 @@ #include "r_main.h" #include "r_state.h" +#include "k_bot.h" // K_BotHatesThisSector +#include "k_kart.h" // K_TripwirePass + // // P_CheckSight // @@ -572,7 +575,7 @@ static boolean P_CrossBlockingSubsector(size_t num, register traceblocking_t *tb if (P_IsLineBlocking(line, tb->compareThing) == true) { - // This line will block us + // This line will always block us return false; } } @@ -656,3 +659,192 @@ boolean P_TraceBlockingLines(mobj_t *t1, mobj_t *t2) // the head node is the last node output return P_CrossBSPNodeBlocking((INT32)numnodes - 1, &tb); } + +// +// ANOTHER version, this time for bot traversal. +// (TODO: since we have so many versions of this function, the differences +// should maybe just be a function var that gets called?) +// + +static boolean P_CrossBotTraversalSubsector(size_t num, register traceblocking_t *tb) +{ + seg_t *seg; + INT32 count; + +#ifdef RANGECHECK + if (num >= numsubsectors) + I_Error("P_CrossBotTraversalSubsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors)); +#endif + + // haleyjd 02/23/06: this assignment should be after the above check + seg = segs + subsectors[num].firstline; + + for (count = subsectors[num].numlines; --count >= 0; seg++) // check lines + { + line_t *line = seg->linedef; + divline_t divl; + const vertex_t *v1,*v2; + fixed_t maxstep = INT32_MAX; + + if (seg->glseg) + continue; + + // already checked other side? + if (line->validcount == validcount) + continue; + + line->validcount = validcount; + + // OPTIMIZE: killough 4/20/98: Added quick bounding-box rejection test + if (line->bbox[BOXLEFT ] > tb->bbox[BOXRIGHT ] || + line->bbox[BOXRIGHT ] < tb->bbox[BOXLEFT ] || + line->bbox[BOXBOTTOM] > tb->bbox[BOXTOP ] || + line->bbox[BOXTOP] < tb->bbox[BOXBOTTOM]) + continue; + + v1 = line->v1; + v2 = line->v2; + + // line isn't crossed? + if (P_DivlineSide(v1->x, v1->y, &tb->strace) == + P_DivlineSide(v2->x, v2->y, &tb->strace)) + continue; + + // stop because it is not two sided anyway + if (!(line->flags & ML_TWOSIDED)) + return false; + + divl.dx = v2->x - (divl.x = v1->x); + divl.dy = v2->y - (divl.y = v1->y); + + // line isn't crossed? + if (P_DivlineSide(tb->strace.x, tb->strace.y, &divl) == + P_DivlineSide(tb->t2x, tb->t2y, &divl)) + continue; + + if (P_IsLineBlocking(line, tb->compareThing) == true) + { + // This line will always block us + return false; + } + + // set openrange, opentop, openbottom + P_LineOpening(line, tb->compareThing); + maxstep = P_GetThingStepUp(tb->compareThing); + + if ((openrange < tb->compareThing->height) // doesn't fit + || (opentop - tb->compareThing->z < tb->compareThing->height) // mobj is too high + || (openbottom - tb->compareThing->z > maxstep)) // too big a step up + { + // This line situationally blocks us + return false; + } + + // Treat damage sectors like walls + if (tb->compareThing->player != NULL) + { + boolean alreadyHates = K_BotHatesThisSector(tb->compareThing->player, tb->compareThing->subsector->sector, tb->compareThing->x, tb->compareThing->y); + + if (alreadyHates == false) + { + INT32 lineside = 0; + vertex_t pos; + + P_ClosestPointOnLine(tb->compareThing->x, tb->compareThing->y, line, &pos); + lineside = P_PointOnLineSide(tb->compareThing->x, tb->compareThing->y, line); + + if (K_BotHatesThisSector(tb->compareThing->player, ((lineside == 1) ? line->frontsector : line->backsector), pos.x, pos.y)) + { + // This line does not block us, but we don't want to be in it. + return false; + } + } + + if (P_IsLineTripWire(line) == true && K_TripwirePass(tb->compareThing->player) == false) + { + // Can't go through trip wire. + return false; + } + } + } + + // passed the subsector ok + return true; +} + +static boolean P_CrossBSPNodeBotTraversal(INT32 bspnum, register traceblocking_t *tb) +{ + while (!(bspnum & NF_SUBSECTOR)) + { + register node_t *bsp = nodes + bspnum; + INT32 side = P_DivlineSide(tb->strace.x,tb->strace.y,(divline_t *)bsp)&1; + if (side == P_DivlineSide(tb->t2x, tb->t2y, (divline_t *) bsp)) + bspnum = bsp->children[side]; // doesn't touch the other side + else // the partition plane is crossed here + { + if (!P_CrossBSPNodeBotTraversal(bsp->children[side], tb)) + return false; // cross the starting side + else + bspnum = bsp->children[side^1]; // cross the ending side + } + } + + return P_CrossBotTraversalSubsector((bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR), tb); +} + +boolean P_TraceBotTraversal(mobj_t *t1, mobj_t *t2) +{ + const sector_t *s1, *s2; + size_t pnum; + traceblocking_t tb; + + // First check for trivial rejection. + if (!t1 || !t2) + return false; + + I_Assert(!P_MobjWasRemoved(t1)); + I_Assert(!P_MobjWasRemoved(t2)); + + if (!t1->subsector || !t2->subsector + || !t1->subsector->sector || !t2->subsector->sector) + return false; + + s1 = t1->subsector->sector; + s2 = t2->subsector->sector; + pnum = (s1-sectors)*numsectors + (s2-sectors); + + if (rejectmatrix != NULL) + { + // Check in REJECT table. + if (rejectmatrix[pnum>>3] & (1 << (pnum&7))) // can't possibly be connected + return false; + } + + // killough 11/98: shortcut for melee situations + // same subsector? obviously visible + // haleyjd 02/23/06: can't do this if there are polyobjects in the subsec + if (!t1->subsector->polyList && + t1->subsector == t2->subsector) + return true; + + validcount++; + + tb.strace.dx = (tb.t2x = t2->x) - (tb.strace.x = t1->x); + tb.strace.dy = (tb.t2y = t2->y) - (tb.strace.y = t1->y); + + if (t1->x > t2->x) + tb.bbox[BOXRIGHT] = t1->x, tb.bbox[BOXLEFT] = t2->x; + else + tb.bbox[BOXRIGHT] = t2->x, tb.bbox[BOXLEFT] = t1->x; + + if (t1->y > t2->y) + tb.bbox[BOXTOP] = t1->y, tb.bbox[BOXBOTTOM] = t2->y; + else + tb.bbox[BOXTOP] = t2->y, tb.bbox[BOXBOTTOM] = t1->y; + + tb.compareThing = t1; + + // the head node is the last node output + return P_CrossBSPNodeBotTraversal((INT32)numnodes - 1, &tb); +} + diff --git a/src/p_spec.c b/src/p_spec.c index 07825759c..caf4704d2 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2982,9 +2982,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // reasonable defaults. if (!quake.intensity) - quake.intensity = 8<spheres; + + // Not alive + if ((gametyperules & GTR_BUMPERS) && (player->bumpers <= 0)) + return 0; + + if (num_spheres > 40) // Reached the cap, don't waste 'em! + num_spheres = 40; + else if (num_spheres < 0) + num_spheres = 0; + + num_spheres -= player->spheres; + + player->spheres += num_spheres; + + return num_spheres; +} + // // P_GivePlayerLives // @@ -1145,6 +1165,9 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->old_x = mobj->old_x; ghost->old_y = mobj->old_y; ghost->old_z = mobj->old_z; + ghost->old_angle = (mobj->player ? mobj->player->old_drawangle : mobj->old_angle); + ghost->old_pitch = mobj->old_pitch; + ghost->old_roll = mobj->old_roll; return ghost; } @@ -1769,6 +1792,55 @@ static void P_3dMovement(player_t *player) if (player->mo->movefactor != FRACUNIT) // Friction-scaled acceleration... movepushforward = FixedMul(movepushforward, player->mo->movefactor); + { + INT32 a = K_GetUnderwaterTurnAdjust(player); + INT32 adj = 0; + + if (a) + { + const fixed_t maxadj = ANG10/4; + + adj = a / 4; + + if (adj > 0) + { + if (adj > maxadj) + adj = maxadj; + } + else if (adj < 0) + { + if (adj < -(maxadj)) + adj = -(maxadj); + } + + if (abs(player->underwatertilt + adj) > abs(a)) + adj = (a - player->underwatertilt); + + if (abs(a) < abs(player->underwatertilt)) + adj = 0; + + movepushangle += a; + } + + if (adj) + { + player->underwatertilt += adj; + + if (abs(player->underwatertilt) > ANG30) + { + player->underwatertilt = + player->underwatertilt > 0 ? ANG30 + : -(ANG30); + } + } + else + { + player->underwatertilt = + FixedMul(player->underwatertilt, + 7*FRACUNIT/8); + } + } + totalthrust.x += P_ReturnThrustX(player->mo, movepushangle, movepushforward); totalthrust.y += P_ReturnThrustY(player->mo, movepushangle, movepushforward); } @@ -2055,6 +2127,10 @@ void P_MovePlayer(player_t *player) else if (player->drift != 0) { INT32 a = (ANGLE_45 / 5) * player->drift; + + if (player->mo->eflags & MFE_UNDERWATER) + a /= 2; + player->drawangle += a; } } @@ -2446,6 +2522,8 @@ static void P_ConsiderAllGone(void) // static void P_DeathThink(player_t *player) { + boolean playerGone = false; + player->deltaviewheight = 0; if (player->deadtimer < INT32_MAX) @@ -2466,7 +2544,19 @@ static void P_DeathThink(player_t *player) K_KartPlayerHUDUpdate(player); - if (player->lives > 0 && !(player->pflags & PF_NOCONTEST) && player->deadtimer > TICRATE) + if (player->pflags & PF_NOCONTEST) + { + playerGone = true; + } + else if (player->bot == false) + { + if (G_GametypeUsesLives() == true && player->lives == 0) + { + playerGone = true; + } + } + + if (playerGone == false && player->deadtimer > TICRATE) { player->playerstate = PST_REBORN; } @@ -2850,6 +2940,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall subsector_t *newsubsec; #endif + thiscam->old_x = thiscam->x; + thiscam->old_y = thiscam->y; + thiscam->old_z = thiscam->z; + thiscam->old_angle = thiscam->angle; + thiscam->old_aiming = thiscam->aiming; + democam.soundmobj = NULL; // reset this each frame, we don't want the game crashing for stupid reasons now do we // We probably shouldn't move the camera if there is no player or player mobj somehow @@ -4174,10 +4270,10 @@ void P_PlayerThink(player_t *player) player->playerstate = PST_DEAD; } - if (player->mo->hitlag > 0) - { - return; - } + player->old_drawangle = player->drawangle; + player->old_viewrollangle = player->viewrollangle; + + player->pflags &= ~PF_HITFINISHLINE; if (player->awayviewmobj && P_MobjWasRemoved(player->awayviewmobj)) { @@ -4194,6 +4290,11 @@ void P_PlayerThink(player_t *player) if (player->awayviewtics && player->awayviewtics != -1) player->awayviewtics--; + if (player->mo->hitlag > 0) + { + return; + } + // Track airtime if (P_IsObjectOnGround(player->mo)) { diff --git a/src/r_data.c b/src/r_data.c index 04b6c232b..ddeb5e3b5 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -30,6 +30,9 @@ #include "byteptr.h" #include "dehacked.h" +// DRRR +#include "k_brightmap.h" + // // Graphics. // SRB2 graphics for walls and sprites @@ -615,6 +618,7 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) { double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb, cdestbright; double maskamt = 0, othermask = 0; + double fmaskamt = 0, fothermask = 0; UINT8 cr = R_GetRgbaR(extra_colormap->rgba), cg = R_GetRgbaG(extra_colormap->rgba), @@ -622,8 +626,8 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) ca = R_GetRgbaA(extra_colormap->rgba), cfr = R_GetRgbaR(extra_colormap->fadergba), cfg = R_GetRgbaG(extra_colormap->fadergba), - cfb = R_GetRgbaB(extra_colormap->fadergba); -// cfa = R_GetRgbaA(extra_colormap->fadergba); // unused in software + cfb = R_GetRgbaB(extra_colormap->fadergba), + cfa = R_GetRgbaA(extra_colormap->fadergba); UINT8 fadestart = extra_colormap->fadestart, fadedist = extra_colormap->fadeend - extra_colormap->fadestart; @@ -654,14 +658,11 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) cdestb = cfb; cdestbright = sqrt((cfr*cfr) + (cfg*cfg) + (cfb*cfb)); - // fade alpha unused in software - // maskamt = (double)(cfa/24.0l); - // othermask = 1 - maskamt; - // maskamt /= 0xff; + fmaskamt = (double)(cfa/24.0l); + fothermask = 1 - fmaskamt; + //fmaskamt /= 0xff; - // cdestr *= maskamt; - // cdestg *= maskamt; - // cdestb *= maskamt; + (void)fothermask; // unused, but don't feel like commenting it out ///////////////////// // This code creates the colormap array used by software renderer @@ -701,16 +702,16 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) if (cbrightness < cdestbright) { cbest = 255.0l - min(r, min(g, b)); - cdist = 255.0l - cdestbright; + cdist = 255.0l - max(cdestr, max(cdestg, cdestb)); } else { cbest = max(r, max(g, b)); - cdist = cdestbright; + cdist = min(cdestr, min(cdestg, cdestb)); } // Add/subtract this value during fading. - brightChange[i] = fabs(cbest - cdist) / (double)fadedist; + brightChange[i] = (fabs(cbest - cdist) / (double)fadedist) * fmaskamt; } // Now allocate memory for the actual colormap array itself! @@ -1177,6 +1178,9 @@ void R_InitTextureData(void) CONS_Printf("P_InitPicAnims()...\n"); P_InitPicAnims(); + + CONS_Printf("K_InitBrightmaps()...\n"); + K_InitBrightmaps(); } // diff --git a/src/r_draw.c b/src/r_draw.c index 4adfb6663..946763a6e 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -26,6 +26,7 @@ #include "z_zone.h" #include "console.h" // Until buffering gets finished #include "k_color.h" // SRB2kart +#include "i_threads.h" #ifdef HWRENDER #include "hardware/hw_main.h" @@ -71,12 +72,14 @@ UINT8 *topleft; // ========================================================================= lighttable_t *dc_colormap; +lighttable_t *dc_fullbright; INT32 dc_x = 0, dc_yl = 0, dc_yh = 0; fixed_t dc_iscale, dc_texturemid; UINT8 dc_hires; // under MSVC boolean is a byte, while on other systems, it a bit, // soo lets make it a byte on all system for the ASM code UINT8 *dc_source; +UINT8 *dc_brightmap; // ----------------------- // translucency stuff here @@ -108,6 +111,7 @@ INT32 dc_numlights = 0, dc_maxlights, dc_texheight; INT32 ds_y, ds_x1, ds_x2; lighttable_t *ds_colormap; +lighttable_t *ds_fullbright; lighttable_t *ds_translation; // Lactozilla: Sprite splat drawer fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; @@ -117,6 +121,7 @@ UINT16 ds_flatwidth, ds_flatheight; boolean ds_powersoftwo; UINT8 *ds_source; // points to the start of a flat +UINT8 *ds_brightmap; // start of brightmap flat UINT8 *ds_transmap; // one of the translucency tables // Vectors for Software's tilted slope drawers @@ -192,6 +197,29 @@ CV_PossibleValue_t Followercolor_cons_t[MAXSKINCOLORS+3]; // +3 to account for " #define TRANSTAB_AMTMUL10 (255.0f / 10.0f) +static void R_AllocateBlendTables(void) +{ + INT32 i; + + for (i = 0; i < NUMBLENDMAPS; i++) + { + if (i == blendtab_modulate) + continue; + blendtables[i] = Z_MallocAlign((NUMTRANSTABLES + 1) * 0x10000, PU_STATIC, NULL, 16); + } + + // Modulation blending only requires a single table + blendtables[blendtab_modulate] = Z_MallocAlign(0x10000, PU_STATIC, NULL, 16); +} + +#ifdef HAVE_THREADS +static void R_GenerateBlendTables_Thread(void *userdata) +{ + (void)userdata; + R_GenerateBlendTables(); +} +#endif + /** \brief Initializes the translucency tables used by the Software renderer. */ void R_InitTranslucencyTables(void) @@ -212,20 +240,20 @@ void R_InitTranslucencyTables(void) W_ReadLump(W_GetNumForName("TRANS80"), transtables+0x70000); W_ReadLump(W_GetNumForName("TRANS90"), transtables+0x80000); + R_AllocateBlendTables(); + +#ifdef HAVE_THREADS + I_spawn_thread("blend-tables", + R_GenerateBlendTables_Thread, NULL); +#else R_GenerateBlendTables(); +#endif } void R_GenerateBlendTables(void) { INT32 i; - for (i = 0; i < NUMBLENDMAPS; i++) - { - if (i == blendtab_modulate) - continue; - blendtables[i] = Z_MallocAlign((NUMTRANSTABLES + 1) * 0x10000, PU_STATIC, NULL, 16); - } - for (i = 0; i <= 9; i++) { const size_t offs = (0x10000 * i); @@ -236,8 +264,6 @@ void R_GenerateBlendTables(void) R_GenerateTranslucencyTable(blendtables[blendtab_reversesubtract] + offs, AST_REVERSESUBTRACT, alpha); } - // Modulation blending only requires a single table - blendtables[blendtab_modulate] = Z_MallocAlign(0x10000, PU_STATIC, NULL, 16); R_GenerateTranslucencyTable(blendtables[blendtab_modulate], AST_MODULATE, 0); } diff --git a/src/r_draw.h b/src/r_draw.h index 646eb5ec8..7b44d6185 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -32,11 +32,13 @@ extern UINT8 *topleft; // ------------------------- extern lighttable_t *dc_colormap; +extern lighttable_t *dc_fullbright; extern INT32 dc_x, dc_yl, dc_yh; extern fixed_t dc_iscale, dc_texturemid; extern UINT8 dc_hires; extern UINT8 *dc_source; // first pixel in a column +extern UINT8 *dc_brightmap; // brightmap texture column, can be NULL // translucency stuff here extern UINT8 *dc_transmap; @@ -57,6 +59,7 @@ extern INT32 dc_texheight; extern INT32 ds_y, ds_x1, ds_x2; extern lighttable_t *ds_colormap; +extern lighttable_t *ds_fullbright; extern lighttable_t *ds_translation; extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; @@ -66,6 +69,7 @@ extern UINT16 ds_flatwidth, ds_flatheight; extern boolean ds_powersoftwo; extern UINT8 *ds_source; +extern UINT8 *ds_brightmap; extern UINT8 *ds_transmap; typedef struct { @@ -167,6 +171,7 @@ void R_DrawViewBorder(void); #endif #define TRANSPARENTPIXEL 255 +#define BRIGHTPIXEL 0 // ----------------- // 8bpp DRAWING CODE diff --git a/src/r_draw8.c b/src/r_draw8.c index af64edbce..0dd8463f6 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -57,7 +57,9 @@ void R_DrawColumn_8(void) // This is as fast as it gets. { register const UINT8 *source = dc_source; + register const UINT8 *brightmap = dc_brightmap; register const lighttable_t *colormap = dc_colormap; + register const lighttable_t *fullbright = dc_fullbright; register INT32 heightmask = dc_texheight-1; if (dc_texheight & heightmask) // not a power of 2 -- killough { @@ -75,7 +77,14 @@ void R_DrawColumn_8(void) // Re-map color indices from wall texture column // using a lighting/special effects LUT. // heightmask is the Tutti-Frutti fix - *dest = colormap[source[frac>>FRACBITS]]; + if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = fullbright[source[frac>>FRACBITS]]; + } + else + { + *dest = colormap[source[frac>>FRACBITS]]; + } dest += vid.width; // Avoid overflow. @@ -92,15 +101,42 @@ void R_DrawColumn_8(void) { while ((count -= 2) >= 0) // texture height is a power of 2 { - *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; + if (brightmap != NULL && brightmap[(frac>>FRACBITS) & heightmask] == BRIGHTPIXEL) + { + *dest = fullbright[source[(frac>>FRACBITS) & heightmask]]; + } + else + { + *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; + } + dest += vid.width; frac += fracstep; - *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; + + if (brightmap != NULL && brightmap[(frac>>FRACBITS) & heightmask] == BRIGHTPIXEL) + { + *dest = fullbright[source[(frac>>FRACBITS) & heightmask]]; + } + else + { + *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; + } + dest += vid.width; frac += fracstep; } + if (count & 1) - *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; + { + if (brightmap != NULL && brightmap[(frac>>FRACBITS) & heightmask] == BRIGHTPIXEL) + { + *dest = fullbright[source[(frac>>FRACBITS) & heightmask]]; + } + else + { + *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; + } + } } } } @@ -140,7 +176,9 @@ void R_Draw2sMultiPatchColumn_8(void) // This is as fast as it gets. { register const UINT8 *source = dc_source; + register const UINT8 *brightmap = dc_brightmap; register const lighttable_t *colormap = dc_colormap; + register const lighttable_t *fullbright = dc_fullbright; register INT32 heightmask = dc_texheight-1; register UINT8 val; if (dc_texheight & heightmask) // not a power of 2 -- killough @@ -160,9 +198,17 @@ void R_Draw2sMultiPatchColumn_8(void) // using a lighting/special effects LUT. // heightmask is the Tutti-Frutti fix val = source[frac>>FRACBITS]; - if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + { + if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = fullbright[val]; + } + else + { + *dest = colormap[val]; + } + } dest += vid.width; @@ -182,20 +228,51 @@ void R_Draw2sMultiPatchColumn_8(void) { val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + { + if (brightmap != NULL && brightmap[(frac>>FRACBITS) & heightmask] == BRIGHTPIXEL) + { + *dest = fullbright[val]; + } + else + { + *dest = colormap[val]; + } + } + dest += vid.width; frac += fracstep; + val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + { + if (brightmap != NULL && brightmap[(frac>>FRACBITS) & heightmask] == BRIGHTPIXEL) + { + *dest = fullbright[val]; + } + else + { + *dest = colormap[val]; + } + } + dest += vid.width; frac += fracstep; } + if (count & 1) { val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + { + if (brightmap != NULL && brightmap[(frac>>FRACBITS) & heightmask] == BRIGHTPIXEL) + { + *dest = fullbright[val]; + } + else + { + *dest = colormap[val]; + } + } } } } @@ -236,8 +313,10 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void) // This is as fast as it gets. { register const UINT8 *source = dc_source; + register const UINT8 *brightmap = dc_brightmap; register const UINT8 *transmap = dc_transmap; register const lighttable_t *colormap = dc_colormap; + register const lighttable_t *fullbright = dc_fullbright; register INT32 heightmask = dc_texheight-1; register UINT8 val; if (dc_texheight & heightmask) // not a power of 2 -- killough @@ -257,9 +336,17 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void) // using a lighting/special effects LUT. // heightmask is the Tutti-Frutti fix val = source[frac>>FRACBITS]; - if (val != TRANSPARENTPIXEL) - *dest = *(transmap + (colormap[val]<<8) + (*dest)); + { + if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = *(transmap + (fullbright[val]<<8) + (*dest)); + } + else + { + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + } + } dest += vid.width; @@ -279,12 +366,33 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void) { val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) - *dest = *(transmap + (colormap[val]<<8) + (*dest)); + { + if (brightmap != NULL && brightmap[(frac>>FRACBITS) & heightmask] == BRIGHTPIXEL) + { + *dest = *(transmap + (fullbright[val]<<8) + (*dest)); + } + else + { + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + } + } + dest += vid.width; frac += fracstep; + val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) - *dest = *(transmap + (colormap[val]<<8) + (*dest)); + { + if (brightmap != NULL && brightmap[(frac>>FRACBITS) & heightmask] == BRIGHTPIXEL) + { + *dest = *(transmap + (fullbright[val]<<8) + (*dest)); + } + else + { + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + } + } + dest += vid.width; frac += fracstep; } @@ -292,7 +400,16 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void) { val = source[(frac>>FRACBITS) & heightmask]; if (val != TRANSPARENTPIXEL) - *dest = *(transmap + (colormap[val]<<8) + (*dest)); + { + if (brightmap != NULL && brightmap[(frac>>FRACBITS) & heightmask] == BRIGHTPIXEL) + { + *dest = *(transmap + (fullbright[val]<<8) + (*dest)); + } + else + { + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + } + } } } } @@ -372,8 +489,10 @@ void R_DrawTranslucentColumn_8(void) // This is as fast as it gets. { register const UINT8 *source = dc_source; + register const UINT8 *brightmap = dc_brightmap; register const UINT8 *transmap = dc_transmap; register const lighttable_t *colormap = dc_colormap; + register const lighttable_t *fullbright = dc_fullbright; register INT32 heightmask = dc_texheight - 1; if (dc_texheight & heightmask) { @@ -392,7 +511,14 @@ void R_DrawTranslucentColumn_8(void) // Re-map color indices from wall texture column // using a lighting/special effects LUT. // heightmask is the Tutti-Frutti fix - *dest = *(transmap + (colormap[source[frac>>FRACBITS]]<<8) + (*dest)); + if (brightmap != NULL && brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = *(transmap + (fullbright[source[frac>>FRACBITS]]<<8) + (*dest)); + } + else + { + *dest = *(transmap + (colormap[source[frac>>FRACBITS]]<<8) + (*dest)); + } dest += vid.width; if ((frac += fracstep) >= heightmask) frac -= heightmask; @@ -403,15 +529,39 @@ void R_DrawTranslucentColumn_8(void) { while ((count -= 2) >= 0) // texture height is a power of 2 { - *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + if (brightmap != NULL && brightmap[(frac>>FRACBITS)&heightmask] == BRIGHTPIXEL) + { + *dest = *(transmap + (fullbright[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + } + else + { + *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + } dest += vid.width; frac += fracstep; - *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + + if (brightmap != NULL && brightmap[(frac>>FRACBITS)&heightmask] == BRIGHTPIXEL) + { + *dest = *(transmap + (fullbright[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + } + else + { + *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + } dest += vid.width; frac += fracstep; } if (count & 1) - *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + { + if (brightmap != NULL && brightmap[(frac>>FRACBITS)&heightmask] == BRIGHTPIXEL) + { + *dest = *(transmap + (fullbright[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + } + else + { + *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + } + } } } } @@ -462,7 +612,14 @@ void R_DrawTranslatedTranslucentColumn_8(void) // using a lighting/special effects LUT. // heightmask is the Tutti-Frutti fix - *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]<<8) + (*dest)); + if (dc_brightmap != NULL && dc_brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = *(dc_transmap + (dc_fullbright[dc_translation[dc_source[frac>>FRACBITS]]]<<8) + (*dest)); + } + else + { + *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]<<8) + (*dest)); + } dest += vid.width; if ((frac += fracstep) >= heightmask) @@ -474,15 +631,41 @@ void R_DrawTranslatedTranslucentColumn_8(void) { while ((count -= 2) >= 0) // texture height is a power of 2 { - *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + if (dc_brightmap != NULL && dc_brightmap[(frac>>FRACBITS)&heightmask] == BRIGHTPIXEL) + { + *dest = *(dc_transmap + (dc_fullbright[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + } + else + { + *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + } + dest += vid.width; frac += fracstep; - *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + + if (dc_brightmap != NULL && dc_brightmap[(frac>>FRACBITS)&heightmask] == BRIGHTPIXEL) + { + *dest = *(dc_transmap + (dc_fullbright[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + } + else + { + *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + } + dest += vid.width; frac += fracstep; } if (count & 1) - *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + { + if (dc_brightmap != NULL && dc_brightmap[(frac>>FRACBITS)&heightmask] == BRIGHTPIXEL) + { + *dest = *(dc_transmap + (dc_fullbright[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + } + else + { + *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + } + } } } } @@ -524,7 +707,14 @@ void R_DrawTranslatedColumn_8(void) // used with PLAY sprites. // Thus the "green" ramp of the player 0 sprite // is mapped to gray, red, black/indigo. - *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]; + if (dc_brightmap != NULL && dc_brightmap[frac>>FRACBITS] == BRIGHTPIXEL) + { + *dest = dc_fullbright[dc_translation[dc_source[frac>>FRACBITS]]]; + } + else + { + *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]; + } dest += vid.width; @@ -539,6 +729,9 @@ void R_DrawTranslatedColumn_8(void) #define SPANSIZE 16 #define INVSPAN 0.0625f +// 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) +#define MAXFLATBYTES 4194303 + /** \brief The R_DrawSpan_8 function Draws the actual span. */ @@ -547,13 +740,17 @@ void R_DrawSpan_8 (void) fixed_t xposition; fixed_t yposition; fixed_t xstep, ystep; + UINT32 bit; UINT8 *source; + UINT8 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; size_t count = (ds_x2 - ds_x1 + 1); + size_t i; xposition = ds_xfrac; yposition = ds_yfrac; xstep = ds_xstep; ystep = ds_ystep; @@ -569,7 +766,9 @@ void R_DrawSpan_8 (void) xstep <<= nflatshiftup; ystep <<= nflatshiftup; source = ds_source; + brightmap = ds_brightmap; colormap = ds_colormap; + fullbright = ds_fullbright; dest = ylookup[ds_y] + columnofs[ds_x1]; if (dest+8 > deststop) @@ -580,44 +779,37 @@ void R_DrawSpan_8 (void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - dest[0] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - dest[1] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[2] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[3] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[4] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[5] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[6] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[7] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; + for (i = 0; i < 8; i++) + { + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + dest[i] = fullbright[source[bit]]; + } + else + { + dest[i] = colormap[source[bit]]; + } + xposition += xstep; + yposition += ystep; + } dest += 8; count -= 8; } while (count-- && dest <= deststop) { - *dest++ = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest++ = fullbright[source[bit]]; + } + else + { + *dest++ = colormap[source[bit]]; + } + xposition += xstep; yposition += ystep; } @@ -658,13 +850,16 @@ void R_DrawTiltedSpan_8(void) int i; UINT8 *source; + UINT8 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *dest; double startz, startu, startv; double izstep, uzstep, vzstep; double endz, endu, endv; UINT32 stepu, stepv; + UINT32 bit; iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); @@ -684,8 +879,11 @@ void R_DrawTiltedSpan_8(void) vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); dest = ylookup[ds_y] + columnofs[ds_x1]; + source = ds_source; + brightmap = ds_brightmap; //colormap = ds_colormap; + fullbright = ds_fullbright; #if 0 // The "perfect" reference version of this routine. Pretty slow. // Use it only to see how things are supposed to look. @@ -695,10 +893,16 @@ void R_DrawTiltedSpan_8(void) double z = 1.f/iz; u = (INT64)(uz*z) + viewx; v = (INT64)(vz*z) + viewy; - - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[source[bit]]; + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = colormap[source[bit]]; + } dest++; iz += ds_szp->x; uz += ds_sup->x; @@ -731,8 +935,16 @@ void R_DrawTiltedSpan_8(void) for (i = SPANSIZE-1; i >= 0; i--) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[source[bit]]; + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = colormap[source[bit]]; + } dest++; u += stepu; v += stepv; @@ -747,8 +959,16 @@ void R_DrawTiltedSpan_8(void) { u = (INT64)(startu); v = (INT64)(startv); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[source[bit]]; + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = colormap[source[bit]]; + } } else { @@ -768,8 +988,16 @@ void R_DrawTiltedSpan_8(void) for (; width != 0; width--) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[source[bit]]; + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = colormap[source[bit]]; + } dest++; u += stepu; v += stepv; @@ -791,13 +1019,16 @@ void R_DrawTiltedTranslucentSpan_8(void) int i; UINT8 *source; + UINT8 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *dest; double startz, startu, startv; double izstep, uzstep, vzstep; double endz, endu, endv; UINT32 stepu, stepv; + UINT32 bit; iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); @@ -817,8 +1048,11 @@ void R_DrawTiltedTranslucentSpan_8(void) vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); dest = ylookup[ds_y] + columnofs[ds_x1]; + source = ds_source; + brightmap = ds_brightmap; //colormap = ds_colormap; + fullbright = ds_fullbright; #if 0 // The "perfect" reference version of this routine. Pretty slow. // Use it only to see how things are supposed to look. @@ -829,8 +1063,16 @@ void R_DrawTiltedTranslucentSpan_8(void) u = (INT64)(uz*z) + viewx; v = (INT64)(vz*z) + viewy; - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dest); + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest); + } dest++; iz += ds_szp->x; uz += ds_sup->x; @@ -863,8 +1105,16 @@ void R_DrawTiltedTranslucentSpan_8(void) for (i = SPANSIZE-1; i >= 0; i--) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dest); + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest); + } dest++; u += stepu; v += stepv; @@ -879,8 +1129,16 @@ void R_DrawTiltedTranslucentSpan_8(void) { u = (INT64)(startu); v = (INT64)(startv); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dest); + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest); + } } else { @@ -900,8 +1158,16 @@ void R_DrawTiltedTranslucentSpan_8(void) for (; width != 0; width--) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dest); + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest); + } dest++; u += stepu; v += stepv; @@ -923,7 +1189,9 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) int i; UINT8 *source; + UINT8 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *dest; UINT8 *dsrc; @@ -931,6 +1199,7 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) double izstep, uzstep, vzstep; double endz, endu, endv; UINT32 stepu, stepv; + UINT32 bit; iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); @@ -952,7 +1221,9 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) dest = ylookup[ds_y] + columnofs[ds_x1]; dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; source = ds_source; + brightmap = ds_brightmap; //colormap = ds_colormap; + fullbright = ds_fullbright; #if 0 // The "perfect" reference version of this routine. Pretty slow. // Use it only to see how things are supposed to look. @@ -963,8 +1234,16 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) u = (INT64)(uz*z) + viewx; v = (INT64)(vz*z) + viewy; - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++); + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dsrc++); + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc++); + } dest++; iz += ds_szp->x; uz += ds_sup->x; @@ -997,8 +1276,16 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) for (i = SPANSIZE-1; i >= 0; i--) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++); + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dsrc++); + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc++); + } dest++; u += stepu; v += stepv; @@ -1013,8 +1300,16 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) { u = (INT64)(startu); v = (INT64)(startv); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++); + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dsrc++); + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc++); + } } else { @@ -1034,8 +1329,16 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) for (; width != 0; width--) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++); + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dsrc++); + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc++); + } dest++; u += stepu; v += stepv; @@ -1054,7 +1357,9 @@ void R_DrawTiltedSplat_8(void) int i; UINT8 *source; + UINT8 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *dest; UINT8 val; @@ -1063,6 +1368,7 @@ void R_DrawTiltedSplat_8(void) double izstep, uzstep, vzstep; double endz, endu, endv; UINT32 stepu, stepv; + UINT32 bit; iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); @@ -1082,8 +1388,11 @@ void R_DrawTiltedSplat_8(void) vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); dest = ylookup[ds_y] + columnofs[ds_x1]; + source = ds_source; + brightmap = ds_brightmap; //colormap = ds_colormap; + fullbright = ds_fullbright; #if 0 // The "perfect" reference version of this routine. Pretty slow. // Use it only to see how things are supposed to look. @@ -1094,11 +1403,20 @@ void R_DrawTiltedSplat_8(void) u = (INT64)(uz*z) + viewx; v = (INT64)(vz*z) + viewy; - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[val]; + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = colormap[val]; + } + } dest++; iz += ds_szp->x; @@ -1132,10 +1450,20 @@ void R_DrawTiltedSplat_8(void) for (i = SPANSIZE-1; i >= 0; i--) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[val]; + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = colormap[val]; + } + } dest++; u += stepu; v += stepv; @@ -1150,10 +1478,20 @@ void R_DrawTiltedSplat_8(void) { u = (INT64)(startu); v = (INT64)(startv); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[val]; + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = colormap[val]; + } + } } else { @@ -1173,10 +1511,20 @@ void R_DrawTiltedSplat_8(void) for (; width != 0; width--) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[val]; + } + else + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = colormap[val]; + } + } dest++; u += stepu; v += stepv; @@ -1194,13 +1542,17 @@ void R_DrawSplat_8 (void) fixed_t xposition; fixed_t yposition; fixed_t xstep, ystep; + UINT32 bit; UINT8 *source; + UINT8 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; size_t count = (ds_x2 - ds_x1 + 1); + size_t i; UINT32 val; xposition = ds_xfrac; yposition = ds_yfrac; @@ -1217,7 +1569,9 @@ void R_DrawSplat_8 (void) xstep <<= nflatshiftup; ystep <<= nflatshiftup; source = ds_source; + brightmap = ds_brightmap; colormap = ds_colormap; + fullbright = ds_fullbright; dest = ylookup[ds_y] + columnofs[ds_x1]; while (count >= 8) @@ -1225,80 +1579,44 @@ void R_DrawSplat_8 (void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - // - // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[0] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[1] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[2] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[3] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[4] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[5] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[6] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[7] = colormap[val]; - xposition += xstep; - yposition += ystep; + for (i = 0; i < 8; i++) + { + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + bit &= MAXFLATBYTES; + val = source[bit]; + if (val != TRANSPARENTPIXEL) + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + dest[i] = fullbright[val]; + } + else + { + dest[i] = colormap[val]; + } + } + xposition += xstep; + yposition += ystep; + } dest += 8; count -= 8; } while (count-- && dest <= deststop) { - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val = source[bit]; if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[val]; + } + else + { + *dest = colormap[val]; + } + } dest++; xposition += xstep; yposition += ystep; @@ -1313,13 +1631,17 @@ void R_DrawTranslucentSplat_8 (void) fixed_t xposition; fixed_t yposition; fixed_t xstep, ystep; + UINT32 bit; UINT8 *source; + UINT8 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; size_t count = (ds_x2 - ds_x1 + 1); + size_t i; UINT32 val; xposition = ds_xfrac; yposition = ds_yfrac; @@ -1336,7 +1658,9 @@ void R_DrawTranslucentSplat_8 (void) xstep <<= nflatshiftup; ystep <<= nflatshiftup; source = ds_source; + brightmap = ds_brightmap; colormap = ds_colormap; + fullbright = ds_fullbright; dest = ylookup[ds_y] + columnofs[ds_x1]; while (count >= 8) @@ -1344,62 +1668,45 @@ void R_DrawTranslucentSplat_8 (void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[0] = *(ds_transmap + (colormap[val] << 8) + dest[0]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[1] = *(ds_transmap + (colormap[val] << 8) + dest[1]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[2] = *(ds_transmap + (colormap[val] << 8) + dest[2]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[3] = *(ds_transmap + (colormap[val] << 8) + dest[3]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[4] = *(ds_transmap + (colormap[val] << 8) + dest[4]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[5] = *(ds_transmap + (colormap[val] << 8) + dest[5]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[6] = *(ds_transmap + (colormap[val] << 8) + dest[6]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[7] = *(ds_transmap + (colormap[val] << 8) + dest[7]); - xposition += xstep; - yposition += ystep; + for (i = 0; i < 8; i++) + { + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val = source[bit]; + if (val != TRANSPARENTPIXEL) + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + dest[i] = *(ds_transmap + (fullbright[val] << 8) + dest[i]); + } + else + { + dest[i] = *(ds_transmap + (colormap[val] << 8) + dest[i]); + } + + } + xposition += xstep; + yposition += ystep; + } dest += 8; count -= 8; } while (count-- && dest <= deststop) { - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val = source[bit]; if (val != TRANSPARENTPIXEL) - *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[val] << 8) + *dest); + } + else + { + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + } + + } dest++; xposition += xstep; yposition += ystep; @@ -1414,14 +1721,18 @@ void R_DrawFloorSprite_8 (void) fixed_t xposition; fixed_t yposition; fixed_t xstep, ystep; + UINT32 bit; UINT16 *source; + UINT16 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *translation; UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; size_t count = (ds_x2 - ds_x1 + 1); + size_t i; UINT32 val; xposition = ds_xfrac; yposition = ds_yfrac; @@ -1438,7 +1749,9 @@ void R_DrawFloorSprite_8 (void) xstep <<= nflatshiftup; ystep <<= nflatshiftup; source = (UINT16 *)ds_source; + brightmap = (UINT16 *)ds_brightmap; colormap = ds_colormap; + fullbright = ds_fullbright; translation = ds_translation; dest = ylookup[ds_y] + columnofs[ds_x1]; @@ -1447,70 +1760,43 @@ void R_DrawFloorSprite_8 (void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val = source[val]; - if (val & 0xFF00) - dest[0] = colormap[translation[val & 0xFF]]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val = source[val]; - if (val & 0xFF00) - dest[1] = colormap[translation[val & 0xFF]]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val = source[val]; - if (val & 0xFF00) - dest[2] = colormap[translation[val & 0xFF]]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val = source[val]; - if (val & 0xFF00) - dest[3] = colormap[translation[val & 0xFF]]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val = source[val]; - if (val & 0xFF00) - dest[4] = colormap[translation[val & 0xFF]]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val = source[val]; - if (val & 0xFF00) - dest[5] = colormap[translation[val & 0xFF]]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val = source[val]; - if (val & 0xFF00) - dest[6] = colormap[translation[val & 0xFF]]; - xposition += xstep; - yposition += ystep; - - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val = source[val]; - if (val & 0xFF00) - dest[7] = colormap[translation[val & 0xFF]]; - xposition += xstep; - yposition += ystep; + for (i = 0; i < 8; i++) + { + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val = source[bit]; + if (val & 0xFF00) + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[translation[val & 0xFF]]; + } + else + { + *dest = colormap[translation[val & 0xFF]]; + } + } + xposition += xstep; + yposition += ystep; + } dest += 8; count -= 8; } while (count-- && dest <= deststop) { - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val = source[bit]; if (val & 0xFF00) - *dest = colormap[translation[val & 0xFF]]; + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[translation[val & 0xFF]]; + } + else + { + *dest = colormap[translation[val & 0xFF]]; + } + } dest++; xposition += xstep; yposition += ystep; @@ -1525,14 +1811,18 @@ void R_DrawTranslucentFloorSprite_8 (void) fixed_t xposition; fixed_t yposition; fixed_t xstep, ystep; + UINT32 bit; UINT16 *source; + UINT16 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *translation; UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; size_t count = (ds_x2 - ds_x1 + 1); + size_t i; UINT32 val; xposition = ds_xfrac; yposition = ds_yfrac; @@ -1549,7 +1839,9 @@ void R_DrawTranslucentFloorSprite_8 (void) xstep <<= nflatshiftup; ystep <<= nflatshiftup; source = (UINT16 *)ds_source; + brightmap = (UINT16 *)ds_brightmap; colormap = ds_colormap; + fullbright = ds_fullbright; translation = ds_translation; dest = ylookup[ds_y] + columnofs[ds_x1]; @@ -1558,62 +1850,43 @@ void R_DrawTranslucentFloorSprite_8 (void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val & 0xFF00) - dest[0] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[0]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val & 0xFF00) - dest[1] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[1]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val & 0xFF00) - dest[2] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[2]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val & 0xFF00) - dest[3] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[3]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val & 0xFF00) - dest[4] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[4]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val & 0xFF00) - dest[5] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[5]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val & 0xFF00) - dest[6] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[6]); - xposition += xstep; - yposition += ystep; - - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; - if (val & 0xFF00) - dest[7] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[7]); - xposition += xstep; - yposition += ystep; + for (i = 0; i < 8; i++) + { + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val = source[bit]; + if (val & 0xFF00) + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + dest[i] = *(ds_transmap + (fullbright[translation[val & 0xFF]] << 8) + dest[i]); + } + else + { + dest[i] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[i]); + } + } + xposition += xstep; + yposition += ystep; + } dest += 8; count -= 8; } while (count-- && dest <= deststop) { - val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val = source[bit]; if (val & 0xFF00) - *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[translation[val & 0xFF]] << 8) + *dest); + } + else + { + *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + } + } dest++; xposition += xstep; yposition += ystep; @@ -1632,7 +1905,9 @@ void R_DrawTiltedFloorSprite_8(void) int i; UINT16 *source; + UINT16 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *translation; UINT8 *dest; UINT16 val; @@ -1641,6 +1916,7 @@ void R_DrawTiltedFloorSprite_8(void) double izstep, uzstep, vzstep; double endz, endu, endv; UINT32 stepu, stepv; + UINT32 bit; iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); @@ -1648,7 +1924,9 @@ void R_DrawTiltedFloorSprite_8(void) dest = ylookup[ds_y] + columnofs[ds_x1]; source = (UINT16 *)ds_source; + brightmap = (UINT16 *)ds_brightmap; colormap = ds_colormap; + fullbright = ds_fullbright; translation = ds_translation; startz = 1.f/iz; @@ -1677,9 +1955,19 @@ void R_DrawTiltedFloorSprite_8(void) for (i = SPANSIZE-1; i >= 0; i--) { - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val & 0xFF00) - *dest = colormap[translation[val & 0xFF]]; + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[translation[val & 0xFF]]; + } + else + { + *dest = colormap[translation[val & 0xFF]]; + } + } dest++; u += stepu; @@ -1695,9 +1983,19 @@ void R_DrawTiltedFloorSprite_8(void) { u = (INT64)(startu); v = (INT64)(startv); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val & 0xFF00) - *dest = colormap[translation[val & 0xFF]]; + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[translation[val & 0xFF]]; + } + else + { + *dest = colormap[translation[val & 0xFF]]; + } + } } else { @@ -1717,9 +2015,19 @@ void R_DrawTiltedFloorSprite_8(void) for (; width != 0; width--) { - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val & 0xFF00) - *dest = colormap[translation[val & 0xFF]]; + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = fullbright[translation[val & 0xFF]]; + } + else + { + *dest = colormap[translation[val & 0xFF]]; + } + } dest++; u += stepu; @@ -1741,7 +2049,9 @@ void R_DrawTiltedTranslucentFloorSprite_8(void) int i; UINT16 *source; + UINT16 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *translation; UINT8 *dest; UINT16 val; @@ -1750,6 +2060,7 @@ void R_DrawTiltedTranslucentFloorSprite_8(void) double izstep, uzstep, vzstep; double endz, endu, endv; UINT32 stepu, stepv; + UINT32 bit; iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); @@ -1757,7 +2068,9 @@ void R_DrawTiltedTranslucentFloorSprite_8(void) dest = ylookup[ds_y] + columnofs[ds_x1]; source = (UINT16 *)ds_source; + brightmap = (UINT16 *)ds_brightmap; colormap = ds_colormap; + fullbright = ds_fullbright; translation = ds_translation; startz = 1.f/iz; @@ -1786,9 +2099,19 @@ void R_DrawTiltedTranslucentFloorSprite_8(void) for (i = SPANSIZE-1; i >= 0; i--) { - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val & 0xFF00) - *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[translation[val & 0xFF]] << 8) + *dest); + } + else + { + *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + } + } dest++; u += stepu; @@ -1804,9 +2127,19 @@ void R_DrawTiltedTranslucentFloorSprite_8(void) { u = (INT64)(startu); v = (INT64)(startv); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val & 0xFF00) - *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[translation[val & 0xFF]] << 8) + *dest); + } + else + { + *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + } + } } else { @@ -1826,9 +2159,19 @@ void R_DrawTiltedTranslucentFloorSprite_8(void) for (; width != 0; width--) { - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + val = source[bit]; if (val & 0xFF00) - *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + { + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[translation[val & 0xFF]] << 8) + *dest); + } + else + { + *dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest); + } + } dest++; u += stepu; @@ -1846,14 +2189,17 @@ void R_DrawTranslucentSpan_8 (void) fixed_t xposition; fixed_t yposition; fixed_t xstep, ystep; + UINT32 bit; UINT8 *source; + UINT8 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; size_t count = (ds_x2 - ds_x1 + 1); - UINT32 val; + size_t i; xposition = ds_xfrac; yposition = ds_yfrac; xstep = ds_xstep; ystep = ds_ystep; @@ -1869,7 +2215,9 @@ void R_DrawTranslucentSpan_8 (void) xstep <<= nflatshiftup; ystep <<= nflatshiftup; source = ds_source; + brightmap = ds_brightmap; colormap = ds_colormap; + fullbright = ds_fullbright; dest = ylookup[ds_y] + columnofs[ds_x1]; while (count >= 8) @@ -1877,45 +2225,35 @@ void R_DrawTranslucentSpan_8 (void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - dest[0] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[0]); - xposition += xstep; - yposition += ystep; - - dest[1] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[1]); - xposition += xstep; - yposition += ystep; - - dest[2] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[2]); - xposition += xstep; - yposition += ystep; - - dest[3] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[3]); - xposition += xstep; - yposition += ystep; - - dest[4] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[4]); - xposition += xstep; - yposition += ystep; - - dest[5] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[5]); - xposition += xstep; - yposition += ystep; - - dest[6] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[6]); - xposition += xstep; - yposition += ystep; - - dest[7] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[7]); - xposition += xstep; - yposition += ystep; + for (i = 0; i < 8; i++) + { + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + dest[i] = *(ds_transmap + (fullbright[source[bit]] << 8) + dest[i]); + } + else + { + dest[i] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[i]); + } + xposition += xstep; + yposition += ystep; + } dest += 8; count -= 8; } while (count-- && dest <= deststop) { - val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - *dest = *(ds_transmap + (colormap[source[val]] << 8) + *dest); + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dest); + } + else + { + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest); + } dest++; xposition += xstep; yposition += ystep; @@ -1927,13 +2265,17 @@ void R_DrawTranslucentWaterSpan_8(void) UINT32 xposition; UINT32 yposition; UINT32 xstep, ystep; + UINT32 bit; UINT8 *source; + UINT8 *brightmap; UINT8 *colormap; + UINT8 *fullbright; UINT8 *dest; UINT8 *dsrc; size_t count; + size_t i; // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the @@ -1946,7 +2288,9 @@ void R_DrawTranslucentWaterSpan_8(void) xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; source = ds_source; + brightmap = ds_brightmap; colormap = ds_colormap; + fullbright = ds_fullbright; dest = ylookup[ds_y] + columnofs[ds_x1]; dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; count = ds_x2 - ds_x1 + 1; @@ -1956,44 +2300,35 @@ void R_DrawTranslucentWaterSpan_8(void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - dest[0] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[1] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[2] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[3] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[4] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[5] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[6] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[7] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; + for (i = 0; i < 8; i++) + { + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + dest[i] = fullbright[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + } + else + { + dest[i] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + } + xposition += xstep; + yposition += ystep; + } dest += 8; count -= 8; } while (count--) { - *dest++ = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL) + { + *dest++ = fullbright[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + } + else + { + *dest++ = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + } xposition += xstep; yposition += ystep; } @@ -2114,8 +2449,12 @@ void R_DrawColumnShadowed_8(void) if (height <= dc_yl) { dc_colormap = dc_lightlist[i].rcolormap; + dc_fullbright = colormaps; if (encoremap) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } if (solid && dc_yl < bheight) dc_yl = bheight; continue; @@ -2132,8 +2471,12 @@ void R_DrawColumnShadowed_8(void) dc_yl = dc_yh + 1; dc_colormap = dc_lightlist[i].rcolormap; + dc_fullbright = colormaps; if (encoremap) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } } dc_yh = realyh; if (dc_yl <= realyh) diff --git a/src/r_fps.c b/src/r_fps.c index 2d2b4f61e..7258d3b75 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -83,10 +83,7 @@ static void R_SetupFreelook(player_t *player, boolean skybox) void R_InterpolateView(fixed_t frac) { - boolean skybox = false; - INT32 i; - - if (FIXED_TO_FLOAT(frac) < 0) + if (frac < 0) frac = 0; if (frac > FRACUNIT) frac = FRACUNIT; @@ -97,31 +94,20 @@ void R_InterpolateView(fixed_t frac) viewangle = oldview->angle + R_LerpAngle(oldview->angle, newview->angle, frac); aimingangle = oldview->aim + R_LerpAngle(oldview->aim, newview->aim, frac); + viewroll = oldview->roll + R_LerpAngle(oldview->roll, newview->roll, frac); viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT); viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); - // this is gonna create some interesting visual errors for long distance teleports... - // might want to recalculate the view sector every frame instead... viewplayer = newview->player; viewsector = R_PointInSubsector(viewx, viewy)->sector; - // well, this ain't pretty - for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) - { - if (newview == &skyview_new[i]) - { - skybox = true; - break; - } - } - - R_SetupFreelook(newview->player, skybox); + R_SetupFreelook(newview->player, newview->sky); } void R_UpdateViewInterpolation(void) { - INT32 i; + UINT8 i; for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { @@ -132,7 +118,7 @@ void R_UpdateViewInterpolation(void) void R_SetViewContext(enum viewcontext_e _viewcontext) { - INT32 i; + UINT8 i = 0; I_Assert(_viewcontext >= VIEWCONTEXT_PLAYER1 && _viewcontext <= VIEWCONTEXT_SKY4); diff --git a/src/r_fps.h b/src/r_fps.h index 2d4dbe874..eb674b142 100644 --- a/src/r_fps.h +++ b/src/r_fps.h @@ -41,6 +41,7 @@ typedef struct { angle_t angle; angle_t aim; + angle_t roll; fixed_t cos; fixed_t sin; mobj_t *mobj; diff --git a/src/r_main.c b/src/r_main.c index 330577f2c..0803f5a9e 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -71,7 +71,7 @@ size_t framecount; size_t loopcount; fixed_t viewx, viewy, viewz; -angle_t viewangle, aimingangle; +angle_t viewangle, aimingangle, viewroll; UINT8 viewssnum; fixed_t viewcos, viewsin; sector_t *viewsector; @@ -149,10 +149,6 @@ static void ChaseCam_OnChange(void); static void ChaseCam2_OnChange(void); static void ChaseCam3_OnChange(void); static void ChaseCam4_OnChange(void); -void SendWeaponPref(void); -void SendWeaponPref2(void); -void SendWeaponPref3(void); -void SendWeaponPref4(void); consvar_t cv_tailspickup = CVAR_INIT ("tailspickup", "On", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL); consvar_t cv_chasecam[MAXSPLITSCREENPLAYERS] = { @@ -656,7 +652,7 @@ void R_CheckViewMorph(int s) float fisheyemap[MAXVIDWIDTH/2 + 1]; #endif - angle_t rollangle = R_ViewRollAngle(&players[displayplayers[s]]); + angle_t rollangle = viewroll; #ifdef WOUGHMP_WOUGHMP fixed_t fisheye = cv_cam2_turnmultiplier.value; // temporary test value #endif @@ -1141,7 +1137,7 @@ void R_Init(void) R_InitLightTables(); //I_OutputMsg("\nR_InitTranslucencyTables\n"); - R_InitTranslucencyTables(); + //R_InitTranslucencyTables(); R_InitDrawNodes(); @@ -1206,8 +1202,8 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y) void R_SetupFrame(player_t *player) { camera_t *thiscam = &camera[0]; - boolean chasecam = false; - UINT8 i; + boolean chasecam = (cv_chasecam[0].value != 0); + UINT8 i = 0; for (i = 0; i <= r_splitscreen; i++) { @@ -1221,12 +1217,17 @@ void R_SetupFrame(player_t *player) } if (i > r_splitscreen) - return; // shouldn't be possible, but just in case + { + i = 0; // Shouldn't be possible, but just in case. + thiscam = &camera[0]; + chasecam = (cv_chasecam[0].value != 0); + R_SetViewContext(VIEWCONTEXT_PLAYER1); + } if (player->spectator) // no spectator chasecam chasecam = false; // force chasecam off - if (chasecam && !thiscam->chase) + if (chasecam && (thiscam && !thiscam->chase)) { P_ResetCamera(player, thiscam); thiscam->chase = true; @@ -1270,6 +1271,7 @@ void R_SetupFrame(player_t *player) newview->aim = localaiming[i]; } } + newview->roll = R_ViewRollAngle(player); newview->z += quake.z; newview->player = player; @@ -1302,7 +1304,7 @@ void R_SetupFrame(player_t *player) // newview->sin = FINESINE(viewangle>>ANGLETOFINESHIFT); // newview->cos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); - R_InterpolateView(cv_frameinterpolation.value == 1 ? rendertimefrac : FRACUNIT); + R_InterpolateView(rendertimefrac); } void R_SkyboxFrame(player_t *player) @@ -1310,22 +1312,21 @@ void R_SkyboxFrame(player_t *player) camera_t *thiscam = &camera[0]; UINT8 i = 0; - if (r_splitscreen) + for (i = 0; i <= r_splitscreen; i++) { - for (i = 1; i <= r_splitscreen; i++) + if (player == &players[displayplayers[i]]) { - if (player == &players[displayplayers[i]]) - { - thiscam = &camera[i]; - R_SetViewContext(VIEWCONTEXT_SKY1 + i); - break; - } + thiscam = &camera[i]; + R_SetViewContext(VIEWCONTEXT_SKY1 + i); + break; } + } - if (i > r_splitscreen) - { - i = 0; - } + if (i > r_splitscreen) + { + i = 0; // Shouldn't be possible, but just in case. + thiscam = &camera[0]; + R_SetViewContext(VIEWCONTEXT_SKY1); } // cut-away view stuff @@ -1343,7 +1344,7 @@ void R_SkyboxFrame(player_t *player) newview->aim = player->awayviewaiming; newview->angle = player->awayviewmobj->angle; } - else if (thiscam->chase) + else if (thiscam && thiscam->chase) { newview->aim = thiscam->aiming; newview->angle = thiscam->angle; @@ -1359,6 +1360,7 @@ void R_SkyboxFrame(player_t *player) } } newview->angle += r_viewmobj->angle; + newview->roll = R_ViewRollAngle(player); newview->player = player; @@ -1445,7 +1447,7 @@ void R_SkyboxFrame(player_t *player) // newview->sin = FINESINE(viewangle>>ANGLETOFINESHIFT); // newview->cos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); - R_InterpolateView(cv_frameinterpolation.value == 1 ? rendertimefrac : FRACUNIT); + R_InterpolateView(rendertimefrac); } boolean R_ViewpointHasChasecam(player_t *player) diff --git a/src/r_patch.h b/src/r_patch.h index 601144a1d..b86908281 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -42,6 +42,7 @@ patch_t *Patch_GetRotatedSprite( INT32 R_GetRollAngle(angle_t rollangle); angle_t R_GetPitchRollAngle(mobj_t *mobj, player_t *viewPlayer); +angle_t R_ModelRotationAngle(mobj_t *mobj, player_t *viewPlayer); angle_t R_SpriteRotationAngle(mobj_t *mobj, player_t *viewPlayer); #endif diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index 3744dfce2..74afeb396 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -42,7 +42,11 @@ static angle_t R_PlayerSpriteRotation(player_t *player, player_t *viewPlayer) angle_t rollAngle = 0; - if (sliptideLift) + if (player->mo->eflags & MFE_UNDERWATER) + { + rollAngle -= player->underwatertilt; + } + else if (sliptideLift) { /* (from side) tilt downward if turning toward camera, upward if away. */ @@ -60,10 +64,9 @@ static angle_t R_PlayerSpriteRotation(player_t *player, player_t *viewPlayer) return rollAngle; } -angle_t R_SpriteRotationAngle(mobj_t *mobj, player_t *viewPlayer) +angle_t R_ModelRotationAngle(mobj_t *mobj, player_t *viewPlayer) { - angle_t rollOrPitch = R_GetPitchRollAngle(mobj, viewPlayer); - angle_t rollAngle = (rollOrPitch + mobj->rollangle); + angle_t rollAngle = mobj->rollangle; if (mobj->player) { @@ -73,6 +76,12 @@ angle_t R_SpriteRotationAngle(mobj_t *mobj, player_t *viewPlayer) return rollAngle; } +angle_t R_SpriteRotationAngle(mobj_t *mobj, player_t *viewPlayer) +{ + angle_t rollOrPitch = R_GetPitchRollAngle(mobj, viewPlayer); + return (rollOrPitch + R_ModelRotationAngle(mobj, viewPlayer)); +} + INT32 R_GetRollAngle(angle_t rollangle) { INT32 ra = AngleFixed(rollangle)>>FRACBITS; diff --git a/src/r_picformats.h b/src/r_picformats.h index 8d3999013..0a822cc48 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -105,6 +105,7 @@ typedef struct } spriteinfo_t; // Portable Network Graphics +#define PNG_HEADER_SIZE (8) boolean Picture_IsLumpPNG(const UINT8 *d, size_t s); #define Picture_ThrowPNGError(lumpname, wadfilename) I_Error("W_Wad: Lump \"%s\" in file \"%s\" is a .png - please convert to either Doom or Flat (raw) image format.", lumpname, wadfilename); // Fears Of LJ Sonic diff --git a/src/r_plane.c b/src/r_plane.c index 8ec7e2b99..d2f294cdc 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -235,7 +235,9 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) } if (currentplane->slope) + { ds_colormap = colormaps; + } else { pindex = distance >> LIGHTZSHIFT; @@ -244,8 +246,13 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) ds_colormap = planezlight[pindex]; } + ds_fullbright = colormaps; + if (encoremap && !currentplane->noencore) + { ds_colormap += COLORMAP_REMAPOFFSET; + ds_fullbright += COLORMAP_REMAPOFFSET; + } if (currentplane->extra_colormap) ds_colormap = currentplane->extra_colormap->colormap + (ds_colormap - colormaps); @@ -641,7 +648,7 @@ static void R_DrawSkyPlane(visplane_t *pl) // Reset column drawer function (note: couldn't we just call walldrawerfunc directly?) // (that is, unless we'll need to switch drawers in future for some reason) - colfunc = colfuncs[BASEDRAWFUNC]; + R_SetColumnFunc(BASEDRAWFUNC, false); // use correct aspect ratio scale dc_iscale = skyscale[viewssnum]; @@ -651,8 +658,12 @@ static void R_DrawSkyPlane(visplane_t *pl) // Because of this hack, sky is not affected // by sector colormaps (INVUL inverse mapping is not implemented in SRB2 so is irrelevant). dc_colormap = colormaps; + dc_fullbright = colormaps; if (encoremap) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } dc_texturemid = skytexturemid; dc_texheight = textureheight[skytexture] >>FRACBITS; @@ -669,6 +680,7 @@ static void R_DrawSkyPlane(visplane_t *pl) dc_source = R_GetColumn(texturetranslation[skytexture], -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 + dc_brightmap = NULL; colfunc(); } } @@ -808,7 +820,8 @@ void R_DrawSinglePlane(visplane_t *pl) } planeripple.active = false; - spanfunc = spanfuncs[BASEDRAWFUNC]; + ds_brightmap = NULL; + R_SetSpanFunc(BASEDRAWFUNC, false, false); if (pl->polyobj) { @@ -965,6 +978,17 @@ void R_DrawSinglePlane(visplane_t *pl) R_CheckFlatLength(ds_flatwidth * ds_flatheight); } + if (type == LEVELFLAT_TEXTURE) + { + // Get the span's brightmap. + // FLATS not supported, SORRY!! + INT32 bmNum = R_GetTextureBrightmap(levelflat->u.texture.num); + if (bmNum != 0) + { + ds_brightmap = (UINT8 *)R_GenerateTextureAsFlat(bmNum); + } + } + if (!pl->slope // Don't mess with angle on slopes! We'll handle this ourselves later && viewangle != pl->viewangle+pl->plangle) { @@ -1080,15 +1104,7 @@ void R_DrawSinglePlane(visplane_t *pl) planezlight = zlight[light]; // Use the correct span drawer depending on the powers-of-twoness - if (!ds_powersoftwo) - { - if (spanfuncs_npo2[spanfunctype]) - spanfunc = spanfuncs_npo2[spanfunctype]; - else - spanfunc = spanfuncs[spanfunctype]; - } - else - spanfunc = spanfuncs[spanfunctype]; + R_SetSpanFunc(spanfunctype, !ds_powersoftwo, ds_brightmap != NULL); // set the maximum value for unsigned pl->top[pl->maxx+1] = 0xffff; diff --git a/src/r_segs.c b/src/r_segs.c index 5c9538e34..5a8172615 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -36,6 +36,7 @@ static boolean markceiling; static boolean maskedtexture; static INT32 toptexture, bottomtexture, midtexture; +static INT32 topbrightmap, bottombrightmap, midbrightmap; static INT32 numthicksides, numbackffloors; angle_t rw_normalangle; @@ -83,7 +84,7 @@ static fixed_t *maskedtextureheight = NULL; // multi-patch textures. They are not normally needed as multi-patch // textures don't have holes in it. At least not for now. -static void R_Render2sidedMultiPatchColumn(column_t *column) +static void R_Render2sidedMultiPatchColumn(column_t *column, column_t *brightmap) { INT32 topscreen, bottomscreen; @@ -93,6 +94,8 @@ static void R_Render2sidedMultiPatchColumn(column_t *column) dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS; dc_yh = (bottomscreen-1)>>FRACBITS; + dc_brightmap = NULL; + if (windowtop != INT32_MAX && windowbottom != INT32_MAX) { dc_yl = ((windowtop + FRACUNIT)>>FRACBITS); @@ -110,10 +113,14 @@ static void R_Render2sidedMultiPatchColumn(column_t *column) if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0) { dc_source = (UINT8 *)column + 3; + if (brightmap != NULL) + { + dc_brightmap = (UINT8 *)brightmap + 3; + } - if (colfunc == colfuncs[BASEDRAWFUNC]) + if (R_CheckColumnFunc(BASEDRAWFUNC) == true) (colfuncs[COLDRAWFUNC_TWOSMULTIPATCH])(); - else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) + else if (R_CheckColumnFunc(COLDRAWFUNC_FUZZY) == true) (colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS])(); else colfunc(); @@ -132,12 +139,12 @@ transnum_t R_GetLinedefTransTable(line_t *ldef) void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { size_t pindex; - column_t *col; - INT32 lightnum, texnum, i; + column_t *col, *bmCol = NULL; + INT32 lightnum, texnum, bmnum, i; fixed_t height, realbot; lightlist_t *light; r_lightlist_t *rlight; - void (*colfunc_2s)(column_t *); + void (*colfunc_2s)(column_t *, column_t *); line_t *ldef; sector_t *front, *back; INT32 times, repeats; @@ -155,6 +162,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) frontsector = curline->frontsector; backsector = curline->backsector; texnum = R_GetTextureNum(curline->sidedef->midtexture); + bmnum = R_GetTextureBrightmap(texnum); windowbottom = windowtop = sprbotscreen = INT32_MAX; ldef = curline->linedef; @@ -188,16 +196,18 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (transtable != NUMTRANSMAPS && (blendmode || transtable)) { dc_transmap = R_GetBlendTable(blendmode, transtable); - colfunc = colfuncs[COLDRAWFUNC_FUZZY]; + R_SetColumnFunc(COLDRAWFUNC_FUZZY, bmnum != 0); } else if (ldef->special == 909) { - colfunc = colfuncs[COLDRAWFUNC_FOG]; + R_SetColumnFunc(COLDRAWFUNC_FOG, bmnum != 0); windowtop = frontsector->ceilingheight; windowbottom = frontsector->floorheight; } else - colfunc = colfuncs[BASEDRAWFUNC]; + { + R_SetColumnFunc(BASEDRAWFUNC, bmnum != 0); + } if (curline->polyseg && curline->polyseg->translucency > 0) { @@ -205,7 +215,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) return; dc_transmap = R_GetTranslucencyTable(curline->polyseg->translucency); - colfunc = colfuncs[COLDRAWFUNC_FUZZY]; + R_SetColumnFunc(COLDRAWFUNC_FUZZY, bmnum != 0); } range = max(ds->x2-ds->x1, 1); @@ -215,6 +225,8 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // Texture must be cached before setting colfunc_2s, // otherwise texture[texnum]->holes may be false when it shouldn't be R_CheckTextureCache(texnum); + if (bmnum) { R_CheckTextureCache(bmnum); } + // handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures // are not stored per-column with post info in SRB2 if (textures[texnum]->holes) @@ -265,7 +277,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) rlight->extra_colormap = *light->extra_colormap; rlight->flags = light->flags; - if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY]) + if ((R_CheckColumnFunc(COLDRAWFUNC_FUZZY) == false) || (rlight->flags & FF_FOG) || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG))) lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); @@ -282,13 +294,13 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) } else { - if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY]) + if ((R_CheckColumnFunc(COLDRAWFUNC_FUZZY) == false) || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); else lightnum = LIGHTLEVELS - 1; - if (colfunc == colfuncs[COLDRAWFUNC_FOG] + if ((R_CheckColumnFunc(COLDRAWFUNC_FOG) == true) || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) ; else @@ -400,6 +412,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // draw the texture col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); + if (bmnum) { bmCol = (column_t *)((UINT8 *)R_GetColumn(bmnum, maskedtexturecol[dc_x]) - 3); } for (i = 0; i < dc_numlights; i++) { @@ -431,8 +444,12 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (height <= windowtop) { dc_colormap = rlight->rcolormap; + dc_fullbright = colormaps; if (encoremap && !(ldef->flags & ML_TFERLINE)) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } continue; } @@ -440,7 +457,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (windowbottom >= realbot) { windowbottom = realbot; - colfunc_2s(col); + colfunc_2s(col, bmCol); for (i++; i < dc_numlights; i++) { rlight = &dc_lightlist[i]; @@ -449,15 +466,19 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) continue; } - colfunc_2s(col); + colfunc_2s(col, bmCol); windowtop = windowbottom + 1; dc_colormap = rlight->rcolormap; + dc_fullbright = colormaps; if (encoremap && !(ldef->flags & ML_TFERLINE)) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } } windowbottom = realbot; if (windowtop < windowbottom) - colfunc_2s(col); + colfunc_2s(col, bmCol); spryscale += rw_scalestep; continue; @@ -470,8 +491,12 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) pindex = MAXLIGHTSCALE - 1; dc_colormap = walllights[pindex]; + dc_fullbright = colormaps; if (encoremap && !(ldef->flags & ML_TFERLINE)) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } if (frontsector->extra_colormap) dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); @@ -481,6 +506,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // draw the texture col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); + if (bmnum) { bmCol = (column_t *)((UINT8 *)R_GetColumn(bmnum, maskedtexturecol[dc_x]) - 3); } #if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red if (curline->dontrenderme && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES)) @@ -535,19 +561,20 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) } else #endif - colfunc_2s(col); + colfunc_2s(col, bmCol); } spryscale += rw_scalestep; } } - colfunc = colfuncs[BASEDRAWFUNC]; + + R_SetColumnFunc(BASEDRAWFUNC, false); } // Loop through R_DrawMaskedColumn calls -static void R_DrawRepeatMaskedColumn(column_t *col) +static void R_DrawRepeatMaskedColumn(column_t *col, column_t *bm) { while (sprtopscreen < sprbotscreen) { - R_DrawMaskedColumn(col); + R_DrawMaskedColumn(col, bm); if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow sprtopscreen = INT32_MAX; else @@ -555,10 +582,10 @@ static void R_DrawRepeatMaskedColumn(column_t *col) } } -static void R_DrawRepeatFlippedMaskedColumn(column_t *col) +static void R_DrawRepeatFlippedMaskedColumn(column_t *col, column_t *bm) { do { - R_DrawFlippedMaskedColumn(col); + R_DrawFlippedMaskedColumn(col, bm); sprtopscreen += dc_texheight*spryscale; } while (sprtopscreen < sprbotscreen); } @@ -582,9 +609,9 @@ static boolean R_IsFFloorTranslucent(visffloor_t *pfloor) void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { size_t pindex; - column_t * col; + column_t * col, *bmCol = NULL; INT32 lightnum; - INT32 texnum; + INT32 texnum, bmnum; sector_t tempsec; INT32 templight; INT32 i, p; @@ -605,7 +632,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) fixed_t left_top, left_bottom; // needed here for slope skewing pslope_t *skewslope = NULL; - void (*colfunc_2s) (column_t *); + void (*colfunc_2s) (column_t *, column_t *); // Calculate light table. // Use different light tables @@ -616,14 +643,16 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) backsector = pfloor->target; frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector; texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture); + bmnum = R_GetTextureBrightmap(texnum); - colfunc = colfuncs[BASEDRAWFUNC]; + R_SetColumnFunc(BASEDRAWFUNC, bmnum != 0); if (pfloor->master->flags & ML_TFERLINE) { size_t linenum = curline->linedef-backsector->lines[0]; newline = pfloor->master->frontsector->lines[0] + linenum; texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture); + bmnum = R_GetTextureBrightmap(texnum); } if (pfloor->flags & FF_TRANSLUCENT) @@ -641,10 +670,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) } if (fuzzy) - colfunc = colfuncs[COLDRAWFUNC_FUZZY]; + { + R_SetColumnFunc(COLDRAWFUNC_FUZZY, bmnum != 0); + } } else if (pfloor->flags & FF_FOG) - colfunc = colfuncs[COLDRAWFUNC_FOG]; + { + R_SetColumnFunc(COLDRAWFUNC_FOG, bmnum != 0); + } range = max(ds->x2-ds->x1, 1); //SoM: Moved these up here so they are available for my lightlist calculations @@ -752,7 +785,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); else if (pfloor->flags & FF_FOG) lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); - else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) + else if (R_CheckColumnFunc(COLDRAWFUNC_FUZZY) == true) lightnum = LIGHTLEVELS-1; else lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false) @@ -833,6 +866,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // Texture must be cached before setting colfunc_2s, // otherwise texture[texnum]->holes may be false when it shouldn't be R_CheckTextureCache(texnum); + if (bmnum) { R_CheckTextureCache(bmnum); } + //faB: handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures // are not stored per-column with post info anymore in Doom Legacy if (textures[texnum]->holes) @@ -916,6 +951,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // Get data for the column col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc_x]) - 3); + if (bmnum) { bmCol = (column_t *)((UINT8 *)R_GetColumn(bmnum, maskedtexturecol[dc_x]) - 3); } // SoM: New code does not rely on R_DrawColumnShadowed_8 which // will (hopefully) put less strain on the stack. @@ -998,8 +1034,12 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (lighteffect) { dc_colormap = rlight->rcolormap; + dc_fullbright = colormaps; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } } if (solid && windowtop < bheight) windowtop = bheight; @@ -1011,7 +1051,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { windowbottom = sprbotscreen; // draw the texture - colfunc_2s (col); + colfunc_2s (col, bmCol); for (i++; i < dc_numlights; i++) { rlight = &dc_lightlist[i]; @@ -1022,7 +1062,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) continue; } // draw the texture - colfunc_2s (col); + colfunc_2s (col, bmCol); if (solid) windowtop = bheight; else @@ -1030,14 +1070,18 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (lighteffect) { dc_colormap = rlight->rcolormap; + dc_fullbright = colormaps; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } } } windowbottom = sprbotscreen; // draw the texture, if there is any space left if (windowtop < windowbottom) - colfunc_2s (col); + colfunc_2s (col, bmCol); spryscale += rw_scalestep; continue; @@ -1050,9 +1094,13 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) pindex = MAXLIGHTSCALE - 1; dc_colormap = walllights[pindex]; + dc_fullbright = colormaps; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } if (pfloor->flags & FF_FOG && pfloor->master->frontsector->extra_colormap) dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps); @@ -1060,11 +1108,12 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); // draw the texture - colfunc_2s (col); + colfunc_2s (col, bmCol); spryscale += rw_scalestep; } } - colfunc = colfuncs[BASEDRAWFUNC]; + + R_SetColumnFunc(BASEDRAWFUNC, false); #undef CLAMPMAX #undef CLAMPMIN @@ -1311,8 +1360,12 @@ static void R_RenderSegLoop (void) pindex = MAXLIGHTSCALE-1; dc_colormap = walllights[pindex]; + dc_fullbright = colormaps; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } dc_x = rw_x; dc_iscale = 0xffffffffu / (unsigned)rw_scale; @@ -1350,7 +1403,7 @@ static void R_RenderSegLoop (void) else dc_lightlist[i].rcolormap = xwalllights[pindex]; - colfunc = colfuncs[COLDRAWFUNC_SHADOWED]; + R_SetColumnFunc(COLDRAWFUNC_SHADOWED, false); } } @@ -1366,8 +1419,11 @@ static void R_RenderSegLoop (void) dc_yh = yh; dc_texturemid = rw_midtexturemid; dc_source = R_GetColumn(midtexture,texturecolumn); + dc_brightmap = (midbrightmap ? R_GetColumn(midbrightmap, texturecolumn) : NULL); dc_texheight = textureheight[midtexture]>>FRACBITS; + R_SetColumnFunc(colfunctype, dc_brightmap != NULL); + //profile stuff --------------------------------------------------------- #ifdef TIMING ProfZeroTimer(); @@ -1427,7 +1483,9 @@ static void R_RenderSegLoop (void) dc_yh = mid; dc_texturemid = rw_toptexturemid; dc_source = R_GetColumn(toptexture,texturecolumn); + dc_brightmap = (topbrightmap ? R_GetColumn(topbrightmap, texturecolumn) : NULL); dc_texheight = textureheight[toptexture]>>FRACBITS; + R_SetColumnFunc(colfunctype, dc_brightmap != NULL); colfunc(); ceilingclip[rw_x] = (INT16)mid; } @@ -1462,9 +1520,10 @@ static void R_RenderSegLoop (void) dc_yl = mid; dc_yh = yh; dc_texturemid = rw_bottomtexturemid; - dc_source = R_GetColumn(bottomtexture, - texturecolumn); + dc_source = R_GetColumn(bottomtexture,texturecolumn); + dc_brightmap = (bottombrightmap ? R_GetColumn(bottombrightmap, texturecolumn) : NULL); dc_texheight = textureheight[bottomtexture]>>FRACBITS; + R_SetColumnFunc(colfunctype, dc_brightmap != NULL); colfunc(); floorclip[rw_x] = (INT16)mid; } @@ -1558,7 +1617,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) memset(&segleft, 0x00, sizeof(segleft)); memset(&segright, 0x00, sizeof(segright)); - colfunc = colfuncs[BASEDRAWFUNC]; + R_SetColumnFunc(BASEDRAWFUNC, false); if (ds_p == drawsegs+maxdrawsegs) { @@ -1738,6 +1797,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) worldbottomslope -= viewz; midtexture = toptexture = bottomtexture = maskedtexture = 0; + midbrightmap = topbrightmap = bottombrightmap = 0; ds_p->maskedtexturecol = NULL; ds_p->numthicksides = numthicksides = 0; ds_p->thicksidecol = NULL; @@ -1785,6 +1845,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) fixed_t texheight; // single sided line midtexture = R_GetTextureNum(sidedef->midtexture); + midbrightmap = R_GetTextureBrightmap(midtexture); texheight = textureheight[midtexture]; // a single sided line is terminal, so it must mark ends markfloor = markceiling = true; @@ -2021,11 +2082,14 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (!toptexture) //Second side has no texture, use the first side's instead. toptexture = R_GetTextureNum(sidedef->toptexture); + + topbrightmap = R_GetTextureBrightmap(toptexture); texheight = textureheight[toptexture]; } else { toptexture = R_GetTextureNum(sidedef->toptexture); + topbrightmap = R_GetTextureBrightmap(toptexture); texheight = textureheight[toptexture]; } if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked @@ -2052,6 +2116,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) { // bottom texture bottomtexture = R_GetTextureNum(sidedef->bottomtexture); + bottombrightmap = R_GetTextureBrightmap(bottomtexture); if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked if (linedef->flags & ML_DONTPEGBOTTOM) @@ -2772,7 +2837,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_bsilheight = &(ds_p->bsilheight); R_RenderSegLoop(); - colfunc = colfuncs[BASEDRAWFUNC]; + R_SetColumnFunc(BASEDRAWFUNC, false); if (portalline) // if curline is a portal, set portalrender for drawseg ds_p->portalpass = portalrender+1; diff --git a/src/r_skins.c b/src/r_skins.c index 1e80e18ce..ba7ed0811 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -311,11 +311,6 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) } player->skincolor = newcolor = skin->prefcolor; - if (player->bot && botingame) - { - botskin = (UINT8)(skinnum + 1); - botcolor = skin->prefcolor; - } } #endif diff --git a/src/r_splats.c b/src/r_splats.c index 63052049e..28acd0ab0 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -444,6 +444,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr } ds_colormap = vis->colormap; + ds_fullbright = colormaps; ds_translation = R_GetSpriteTranslation(vis); if (ds_translation == NULL) ds_translation = colormaps; @@ -468,10 +469,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr else ds_transmap = NULL; - if (ds_powersoftwo) - spanfunc = spanfuncs[spanfunctype]; - else - spanfunc = spanfuncs_npo2[spanfunctype]; + R_SetSpanFunc(spanfunctype, !ds_powersoftwo, false); if (maxy >= vid.height) maxy = vid.height-1; diff --git a/src/r_state.h b/src/r_state.h index cb55e2c2b..dc577448e 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -54,6 +54,9 @@ extern extracolormap_t *extra_colormaps; // for global animation extern INT32 *texturetranslation; +// for brightmaps +extern INT32 *texturebrightmaps; + // Sprites extern size_t numspritelumps, max_spritelumps; @@ -93,7 +96,7 @@ extern side_t *spawnsides; // POV data. // extern fixed_t viewx, viewy, viewz; -extern angle_t viewangle, aimingangle; +extern angle_t viewangle, aimingangle, viewroll; extern UINT8 viewssnum; // splitscreen view number extern boolean viewsky, skyVisible; extern boolean skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisible of each splitscreen player diff --git a/src/r_textures.c b/src/r_textures.c index 9716724b5..9254cb91b 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -55,6 +55,7 @@ INT32 *texturewidth; fixed_t *textureheight; // needed for texture pegging INT32 *texturetranslation; +INT32 *texturebrightmaps; // Painfully simple texture id cacheing to make maps load faster. :3 static struct { @@ -500,6 +501,20 @@ INT32 R_GetTextureNum(INT32 texnum) return texturetranslation[texnum]; } +// +// R_GetTextureBrightmap +// +// Returns the actual texture id that we should use. +// This can either be the texture's brightmap, +// or 0 if not valid. +// +INT32 R_GetTextureBrightmap(INT32 texnum) +{ + if (texnum < 0 || texnum >= numtextures) + return 0; + return texturebrightmaps[texnum]; +} + // // R_CheckTextureCache // @@ -725,6 +740,7 @@ Rloadflats (INT32 i, INT32 w) UINT16 texstart, texend; texture_t *texture; texpatch_t *patch; + UINT8 header[PNG_HEADER_SIZE]; // Yes if (wadfiles[w]->type == RET_PK3) @@ -743,7 +759,6 @@ Rloadflats (INT32 i, INT32 w) // Work through each lump between the markers in the WAD. for (j = 0; j < (texend - texstart); j++) { - UINT8 *flatlump; UINT16 wadnum = (UINT16)w; lumpnum_t lumpnum = texstart + j; size_t lumplength; @@ -755,7 +770,7 @@ Rloadflats (INT32 i, INT32 w) continue; // If it is then SKIP IT } - flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + W_ReadLumpHeaderPwad(wadnum, lumpnum, header, sizeof header, 0); lumplength = W_LumpLengthPwad(wadnum, lumpnum); switch (lumplength) @@ -790,12 +805,14 @@ Rloadflats (INT32 i, INT32 w) M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); #ifndef NO_PNG_LUMPS - if (Picture_IsLumpPNG((UINT8 *)flatlump, lumplength)) + if (Picture_IsLumpPNG(header, lumplength)) { + UINT8 *flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); INT32 width, height; Picture_PNGDimensions((UINT8 *)flatlump, &width, &height, NULL, NULL, lumplength); texture->width = (INT16)width; texture->height = (INT16)height; + Z_Free(flatlump); } else #endif @@ -814,8 +831,6 @@ Rloadflats (INT32 i, INT32 w) patch->lump = texstart + j; patch->flip = 0; - Z_Unlock(flatlump); - texturewidth[i] = texture->width; textureheight[i] = texture->height << FRACBITS; i++; @@ -835,8 +850,8 @@ Rloadtextures (INT32 i, INT32 w) UINT16 j; UINT16 texstart, texend, texturesLumpPos; texture_t *texture; - softwarepatch_t *patchlump; texpatch_t *patch; + softwarepatch_t patchlump; // Get the lump numbers for the markers in the WAD, if they exist. if (wadfiles[w]->type == RET_PK3) @@ -876,7 +891,7 @@ Rloadtextures (INT32 i, INT32 w) continue; // If it is then SKIP IT } - patchlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + W_ReadLumpHeaderPwad(wadnum, lumpnum, &patchlump, PNG_HEADER_SIZE, 0); #ifndef NO_PNG_LUMPS lumplength = W_LumpLengthPwad(wadnum, lumpnum); #endif @@ -888,18 +903,20 @@ Rloadtextures (INT32 i, INT32 w) M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); #ifndef NO_PNG_LUMPS - if (Picture_IsLumpPNG((UINT8 *)patchlump, lumplength)) + if (Picture_IsLumpPNG((UINT8 *)&patchlump, lumplength)) { + UINT8 *png = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); INT32 width, height; - Picture_PNGDimensions((UINT8 *)patchlump, &width, &height, NULL, NULL, lumplength); + Picture_PNGDimensions(png, &width, &height, NULL, NULL, lumplength); texture->width = (INT16)width; texture->height = (INT16)height; + Z_Free(png); } else #endif { - texture->width = SHORT(patchlump->width); - texture->height = SHORT(patchlump->height); + texture->width = SHORT(patchlump.width); + texture->height = SHORT(patchlump.height); } texture->type = TEXTURETYPE_SINGLEPATCH; @@ -915,8 +932,6 @@ Rloadtextures (INT32 i, INT32 w) patch->lump = texstart + j; patch->flip = 0; - Z_Unlock(patchlump); - texturewidth[i] = texture->width; textureheight[i] = texture->height << FRACBITS; i++; @@ -944,6 +959,7 @@ void R_LoadTextures(void) Z_Free(textures[i]); Z_Free(texturecache[i]); } + Z_Free(texturebrightmaps); Z_Free(texturetranslation); Z_Free(textures); } @@ -1044,9 +1060,14 @@ void R_LoadTextures(void) textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4)); // Create translation table for global animation. texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL); + // Create brightmap texture table. + texturebrightmaps = Z_Malloc((numtextures + 1) * sizeof(*texturebrightmaps), PU_STATIC, NULL); for (i = 0; i < numtextures; i++) + { texturetranslation[i] = i; + texturebrightmaps[i] = 0; + } for (i = 0, w = 0; w < numwadfiles; w++) { diff --git a/src/r_textures.h b/src/r_textures.h index 6e0cc168a..dada043a6 100644 --- a/src/r_textures.h +++ b/src/r_textures.h @@ -82,6 +82,7 @@ void R_FlushTextureCache(void); UINT8 *R_GenerateTexture(size_t texnum); UINT8 *R_GenerateTextureAsFlat(size_t texnum); INT32 R_GetTextureNum(INT32 texnum); +INT32 R_GetTextureBrightmap(INT32 texnum); void R_CheckTextureCache(INT32 tex); void R_ClearTextureNumCache(boolean btell); diff --git a/src/r_things.c b/src/r_things.c index 9d2d87eb8..09c6b4177 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -35,7 +35,6 @@ #include "p_slopes.h" #include "d_netfil.h" // blargh. for nameonly(). #include "m_cheat.h" // objectplace -#include "k_color.h" // SRB2kart #include "p_local.h" // stplyr #ifdef HWRENDER #include "hardware/hw_md2.h" @@ -44,6 +43,10 @@ #include "hardware/hw_drv.h" #endif +// SRB2kart +#include "k_color.h" +#include "k_kart.h" // HITLAGJITTERS + #define MINZ (FRACUNIT*4) #define BASEYCENTER (BASEVIDHEIGHT/2) @@ -283,16 +286,18 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 #ifndef NO_PNG_LUMPS { - softwarepatch_t *png = W_CacheLumpNumPwad(wadnum, l, PU_STATIC); + UINT8 header[PNG_HEADER_SIZE]; size_t len = W_LumpLengthPwad(wadnum, l); - if (Picture_IsLumpPNG((UINT8 *)png, len)) + W_ReadLumpHeaderPwad(wadnum, l, header, sizeof header, 0); + + if (Picture_IsLumpPNG(header, len)) { + UINT8 *png = W_CacheLumpNumPwad(wadnum, l, PU_STATIC); Picture_PNGDimensions((UINT8 *)png, &width, &height, &topoffset, &leftoffset, len); isPNG = true; + Z_Free(png); } - - Z_Free(png); } if (!isPNG) @@ -599,7 +604,7 @@ INT16 *mceilingclip; fixed_t spryscale = 0, sprtopscreen = 0, sprbotscreen = 0; fixed_t windowtop = 0, windowbottom = 0; -void R_DrawMaskedColumn(column_t *column) +void R_DrawMaskedColumn(column_t *column, column_t *brightmap) { INT32 topscreen; INT32 bottomscreen; @@ -608,6 +613,9 @@ void R_DrawMaskedColumn(column_t *column) basetexturemid = dc_texturemid; + R_SetColumnFunc(colfunctype, brightmap != NULL); + dc_brightmap = NULL; + for (; column->topdelta != 0xff ;) { // calculate unclipped screen coordinates @@ -642,6 +650,11 @@ void R_DrawMaskedColumn(column_t *column) if (dc_yl <= dc_yh && dc_yh > 0) { dc_source = (UINT8 *)column + 3; + if (brightmap != NULL) + { + dc_brightmap = (UINT8 *)brightmap + 3; + } + dc_texturemid = basetexturemid - (topdelta<length + 4); + if (brightmap != NULL) + { + brightmap = (column_t *)((UINT8 *)brightmap + brightmap->length + 4); + } } dc_texturemid = basetexturemid; @@ -663,7 +680,7 @@ void R_DrawMaskedColumn(column_t *column) INT32 lengthcol; // column->length : for flipped column function pointers and multi-patch on 2sided wall = texture->height -void R_DrawFlippedMaskedColumn(column_t *column) +void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap) { INT32 topscreen; INT32 bottomscreen; @@ -671,6 +688,9 @@ void R_DrawFlippedMaskedColumn(column_t *column) INT32 topdelta, prevdelta = -1; UINT8 *d,*s; + R_SetColumnFunc(colfunctype, brightmap != NULL); + dc_brightmap = NULL; + for (; column->topdelta != 0xff ;) { // calculate unclipped screen coordinates @@ -709,6 +729,14 @@ void R_DrawFlippedMaskedColumn(column_t *column) dc_source = ZZ_Alloc(column->length); for (s = (UINT8 *)column+2+column->length, d = dc_source; d < dc_source+column->length; --s) *d++ = *s; + + if (brightmap != NULL) + { + dc_brightmap = ZZ_Alloc(brightmap->length); + for (s = (UINT8 *)brightmap+2+brightmap->length, d = dc_brightmap; d < dc_brightmap+brightmap->length; --s) + *d++ = *s; + } + dc_texturemid = basetexturemid - (topdelta<length + 4); + if (brightmap != NULL) + { + brightmap = (column_t *)((UINT8 *)brightmap + brightmap->length + 4); + } } dc_texturemid = basetexturemid; @@ -776,7 +808,7 @@ UINT8 *R_GetSpriteTranslation(vissprite_t *vis) static void R_DrawVisSprite(vissprite_t *vis) { column_t *column; - void (*localcolfunc)(column_t *); + void (*localcolfunc)(column_t *, column_t *); INT32 texturecolumn; INT32 pwidth; fixed_t frac; @@ -800,26 +832,27 @@ static void R_DrawVisSprite(vissprite_t *vis) if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // ditto } - colfunc = colfuncs[BASEDRAWFUNC]; // hack: this isn't resetting properly somewhere. + R_SetColumnFunc(BASEDRAWFUNC, false); // hack: this isn't resetting properly somewhere. dc_colormap = vis->colormap; + dc_fullbright = colormaps; dc_translation = R_GetSpriteTranslation(vis); if (R_SpriteIsFlashing(vis)) // Bosses "flash" - colfunc = colfuncs[COLDRAWFUNC_TRANS]; // translate certain pixels to white + R_SetColumnFunc(COLDRAWFUNC_TRANS, false); // translate certain pixels to white else if (vis->mobj->color && vis->transmap) // Color mapping { - colfunc = colfuncs[COLDRAWFUNC_TRANSTRANS]; + R_SetColumnFunc(COLDRAWFUNC_TRANSTRANS, false); dc_transmap = vis->transmap; } else if (vis->transmap) { - colfunc = colfuncs[COLDRAWFUNC_FUZZY]; + R_SetColumnFunc(COLDRAWFUNC_FUZZY, false); dc_transmap = vis->transmap; //Fab : 29-04-98: translucency table } else if (vis->mobj->color) // translate green skin to another color - colfunc = colfuncs[COLDRAWFUNC_TRANS]; + R_SetColumnFunc(COLDRAWFUNC_TRANS, false); else if (vis->mobj->sprite == SPR_PLAY) // Looks like a player, but doesn't have a color? Get rid of green sonic syndrome. - colfunc = colfuncs[COLDRAWFUNC_TRANS]; + R_SetColumnFunc(COLDRAWFUNC_TRANS, false); if (vis->extra_colormap && !(vis->renderflags & RF_NOCOLORMAPS)) { @@ -831,8 +864,13 @@ static void R_DrawVisSprite(vissprite_t *vis) if (!dc_colormap) dc_colormap = colormaps; + dc_fullbright = colormaps; + if (encoremap && !vis->mobj->color && !(vis->mobj->flags & MF_DONTENCOREMAP)) - dc_colormap += COLORMAP_REMAPOFFSET; + { + dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } dc_texturemid = vis->texturemid; dc_texheight = 0; @@ -905,7 +943,7 @@ static void R_DrawVisSprite(vissprite_t *vis) column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); - localcolfunc (column); + localcolfunc (column, NULL); } } else if (vis->cut & SC_SHEAR) @@ -927,7 +965,7 @@ static void R_DrawVisSprite(vissprite_t *vis) #endif sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); - localcolfunc (column); + localcolfunc (column, NULL); } } else @@ -947,11 +985,11 @@ static void R_DrawVisSprite(vissprite_t *vis) #else column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); #endif - localcolfunc (column); + localcolfunc (column, NULL); } } - colfunc = colfuncs[BASEDRAWFUNC]; + R_SetColumnFunc(BASEDRAWFUNC, false); dc_hires = 0; vis->x1 = x1; @@ -981,13 +1019,17 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) if (vis->transmap) { - colfunc = colfuncs[COLDRAWFUNC_FUZZY]; + R_SetColumnFunc(COLDRAWFUNC_FUZZY, false); dc_transmap = vis->transmap; //Fab : 29-04-98: translucency table } dc_colormap = colormaps; + dc_fullbright = colormaps; if (encoremap) + { dc_colormap += COLORMAP_REMAPOFFSET; + dc_fullbright += COLORMAP_REMAPOFFSET; + } dc_iscale = FixedDiv(FRACUNIT, vis->scale); dc_texturemid = vis->texturemid; @@ -1016,10 +1058,10 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) #else column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); #endif - R_DrawMaskedColumn(column); + R_DrawMaskedColumn(column, NULL); } - colfunc = colfuncs[BASEDRAWFUNC]; + R_SetColumnFunc(BASEDRAWFUNC, false); } // @@ -1431,31 +1473,29 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t interpx = thing->x; fixed_t interpy = thing->y; fixed_t interpz = thing->z; - angle_t interpangle = thing->angle; - - // use player drawangle if player - if (thing->player) interpangle = thing->player->drawangle; + angle_t interpangle = (thing->player ? thing->player->drawangle : thing->angle); // do interpolation - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z); + if (thing->player) { - interpangle = thing->player->drawangle; + interpangle = thing->player->old_drawangle + FixedMul(rendertimefrac, thing->player->drawangle - thing->player->old_drawangle); } else { - interpangle = thing->angle; + interpangle = thing->old_angle + FixedMul(rendertimefrac, thing->angle - thing->old_angle); } } // hitlag vibrating (todo: interp somehow?) if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG)) { - fixed_t mul = thing->hitlag * (FRACUNIT / 10); + fixed_t mul = thing->hitlag * HITLAGJITTERS; if (leveltime & 1) { @@ -1777,7 +1817,7 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t linkscale; thing = thing->tracer; - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = thing->old_x + FixedMul(thing->x - thing->old_x, rendertimefrac); interpy = thing->old_y + FixedMul(thing->y - thing->old_y, rendertimefrac); @@ -2126,7 +2166,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) fixed_t interpz = thing->z; // do interpolation - if (cv_frameinterpolation.value == 1 && !paused) + if (cv_frameinterpolation.value == 1) { interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); diff --git a/src/r_things.h b/src/r_things.h index cbbb0f2d8..7ff1bd4c7 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -47,8 +47,8 @@ extern fixed_t windowtop; extern fixed_t windowbottom; extern INT32 lengthcol; -void R_DrawMaskedColumn(column_t *column); -void R_DrawFlippedMaskedColumn(column_t *column); +void R_DrawMaskedColumn(column_t *column, column_t *brightmap); +void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap); // ---------------- // SPRITE RENDERING diff --git a/src/screen.c b/src/screen.c index 05e7cf3b4..745b2a065 100644 --- a/src/screen.c +++ b/src/screen.c @@ -49,10 +49,17 @@ // -------------------------------------------- void (*colfunc)(void); void (*colfuncs[COLDRAWFUNC_MAX])(void); +#ifdef USE_COL_SPAN_ASM +void (*colfuncs_asm[COLDRAWFUNC_MAX])(void); +#endif +int colfunctype; void (*spanfunc)(void); void (*spanfuncs[SPANDRAWFUNC_MAX])(void); void (*spanfuncs_npo2[SPANDRAWFUNC_MAX])(void); +#ifdef USE_COL_SPAN_ASM +void (*spanfuncs_asm[SPANDRAWFUNC_MAX])(void); +#endif // ------------------ // global video state @@ -118,9 +125,6 @@ void SCR_SetDrawFuncs(void) colfuncs[BASEDRAWFUNC] = R_DrawColumn_8; spanfuncs[BASEDRAWFUNC] = R_DrawSpan_8; - colfunc = colfuncs[BASEDRAWFUNC]; - spanfunc = spanfuncs[BASEDRAWFUNC]; - colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8; colfuncs[COLDRAWFUNC_TRANS] = R_DrawTranslatedColumn_8; colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8; @@ -160,26 +164,29 @@ void SCR_SetDrawFuncs(void) spanfuncs_npo2[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_FOG] = NULL; // Not needed -#ifdef RUSEASM +#if (defined(RUSEASM) && defined(USE_COL_SPAN_ASM)) if (R_ASM) { if (R_MMX) { - colfuncs[BASEDRAWFUNC] = R_DrawColumn_8_MMX; - //colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8_ASM; - //colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8_ASM; - colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8_MMX; - spanfuncs[BASEDRAWFUNC] = R_DrawSpan_8_MMX; + colfuncs_asm[BASEDRAWFUNC] = R_DrawColumn_8_MMX; + //colfuncs_asm[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8_ASM; + //colfuncs_asm[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8_ASM; + colfuncs_asm[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8_MMX; + spanfuncs_asm[BASEDRAWFUNC] = R_DrawSpan_8_MMX; } else { - colfuncs[BASEDRAWFUNC] = R_DrawColumn_8_ASM; - //colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8_ASM; - //colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8_ASM; - colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8_ASM; + colfuncs_asm[BASEDRAWFUNC] = R_DrawColumn_8_ASM; + //colfuncs_asm[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8_ASM; + //colfuncs_asm[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8_ASM; + colfuncs_asm[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8_ASM; } } #endif + + R_SetColumnFunc(BASEDRAWFUNC, false); + R_SetSpanFunc(BASEDRAWFUNC, false, false); } /* else if (vid.bpp > 1) { @@ -201,6 +208,65 @@ void SCR_SetDrawFuncs(void) */ } +void R_SetColumnFunc(size_t id, boolean brightmapped) +{ + I_Assert(id < COLDRAWFUNC_MAX); + + colfunctype = id; + +#ifdef USE_COL_SPAN_ASM + if (colfuncs_asm[id] != NULL && brightmapped == false) + { + colfunc = colfuncs_asm[id]; + } + else +#endif + { + colfunc = colfuncs[id]; + } +} + +void R_SetSpanFunc(size_t id, boolean npo2, boolean brightmapped) +{ + I_Assert(id < COLDRAWFUNC_MAX); + + if (spanfuncs_npo2[id] != NULL && npo2 == true) + { + spanfunc = spanfuncs_npo2[id]; + } +#ifdef USE_COL_SPAN_ASM + else if (spanfuncs_asm[id] != NULL && brightmapped == false) + { + spanfunc = spanfuncs_asm[id]; + } +#endif + else + { + spanfunc = spanfuncs[id]; + } +} + +boolean R_CheckColumnFunc(size_t id) +{ + size_t i; + + if (colfunc == NULL) + { + // Shouldn't happen. + return false; + } + + for (i = 0; i < COLDRAWFUNC_MAX; i++) + { + if (colfunc == colfuncs[id] || colfunc == colfuncs_asm[id]) + { + return true; + } + } + + return false; +} + void SCR_SetMode(void) { if (dedicated) @@ -447,9 +513,46 @@ boolean SCR_IsAspectCorrect(INT32 width, INT32 height) // XMOD FPS display // moved out of os-specific code for consistency -static boolean fpsgraph[TICRATE]; +static boolean ticsgraph[TICRATE]; static tic_t lasttic; +static UINT32 fpstime = 0; +static UINT32 lastupdatetime = 0; + +#define FPSUPDATERATE 1/20 // What fraction of a second to update at. The fraction will not simplify to 0, trust me. +#define FPSMAXSAMPLES 16 + +static UINT32 fpssamples[FPSMAXSAMPLES]; +static UINT32 fpssampleslen = 0; +static UINT32 fpssum = 0; +double aproxfps = 0.0f; + +void SCR_CalcAproxFps(void) +{ + tic_t i = 0; + if (I_PreciseToMicros(fpstime - lastupdatetime) > 1000000 * FPSUPDATERATE) + { + if (fpssampleslen == FPSMAXSAMPLES) + { + fpssum -= fpssamples[0]; + + for (i = 1; i < fpssampleslen; i++) + fpssamples[i-1] = fpssamples[i]; + } + else + fpssampleslen++; + + fpssamples[fpssampleslen-1] = I_GetPreciseTime() - fpstime; + fpssum += fpssamples[fpssampleslen-1]; + + aproxfps = 1000000 / (I_PreciseToMicros(fpssum) / (double)fpssampleslen); + + lastupdatetime = I_GetPreciseTime(); + } + + fpstime = I_GetPreciseTime(); +} + void SCR_DisplayTicRate(void) { tic_t i; @@ -458,25 +561,51 @@ void SCR_DisplayTicRate(void) const UINT8 *ticcntcolor = NULL; for (i = lasttic + 1; i < TICRATE+lasttic && i < ontic; ++i) - fpsgraph[i % TICRATE] = false; + ticsgraph[i % TICRATE] = false; - fpsgraph[ontic % TICRATE] = true; + ticsgraph[ontic % TICRATE] = true; for (i = 0;i < TICRATE;++i) - if (fpsgraph[i]) + if (ticsgraph[i]) ++totaltics; - if (totaltics <= TICRATE/2) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_RASPBERRY, GTC_CACHE); - else if (totaltics == TICRATE) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE); - // draw "FPS" V_DrawFixedPatch(306<= 60.0f) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE); + + /* + if (cv_fpscap.value != 0) + { + // draw total frame: + //V_DrawPingNum(318, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, cv_fpscap.value, ticcntcolor); + // draw "/" + //V_DrawFixedPatch(306<= TICRATE) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE); + + // draw total frame: + V_DrawPingNum(318, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, TICRATE, ticcntcolor); + // draw "/" + V_DrawFixedPatch(306<disksize; - unsigned long decSize = l->size; + unsigned long decSize = size; rawData = Z_Malloc(rawSize, PU_STATIC, NULL); - decData = Z_Malloc(decSize, PU_STATIC, NULL); + decData = dest; if (fread(rawData, 1, rawSize, handle) < rawSize) I_Error("wad %d, lump %d: cannot read compressed data", wad, lump); @@ -1501,12 +1501,8 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si zErr = inflateInit2(&strm, -15); if (zErr == Z_OK) { - zErr = inflate(&strm, Z_FINISH); - if (zErr == Z_STREAM_END) - { - M_Memcpy(dest, decData, size); - } - else + zErr = inflate(&strm, Z_SYNC_FLUSH); + if (zErr != Z_OK && zErr != Z_STREAM_END) { size = 0; zerr(zErr); @@ -1520,7 +1516,6 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si } Z_Free(rawData); - Z_Free(decData); #ifdef NO_PNG_LUMPS if (Picture_IsLumpPNG((UINT8 *)dest, size)) diff --git a/src/y_inter.c b/src/y_inter.c index e548df1f9..1acceda26 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1322,7 +1322,7 @@ static void Y_VoteStops(SINT8 pick, SINT8 level) if (gametype != votelevels[level][1]) { INT16 lastgametype = gametype; - gametype = votelevels[level][1]; + G_SetGametype(votelevels[level][1]); D_GameTypeChanged(lastgametype); forceresetplayers = true; }