diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 1dacabd9f..308eb2616 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -97,6 +97,8 @@ UINT16 pingmeasurecount = 1; UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will be sent to everyone. UINT32 playerpingtable[MAXPLAYERS]; //table of player latency values. tic_t servermaxping = 800; // server's max ping. Defaults to 800 +static tic_t lowest_lag; +boolean server_lagless; SINT8 nodetoplayer[MAXNETNODES]; SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen) SINT8 nodetoplayer3[MAXNETNODES]; // say the numplayer for this node if any (splitscreen == 2) @@ -4960,6 +4962,9 @@ static void CL_SendClientCmd(void) size_t packetsize = 0; boolean mis = false; + if (lowest_lag && ( gametic % lowest_lag )) + return; + netbuffer->packettype = PT_CLIENTCMD; if (cl_packetmissed) @@ -5428,16 +5433,65 @@ static tic_t gametime = 0; static void UpdatePingTable(void) { + tic_t fastest; + tic_t lag; + INT32 i; + if (server) { if (netgame && !(gametime % 35)) // update once per second. PingUpdate(); + + fastest = 0; + // update node latency values so we can take an average later. for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i])); + { + if (playeringame[i] && playernode[i] > 0) + { + if (! server_lagless && playernode[i] > 0) + { + lag = GetLag(playernode[i]); + realpingtable[i] += G_TicsToMilliseconds(lag); + + if (! fastest || lag < fastest) + fastest = lag; + } + else + realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i])); + } + } pingmeasurecount++; + + if (server_lagless) + lowest_lag = 0; + else + { + lowest_lag = fastest; + + if (fastest) + lag = fastest; + else + lag = GetLag(0); + + lag = ( realpingtable[0] + G_TicsToMilliseconds(lag) ); + + switch (playerpernode[0]) + { + case 4: + realpingtable[nodetoplayer4[0]] = lag; + /*FALLTHRU*/ + case 3: + realpingtable[nodetoplayer3[0]] = lag; + /*FALLTHRU*/ + case 2: + realpingtable[nodetoplayer2[0]] = lag; + /*FALLTHRU*/ + case 1: + realpingtable[nodetoplayer[0]] = lag; + } + } } } diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 0bd85b614..a33d06a2c 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -543,6 +543,8 @@ extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS]; extern tic_t servermaxping; +extern boolean server_lagless; + extern consvar_t #ifdef VANILLAJOINNEXTROUND cv_joinnextround, diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 3b70d397b..78054ff3d 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -93,6 +93,8 @@ static void TeamScramble_OnChange(void); static void NetTimeout_OnChange(void); static void JoinTimeout_OnChange(void); +static void Lagless_OnChange (void); + static void Ringslinger_OnChange(void); static void Gravity_OnChange(void); static void ForceSkin_OnChange(void); @@ -449,6 +451,8 @@ consvar_t cv_jointimeout = {"jointimeout", "105", CV_CALL|CV_SAVE, nettimeout_co static CV_PossibleValue_t maxping_cons_t[] = {{0, "MIN"}, {1000, "MAX"}, {0, NULL}}; consvar_t cv_maxping = {"maxping", "800", CV_SAVE, maxping_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_lagless = {"lagless", "Off", CV_SAVE|CV_NETVAR|CV_CALL, CV_OnOff, Lagless_OnChange, 0, NULL, NULL, 0, 0, NULL}; + static CV_PossibleValue_t pingtimeout_cons_t[] = {{8, "MIN"}, {120, "MAX"}, {0, NULL}}; consvar_t cv_pingtimeout = {"pingtimeout", "10", CV_SAVE, pingtimeout_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -713,6 +717,7 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_skipmapcheck); CV_RegisterVar(&cv_sleep); CV_RegisterVar(&cv_maxping); + CV_RegisterVar(&cv_lagless); CV_RegisterVar(&cv_pingtimeout); CV_RegisterVar(&cv_showping); @@ -4763,6 +4768,14 @@ static void JoinTimeout_OnChange(void) jointimeout = (tic_t)cv_jointimeout.value; } +static void +Lagless_OnChange (void) +{ + /* don't back out of dishonesty, or go lagless after playing honestly */ + if (cv_lagless.value && gamestate == GS_LEVEL) + server_lagless = true; +} + UINT32 timelimitintics = 0; /** Deals with a timelimit change by printing the change to the console. diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 74273fc90..d2a88eddf 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -145,6 +145,7 @@ extern consvar_t cv_ringslinger, cv_soundtest; extern consvar_t cv_specialrings, cv_powerstones, cv_matchboxes, cv_competitionboxes; extern consvar_t cv_maxping; +extern consvar_t cv_lagless; extern consvar_t cv_pingtimeout; extern consvar_t cv_showping; diff --git a/src/dehacked.c b/src/dehacked.c index 6b99eeb7c..31986e942 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1774,7 +1774,6 @@ static actionpointer_t actionpointers[] = {{A_GrenadeRing}, "A_GRENADERING"}, // SRB2kart {{A_SetSolidSteam}, "A_SETSOLIDSTEAM"}, {{A_UnsetSolidSteam}, "A_UNSETSOLIDSTEAM"}, - {{A_SignPlayer}, "A_SIGNPLAYER"}, {{A_OverlayThink}, "A_OVERLAYTHINK"}, {{A_JetChase}, "A_JETCHASE"}, {{A_JetbThink}, "A_JETBTHINK"}, @@ -4887,27 +4886,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_BUBBLES2", // Level End Sign - "S_SIGN1", - "S_SIGN2", - "S_SIGN3", - "S_SIGN4", - "S_SIGN5", - "S_SIGN6", - "S_SIGN7", - "S_SIGN8", - "S_SIGN9", - "S_SIGN10", - "S_SIGN11", - "S_SIGN12", - "S_SIGN13", - "S_SIGN14", - "S_SIGN15", - "S_SIGN16", - "S_SIGN17", - "S_SIGN18", - "S_SIGN19", - "S_SIGN20", - "S_SIGN_END", + "S_SIGN_POLE", + "S_SIGN_BACK", + "S_SIGN_SIDE", + "S_SIGN_FACE", // Steam Riser "S_STEAM1", @@ -5690,6 +5672,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SNOW2", "S_SNOW3", + // Blizzard Snowball + "S_BLIZZARDSNOW1", + "S_BLIZZARDSNOW2", + "S_BLIZZARDSNOW3", + // Water Splish "S_SPLISH1", "S_SPLISH2", @@ -6784,9 +6771,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_LAMPPOST", "S_MOSSYTREE", - "S_SHADOW", - "S_WHITESHADOW", - "S_BUMP1", "S_BUMP2", "S_BUMP3", @@ -7368,6 +7352,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s // Interactive Objects "MT_BUBBLES", // Bubble source "MT_SIGN", // Level end sign + "MT_SIGN_PIECE", "MT_SPIKEBALL", // Spike Ball "MT_SPECIALSPIKEBALL", "MT_SPINFIRE", @@ -7594,6 +7579,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s // Environmental Effects "MT_RAIN", // Rain "MT_SNOWFLAKE", // Snowflake + "MT_BLIZZARDSNOW", // Blizzard Snowball "MT_SPLISH", // Water splish! "MT_SMOKE", "MT_SMALLBUBBLE", // small bubble @@ -7854,8 +7840,6 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_LAMPPOST", "MT_MOSSYTREE", - "MT_SHADOW", - "MT_BUMP", "MT_FLINGENERGY", @@ -8702,10 +8686,10 @@ struct { // Precipitation {"PRECIP_NONE",PRECIP_NONE}, - {"PRECIP_STORM",PRECIP_STORM}, - {"PRECIP_SNOW",PRECIP_SNOW}, {"PRECIP_RAIN",PRECIP_RAIN}, - {"PRECIP_BLANK",PRECIP_BLANK}, + {"PRECIP_SNOW",PRECIP_SNOW}, + {"PRECIP_BLIZZARD",PRECIP_BLIZZARD}, + {"PRECIP_STORM",PRECIP_STORM}, {"PRECIP_STORM_NORAIN",PRECIP_STORM_NORAIN}, {"PRECIP_STORM_NOSTRIKES",PRECIP_STORM_NOSTRIKES}, diff --git a/src/doomstat.h b/src/doomstat.h index 59e2bd5c4..f4f7acfd0 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -41,18 +41,36 @@ extern UINT32 mapmusposition; extern INT16 maptol; extern UINT8 globalweather; -extern INT32 curWeather; +extern UINT8 curWeather; extern INT32 cursaveslot; extern INT16 lastmapsaved; extern boolean gamecomplete; -#define PRECIP_NONE 0 -#define PRECIP_STORM 1 -#define PRECIP_SNOW 2 -#define PRECIP_RAIN 3 -#define PRECIP_BLANK 4 -#define PRECIP_STORM_NORAIN 5 -#define PRECIP_STORM_NOSTRIKES 6 +typedef enum +{ + PRECIP_NONE = 0, + PRECIP_RAIN, + PRECIP_SNOW, + PRECIP_BLIZZARD, + PRECIP_STORM, + PRECIP_STORM_NORAIN, + PRECIP_STORM_NOSTRIKES, + MAXPRECIP +} preciptype_t; + +typedef enum +{ + PRECIPFX_THUNDER = 1, + PRECIPFX_LIGHTNING = 1<<1 +} precipeffect_t; + +typedef struct +{ + mobjtype_t type; + precipeffect_t effects; +} precipprops_t; + +extern precipprops_t precipprops[MAXPRECIP]; // Set if homebrew PWAD stuff has been added. extern boolean modifiedgame; diff --git a/src/g_game.c b/src/g_game.c index aa26dd374..df74da9fd 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -83,8 +83,21 @@ UINT32 mapmusposition; // Position to jump to INT16 gamemap = 1; INT16 maptol; + UINT8 globalweather = 0; -INT32 curWeather = PRECIP_NONE; +UINT8 curWeather = PRECIP_NONE; + +precipprops_t precipprops[MAXPRECIP] = +{ + {MT_NULL, 0}, // PRECIP_NONE + {MT_RAIN, 0}, // PRECIP_RAIN + {MT_SNOWFLAKE, 0}, // PRECIP_SNOW + {MT_BLIZZARDSNOW, 0}, // PRECIP_BLIZZARD + {MT_RAIN, PRECIPFX_THUNDER|PRECIPFX_LIGHTNING}, // PRECIP_STORM + {MT_NULL, PRECIPFX_THUNDER|PRECIPFX_LIGHTNING}, // PRECIP_STORM_NORAIN + {MT_RAIN, PRECIPFX_THUNDER} // PRECIP_STORM_NOSTRIKES +}; + INT32 cursaveslot = -1; // Auto-save 1p savegame slot INT16 lastmapsaved = 0; // Last map we auto-saved at boolean gamecomplete = false; @@ -1781,6 +1794,8 @@ void G_DoLoadLevel(boolean resetplayer) // clear hud messages remains (usually from game startup) CON_ClearHUD(); + + server_lagless = cv_lagless.value; } static INT32 pausedelay = 0; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 659af386d..6ccaf1bc5 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -39,6 +39,7 @@ #include "../st_stuff.h" #include "../i_system.h" #include "../m_cheat.h" +#include "../r_things.h" // R_GetShadowZ #ifdef ESLOPE #include "../p_slopes.h" #endif @@ -3563,6 +3564,9 @@ static void HWR_Subsector(size_t num) sub->sector->extra_colormap = gr_frontsector->extra_colormap; + //R_PlaneLightOverride(gr_frontsector, false, &floorlightlevel); + //R_PlaneLightOverride(gr_frontsector, true, &ceilinglightlevel); + // render floor ? #ifdef DOPLANES // yeah, easy backface cull! :) @@ -4058,37 +4062,6 @@ static gr_vissprite_t *HWR_NewVisSprite(void) return HWR_GetVisSprite(gr_visspritecount++); } -// Finds a floor through which light does not pass. -static fixed_t HWR_OpaqueFloorAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) -{ - const sector_t *sec = R_PointInSubsector(x, y)->sector; - fixed_t floorz = sec->floorheight; - - if (sec->ffloors) - { - ffloor_t *rover; - fixed_t delta1, delta2; - const fixed_t thingtop = z + height; - - for (rover = sec->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS) - || !(rover->flags & FF_RENDERPLANES) - || rover->flags & FF_TRANSLUCENT - || rover->flags & FF_FOG - || rover->flags & FF_INVERTPLANES) - continue; - - delta1 = z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)); - delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)); - if (*rover->topheight > floorz && abs(delta1) < abs(delta2)) - floorz = *rover->topheight; - } - } - - return floorz; -} - // // HWR_DoCulling // Hardware version of R_DoCulling @@ -4129,185 +4102,116 @@ static boolean HWR_DoCulling(line_t *cullheight, line_t *viewcullheight, float v return false; } -static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float this_scale) +static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) { - FOutVector swallVerts[4]; + GLPatch_t *gpatch; + FOutVector shadowVerts[4]; FSurfaceInfo sSurf; - fixed_t floorheight, mobjfloor; - float offset = 0; + float fscale; float fx; float fy; float offset; + UINT8 lightlevel = 0; + extracolormap_t *colormap = NULL; + UINT8 i; - mobjfloor = HWR_OpaqueFloorAtPos( - spr->mobj->x, spr->mobj->y, - spr->mobj->z, spr->mobj->height); - if (cv_shadowoffs.value) + INT32 light; + fixed_t scalemul; + UINT16 alpha; + fixed_t floordiff; + fixed_t floorz; + fixed_t slopez; + pslope_t *floorslope; + + floorz = R_GetShadowZ(thing, &floorslope); + floordiff = abs(thing->z - floorz); + + alpha = floordiff / (4*FRACUNIT) + 75; + if (alpha >= 255) return; + alpha = 255 - alpha; + + if (thing->whiteshadow) { - angle_t shadowdir; - - // Set direction - if (splitscreen && stplyr == &players[displayplayers[1]]) - shadowdir = localangle[1] + FixedAngle(cv_cam2_rotate.value); - else if (splitscreen > 1 && stplyr == &players[displayplayers[2]]) - shadowdir = localangle[2] + FixedAngle(cv_cam3_rotate.value); - else if (splitscreen > 2 && stplyr == &players[displayplayers[3]]) - shadowdir = localangle[3] + FixedAngle(cv_cam4_rotate.value); - else - shadowdir = localangle[0] + FixedAngle(cv_cam_rotate.value); - - // Find floorheight - floorheight = HWR_OpaqueFloorAtPos( - spr->mobj->x + P_ReturnThrustX(spr->mobj, shadowdir, spr->mobj->z - mobjfloor), - spr->mobj->y + P_ReturnThrustY(spr->mobj, shadowdir, spr->mobj->z - mobjfloor), - spr->mobj->z, spr->mobj->height); - - // The shadow is falling ABOVE it's mobj? - // Don't draw it, then! - if (spr->mobj->z < floorheight) - return; - else - { - fixed_t floorz; - floorz = HWR_OpaqueFloorAtPos( - spr->mobj->x + P_ReturnThrustX(spr->mobj, shadowdir, spr->mobj->z - floorheight), - spr->mobj->y + P_ReturnThrustY(spr->mobj, shadowdir, spr->mobj->z - floorheight), - spr->mobj->z, spr->mobj->height); - // The shadow would be falling on a wall? Don't draw it, then. - // Would draw midair otherwise. - if (floorz < floorheight) - return; - } - - floorheight = FixedInt(spr->mobj->z - floorheight); - - offset = floorheight; + gpatch = (GLPatch_t *)W_CachePatchName("LSHADOW", PU_CACHE); + lightlevel = 255; } else - floorheight = FixedInt(spr->mobj->z - mobjfloor); + { + gpatch = (GLPatch_t *)W_CachePatchName("DSHADOW", PU_CACHE); + lightlevel = 0; + } + + if (!(gpatch && gpatch->mipmap.grInfo.format)) return; + HWR_GetPatch(gpatch); + + scalemul = FixedMul(FRACUNIT - floordiff/640, scale); + scalemul = FixedMul(scalemul, (thing->radius*2) / gpatch->height); + + fscale = FIXED_TO_FLOAT(scalemul); + fx = FIXED_TO_FLOAT(thing->x); + fy = FIXED_TO_FLOAT(thing->y); - // create the sprite billboard - // // 3--2 // | /| // |/ | // 0--1 - // x1/x2 were already scaled in HWR_ProjectSprite - // First match the normal sprite - swallVerts[0].x = swallVerts[3].x = spr->x1; - swallVerts[2].x = swallVerts[1].x = spr->x2; - swallVerts[0].z = swallVerts[3].z = spr->z1; - swallVerts[2].z = swallVerts[1].z = spr->z2; - - if (spr->mobj && fabsf(this_scale - 1.0f) > 1.0E-36f) - { - // Always a pixel above the floor, perfectly flat. - swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset * this_scale - (floorheight+3); - - // Now transform the TOP vertices along the floor in the direction of the camera - swallVerts[3].x = spr->x1 + ((gpatch->height * this_scale) + offset) * gr_viewcos; - swallVerts[2].x = spr->x2 + ((gpatch->height * this_scale) + offset) * gr_viewcos; - swallVerts[3].z = spr->z1 + ((gpatch->height * this_scale) + offset) * gr_viewsin; - swallVerts[2].z = spr->z2 + ((gpatch->height * this_scale) + offset) * gr_viewsin; - } + if (thing && fabsf(fscale - 1.0f) > 1.0E-36f) + offset = (gpatch->height/2) * fscale; else - { - // Always a pixel above the floor, perfectly flat. - swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset - (floorheight+3); + offset = (float)(gpatch->height/2); - // Now transform the TOP vertices along the floor in the direction of the camera - swallVerts[3].x = spr->x1 + (gpatch->height + offset) * gr_viewcos; - swallVerts[2].x = spr->x2 + (gpatch->height + offset) * gr_viewcos; - swallVerts[3].z = spr->z1 + (gpatch->height + offset) * gr_viewsin; - swallVerts[2].z = spr->z2 + (gpatch->height + offset) * gr_viewsin; + shadowVerts[2].x = shadowVerts[3].x = fx + offset; + shadowVerts[1].x = shadowVerts[0].x = fx - offset; + shadowVerts[1].z = shadowVerts[2].z = fy - offset; + shadowVerts[0].z = shadowVerts[3].z = fy + offset; + + for (i = 0; i < 4; i++) + { + float oldx = shadowVerts[i].x; + float oldy = shadowVerts[i].z; + shadowVerts[i].x = fx + ((oldx - fx) * gr_viewcos) - ((oldy - fy) * gr_viewsin); + shadowVerts[i].z = fy + ((oldx - fx) * gr_viewsin) + ((oldy - fy) * gr_viewcos); } - // We also need to move the bottom ones away when shadowoffs is on - if (cv_shadowoffs.value) + if (floorslope) { - swallVerts[0].x = spr->x1 + offset * gr_viewcos; - swallVerts[1].x = spr->x2 + offset * gr_viewcos; - swallVerts[0].z = spr->z1 + offset * gr_viewsin; - swallVerts[1].z = spr->z2 + offset * gr_viewsin; - } - - if (spr->flip) - { - swallVerts[0].sow = swallVerts[3].sow = gpatch->max_s; - swallVerts[2].sow = swallVerts[1].sow = 0; - } - else - { - swallVerts[0].sow = swallVerts[3].sow = 0; - swallVerts[2].sow = swallVerts[1].sow = gpatch->max_s; - } - - // flip the texture coords (look familiar?) - if (spr->vflip) - { - swallVerts[3].tow = swallVerts[2].tow = gpatch->max_t; - swallVerts[0].tow = swallVerts[1].tow = 0; - } - else - { - swallVerts[3].tow = swallVerts[2].tow = 0; - swallVerts[0].tow = swallVerts[1].tow = gpatch->max_t; - } - - sSurf.FlatColor.s.red = 0x00; - sSurf.FlatColor.s.blue = 0x00; - sSurf.FlatColor.s.green = 0x00; - - /*if (spr->mobj->frame & FF_TRANSMASK || spr->mobj->flags2 & MF2_SHADOW) - { - sector_t *sector = spr->mobj->subsector->sector; - UINT8 lightlevel = 255; - extracolormap_t *colormap = sector->extra_colormap; - - if (sector->numlights) + for (i = 0; i < 4; i++) { - INT32 light = R_GetPlaneLight(sector, spr->mobj->floorz, false); - - if (!(spr->mobj->frame & FF_FULLBRIGHT)) - { - lightlevel = *sector->lightlist[light].lightlevel; - if (spr->mobj->frame & FF_SEMIBRIGHT) - lightlevel = 128 + (lightlevel>>1); - } - - if (sector->lightlist[light].extra_colormap) - colormap = sector->lightlist[light].extra_colormap; + slopez = P_GetZAt(floorslope, FLOAT_TO_FIXED(shadowVerts[i].x), FLOAT_TO_FIXED(shadowVerts[i].z)); + shadowVerts[i].y = FIXED_TO_FLOAT(slopez) + 0.05f; } - else - { - lightlevel = sector->lightlevel; - - if (sector->extra_colormap) - colormap = sector->extra_colormap; - } - - if (colormap) - sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, colormap->rgba, colormap->fadergba, false, true); - else - sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, NORMALFOG, FADEFOG, false, true); - }*/ - - // shadow is always half as translucent as the sprite itself - if (!cv_translucency.value) // use default translucency (main sprite won't have any translucency) - sSurf.FlatColor.s.alpha = 0x80; // default - else if (spr->mobj->flags2 & MF2_SHADOW) - sSurf.FlatColor.s.alpha = 0x20; - else if (spr->mobj->frame & FF_TRANSMASK) - { - HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &sSurf); - sSurf.FlatColor.s.alpha /= 2; //cut alpha in half! } else - sSurf.FlatColor.s.alpha = 0x80; // default - - if (sSurf.FlatColor.s.alpha > floorheight/4) { - sSurf.FlatColor.s.alpha = (UINT8)(sSurf.FlatColor.s.alpha - floorheight/4); - HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated|PF_Clip); + for (i = 0; i < 4; i++) + shadowVerts[i].y = FIXED_TO_FLOAT(floorz) + 0.05f; } + + shadowVerts[0].sow = shadowVerts[3].sow = 0; + shadowVerts[2].sow = shadowVerts[1].sow = gpatch->max_s; + + shadowVerts[3].tow = shadowVerts[2].tow = 0; + shadowVerts[0].tow = shadowVerts[1].tow = gpatch->max_t; + + if (thing->subsector->sector->numlights) + { + light = R_GetPlaneLight(thing->subsector->sector, floorz, false); // Always use the light at the top instead of whatever I was doing before + + if (thing->subsector->sector->lightlist[light].extra_colormap) + colormap = thing->subsector->sector->lightlist[light].extra_colormap; + } + else + { + if (thing->subsector->sector->extra_colormap) + colormap = thing->subsector->sector->extra_colormap; + } + + if (colormap) + sSurf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); + else + sSurf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + + sSurf.FlatColor.s.alpha = alpha; + + HWD.pfnDrawPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated|PF_Clip); } // This is expecting a pointer to an array containing 4 wallVerts for a sprite @@ -4384,22 +4288,6 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) //Hurdler: 25/04/2000: now support colormap in hardware mode HWR_GetMappedPatch(gpatch, spr->colormap); - // Draw shadow BEFORE sprite - if (cv_shadow.value // Shadows enabled - && (spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow. - && !(spr->mobj->flags2 & MF2_DEBRIS) // Debris have no corona or shadow. -#ifdef ALAM_LIGHTING - && !(t_lspr[spr->mobj->sprite]->type // Things with dynamic lights have no shadow. - && (!spr->mobj->player || spr->mobj->player->powers[pw_super])) // Except for non-super players. -#endif - && (spr->mobj->z >= spr->mobj->floorz)) // Without this, your shadow shows on the floor, even after you die and fall through the ground. - { - //////////////////// - // SHADOW SPRITE! // - //////////////////// - HWR_DrawSpriteShadow(spr, gpatch, this_scale); - } - baseWallVerts[0].x = baseWallVerts[3].x = spr->x1; baseWallVerts[2].x = baseWallVerts[1].x = spr->x2; baseWallVerts[0].z = baseWallVerts[3].z = spr->z1; @@ -4802,22 +4690,6 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) //Hurdler: 25/04/2000: now support colormap in hardware mode HWR_GetMappedPatch(gpatch, spr->colormap); - // Draw shadow BEFORE sprite - if (cv_shadow.value // Shadows enabled - && (spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow. - && !(spr->mobj->flags2 & MF2_DEBRIS) // Debris have no corona or shadow. -#ifdef ALAM_LIGHTING - && !(t_lspr[spr->mobj->sprite]->type // Things with dynamic lights have no shadow. - && (!spr->mobj->player || spr->mobj->player->powers[pw_super])) // Except for non-super players. -#endif - && (spr->mobj->z >= spr->mobj->floorz)) // Without this, your shadow shows on the floor, even after you die and fall through the ground. - { - //////////////////// - // SHADOW SPRITE! // - //////////////////// - HWR_DrawSpriteShadow(spr, gpatch, this_scale); - } - // if it has a dispoffset, push it a little towards the camera if (spr->dispoffset) { float co = -gr_viewcos*(0.05f*spr->dispoffset); @@ -5430,6 +5302,12 @@ static void HWR_DrawSprites(void) HWR_DrawPrecipitationSprite(spr); else #endif + { + if (spr->mobj && spr->mobj->shadowscale && cv_shadow.value) + { + HWR_DrawDropShadow(spr->mobj, spr->mobj->shadowscale); + } + if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { // 8/1/19: Only don't display player models if no default SPR_PLAY is found. @@ -5445,6 +5323,7 @@ static void HWR_DrawSprites(void) else HWR_DrawMD2(spr); } + } } } } @@ -5882,10 +5761,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) // okay, we can't return now... this is a hack, but weather isn't networked, so it should be ok if (!(thing->precipflags & PCF_THUNK)) { - if (thing->precipflags & PCF_RAIN) - P_RainThinker(thing); - else - P_SnowThinker(thing); + P_PrecipThinker(thing); thing->precipflags |= PCF_THUNK; } diff --git a/src/info.c b/src/info.c index 444d79196..b1d95859b 100644 --- a/src/info.c +++ b/src/info.c @@ -44,23 +44,23 @@ char sprnames[NUMSPRITES + 1][5] = "BSZ7","BSZ8","STLG","DBAL","RCRY","ARMA","ARMF","ARMB","WIND","MAGN", "ELEM","FORC","PITY","IVSP","SSPK","GOAL","BIRD","BUNY","MOUS","CHIC", "COWZ","RBRD","SPVY","SPVR","SPVB","SPVG","SPDY","SPDR","SPDB","SPDG", - "SPHY","SPHR","SPHB","SPHG","RAIN","SNO1","SPLH","SPLA","SMOK","BUBP", - "BUBO","BUBN","BUBM","POPP","TFOG","SEED","PRTL","SCOR","DRWN","TTAG", - "GFLG","RRNG","RNGB","RNGR","RNGI","RNGA","RNGE","RNGS","RNGG","PIKB", - "PIKR","PIKA","PIKE","PIKS","PIKG","TAUT","TGRE","TSCR","COIN","CPRK", - "GOOM","BGOM","FFWR","FBLL","SHLL","PUMA","HAMM","KOOP","BFLM","MAXE", - "MUS1","MUS2","TOAD","NDRN","SUPE","SUPZ","NDRL","NSPK","NBMP","HOOP", - "NSCR","NPRU","CAPS","SUPT","SPRK","BOM1","BOM2","BOM3","BOM4","ROIA", - "ROIB","ROIC","ROID","ROIE","ROIF","ROIG","ROIH","ROII","ROIJ","ROIK", - "ROIL","ROIM","ROIN","ROIO","ROIP","BBAL","GWLG","GWLR","SRBA","SRBB", - "SRBC","SRBD","SRBE","SRBF","SRBG","SRBH","SRBI","SRBJ","SRBK","SRBL", - "SRBM","SRBN","SRBO", + "SPHY","SPHR","SPHB","SPHG","RAIN","SNO1","SNO2","SPLH","SPLA","SMOK", + "BUBP","BUBO","BUBN","BUBM","POPP","TFOG","SEED","PRTL","SCOR","DRWN", + "TTAG","GFLG","RRNG","RNGB","RNGR","RNGI","RNGA","RNGE","RNGS","RNGG", + "PIKB","PIKR","PIKA","PIKE","PIKS","PIKG","TAUT","TGRE","TSCR","COIN", + "CPRK","GOOM","BGOM","FFWR","FBLL","SHLL","PUMA","HAMM","KOOP","BFLM", + "MAXE","MUS1","MUS2","TOAD","NDRN","SUPE","SUPZ","NDRL","NSPK","NBMP", + "HOOP","NSCR","NPRU","CAPS","SUPT","SPRK","BOM1","BOM2","BOM3","BOM4", + "ROIA","ROIB","ROIC","ROID","ROIE","ROIF","ROIG","ROIH","ROII","ROIJ", + "ROIK","ROIL","ROIM","ROIN","ROIO","ROIP","BBAL","GWLG","GWLR","SRBA", + "SRBB","SRBC","SRBD","SRBE","SRBF","SRBG","SRBH","SRBI","SRBJ","SRBK", + "SRBL","SRBM","SRBN","SRBO", //SRB2kart Sprites "RNDM","RPOP","SGNS","FAST","DSHR","BOST","BOSM","KFRE","KINV","KINF", "WIPD","DRIF","BDRF","DUST","RSHE","FITM","BANA","ORBN","JAWZ","SSMN", "KRBM","BHOG","BHBM","SPBM","THNS","SINK","SITR","KBLN","DEZL","POKE", "AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM","SACO","CRAB", - "SHAD","BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB","ARRO","ITEM", + "BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB","ARRO","ITEM", "ITMO","ITMI","ITMN","WANT","PBOM","HIT1","HIT2","HIT3","RETI","AIDU", "KSPK","LZI1","LZI2","KLIT","FZSM","FZBM","FPRT","SBUS","MARB","FUFO", "RUST","BLON","VAPE","HTZA","HTZB","SGVA","SGVB","SGVC","PGTR","PGF1", @@ -193,7 +193,7 @@ state_t states[NUMSTATES] = {SPR_NULL, 0, 18, {NULL}, 0, 4, S_NULL}, // S_PLAY_ICON3 // Level end sign (uses player sprite) - {SPR_PLAY, 18, 1, {NULL}, 0, 24, S_PLAY_SIGN}, // S_PLAY_SIGN S + {SPR_PLAY, 18|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_PLAY_SIGN}, // S_PLAY_SIGN // Blue Crawla {SPR_POSS, 0, 5, {A_Look}, 0, 0, S_POSS_STND}, // S_POSS_STND @@ -1063,27 +1063,10 @@ state_t states[NUMSTATES] = {SPR_BUBL, 1, 8, {A_BubbleCheck}, 0, 0, S_BUBBLES1}, // S_BUBBLES2 // Level End Sign - {SPR_SIGN, 0, 1, {NULL}, 0, 0, S_SIGN2}, // S_SIGN1 - {SPR_SIGN, 1, 1, {NULL}, 0, 0, S_SIGN3}, // S_SIGN2 - {SPR_SIGN, 2, 1, {NULL}, 0, 0, S_SIGN4}, // S_SIGN3 - {SPR_SIGN, 3, 1, {NULL}, 0, 0, S_SIGN5}, // S_SIGN4 - {SPR_SIGN, 0, 1, {NULL}, 0, 0, S_SIGN6}, // S_SIGN5 - {SPR_SIGN, 1, 1, {NULL}, 0, 0, S_SIGN7}, // S_SIGN6 - {SPR_SIGN, 2, 1, {NULL}, 0, 0, S_SIGN8}, // S_SIGN7 - {SPR_SIGN, 4, 1, {NULL}, 0, 0, S_SIGN9}, // S_SIGN8 - {SPR_SIGN, 0, 1, {NULL}, 0, 0, S_SIGN10}, // S_SIGN9 - {SPR_SIGN, 1, 1, {NULL}, 0, 0, S_SIGN11}, // S_SIGN10 - {SPR_SIGN, 2, 1, {NULL}, 0, 0, S_SIGN12}, // S_SIGN11 - {SPR_SIGN, 5, 1, {NULL}, 0, 0, S_SIGN13}, // S_SIGN12 - {SPR_SIGN, 0, 1, {NULL}, 0, 0, S_SIGN14}, // S_SIGN13 - {SPR_SIGN, 1, 1, {NULL}, 0, 0, S_SIGN15}, // S_SIGN14 - {SPR_SIGN, 2, 1, {NULL}, 0, 0, S_SIGN16}, // S_SIGN15 - {SPR_SIGN, 6, 1, {NULL}, 0, 0, S_SIGN17}, // S_SIGN16 - {SPR_SIGN, 0, 1, {NULL}, 0, 0, S_SIGN18}, // S_SIGN17 - {SPR_SIGN, 1, 1, {NULL}, 0, 0, S_SIGN19}, // S_SIGN18 - {SPR_SIGN, 2, 1, {NULL}, 0, 0, S_SIGN20}, // S_SIGN19 - {SPR_SIGN, 7, 1, {NULL}, 0, 0, S_SIGN1}, // S_SIGN20 - {SPR_SIGN, 8, -1, {A_SignPlayer}, 0, 0, S_NULL}, // S_SIGN_END + {SPR_SIGN, 0, -1, {NULL}, 0, 0, S_SIGN_POLE}, // S_SIGN_POLE + {SPR_SIGN, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_SIGN_BACK}, // S_SIGN_BACK + {SPR_SIGN, 2|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_SIGN_SIDE}, // S_SIGN_SIDE + {SPR_SIGN, 3|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_SIGN_FACE}, // S_SIGN_FACE // Steam Riser {SPR_STEM, 0, 2, {A_SetSolidSteam}, 0, 0, S_STEAM2}, // S_STEAM1 @@ -1869,13 +1852,18 @@ state_t states[NUMSTATES] = // Rain {SPR_RAIN, FF_TRANS50, -1, {NULL}, 0, 0, S_NULL}, // S_RAIN1 - {SPR_RAIN, FF_TRANS50, 1, {NULL}, 0, 0, S_RAIN1}, // S_RAINRETURN + {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_RAINRETURN // Snowflake {SPR_SNO1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SNOW1 {SPR_SNO1, 1, -1, {NULL}, 0, 0, S_NULL}, // S_SNOW2 {SPR_SNO1, 2, -1, {NULL}, 0, 0, S_NULL}, // S_SNOW3 + // Blizzard Snowball + {SPR_SNO2, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLIZZARDSNOW1 + {SPR_SNO2, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BLIZZARDSNOW2 + {SPR_SNO2, 2, -1, {NULL}, 0, 0, S_NULL}, // S_BLIZZARDSNOW3 + // Water Splish {SPR_SPLH, FF_TRANS50 , 2, {NULL}, 0, 0, S_SPLISH2}, // S_SPLISH1 {SPR_SPLH, FF_TRANS50|1, 2, {NULL}, 0, 0, S_SPLISH3}, // S_SPLISH2 @@ -1888,9 +1876,9 @@ state_t states[NUMSTATES] = {SPR_SPLH, FF_TRANS50|8, 2, {NULL}, 0, 0, S_NULL}, // S_SPLISH9 // Water Splash - {SPR_SPLA, FF_TRANS50 , 3, {NULL}, 0, 0, S_SPLASH2}, // S_SPLASH1 - {SPR_SPLA, FF_TRANS70|1, 3, {NULL}, 0, 0, S_SPLASH3}, // S_SPLASH2 - {SPR_SPLA, FF_TRANS90|2, 3, {NULL}, 0, 0, S_RAINRETURN}, // S_SPLASH3 + {SPR_SPLA, FF_TRANS50 , 3, {NULL}, 0, 0, S_SPLASH2}, // S_SPLASH1 + {SPR_SPLA, FF_TRANS70|1, 3, {NULL}, 0, 0, S_SPLASH3}, // S_SPLASH2 + {SPR_SPLA, FF_TRANS90|2, 3, {NULL}, 0, 0, S_NULL}, // S_SPLASH3 // Smoke {SPR_SMOK, FF_TRANS50 , 4, {NULL}, 0, 0, S_SMOKE2}, // S_SMOKE1 @@ -2993,10 +2981,6 @@ state_t states[NUMSTATES] = {SPR_CRAB, 10, -1, {NULL}, 0, 0, S_NULL}, // S_LAMPPOST {SPR_CRAB, 11, -1, {NULL}, 0, 0, S_NULL}, // S_MOSSYTREE - // Fake Shadow - {SPR_SHAD, FF_TRANS50, -1, {NULL}, 0, 0, S_NULL}, // S_SHADOW - {SPR_SHAD, FF_FULLBRIGHT|FF_TRANS50|1, -1, {NULL}, 0, 0, S_NULL}, // S_WHITESHADOW - {SPR_BUMP, FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_BUMP2}, // S_BUMP1 {SPR_BUMP, FF_FULLBRIGHT|1, 3, {NULL}, 0, 0, S_BUMP3}, // S_BUMP2 {SPR_BUMP, FF_FULLBRIGHT|2, 3, {NULL}, 0, 0, S_NULL}, // S_BUMP3 @@ -6439,7 +6423,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 501, // doomednum S_INVISIBLE, // spawnstate 1000, // spawnhealth - S_PLAY_SIGN, // seestate + S_NULL, // seestate sfx_s3kb8, // seesound 8, // reactiontime sfx_s3k7e, // attacksound @@ -6453,7 +6437,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // deathsound 8, // speed 8*FRACUNIT, // radius - 32*FRACUNIT, // height + 48*FRACUNIT, // height 0, // display offset 16, // mass 0, // damage @@ -6462,6 +6446,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_SIGN_PIECE + -1, // doomednum + S_INVISIBLE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 48*FRACUNIT, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_NOTHINK|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + { // MT_SPIKEBALL -1, // doomednum S_SPIKEBALL1, // spawnstate @@ -11443,22 +11454,22 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_RAIN1, // spawnstate 1000, // spawnhealth S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime + sfx_rainin, // seesound + 0, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_NULL, // deathstate + S_SPLASH1, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound -72*FRACUNIT, // speed -- -24*FRACUNIT originally, srb2kart x3 (nya) 1*FRACUNIT, // radius 8*FRACUNIT, // height 0, // display offset - 4, // mass + 80, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP, // flags @@ -11471,7 +11482,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound - 8, // reactiontime + 0, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance @@ -11485,8 +11496,35 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 4*FRACUNIT, // radius 4*FRACUNIT, // height 0, // display offset - 4, // mass - 0, // damage + 0, // mass + 2, // damage + sfx_None, // activesound + MF_NOBLOCKMAP, // flags + S_NULL // raisestate + }, + + { // MT_BLIZZARDSNOW + -1, // doomednum + S_BLIZZARDSNOW1, // 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_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + -24*FRACUNIT, // speed + 4*FRACUNIT, // radius + 4*FRACUNIT, // height + 0, // display offset + 0, // mass + 2, // damage sfx_None, // activesound MF_NOBLOCKMAP, // flags S_NULL // raisestate @@ -17256,33 +17294,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_SHADOW - -1, // doomednum - S_SHADOW, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 60*FRACUNIT, // speed - 50*FRACUNIT, // radius - 1*FRACUNIT, // height - -1, // display offset - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags - S_NULL // raisestate - }, - { // MT_BUMP -1, // doomednum S_BUMP1, // spawnstate diff --git a/src/info.h b/src/info.h index f47a4a151..c1eacfd31 100644 --- a/src/info.h +++ b/src/info.h @@ -63,7 +63,6 @@ void A_ThrownRing(); // Sparkle trail for red ring void A_GrenadeRing(); // SRB2kart void A_SetSolidSteam(); void A_UnsetSolidSteam(); -void A_SignPlayer(); void A_OverlayThink(); void A_JetChase(); void A_JetbThink(); // Jetty-Syn Bomber Thinker @@ -475,6 +474,7 @@ typedef enum sprite // Environmental Effects SPR_RAIN, // Rain SPR_SNO1, // Snowflake + SPR_SNO2, // Blizzard Snowball SPR_SPLH, // Water Splish SPR_SPLA, // Water Splash SPR_SMOK, @@ -639,7 +639,6 @@ typedef enum sprite SPR_CHOM, // Sapphire Coast Chomper SPR_SACO, // Sapphire Coast Fauna SPR_CRAB, // Crystal Abyss mobs - SPR_SHAD, // TD shadows SPR_BRNG, // Chaotix Big Ring SPR_BUMP, // Player/shell bump @@ -1776,27 +1775,10 @@ typedef enum state S_BUBBLES2, // Level End Sign - S_SIGN1, - S_SIGN2, - S_SIGN3, - S_SIGN4, - S_SIGN5, - S_SIGN6, - S_SIGN7, - S_SIGN8, - S_SIGN9, - S_SIGN10, - S_SIGN11, - S_SIGN12, - S_SIGN13, - S_SIGN14, - S_SIGN15, - S_SIGN16, - S_SIGN17, - S_SIGN18, - S_SIGN19, - S_SIGN20, - S_SIGN_END, + S_SIGN_POLE, + S_SIGN_BACK, + S_SIGN_SIDE, + S_SIGN_FACE, // Steam Riser S_STEAM1, @@ -2579,6 +2561,11 @@ typedef enum state S_SNOW2, S_SNOW3, + // Blizzard Snowball + S_BLIZZARDSNOW1, + S_BLIZZARDSNOW2, + S_BLIZZARDSNOW3, + // Water Splish S_SPLISH1, S_SPLISH2, @@ -3673,9 +3660,6 @@ typedef enum state S_LAMPPOST, S_MOSSYTREE, - S_SHADOW, - S_WHITESHADOW, - S_BUMP1, S_BUMP2, S_BUMP3, @@ -4289,6 +4273,7 @@ typedef enum mobj_type // Interactive Objects MT_BUBBLES, // Bubble source MT_SIGN, // Level end sign + MT_SIGN_PIECE, MT_SPIKEBALL, // Spike Ball MT_SPECIALSPIKEBALL, MT_SPINFIRE, @@ -4515,6 +4500,7 @@ typedef enum mobj_type // Environmental Effects MT_RAIN, // Rain MT_SNOWFLAKE, // Snowflake + MT_BLIZZARDSNOW, // Blizzard Snowball MT_SPLISH, // Water splish! MT_SMOKE, MT_SMALLBUBBLE, // small bubble @@ -4775,8 +4761,6 @@ typedef enum mobj_type MT_LAMPPOST, MT_MOSSYTREE, - MT_SHADOW, - MT_BUMP, MT_FLINGENERGY, diff --git a/src/k_kart.c b/src/k_kart.c index 853f50a93..e3b674f33 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1543,20 +1543,16 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) \return boolean */ -static UINT8 K_CheckOffroadCollide(mobj_t *mo, sector_t *sec) +static UINT8 K_CheckOffroadCollide(mobj_t *mo) { UINT8 i; - sector_t *sec2; I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); - sec2 = P_ThingOnSpecial3DFloor(mo); - for (i = 2; i < 5; i++) { - if ((sec2 && GETSECSPECIAL(sec2->special, 1) == i) - || (P_IsObjectOnRealGround(mo, sec) && GETSECSPECIAL(sec->special, 1) == i)) + if (P_MobjTouchingSectorSpecial(mo, 1, i, true)) return i-1; } @@ -1571,25 +1567,16 @@ static UINT8 K_CheckOffroadCollide(mobj_t *mo, sector_t *sec) */ static void K_UpdateOffroad(player_t *player) { - fixed_t offroad; - sector_t *nextsector = R_PointInSubsector( - player->mo->x + player->mo->momx*2, player->mo->y + player->mo->momy*2)->sector; - UINT8 offroadstrength = K_CheckOffroadCollide(player->mo, nextsector); + fixed_t offroadstrength = (K_CheckOffroadCollide(player->mo) << FRACBITS); // If you are in offroad, a timer starts. if (offroadstrength) { - if (K_CheckOffroadCollide(player->mo, player->mo->subsector->sector) && player->kartstuff[k_offroad] == 0) - player->kartstuff[k_offroad] = TICRATE; + if (player->kartstuff[k_offroad] < offroadstrength) + player->kartstuff[k_offroad] += offroadstrength / TICRATE; - if (player->kartstuff[k_offroad] > 0) - { - offroad = (offroadstrength << FRACBITS) / TICRATE; - player->kartstuff[k_offroad] += offroad; - } - - if (player->kartstuff[k_offroad] > (offroadstrength << FRACBITS)) - player->kartstuff[k_offroad] = (offroadstrength << FRACBITS); + if (player->kartstuff[k_offroad] > offroadstrength) + player->kartstuff[k_offroad] = offroadstrength; } else player->kartstuff[k_offroad] = 0; @@ -4593,6 +4580,167 @@ void K_RepairOrbitChain(mobj_t *orbit) } } +// Simplified version of a code bit in P_MobjFloorZ +static fixed_t K_BananaSlopeZ(pslope_t *slope, fixed_t x, fixed_t y, fixed_t radius, boolean ceiling) +{ + fixed_t testx, testy; + + if (slope->d.x < 0) + testx = radius; + else + testx = -radius; + + if (slope->d.y < 0) + testy = radius; + else + testy = -radius; + + if ((slope->zdelta > 0) ^ !!(ceiling)) + { + testx = -testx; + testy = -testy; + } + + testx += x; + testy += y; + + return P_GetZAt(slope, testx, testy); +} + +static void K_CalculateBananaSlope(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z, fixed_t radius, fixed_t height, boolean flip, boolean player) +{ + fixed_t newz; + sector_t *sec; +#ifdef ESLOPE + pslope_t *slope = NULL; +#endif + + sec = R_PointInSubsector(x, y)->sector; + + if (flip) + { +#ifdef ESLOPE + if (sec->c_slope) + { + slope = sec->c_slope; + newz = K_BananaSlopeZ(slope, x, y, radius, true); + } + else +#endif + newz = sec->ceilingheight; + } + else + { +#ifdef ESLOPE + if (sec->f_slope) + { + slope = sec->f_slope; + newz = K_BananaSlopeZ(slope, x, y, radius, false); + } + else +#endif + newz = sec->floorheight; + } + + // Check FOFs for a better suited slope + if (sec->ffloors) + { + ffloor_t *rover; + + for (rover = sec->ffloors; rover; rover = rover->next) + { + fixed_t top, bottom; + fixed_t d1, d2; + + if (!(rover->flags & FF_EXISTS)) + continue; + + if ((!(((rover->flags & FF_BLOCKPLAYER && player) + || (rover->flags & FF_BLOCKOTHERS && !player)) + || (rover->flags & FF_QUICKSAND)) + || (rover->flags & FF_SWIMMABLE))) + continue; + +#ifdef ESLOPE + if (*rover->t_slope) + top = K_BananaSlopeZ(*rover->t_slope, x, y, radius, false); + else +#endif + top = *rover->topheight; + +#ifdef ESLOPE + if (*rover->b_slope) + bottom = K_BananaSlopeZ(*rover->b_slope, x, y, radius, true); + else +#endif + bottom = *rover->bottomheight; + + if (flip) + { + if (rover->flags & FF_QUICKSAND) + { + if (z < top && (z + height) > bottom) + { + if (newz > (z + height)) + { + newz = (z + height); + slope = NULL; + } + } + continue; + } + + d1 = (z + height) - (top + ((bottom - top)/2)); + d2 = z - (top + ((bottom - top)/2)); + + if (bottom < newz && abs(d1) < abs(d2)) + { + newz = bottom; +#ifdef ESLOPE + if (*rover->b_slope) + slope = *rover->b_slope; +#endif + } + } + else + { + if (rover->flags & FF_QUICKSAND) + { + if (z < top && (z + height) > bottom) + { + if (newz < z) + { + newz = z; + slope = NULL; + } + } + continue; + } + + d1 = z - (bottom + ((top - bottom)/2)); + d2 = (z + height) - (bottom + ((top - bottom)/2)); + + if (top > newz && abs(d1) < abs(d2)) + { + newz = top; +#ifdef ESLOPE + if (*rover->t_slope) + slope = *rover->t_slope; +#endif + } + } + } + } + +#if 0 + mobj->standingslope = slope; +#endif + +#ifdef HWRENDER + mobj->modeltilt = slope; +#endif +} + // Move the hnext chain! static void K_MoveHeldObjects(player_t *player) { @@ -4780,8 +4928,7 @@ static void K_MoveHeldObjects(player_t *player) #ifdef ESLOPE if (P_IsObjectOnGround(cur)) { - // Slope values are set in the function, but we DON'T want to use its return value. - P_CalculateShadowFloor(cur, cur->x, cur->y, cur->z, + K_CalculateBananaSlope(cur, cur->x, cur->y, cur->z, cur->radius, cur->height, (cur->eflags & MFE_VERTICALFLIP), false); } #endif @@ -6602,6 +6749,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) P_SetMobjState(ring, S_FASTRING1); ring->extravalue1 = 1; // Ring use animation timer ring->extravalue2 = 1; // Ring use animation flag + ring->shadowscale = 0; P_SetTarget(&ring->target, player->mo); // user player->kartstuff[k_rings]--; player->kartstuff[k_ringdelay] = 3; @@ -7159,7 +7307,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } } - K_KartDrift(player, onground); + K_KartDrift(player, P_IsObjectOnGround(player->mo)); // Not using onground, since we don't want this affected by spring pads // Quick Turning // You can't turn your kart when you're not moving. @@ -7633,6 +7781,9 @@ static patch_t *kp_lapanim_hand[3]; static patch_t *kp_yougotem; static patch_t *kp_itemminimap; +static patch_t *kp_alagles[10]; +static patch_t *kp_blagles[6]; + void K_LoadKartHUDGraphics(void) { INT32 i, j; @@ -7935,6 +8086,20 @@ void K_LoadKartHUDGraphics(void) kp_yougotem = (patch_t *) W_CachePatchName("YOUGOTEM", PU_HUDGFX); kp_itemminimap = (patch_t *) W_CachePatchName("MMAPITEM", PU_HUDGFX); + + sprintf(buffer, "ALAGLESx"); + for (i = 0; i < 10; ++i) + { + buffer[7] = '0'+i; + kp_alagles[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } + + sprintf(buffer, "BLAGLESx"); + for (i = 0; i < 6; ++i) + { + buffer[7] = '0'+i; + kp_blagles[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } } // For the item toggle menu @@ -8907,9 +9072,11 @@ static boolean K_drawKartPositionFaces(void) // void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol) { + static tic_t alagles_timer = 9; INT32 i, rightoffset = 240; const UINT8 *colormap; INT32 dupadjust = (vid.width/vid.dupx), duptweak = (dupadjust - BASEVIDWIDTH)/2; + int y2; //this function is designed for 9 or less score lines only //I_Assert(scorelines <= 9); -- not today bitch, kart fixed it up @@ -8930,15 +9097,39 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I continue; //ignore them. if (netgame // don't draw it offline - && tab[i].num != serverplayer) + && ( tab[i].num != serverplayer || ! server_lagless )) HU_drawPing(x + ((i < 8) ? -17 : rightoffset + 11), y-4, playerpingtable[tab[i].num], 0); STRBUFCPY(strtime, tab[i].name); + y2 = y; + + if (tab[i].num == 0 && server_lagless) + { + y2 = ( y - 4 ); + + V_DrawScaledPatch(x + 20, y2, 0, kp_blagles[(leveltime / 3) % 6]); + // every 70 tics + if (( leveltime % 70 ) == 0) + { + alagles_timer = 9; + } + if (alagles_timer > 0) + { + V_DrawScaledPatch(x + 20, y2, 0, kp_alagles[alagles_timer]); + if (( leveltime % 2 ) == 0) + alagles_timer--; + } + else + V_DrawScaledPatch(x + 20, y2, 0, kp_alagles[0]); + + y2 += SHORT (kp_alagles[0]->height) + 1; + } + if (scorelines > 8) - V_DrawThinString(x + 20, y, ((tab[i].num == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, strtime); + V_DrawThinString(x + 20, y2, ((tab[i].num == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, strtime); else - V_DrawString(x + 20, y, ((tab[i].num == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE, strtime); + V_DrawString(x + 20, y2, ((tab[i].num == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE, strtime); if (players[tab[i].num].mo->color) { diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 7464743c3..3288219cd 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -639,16 +639,6 @@ static int lib_pCheckSolidLava(lua_State *L) return 1; } -static int lib_pSpawnShadowMobj(lua_State *L) -{ - mobj_t *caster = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - NOHUD - if (!caster) - return LUA_ErrInvalid(L, "mobj_t"); - P_SpawnShadowMobj(caster); - return 0; -} - // P_USER //////////// @@ -1313,15 +1303,16 @@ static int lib_pExplodeMissile(lua_State *L) return 0; } -static int lib_pPlayerTouchingSectorSpecial(lua_State *L) +static int lib_pMobjTouchingSectorSpecial(lua_State *L) { - player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); INT32 section = (INT32)luaL_checkinteger(L, 2); INT32 number = (INT32)luaL_checkinteger(L, 3); + boolean touchground = lua_optboolean(L, 4); //HUDSAFE - if (!player) - return LUA_ErrInvalid(L, "player_t"); - LUA_PushUserdata(L, P_PlayerTouchingSectorSpecial(player, section, number), META_SECTOR); + if (!mo) + return LUA_ErrInvalid(L, "mobj_t"); + LUA_PushUserdata(L, P_MobjTouchingSectorSpecial(mo, section, number, touchground), META_SECTOR); return 1; } @@ -2672,7 +2663,6 @@ static luaL_Reg lib[] = { {"P_InsideANonSolidFFloor",lib_pInsideANonSolidFFloor}, {"P_CheckDeathPitCollide",lib_pCheckDeathPitCollide}, {"P_CheckSolidLava",lib_pCheckSolidLava}, - {"P_SpawnShadowMobj",lib_pSpawnShadowMobj}, // p_user {"P_GetPlayerHeight",lib_pGetPlayerHeight}, @@ -2736,7 +2726,7 @@ static luaL_Reg lib[] = { {"P_SetMobjStateNF",lib_pSetMobjStateNF}, {"P_DoSuperTransformation",lib_pDoSuperTransformation}, {"P_ExplodeMissile",lib_pExplodeMissile}, - {"P_PlayerTouchingSectorSpecial",lib_pPlayerTouchingSectorSpecial}, + {"P_MobjTouchingSectorSpecial",lib_pMobjTouchingSectorSpecial}, {"P_FindSpecialLineFromTag",lib_pFindSpecialLineFromTag}, {"P_SwitchWeather",lib_pSwitchWeather}, {"P_LinedefExecute",lib_pLinedefExecute}, diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index dfb344e34..47efd729f 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -85,7 +85,9 @@ enum mobj_e { #ifdef ESLOPE mobj_standingslope, #endif - mobj_colorized + mobj_colorized, + mobj_shadowscale, + mobj_whiteshadow }; static const char *const mobj_opt[] = { @@ -149,6 +151,8 @@ static const char *const mobj_opt[] = { "standingslope", #endif "colorized", + "shadowscale", + "whiteshadow", NULL}; #define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field]) @@ -360,6 +364,12 @@ static int mobj_get(lua_State *L) case mobj_colorized: lua_pushboolean(L, mo->colorized); break; + case mobj_shadowscale: + lua_pushfixed(L, mo->shadowscale); + break; + case mobj_whiteshadow: + lua_pushboolean(L, mo->whiteshadow); + break; default: // extra custom variables in Lua memory lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); @@ -677,6 +687,12 @@ static int mobj_set(lua_State *L) case mobj_colorized: mo->colorized = luaL_checkboolean(L, 3); break; + case mobj_shadowscale: + mo->shadowscale = luaL_checkfixed(L, 3); + break; + case mobj_whiteshadow: + mo->whiteshadow = luaL_checkboolean(L, 3); + break; default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); diff --git a/src/p_enemy.c b/src/p_enemy.c index 03eea951b..521d44b1b 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -118,7 +118,6 @@ void A_ThrownRing(mobj_t *actor); void A_GrenadeRing(mobj_t *actor); void A_SetSolidSteam(mobj_t *actor); void A_UnsetSolidSteam(mobj_t *actor); -void A_SignPlayer(mobj_t *actor); void A_OverlayThink(mobj_t *actor); void A_JetChase(mobj_t *actor); void A_JetbThink(mobj_t *actor); @@ -4181,38 +4180,6 @@ void A_UnsetSolidSteam(mobj_t *actor) actor->flags |= MF_NOCLIP; } -// Function: A_SignPlayer -// -// Description: Changes the state of a level end sign to reflect the player that hit it. -// -// var1 = unused -// var2 = unused -// -void A_SignPlayer(mobj_t *actor) -{ - mobj_t *ov; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SignPlayer", actor)) - return; -#endif - if (!actor->target) - return; - - if (!actor->target->player) - return; - - // Set the sign to be an appropriate background color for this player's skincolor. - actor->color = KartColor_Opposite[actor->target->player->skincolor*2]; - actor->frame += KartColor_Opposite[actor->target->player->skincolor*2+1]; - - // spawn an overlay of the player's face. - ov = P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY); - P_SetTarget(&ov->target, actor); - ov->color = actor->target->player->skincolor; - ov->skin = &skins[actor->target->player->skin]; - P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN -} - // Function: A_OverlayThink // // Description: Moves the overlay to the position of its target. diff --git a/src/p_floor.c b/src/p_floor.c index ccbfd6eae..737a8810b 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1769,6 +1769,7 @@ static mobj_t *SearchMarioNode(msecnode_t *node) case MT_SUPERSPARK: case MT_RAIN: case MT_SNOWFLAKE: + case MT_BLIZZARDSNOW: case MT_SPLISH: case MT_SMOKE: case MT_SMALLBUBBLE: @@ -2275,7 +2276,7 @@ void T_EachTimeThinker(levelspecthink_t *eachtime) continue; if (!(players[i].mo->subsector->sector == sec - || P_PlayerTouchingSectorSpecial(&players[i], 2, (GETSECSPECIAL(sec->special, 2))) == sec)) + || P_MobjTouchingSectorSpecial(players[i].mo, 2, (GETSECSPECIAL(sec->special, 2)), false) == sec)) continue; if (floortouch == true && P_IsObjectOnRealGround(players[i].mo, sec)) diff --git a/src/p_inter.c b/src/p_inter.c index b370682f1..905cf1c1f 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -925,7 +925,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->fuse = 1; special->flags2 |= MF2_JUSTATTACKED; - if (!P_PlayerTouchingSectorSpecial(player, 4, 2 + flagteam)) + if (!P_MobjTouchingSectorSpecial(player->mo, 4, 2 + flagteam, false)) { CONS_Printf(M_GetText("%s returned the %c%s%c to base.\n"), plname, flagcolor, flagtext, 0x80); @@ -2145,6 +2145,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SPECIAL); target->flags2 &= ~(MF2_SKULLFLY|MF2_NIGHTSPULL); target->health = 0; // This makes it easy to check if something's dead elsewhere. + target->shadowscale = 0; #ifdef HAVE_BLUA if (LUAh_MobjDeath(target, inflictor, source) || P_MobjWasRemoved(target)) diff --git a/src/p_local.h b/src/p_local.h index dde84d4f0..23760eaef 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -215,8 +215,6 @@ void P_RespawnSpecials(void); mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type); -mobj_t *P_SpawnShadowMobj(mobj_t * caster); - void P_RecalcPrecipInSector(sector_t *sector); void P_PrecipitationEffects(void); @@ -227,8 +225,6 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state); boolean P_SetMobjState(mobj_t *mobj, statenum_t state); //void P_RunShields(void); void P_RunOverlays(void); -fixed_t P_CalculateShadowFloor(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z, fixed_t radius, fixed_t height, boolean flip, boolean player); -void P_RunShadows(void); void P_RunBattleOvertime(void); void P_MobjThinker(mobj_t *mobj); boolean P_RailThinker(mobj_t *mobj); diff --git a/src/p_map.c b/src/p_map.c index 521a1302f..1ddbbc10a 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2933,28 +2933,15 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) const fixed_t maxstepmove = FixedMul(MAXSTEPMOVE, mapobjectscale); fixed_t maxstep = maxstepmove; - if (thing->player) - { - if (thing->player->kartstuff[k_waterskip]) - maxstep += maxstepmove; // Force some stepmove when waterskipping + if (thing->player && thing->player->kartstuff[k_waterskip]) + maxstep += maxstepmove; // Add some extra stepmove when waterskipping - // If using type Section1:13, double the maxstep. - if (P_PlayerTouchingSectorSpecial(thing->player, 1, 13) - || GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 13) - maxstep += maxstepmove; - // If using type Section1:12, no maxstep. For ledges you don't want the player to climb! (see: Egg Zeppelin & SMK port walls) - else if (P_PlayerTouchingSectorSpecial(thing->player, 1, 12) - || GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 12) - maxstep -= maxstepmove; - - // Don't 'step up' while springing, - // Only step up "if needed". - /* // SRB2kart - don't need - if (thing->state == &states[S_PLAY_SPRING] - && P_MobjFlip(thing)*thing->momz > FixedMul(FRACUNIT, thing->scale)) - maxstep = 0; - */ - } + // 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; @@ -2977,12 +2964,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) return false; // mobj must lower itself to fit // Ramp test - if (maxstep > 0 && !( - thing->player && ( - P_PlayerTouchingSectorSpecial(thing->player, 1, 14) - || GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 14) - ) - ) + if ((maxstep > 0) && !(P_MobjTouchingSectorSpecial(thing, 1, 14, false))) { // If the floor difference is MAXSTEPMOVE or less, and the sector isn't Section1:14, ALWAYS // step down! Formerly required a Section1:13 sector for the full MAXSTEPMOVE, but no more. diff --git a/src/p_mobj.c b/src/p_mobj.c index 325229de8..4ef291c82 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -47,7 +47,6 @@ consvar_t cv_splats = {"splats", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0 actioncache_t actioncachehead; static mobj_t *overlaycap = NULL; -static mobj_t *shadowcap = NULL; mobj_t *kitemcap = NULL; // Used for Kart offensive items (the ones that can get removed by sizedown) mobj_t *waypointcap = NULL; @@ -1330,9 +1329,6 @@ fixed_t P_GetMobjGravity(mobj_t *mo) case MT_JAWZ_DUD: gravityadd = (5*gravityadd)/2; break; - case MT_SIGN: - gravityadd /= 8; - break; case MT_KARMAFIREWORK: gravityadd /= 3; break; @@ -3724,11 +3720,15 @@ static void P_PlayerMobjThinker(mobj_t *mobj) mobj->z += mobj->momz; P_SetThingPosition(mobj); P_CheckPosition(mobj, mobj->x, mobj->y); + mobj->floorz = tmfloorz; + mobj->ceilingz = tmceilingz; goto animonly; } else if (mobj->player->pflags & PF_MACESPIN && mobj->tracer) { P_CheckPosition(mobj, mobj->x, mobj->y); + mobj->floorz = tmfloorz; + mobj->ceilingz = tmceilingz; goto animonly; } @@ -3922,51 +3922,60 @@ void P_NullPrecipThinker(precipmobj_t *mobj) mobj->precipflags &= ~PCF_THUNK; } -void P_SnowThinker(precipmobj_t *mobj) +void P_PrecipThinker(precipmobj_t *mobj) { P_CycleStateAnimation((mobj_t *)mobj); - // adjust height - if ((mobj->z += mobj->momz) <= mobj->floorz) - mobj->z = mobj->ceilingz; -} - -void P_RainThinker(precipmobj_t *mobj) -{ - P_CycleStateAnimation((mobj_t *)mobj); - - if (mobj->state != &states[S_RAIN1]) + if (mobj->state == &states[S_RAINRETURN]) { - // cycle through states, - // calling action functions at transitions - if (mobj->tics <= 0) - return; - - if (--mobj->tics) - return; - - if (!P_SetPrecipMobjState(mobj, mobj->state->nextstate)) - return; - - if (mobj->state != &states[S_RAINRETURN]) - return; - + // Reset to ceiling! + P_SetPrecipMobjState(mobj, mobj->info->spawnstate); mobj->z = mobj->ceilingz; - P_SetPrecipMobjState(mobj, S_RAIN1); - - return; + mobj->momz = mobj->info->speed; + mobj->precipflags &= ~PCF_SPLASH; } + if (mobj->tics != -1) + { + if (mobj->tics) + { + mobj->tics--; + } + + if (mobj->tics == 0) + { + if ((mobj->precipflags & PCF_SPLASH) && (mobj->state->nextstate == S_NULL)) + { + // HACK: sprite changes are 1 tic late, so you would see splashes on the ceiling if not for this state. + // We need to use the settings from the previous state, since some of those are NOT 1 tic late. + INT32 frame = (mobj->frame & ~FF_FRAMEMASK); + P_SetPrecipMobjState(mobj, S_RAINRETURN); + mobj->frame = frame; + return; + } + else + { + if (!P_SetPrecipMobjState(mobj, mobj->state->nextstate)) + return; + } + } + } + + if (mobj->precipflags & PCF_SPLASH) + return; + // adjust height if ((mobj->z += mobj->momz) <= mobj->floorz) { - // no splashes on sky or bottomless pits - if (mobj->precipflags & PCF_PIT) + if ((mobj->info->deathstate == S_NULL) || (mobj->precipflags & PCF_PIT)) // no splashes on sky or bottomless pits + { mobj->z = mobj->ceilingz; + } else { + P_SetPrecipMobjState(mobj, mobj->info->deathstate); mobj->z = mobj->floorz; - P_SetPrecipMobjState(mobj, S_SPLASH1); + mobj->precipflags |= PCF_SPLASH; } } } @@ -6259,287 +6268,6 @@ static void P_RemoveOverlay(mobj_t *thing) } } -// Simplified version of a code bit in P_MobjFloorZ -static fixed_t P_ShadowSlopeZ(pslope_t *slope, fixed_t x, fixed_t y, fixed_t radius, boolean ceiling) -{ - fixed_t testx, testy; - - if (slope->d.x < 0) - testx = radius; - else - testx = -radius; - - if (slope->d.y < 0) - testy = radius; - else - testy = -radius; - - if ((slope->zdelta > 0) ^ !!(ceiling)) - { - testx = -testx; - testy = -testy; - } - - testx += x; - testy += y; - - return P_GetZAt(slope, testx, testy); -} - -// Sets standingslope/modeltilt, returns z position for shadows; used also for stuff like bananas -// (I would've preferred to be able to return both the slope & z, but I'll take what I can get...) -fixed_t P_CalculateShadowFloor(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z, fixed_t radius, fixed_t height, boolean flip, boolean player) -{ - fixed_t newz; - sector_t *sec; -#ifdef ESLOPE - pslope_t *slope = NULL; -#endif - - sec = R_PointInSubsector(x, y)->sector; - - if (flip) - { -#ifdef ESLOPE - if (sec->c_slope) - { - slope = sec->c_slope; - newz = P_ShadowSlopeZ(slope, x, y, radius, true); - } - else -#endif - newz = sec->ceilingheight; - } - else - { -#ifdef ESLOPE - if (sec->f_slope) - { - slope = sec->f_slope; - newz = P_ShadowSlopeZ(slope, x, y, radius, false); - } - else -#endif - newz = sec->floorheight; - } - - // Check FOFs for a better suited slope - if (sec->ffloors) - { - ffloor_t *rover; - - for (rover = sec->ffloors; rover; rover = rover->next) - { - fixed_t top, bottom; - fixed_t d1, d2; - - if (!(rover->flags & FF_EXISTS)) - continue; - - if ((!(((rover->flags & FF_BLOCKPLAYER && player) - || (rover->flags & FF_BLOCKOTHERS && !player)) - || (rover->flags & FF_QUICKSAND)) - || (rover->flags & FF_SWIMMABLE))) - continue; - -#ifdef ESLOPE - if (*rover->t_slope) - top = P_ShadowSlopeZ(*rover->t_slope, x, y, radius, false); - else -#endif - top = *rover->topheight; - -#ifdef ESLOPE - if (*rover->b_slope) - bottom = P_ShadowSlopeZ(*rover->b_slope, x, y, radius, true); - else -#endif - bottom = *rover->bottomheight; - - if (flip) - { - if (rover->flags & FF_QUICKSAND) - { - if (z < top && (z + height) > bottom) - { - if (newz > (z + height)) - { - newz = (z + height); - slope = NULL; - } - } - continue; - } - - d1 = (z + height) - (top + ((bottom - top)/2)); - d2 = z - (top + ((bottom - top)/2)); - - if (bottom < newz && abs(d1) < abs(d2)) - { - newz = bottom; -#ifdef ESLOPE - if (*rover->b_slope) - slope = *rover->b_slope; -#endif - } - } - else - { - if (rover->flags & FF_QUICKSAND) - { - if (z < top && (z + height) > bottom) - { - if (newz < z) - { - newz = z; - slope = NULL; - } - } - continue; - } - - d1 = z - (bottom + ((top - bottom)/2)); - d2 = (z + height) - (bottom + ((top - bottom)/2)); - - if (top > newz && abs(d1) < abs(d2)) - { - newz = top; -#ifdef ESLOPE - if (*rover->t_slope) - slope = *rover->t_slope; -#endif - } - } - } - } - -#if 0 - mobj->standingslope = slope; -#endif -#ifdef HWRENDER - mobj->modeltilt = slope; -#endif - - return newz; -} - -void P_RunShadows(void) -{ - mobj_t *mobj, *next, *dest; - - for (mobj = shadowcap; mobj; mobj = next) - { - boolean flip; - fixed_t newz; - - next = mobj->hnext; - P_SetTarget(&mobj->hnext, NULL); - - if (!mobj->target || P_MobjWasRemoved(mobj->target)) - { - mobj->flags2 |= MF2_DONTDRAW; - continue; // shouldn't you already be dead? - } - - K_MatchGenericExtraFlags(mobj, mobj->target); - flip = (mobj->eflags & MFE_VERTICALFLIP); - - newz = P_CalculateShadowFloor(mobj, mobj->target->x, mobj->target->y, mobj->target->z, - mobj->target->radius, mobj->target->height, flip, (mobj->target->player != NULL)); - - if (flip) - { - if ((mobj->target->z + mobj->target->height) > newz) - mobj->flags2 |= MF2_DONTDRAW; - } - else - { - if (mobj->target->z < newz) - mobj->flags2 |= MF2_DONTDRAW; - } - - // First scale to the same radius - P_SetScale(mobj, FixedDiv(mobj->target->radius, mobj->info->radius)); - - dest = mobj->target; - - if (dest->type == MT_THUNDERSHIELD) - dest = dest->target; - - P_TeleportMove(mobj, dest->x, dest->y, mobj->target->z); - - if ((flip && newz > (mobj->z + mobj->height)) || (!flip && newz < mobj->z)) - { - INT32 i; - fixed_t prevz; - - mobj->z = newz; - - for (i = 0; i < MAXFFLOORS; i++) - { - prevz = mobj->z; - - // Now scale again based on height difference - P_SetScale(mobj, FixedDiv(mobj->scale, max(FRACUNIT, ((mobj->target->z-mobj->z)/200)+FRACUNIT))); - - // Check new position to see if you should still be on that ledge - P_TeleportMove(mobj, dest->x, dest->y, mobj->z); - - mobj->z = newz; - - if (mobj->z == prevz) - break; - } - } - - if (mobj->target->type == MT_FLOATINGITEM) - P_SetScale(mobj, mobj->scale/3); - } - P_SetTarget(&shadowcap, NULL); -} - -// called whenever shadows think -// It must be done this way so that level changes don't break when the shadowcap can't be reset -static void P_AddShadow(mobj_t *thing) -{ - I_Assert(thing != NULL); - - if (shadowcap == NULL) - P_SetTarget(&shadowcap, thing); - else { - mobj_t *mo; - for (mo = shadowcap; mo && mo->hnext; mo = mo->hnext) - ; - - I_Assert(mo != NULL); - I_Assert(mo->hnext == NULL); - - P_SetTarget(&mo->hnext, thing); - } - P_SetTarget(&thing->hnext, NULL); -} - -// Called only when MT_SHADOW (or anything else in the shadowcap list) is removed. -// Keeps the hnext list from corrupting. -static void P_RemoveShadow(mobj_t *thing) -{ - mobj_t *mo; - if (shadowcap == thing) - { - P_SetTarget(&shadowcap, thing->hnext); - P_SetTarget(&thing->hnext, NULL); - return; - } - - for (mo = shadowcap; mo; mo = mo->hnext) - if (mo->hnext == thing) - { - P_SetTarget(&mo->hnext, thing->hnext); - P_SetTarget(&thing->hnext, NULL); - return; - } -} - // SAL'S KART BATTLE MODE OVERTIME HANDLER #define MAXPLANESPERSECTOR (MAXFFLOORS+1)*2 static void P_SpawnOvertimeParticles(fixed_t x, fixed_t y, fixed_t scale, mobjtype_t type, boolean ceiling) @@ -6960,15 +6688,6 @@ void P_MobjThinker(mobj_t *mobj) P_AddOverlay(mobj); break; - case MT_SHADOW: - if (!mobj->target) - { - P_RemoveMobj(mobj); - return; - } - - P_AddShadow(mobj); - break; /*case MT_BLACKORB: case MT_WHITEORB: case MT_GREENORB: @@ -8418,14 +8137,8 @@ void P_MobjThinker(mobj_t *mobj) P_Thrust(mobj, mobj->angle, thrustamount); - if (grounded) - { - sector_t *sec2 = P_ThingOnSpecial3DFloor(mobj); - if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1) - || (P_IsObjectOnRealGround(mobj, mobj->subsector->sector) - && GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1)) - K_DoPogoSpring(mobj, 0, 1); - } + if (P_MobjTouchingSectorSpecial(mobj, 3, 1, true)) + K_DoPogoSpring(mobj, 0, 1); if (mobj->threshold > 0) mobj->threshold--; @@ -8437,7 +8150,6 @@ void P_MobjThinker(mobj_t *mobj) } case MT_JAWZ: { - sector_t *sec2; mobj_t *ghost = P_SpawnGhostMobj(mobj); if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) @@ -8455,10 +8167,7 @@ void P_MobjThinker(mobj_t *mobj) K_DriftDustHandling(mobj); - sec2 = P_ThingOnSpecial3DFloor(mobj); - if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1) - || (P_IsObjectOnRealGround(mobj, mobj->subsector->sector) - && GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1)) + if (P_MobjTouchingSectorSpecial(mobj, 3, 1, true)) K_DoPogoSpring(mobj, 0, 1); break; @@ -8510,14 +8219,8 @@ void P_MobjThinker(mobj_t *mobj) mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); P_Thrust(mobj, mobj->angle, thrustamount); - if (grounded) - { - sector_t *sec2 = P_ThingOnSpecial3DFloor(mobj); - if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1) - || (P_IsObjectOnRealGround(mobj, mobj->subsector->sector) - && GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1)) - K_DoPogoSpring(mobj, 0, 1); - } + if (P_MobjTouchingSectorSpecial(mobj, 3, 1, true)) + K_DoPogoSpring(mobj, 0, 1); if (mobj->threshold > 0) mobj->threshold--; @@ -9025,31 +8728,104 @@ void P_MobjThinker(mobj_t *mobj) } break; case MT_SIGN: // Kart's unique sign behavior - if (mobj->movecount) + if (mobj->movecount != 0) { - if (mobj->z <= mobj->movefactor) + mobj_t *cur = mobj->hnext; + SINT8 newskin = -1; + UINT8 newcolor = SKINCOLOR_NONE; + angle_t endangle = FixedAngle(mobj->extravalue1 << FRACBITS); + + if (mobj->movecount == 1) { - P_SetMobjState(mobj, S_SIGN_END); - if (mobj->info->attacksound) - S_StartSound(mobj, mobj->info->attacksound); - mobj->flags |= MF_NOGRAVITY; // ? - mobj->flags &= ~MF_NOCLIPHEIGHT; - mobj->z = mobj->movefactor; - mobj->movecount = 0; - } - else - { - P_SpawnMobj(mobj->x + (P_RandomRange(-48,48)*mobj->scale), - mobj->y + (P_RandomRange(-48,48)*mobj->scale), - mobj->z + (24*mobj->scale) + (P_RandomRange(-8,8)*mobj->scale), - MT_SIGNSPARKLE); - mobj->flags &= ~MF_NOGRAVITY; - if (abs(mobj->z - mobj->movefactor) <= (512*mobj->scale) && !mobj->cvmem) + if (mobj->z + mobj->momz <= mobj->movefactor) { - if (mobj->info->seesound) - S_StartSound(mobj, mobj->info->seesound); - mobj->cvmem = 1; + if (mobj->info->attacksound) + S_StartSound(mobj, mobj->info->attacksound); + + mobj->z = mobj->movefactor; + mobj->momz = 0; + mobj->movecount = 2; + + newskin = ((skin_t*)mobj->target->skin)-skins; + newcolor = mobj->target->player->skincolor; } + else + { + fixed_t g = (6*mobj->scale); + UINT16 ticstilimpact = abs(mobj->z - mobj->movefactor) / g; + + P_SpawnMobj( + mobj->x + FixedMul(48*mobj->scale, FINECOSINE(mobj->angle >> ANGLETOFINESHIFT)), + mobj->y + FixedMul(48*mobj->scale, FINESINE(mobj->angle >> ANGLETOFINESHIFT)), + mobj->z + ((24 + ((leveltime % 4) * 8)) * mobj->scale), + MT_SIGNSPARKLE + ); + + if (ticstilimpact == (3*TICRATE/2)) + { + if (mobj->info->seesound) + S_StartSound(mobj, mobj->info->seesound); + } + + mobj->angle += ANGLE_45; + mobj->momz = -g; + + if (mobj->angle == endangle + ANGLE_180) + { + if (ticstilimpact <= 8) + { + newskin = ((skin_t*)mobj->target->skin)-skins; + newcolor = mobj->target->player->skincolor; + } + else + { + newskin = leveltime % numskins; + newcolor = skins[newskin].prefcolor; + } + } + } + } + else if (mobj->movecount == 2) + { + if (mobj->angle != endangle) + mobj->angle += ANGLE_11hh; + } + + while (cur && !P_MobjWasRemoved(cur)) + { + fixed_t amt = cur->extravalue1 * mobj->scale; + angle_t dir = mobj->angle + (cur->extravalue2 * ANGLE_90); + fixed_t z = mobj->z + (23*mobj->scale); + + if (cur->state == &states[S_SIGN_FACE]) + { + if (newcolor != SKINCOLOR_NONE) + { + cur->color = KartColor_Opposite[newcolor*2]; + cur->frame = states[S_SIGN_FACE].frame + KartColor_Opposite[newcolor*2+1]; + } + } + else if (cur->state == &states[S_PLAY_SIGN]) + { + z += (5*mobj->scale); + amt += 1; + + if (newskin != -1) + cur->skin = &skins[newskin]; + + if (newcolor != SKINCOLOR_NONE) + cur->color = newcolor; + } + + P_TeleportMove( + cur, + mobj->x + FixedMul(amt, FINECOSINE(dir >> ANGLETOFINESHIFT)), + mobj->y + FixedMul(amt, FINESINE(dir >> ANGLETOFINESHIFT)), + z + ); + cur->angle = dir + ANGLE_90; + + cur = cur->hnext; } } break; @@ -9665,13 +9441,9 @@ void P_MobjThinker(mobj_t *mobj) break; case MT_BLUEFLAG: case MT_REDFLAG: - { - sector_t *sec2; - sec2 = P_ThingOnSpecial3DFloor(mobj); - if ((sec2 && GETSECSPECIAL(sec2->special, 4) == 2) || (GETSECSPECIAL(mobj->subsector->sector->special, 4) == 2)) - mobj->fuse = 1; // Return to base. - break; - } + if (P_MobjTouchingSectorSpecial(mobj, 4, 2, false)) + mobj->fuse = 1; // Return to base. + break; case MT_CANNONBALL: #ifdef FLOORSPLATS R_AddFloorSplat(mobj->tracer->subsector, mobj->tracer, "TARGET", mobj->tracer->x, @@ -10265,6 +10037,63 @@ void P_SceneryThinker(mobj_t *mobj) // GAME SPAWN FUNCTIONS // +static void P_DefaultMobjShadowScale(mobj_t *thing) +{ + thing->shadowscale = 0; + thing->whiteshadow = (thing->frame & FF_FULLBRIGHT); + + switch (thing->type) + { + case MT_PLAYER: + case MT_SMALLMACE: + case MT_BIGMACE: + case MT_PUMA: + case MT_BIGPUMA: + case MT_FALLINGROCK: + case MT_SMK_MOLE: + case MT_SMK_THWOMP: + case MT_BATTLEBUMPER: + case MT_BANANA: + case MT_ORBINAUT: + case MT_ORBINAUT_SHIELD: + case MT_JAWZ: + case MT_JAWZ_DUD: + case MT_JAWZ_SHIELD: + case MT_SSMINE: + case MT_SSMINE_SHIELD: + case MT_BALLHOG: + case MT_SINK: + case MT_THUNDERSHIELD: + case MT_ROCKETSNEAKER: + case MT_SPB: + thing->shadowscale = 3*FRACUNIT/2; + break; + case MT_BANANA_SHIELD: + thing->shadowscale = 12*FRACUNIT/5; + break; + case MT_RANDOMITEM: + thing->shadowscale = FRACUNIT/2; + thing->whiteshadow = false; + break; + case MT_EGGMANITEM: + thing->shadowscale = FRACUNIT; + thing->whiteshadow = false; + break; + case MT_EGGMANITEM_SHIELD: + thing->shadowscale = 3*FRACUNIT/2; + thing->whiteshadow = false; + break; + case MT_RING: + case MT_FLOATINGITEM: + thing->shadowscale = FRACUNIT/2; + break; + default: + if (thing->flags & (MF_ENEMY|MF_BOSS)) + thing->shadowscale = FRACUNIT; + break; + } +} + // // P_SpawnMobj // @@ -10365,6 +10194,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->colorized = false; + // Set shadowscale here, before spawn hook so that Lua can change it + P_DefaultMobjShadowScale(mobj); + #ifdef HAVE_BLUA // DANGER! This can cause P_SpawnMobj to return NULL! // Avoid using P_RemoveMobj on the newly created mobj in "MobjSpawn" Lua hooks! @@ -10658,29 +10490,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) break; } - switch (mobj->type) - { - case MT_PLAYER: - case MT_SMALLMACE: case MT_BIGMACE: - case MT_PUMA: case MT_BIGPUMA: - case MT_FALLINGROCK: - case MT_SMK_MOLE: case MT_SMK_THWOMP: - //case MT_RANDOMITEM: - case MT_FLOATINGITEM: - case MT_BATTLEBUMPER: - case MT_BANANA: case MT_BANANA_SHIELD: - //case MT_EGGMANITEM: case MT_EGGMANITEM_SHIELD: - case MT_ORBINAUT: case MT_ORBINAUT_SHIELD: - case MT_JAWZ: case MT_JAWZ_DUD: case MT_JAWZ_SHIELD: - case MT_SSMINE: case MT_SSMINE_SHIELD: - case MT_BALLHOG: case MT_SINK: - case MT_THUNDERSHIELD: case MT_ROCKETSNEAKER: - case MT_SPB: - P_SpawnShadowMobj(mobj); - default: - break; - } - if (!(mobj->flags & MF_NOTHINK)) P_AddThinker(&mobj->thinker); @@ -10716,133 +10525,23 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) return mobj; } -// -// P_SpawnShadowMobj -// warning: Do not send a shadow mobj as a caster into here, or try to spawn spawn shadows for shadows in P_SpawnMobj, we do not want recursive shadows -// -mobj_t *P_SpawnShadowMobj(mobj_t * caster) -{ - const mobjinfo_t *info = &mobjinfo[MT_SHADOW]; - state_t *st; - mobj_t *mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); - - // this is officially a mobj, declared as soon as possible. - mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; - mobj->type = MT_SHADOW; - mobj->info = info; - - mobj->x = caster->x; - mobj->y = caster->y; - - mobj->radius = info->radius; - mobj->height = info->height; - mobj->flags = info->flags; - - mobj->health = info->spawnhealth; - - mobj->reactiontime = info->reactiontime; - - mobj->lastlook = -1; // stuff moved in P_enemy.P_LookForPlayer - - // do not set the state with P_SetMobjState, - // because action routines can not be called yet - if (caster->frame & FF_FULLBRIGHT) - st = &states[S_WHITESHADOW]; - else - st = &states[info->spawnstate]; - - mobj->state = st; - mobj->tics = st->tics; - mobj->sprite = st->sprite; - mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits.. - P_SetupStateAnimation(mobj, st); - - mobj->friction = ORIG_FRICTION; - - mobj->movefactor = ORIG_FRICTION_FACTOR; - - // All mobjs are created at 100% scale. - mobj->scale = FRACUNIT; - mobj->destscale = mobj->scale; - mobj->scalespeed = FRACUNIT/12; - - if (mapobjectscale != FRACUNIT) //&& !(mobj->type == MT_BLACKEGGMAN) - { - mobj->destscale = mapobjectscale; - mobj->scalespeed = mapobjectscale/12; - } - - P_SetScale(mobj, mobj->destscale); - - // set subsector and/or block links - P_SetThingPosition(mobj); - I_Assert(mobj->subsector != NULL); - - // Make sure scale matches destscale immediately when spawned - P_SetScale(mobj, mobj->destscale); - - mobj->floorz = mobj->subsector->sector->floorheight; - mobj->ceilingz = mobj->subsector->sector->ceilingheight; - - // Tells MobjCheckWater that the water height was not set. - mobj->watertop = INT32_MAX; - - mobj->z = mobj->floorz; - - // defaults onground - if (mobj->z == mobj->floorz) - mobj->eflags |= MFE_ONGROUND; - - if (!(mobj->flags & MF_NOTHINK)) - P_AddThinker(&mobj->thinker); - - // Call action functions when the state is set - if (st->action.acp1 && (mobj->flags & MF_RUNSPAWNFUNC)) - { - if (levelloading) - { - // Cache actions in a linked list - // with function pointer, and - // var1 & var2, which will be executed - // when the level finishes loading. - P_AddCachedAction(mobj, mobj->info->spawnstate); - } - else - { - var1 = st->var1; - var2 = st->var2; -#ifdef HAVE_BLUA - astate = st; -#endif - st->action.acp1(mobj); - // DANGER! This is the ONLY way for P_SpawnMobj to return NULL! - // Avoid using MF_RUNSPAWNFUNC on mobjs whose spawn state expects target or tracer to already be set! - if (P_MobjWasRemoved(mobj)) - return NULL; - } - } - - if (CheckForReverseGravity && !(mobj->flags & MF_NOBLOCKMAP)) - P_CheckGravity(mobj, false); - - P_SetTarget(&mobj->target, caster); // set the shadow's caster as the target - - return mobj; -} - static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) { + const mobjinfo_t *info = &mobjinfo[type]; state_t *st; precipmobj_t *mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); fixed_t starting_floorz; + mobj->type = type; + mobj->info = info; + mobj->x = x; mobj->y = y; - mobj->flags = mobjinfo[type].flags; + mobj->flags = info->flags; // do not set the state with P_SetMobjState, // because action routines can not be called yet - st = &states[mobjinfo[type].spawnstate]; + st = &states[info->spawnstate]; mobj->state = st; mobj->tics = st->tics; @@ -10865,7 +10564,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype mobj->subsector->sector->ceilingheight; mobj->z = z; - mobj->momz = mobjinfo[type].speed; + mobj->momz = info->speed; mobj->thinker.function.acp1 = (actionf_p1)P_NullPrecipThinker; P_AddThinker(&mobj->thinker); @@ -10882,21 +10581,6 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype return mobj; } -static inline precipmobj_t *P_SpawnRainMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) -{ - precipmobj_t *mo = P_SpawnPrecipMobj(x,y,z,type); - mo->precipflags |= PCF_RAIN; - //mo->thinker.function.acp1 = (actionf_p1)P_RainThinker; - return mo; -} - -static inline precipmobj_t *P_SpawnSnowMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) -{ - precipmobj_t *mo = P_SpawnPrecipMobj(x,y,z,type); - //mo->thinker.function.acp1 = (actionf_p1)P_SnowThinker; - return mo; -} - // // P_RemoveMobj // @@ -10954,9 +10638,6 @@ void P_RemoveMobj(mobj_t *mobj) if (mobj->type == MT_OVERLAY) P_RemoveOverlay(mobj); - if (mobj->type == MT_SHADOW) - P_RemoveShadow(mobj); - if (mobj->type == MT_SPB) spbplace = -1; @@ -11088,8 +10769,10 @@ consvar_t cv_suddendeath = {"suddendeath", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHE void P_SpawnPrecipitation(void) { - INT32 i, mrand; - fixed_t basex, basey, x, y, height; + INT32 i, j, k; + mobjtype_t type = precipprops[curWeather].type; + UINT8 randomstates = (UINT8)mobjinfo[type].damage; + fixed_t basex, basey, x, y, z, height; subsector_t *precipsector = NULL; precipmobj_t *rainmo = NULL; @@ -11102,8 +10785,9 @@ void P_SpawnPrecipitation(void) basex = bmaporgx + (i % bmapwidth) * MAPBLOCKSIZE; basey = bmaporgy + (i / bmapwidth) * MAPBLOCKSIZE; - //for (j = 0; j < cv_precipdensity.value; ++j) -- density is 1 for kart always { + UINT16 numparticles = 0; + x = basex + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); y = basey + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); @@ -11118,40 +10802,43 @@ void P_SpawnPrecipitation(void) if (precipsector->sector->ceilingpic != skyflatnum) continue; + height = precipsector->sector->ceilingheight - precipsector->sector->floorheight; + // Exists, but is too small for reasonable precipitation. - if (!(precipsector->sector->floorheight <= precipsector->sector->ceilingheight - (32<sector->ceilingheight; + // Hack around a quirk of this entire system, where taller sectors look like they get less precipitation. + numparticles = 1 + (height / (MAPBLOCKUNITS<<4<sector->ceilingheight; + + for (j = 0; j < numparticles; j++) { - rainmo = P_SpawnSnowMobj(x, y, height, MT_SNOWFLAKE); - mrand = M_RandomByte(); - if (mrand < 64) - P_SetPrecipMobjState(rainmo, S_SNOW3); - else if (mrand < 144) - P_SetPrecipMobjState(rainmo, S_SNOW2); + rainmo = P_SpawnPrecipMobj(x, y, z, type); + + if (randomstates > 0) + { + UINT8 mrand = M_RandomByte(); + UINT8 threshold = UINT8_MAX / (randomstates + 1); + statenum_t st = mobjinfo[type].spawnstate; + + for (k = 0; k < randomstates; k++) + { + if (mrand < (threshold * (k+1))) + { + P_SetPrecipMobjState(rainmo, st+k+1); + break; + } + } + } + + // Randomly assign a height, now that floorz is set. + rainmo->z = M_RandomRange(rainmo->floorz>>FRACBITS, rainmo->ceilingz>>FRACBITS)<z = M_RandomRange(rainmo->floorz>>FRACBITS, rainmo->ceilingz>>FRACBITS)< 255) volume = 255; - if (sounds_rain && (!leveltime || leveltime % 80 == 1)) - S_StartSoundAtVolume(players[displayplayers[0]].mo, sfx_rainin, volume); + if (rainsfx != sfx_None && (!leveltime || leveltime % rainfreq == 1)) + S_StartSoundAtVolume(players[displayplayers[0]].mo, rainsfx, volume); if (!sounds_thunder) return; diff --git a/src/p_mobj.h b/src/p_mobj.h index 3ade78aa4..5cc93a56d 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -253,25 +253,23 @@ typedef enum // PRECIPITATION flags ?! ?! ?! // typedef enum { - // Don't draw. - PCF_INVISIBLE = 1, - // Above pit. - PCF_PIT = 2, - // Above FOF. - PCF_FOF = 4, - // Above MOVING FOF (this means we need to keep floorz up to date...) - PCF_MOVINGFOF = 8, - // Is rain. - PCF_RAIN = 16, - // Ran the thinker this tic. - PCF_THUNK = 32, + PCF_INVISIBLE = 1, // Don't draw. + PCF_PIT = 1<<1, // Above pit. + PCF_FOF = 1<<2, // Above FOF. + PCF_MOVINGFOF = 1<<3, // Above MOVING FOF (this means we need to keep floorz up to date...) + PCF_SPLASH = 1<<4, // Splashed on the ground, return to the ceiling after the animation's over + PCF_THUNK = 1<<5, // Ran the thinker this tic. } precipflag_t; + // Map Object definition. typedef struct mobj_s { // List: thinker links. thinker_t thinker; + mobjtype_t type; + const mobjinfo_t *info; // &mobjinfo[mobj->type] + // Info for drawing: position. fixed_t x, y, z; @@ -324,9 +322,6 @@ typedef struct mobj_s // One last pointer for kart item lists struct mobj_s *itnext; - mobjtype_t type; - const mobjinfo_t *info; // &mobjinfo[mobj->type] - INT32 health; // for player this is rings + 1 // Movement direction, movement generation (zig-zagging). @@ -380,6 +375,9 @@ typedef struct mobj_s boolean colorized; // Whether the mobj uses the rainbow colormap + fixed_t shadowscale; // If this object casts a shadow, and the size relative to radius + boolean whiteshadow; // Use white shadow, set to true by default for fullbright objects + // WARNING: New fields must be added separately to savegame and Lua. } mobj_t; @@ -395,6 +393,9 @@ typedef struct precipmobj_s // List: thinker links. thinker_t thinker; + mobjtype_t type; + const mobjinfo_t *info; // &mobjinfo[mobj->type] + // Info for drawing: position. fixed_t x, y, z; @@ -468,8 +469,7 @@ void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 numb boolean P_BossTargetPlayer(mobj_t *actor, boolean closest); boolean P_SupermanLook4Players(mobj_t *actor); void P_DestroyRobots(void); -void P_SnowThinker(precipmobj_t *mobj); -void P_RainThinker(precipmobj_t *mobj); +void P_PrecipThinker(precipmobj_t *mobj); void P_NullPrecipThinker(precipmobj_t *mobj); void P_RemovePrecipMobj(precipmobj_t *mobj); void P_SetScale(mobj_t *mobj, fixed_t newscale); diff --git a/src/p_setup.c b/src/p_setup.c index 95c61d1ae..784ccd24f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -182,6 +182,8 @@ FUNCNORETURN static ATTRNORETURN void CorruptMapError(const char *msg) static void P_ClearSingleMapHeaderInfo(INT16 i) { const INT16 num = (INT16)(i-1); + INT32 exists = (mapheaderinfo[num]->menuflags & LF2_EXISTSHACK); + DEH_WriteUndoline("LEVELNAME", mapheaderinfo[num]->lvlttl, UNDO_NONE); mapheaderinfo[num]->lvlttl[0] = '\0'; DEH_WriteUndoline("SUBTITLE", mapheaderinfo[num]->subttl, UNDO_NONE); @@ -247,7 +249,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) DEH_WriteUndoline("LEVELFLAGS", va("%d", mapheaderinfo[num]->levelflags), UNDO_NONE); mapheaderinfo[num]->levelflags = 0; DEH_WriteUndoline("MENUFLAGS", va("%d", mapheaderinfo[num]->menuflags), UNDO_NONE); - mapheaderinfo[num]->menuflags = (mainwads ? 0 : LF2_EXISTSHACK); // see p_setup.c - prevents replacing maps in addons with easier versions + mapheaderinfo[num]->menuflags = exists; // see p_setup.c - prevents replacing maps in addons with easier versions // TODO grades support for delfile (pfft yeah right) P_DeleteGrades(num); // SRB2Kart diff --git a/src/p_spec.c b/src/p_spec.c index 8e368d710..c4070ef5c 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1971,57 +1971,28 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) // // Switches the weather! // -void P_SwitchWeather(INT32 weathernum) +void P_SwitchWeather(UINT8 newWeather) { boolean purge = false; - INT32 swap = 0; + mobjtype_t swap = MT_NULL; - switch (weathernum) + if (precipprops[newWeather].type == MT_NULL) { - case PRECIP_NONE: // None - if (curWeather == PRECIP_NONE) - return; // Nothing to do. - purge = true; - break; - case PRECIP_STORM: // Storm - case PRECIP_STORM_NOSTRIKES: // Storm w/ no lightning - case PRECIP_RAIN: // Rain - if (curWeather == PRECIP_SNOW || curWeather == PRECIP_BLANK || curWeather == PRECIP_STORM_NORAIN) - swap = PRECIP_RAIN; - break; - case PRECIP_SNOW: // Snow - if (curWeather == PRECIP_SNOW) - return; // Nothing to do. - if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES || curWeather == PRECIP_BLANK || curWeather == PRECIP_STORM_NORAIN) - swap = PRECIP_SNOW; // Need to delete the other precips. - break; - case PRECIP_STORM_NORAIN: // Storm w/o rain - if (curWeather == PRECIP_SNOW - || curWeather == PRECIP_STORM - || curWeather == PRECIP_STORM_NOSTRIKES - || curWeather == PRECIP_RAIN - || curWeather == PRECIP_BLANK) - swap = PRECIP_STORM_NORAIN; - else if (curWeather == PRECIP_STORM_NORAIN) - return; - break; - case PRECIP_BLANK: - if (curWeather == PRECIP_SNOW - || curWeather == PRECIP_STORM - || curWeather == PRECIP_STORM_NOSTRIKES - || curWeather == PRECIP_RAIN) - swap = PRECIP_BLANK; - else if (curWeather == PRECIP_STORM_NORAIN) - swap = PRECIP_BLANK; - else if (curWeather == PRECIP_BLANK) - return; - break; - default: - CONS_Debug(DBG_GAMELOGIC, "P_SwitchWeather: Unknown weather type %d.\n", weathernum); - break; + // New type is null, we want to purge the weather. + if (precipprops[curWeather].type == MT_NULL) + return; // Nothing to do. + purge = true; + } + else + { + if (precipprops[curWeather].type != MT_NULL) + { + // There are already existing weather particles to reuse. + swap = precipprops[newWeather].type; + } } - if (purge) + if (purge == true) { thinker_t *think; precipmobj_t *precipmobj; @@ -2036,136 +2007,54 @@ void P_SwitchWeather(INT32 weathernum) P_RemovePrecipMobj(precipmobj); } } - else if (swap && !((swap == PRECIP_BLANK && curWeather == PRECIP_STORM_NORAIN) || (swap == PRECIP_STORM_NORAIN && curWeather == PRECIP_BLANK))) // Rather than respawn all that crap, reuse it! + else if (swap != MT_NULL) // Rather than respawn all that crap, reuse it! { + UINT8 randomstates = (UINT8)mobjinfo[swap].damage; thinker_t *think; precipmobj_t *precipmobj; - state_t *st; + statenum_t st; for (think = thinkercap.next; think != &thinkercap; think = think->next) { if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker) continue; // not a precipmobj thinker + precipmobj = (precipmobj_t *)think; - if (swap == PRECIP_RAIN) // Snow To Rain + precipmobj->flags = mobjinfo[swap].flags; + + st = mobjinfo[swap].spawnstate; + + if (randomstates > 0) { - precipmobj->flags = mobjinfo[MT_RAIN].flags; - st = &states[mobjinfo[MT_RAIN].spawnstate]; - precipmobj->state = st; - precipmobj->tics = st->tics; - precipmobj->sprite = st->sprite; - precipmobj->frame = st->frame; - precipmobj->momz = mobjinfo[MT_RAIN].speed; + UINT8 mrand = M_RandomByte(); + UINT8 threshold = UINT8_MAX / (randomstates + 1); + UINT8 i; - precipmobj->precipflags &= ~PCF_INVISIBLE; - - precipmobj->precipflags |= PCF_RAIN; - //think->function.acp1 = (actionf_p1)P_RainThinker; + for (i = 0; i < randomstates; i++) + { + if (mrand < (threshold * (i+1))) + { + st += i+1; + break; + } + } } - else if (swap == PRECIP_SNOW) // Rain To Snow - { - INT32 z; - precipmobj->flags = mobjinfo[MT_SNOWFLAKE].flags; - z = M_RandomByte(); + precipmobj->state = &states[st]; + precipmobj->tics = precipmobj->state->tics; + precipmobj->sprite = precipmobj->state->sprite; + precipmobj->frame = precipmobj->state->frame; - if (z < 64) - z = 2; - else if (z < 144) - z = 1; - else - z = 0; - - st = &states[mobjinfo[MT_SNOWFLAKE].spawnstate+z]; - precipmobj->state = st; - precipmobj->tics = st->tics; - precipmobj->sprite = st->sprite; - precipmobj->frame = st->frame; - precipmobj->momz = mobjinfo[MT_SNOWFLAKE].speed; - - precipmobj->precipflags &= ~(PCF_INVISIBLE|PCF_RAIN); - - //think->function.acp1 = (actionf_p1)P_SnowThinker; - } - else if (swap == PRECIP_BLANK || swap == PRECIP_STORM_NORAIN) // Remove precip, but keep it around for reuse. - { - //think->function.acp1 = (actionf_p1)P_NullPrecipThinker; - - precipmobj->precipflags |= PCF_INVISIBLE; - } + precipmobj->momz = mobjinfo[swap].speed; + precipmobj->precipflags &= ~PCF_INVISIBLE; } } - switch (weathernum) - { - case PRECIP_SNOW: // snow - curWeather = PRECIP_SNOW; + curWeather = newWeather; - if (!swap) - P_SpawnPrecipitation(); - - break; - case PRECIP_RAIN: // rain - { - boolean dontspawn = false; - - if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES) - dontspawn = true; - - curWeather = PRECIP_RAIN; - - if (!dontspawn && !swap) - P_SpawnPrecipitation(); - - break; - } - case PRECIP_STORM: // storm - { - boolean dontspawn = false; - - if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES) - dontspawn = true; - - curWeather = PRECIP_STORM; - - if (!dontspawn && !swap) - P_SpawnPrecipitation(); - - break; - } - case PRECIP_STORM_NOSTRIKES: // storm w/o lightning - { - boolean dontspawn = false; - - if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES) - dontspawn = true; - - curWeather = PRECIP_STORM_NOSTRIKES; - - if (!dontspawn && !swap) - P_SpawnPrecipitation(); - - break; - } - case PRECIP_STORM_NORAIN: // storm w/o rain - curWeather = PRECIP_STORM_NORAIN; - - if (!swap) - P_SpawnPrecipitation(); - - break; - case PRECIP_BLANK: - curWeather = PRECIP_BLANK; - - if (!swap) - P_SpawnPrecipitation(); - - break; - default: - curWeather = PRECIP_NONE; - break; - } + if (swap == MT_NULL && precipprops[newWeather].type != MT_NULL) + P_SpawnPrecipitation(); } // Passed over the finish line forwards @@ -3382,6 +3271,76 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } } +static void P_SetupSignObject(mobj_t *sign, mobj_t *pmo) +{ + mobj_t *cur = sign, *prev = NULL; + + // Setup the sign itself + P_SetTarget(&sign->target, pmo); + P_SetMobjState(sign, S_SIGN_POLE); + + sign->movefactor = sign->z; + sign->z += (768*sign->scale) * P_MobjFlip(sign); + sign->movecount = 1; + sign->extravalue1 = AngleFixed(sign->angle) >> FRACBITS; + + // Setup the overlay pieces + // Front + cur->hnext = P_SpawnMobj(sign->x, sign->y, sign->z, MT_SIGN_PIECE); + P_SetTarget(&cur->hnext->target, sign); + P_SetMobjState(cur->hnext, S_SIGN_FACE); + cur->hnext->extravalue1 = 6; + cur->hnext->extravalue2 = 0; + + prev = cur; + cur = cur->hnext; + cur->hprev = prev; + + // Player icon + cur->hnext = P_SpawnMobj(sign->x, sign->y, sign->z, MT_SIGN_PIECE); + P_SetTarget(&cur->hnext->target, sign); + cur->hnext->skin = pmo->skin; + P_SetMobjState(cur->hnext, S_PLAY_SIGN); + cur->hnext->extravalue1 = 7; + cur->hnext->extravalue2 = 0; + + prev = cur; + cur = cur->hnext; + cur->hprev = prev; + + // Back + cur->hnext = P_SpawnMobj(sign->x, sign->y, sign->z, MT_SIGN_PIECE); + P_SetTarget(&cur->hnext->target, sign); + P_SetMobjState(cur->hnext, S_SIGN_BACK); + cur->hnext->extravalue1 = 6; + cur->hnext->extravalue2 = 2; + + prev = cur; + cur = cur->hnext; + cur->hprev = prev; + + // Sides + cur->hnext = P_SpawnMobj(sign->x, sign->y, sign->z, MT_SIGN_PIECE); + P_SetTarget(&cur->hnext->target, sign); + P_SetMobjState(cur->hnext, S_SIGN_SIDE); + cur->hnext->extravalue1 = 30; + cur->hnext->extravalue2 = 1; + + prev = cur; + cur = cur->hnext; + cur->hprev = prev; + + cur->hnext = P_SpawnMobj(sign->x, sign->y, sign->z, MT_SIGN_PIECE); + P_SetTarget(&cur->hnext->target, sign); + P_SetMobjState(cur->hnext, S_SIGN_SIDE); + cur->hnext->extravalue1 = 30; + cur->hnext->extravalue2 = 3; + + prev = cur; + cur = cur->hnext; + cur->hprev = prev; +} + // // P_SetupSignExit // @@ -3407,13 +3366,7 @@ void P_SetupSignExit(player_t *player) if (thing->state != &states[thing->info->spawnstate]) continue; - P_SetTarget(&thing->target, player->mo); - P_SetMobjState(thing, S_SIGN1); - - // SRB2Kart: Set sign spinning variables - thing->movefactor = thing->z; - thing->z += (768*thing->scale) * P_MobjFlip(thing); - thing->movecount = 1; + P_SetupSignObject(thing, player->mo); ++numfound; } @@ -3435,14 +3388,7 @@ void P_SetupSignExit(player_t *player) if (thing->state != &states[thing->info->spawnstate]) continue; - P_SetTarget(&thing->target, player->mo); - P_SetMobjState(thing, S_SIGN1); - - // SRB2Kart: Set sign spinning variables - thing->movefactor = thing->z; - thing->z += (768*thing->scale) * P_MobjFlip(thing); - thing->movecount = 1; - + P_SetupSignObject(thing, player->mo); ++numfound; } @@ -3450,14 +3396,11 @@ void P_SetupSignExit(player_t *player) return; // SRB2Kart: FINALLY, add in an alternative if no place is found - if (player->mo) + if (player->mo && !P_MobjWasRemoved(player->mo)) { - mobj_t *sign = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + (768*mapobjectscale), MT_SIGN); - - P_SetTarget(&sign->target, player->mo); - P_SetMobjState(sign, S_SIGN1); - sign->movefactor = player->mo->floorz; - sign->movecount = 1; + thing = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->floorz, MT_SIGN); + thing->angle = player->mo->angle; + P_SetupSignObject(thing, player->mo); } } @@ -3511,7 +3454,7 @@ boolean P_IsFlagAtBase(mobjtype_t flag) } // -// P_PlayerTouchingSectorSpecial +// P_MobjTouchingSectorSpecial // // Replaces the old player->specialsector. // This allows a player to touch more than @@ -3521,60 +3464,86 @@ boolean P_IsFlagAtBase(mobjtype_t flag) // the particular type that it finds. // Returns NULL if it doesn't find it. // -sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 number) +// Sal: Couldn't see a reason for this to +// be a player_t only function. +// +sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number, boolean touchground) { + fixed_t topheight, bottomheight; msecnode_t *node; ffloor_t *rover; - if (!player->mo) + if (!mo) return NULL; // Check default case first - if (GETSECSPECIAL(player->mo->subsector->sector->special, section) == number) - return player->mo->subsector->sector; + if (GETSECSPECIAL(mo->subsector->sector->special, section) == number) + { + if (touchground) + { + topheight = P_GetSpecialTopZ(mo, mo->subsector->sector, mo->subsector->sector); + bottomheight = P_GetSpecialBottomZ(mo, mo->subsector->sector, mo->subsector->sector); + + // Thing must be on top of the floor to be affected... + if (mo->subsector->sector->flags & SF_FLIPSPECIAL_FLOOR) + { + if (!(mo->eflags & MFE_VERTICALFLIP) && mo->z <= bottomheight) + return mo->subsector->sector; + } + + if (mo->subsector->sector->flags & SF_FLIPSPECIAL_CEILING) + { + if ((mo->eflags & MFE_VERTICALFLIP) && mo->z + mo->height >= topheight) + return mo->subsector->sector; + } + } + else + { + return mo->subsector->sector; + } + } // Hmm.. maybe there's a FOF that has it... - for (rover = player->mo->subsector->sector->ffloors; rover; rover = rover->next) + for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next) { - fixed_t topheight, bottomheight; - if (GETSECSPECIAL(rover->master->frontsector->special, section) != number) continue; if (!(rover->flags & FF_EXISTS)) continue; - topheight = P_GetSpecialTopZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); - bottomheight = P_GetSpecialBottomZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); + topheight = P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector); + bottomheight = P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector); // Check the 3D floor's type... - if (rover->flags & FF_BLOCKPLAYER) + if (((rover->flags & FF_BLOCKPLAYER) && mo->player) + || ((rover->flags & FF_BLOCKOTHERS) && !mo->player)) { // Thing must be on top of the floor to be affected... if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)) { - if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != topheight) + if ((mo->eflags & MFE_VERTICALFLIP) || mo->z != topheight) continue; } else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)) { - if (!(player->mo->eflags & MFE_VERTICALFLIP) - || player->mo->z + player->mo->height != bottomheight) + if (!(mo->eflags & MFE_VERTICALFLIP) + || mo->z + mo->height != bottomheight) continue; } else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH) { - if (!((player->mo->eflags & MFE_VERTICALFLIP && player->mo->z + player->mo->height == bottomheight) - || (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z == topheight))) + if (!((mo->eflags & MFE_VERTICALFLIP && mo->z + mo->height == bottomheight) + || (!(mo->eflags & MFE_VERTICALFLIP) && mo->z == topheight))) continue; } } else { // Water and DEATH FOG!!! heh - if (player->mo->z > topheight || (player->mo->z + player->mo->height) < bottomheight) + if (mo->z > topheight || (mo->z + mo->height) < bottomheight) continue; } @@ -3582,64 +3551,86 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n return rover->master->frontsector; } - for (node = player->mo->touching_sectorlist; node; node = node->m_sectorlist_next) + for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) { if (GETSECSPECIAL(node->m_sector->special, section) == number) { // This sector has the special we're looking for, but // are we allowed to touch it? - if (node->m_sector == player->mo->subsector->sector + if (node->m_sector == mo->subsector->sector || (node->m_sector->flags & SF_TRIGGERSPECIAL_TOUCH)) - return node->m_sector; + { + if (touchground) + { + topheight = P_GetSpecialTopZ(mo, node->m_sector, node->m_sector); + bottomheight = P_GetSpecialBottomZ(mo, node->m_sector, node->m_sector); + + // Thing must be on top of the floor to be affected... + if (node->m_sector->flags & SF_FLIPSPECIAL_FLOOR) + { + if (!(mo->eflags & MFE_VERTICALFLIP) && mo->z <= bottomheight) + return node->m_sector; + } + + if (node->m_sector->flags & SF_FLIPSPECIAL_CEILING) + { + if ((mo->eflags & MFE_VERTICALFLIP) && mo->z + mo->height >= topheight) + return node->m_sector; + } + } + else + { + return node->m_sector; + } + } } // Hmm.. maybe there's a FOF that has it... for (rover = node->m_sector->ffloors; rover; rover = rover->next) { - fixed_t topheight, bottomheight; - if (GETSECSPECIAL(rover->master->frontsector->special, section) != number) continue; if (!(rover->flags & FF_EXISTS)) continue; - topheight = P_GetSpecialTopZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); - bottomheight = P_GetSpecialBottomZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector); + topheight = P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector); + bottomheight = P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector); // Check the 3D floor's type... - if (rover->flags & FF_BLOCKPLAYER) + if (((rover->flags & FF_BLOCKPLAYER) && mo->player) + || ((rover->flags & FF_BLOCKOTHERS) && !mo->player)) { // Thing must be on top of the floor to be affected... if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)) { - if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != topheight) + if ((mo->eflags & MFE_VERTICALFLIP) || mo->z != topheight) continue; } else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)) { - if (!(player->mo->eflags & MFE_VERTICALFLIP) - || player->mo->z + player->mo->height != bottomheight) + if (!(mo->eflags & MFE_VERTICALFLIP) + || mo->z + mo->height != bottomheight) continue; } else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH) { - if (!((player->mo->eflags & MFE_VERTICALFLIP && player->mo->z + player->mo->height == bottomheight) - || (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z == topheight))) + if (!((mo->eflags & MFE_VERTICALFLIP && mo->z + mo->height == bottomheight) + || (!(mo->eflags & MFE_VERTICALFLIP) && mo->z == topheight))) continue; } } else { // Water and DEATH FOG!!! heh - if (player->mo->z > topheight || (player->mo->z + player->mo->height) < bottomheight) + if (mo->z > topheight || (mo->z + mo->height) < bottomheight) continue; } // This FOF has the special we're looking for, but are we allowed to touch it? - if (node->m_sector == player->mo->subsector->sector + if (node->m_sector == mo->subsector->sector || (rover->master->frontsector->flags & SF_TRIGGERSPECIAL_TOUCH)) return rover->master->frontsector; } @@ -5717,25 +5708,10 @@ void P_InitSpecials(void) CheckForBustableBlocks = CheckForBouncySector = CheckForQuicksand = CheckForMarioBlocks = CheckForFloatBob = CheckForReverseGravity = false; - // Set curWeather - switch (mapheaderinfo[gamemap-1]->weather) - { - case PRECIP_SNOW: // snow - case PRECIP_RAIN: // rain - case PRECIP_STORM: // storm - case PRECIP_STORM_NORAIN: // storm w/o rain - case PRECIP_STORM_NOSTRIKES: // storm w/o lightning - curWeather = mapheaderinfo[gamemap-1]->weather; - break; - default: // blank/none - curWeather = PRECIP_NONE; - break; - } + // Set weather + curWeather = globalweather = mapheaderinfo[gamemap-1]->weather; - // Set globalweather - globalweather = mapheaderinfo[gamemap-1]->weather; - - P_InitTagLists(); // Create xref tables for tags + P_InitTagLists(); // Create xref tables for tags } /** After the map has loaded, scans for specials that spawn 3Dfloors and diff --git a/src/p_spec.h b/src/p_spec.h index 2763a34ad..a49946c2a 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -37,7 +37,7 @@ void P_SpawnSpecials(INT32 fromnetsave); // every tic void P_UpdateSpecials(void); -sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 number); +sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number, boolean touchground); void P_PlayerInSpecialSector(player_t *player); void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector); @@ -61,7 +61,7 @@ void P_CrossSpecialLine(line_t *ld, INT32 side, mobj_t *thing); void P_SetupSignExit(player_t *player); boolean P_IsFlagAtBase(mobjtype_t flag); -void P_SwitchWeather(INT32 weathernum); +void P_SwitchWeather(UINT8 newWeather); boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller); void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller); diff --git a/src/p_tick.c b/src/p_tick.c index 33cc32602..1c87218b9 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -59,8 +59,6 @@ void Command_Numthinkers_f(void) CONS_Printf(M_GetText("numthinkers <#>: Count number of thinkers\n")); CONS_Printf( "\t1: P_MobjThinker\n" - /*"\t2: P_RainThinker\n" - "\t3: P_SnowThinker\n"*/ "\t2: P_NullPrecipThinker\n" "\t3: T_Friction\n" "\t4: T_Pusher\n" @@ -76,14 +74,6 @@ void Command_Numthinkers_f(void) action = (actionf_p1)P_MobjThinker; CONS_Printf(M_GetText("Number of %s: "), "P_MobjThinker"); break; - /*case 2: - action = (actionf_p1)P_RainThinker; - CONS_Printf(M_GetText("Number of %s: "), "P_RainThinker"); - break; - case 3: - action = (actionf_p1)P_SnowThinker; - CONS_Printf(M_GetText("Number of %s: "), "P_SnowThinker"); - break;*/ case 2: action = (actionf_p1)P_NullPrecipThinker; CONS_Printf(M_GetText("Number of %s: "), "P_NullPrecipThinker"); @@ -663,8 +653,6 @@ void P_Ticker(boolean run) //P_RunShields(); P_RunOverlays(); - P_RunShadows(); - P_UpdateSpecials(); P_RespawnSpecials(); diff --git a/src/r_bsp.c b/src/r_bsp.c index 296cbbe87..a748af51c 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -57,6 +57,16 @@ static boolean R_NoEncore(sector_t *sector, boolean ceiling) return ((boolean)(sector->flags & SF_FLIPSPECIAL_FLOOR)); } +static void R_PlaneLightOverride(sector_t *sector, boolean ceiling, INT32 *lightlevel) +{ + if (GETSECSPECIAL(sector->special, 4) == 6) // Fullbright sneaker panels + { + if ((ceiling && (sector->flags & SF_FLIPSPECIAL_CEILING)) + || (!ceiling && (sector->flags & SF_FLIPSPECIAL_FLOOR))) + *lightlevel = 255; + } +} + // // R_ClearDrawSegs // @@ -895,6 +905,9 @@ static void R_Subsector(size_t num) sub->sector->extra_colormap = frontsector->extra_colormap; + R_PlaneLightOverride(frontsector, false, &floorlightlevel); + R_PlaneLightOverride(frontsector, true, &ceilinglightlevel); + if ((( #ifdef ESLOPE frontsector->f_slope ? P_GetZAt(frontsector->f_slope, viewx, viewy) : @@ -923,8 +936,8 @@ static void R_Subsector(size_t num) || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum))) { - ceilingplane = R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic, - ceilinglightlevel, frontsector->ceiling_xoffs, frontsector->ceiling_yoffs, frontsector->ceilingpic_angle, + ceilingplane = R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic, ceilinglightlevel, + frontsector->ceiling_xoffs, frontsector->ceiling_yoffs, frontsector->ceilingpic_angle, ceilingcolormap, NULL #ifdef POLYOBJECTS_PLANES , NULL diff --git a/src/r_main.c b/src/r_main.c index 0d14bed73..a4fa9d463 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -168,8 +168,7 @@ consvar_t cv_flipcam2 = {"flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, consvar_t cv_flipcam3 = {"flipcam3", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam3_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_flipcam4 = {"flipcam4", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam4_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_shadow = {"shadow", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_soniccd = {"soniccd", "Off", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -1505,7 +1504,6 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_chasecam3); CV_RegisterVar(&cv_chasecam4); CV_RegisterVar(&cv_shadow); - CV_RegisterVar(&cv_shadowoffs); CV_RegisterVar(&cv_skybox); CV_RegisterVar(&cv_cam_dist); diff --git a/src/r_main.h b/src/r_main.h index 38a589682..879d4c6eb 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -76,7 +76,7 @@ extern consvar_t cv_showhud, cv_translucenthud; extern consvar_t cv_homremoval; extern consvar_t cv_chasecam, cv_chasecam2, cv_chasecam3, cv_chasecam4; extern consvar_t cv_flipcam, cv_flipcam2, cv_flipcam3, cv_flipcam4; -extern consvar_t cv_shadow, cv_shadowoffs; +extern consvar_t cv_shadow; extern consvar_t cv_translucency; extern consvar_t /*cv_precipdensity,*/ cv_drawdist, /*cv_drawdist_nights,*/ cv_drawdist_precip; extern consvar_t cv_fov; diff --git a/src/r_things.c b/src/r_things.c index 1afbb125c..9ea8bb77b 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -802,9 +802,7 @@ static void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight) static void R_DrawVisSprite(vissprite_t *vis) { column_t *column; -#ifdef RANGECHECK INT32 texturecolumn; -#endif fixed_t frac; patch_t *patch = W_CacheLumpNum(vis->patch, PU_CACHE); fixed_t this_scale = vis->mobj->scale; @@ -920,6 +918,7 @@ static void R_DrawVisSprite(vissprite_t *vis) if (!(vis->scalestep)) { sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); + sprtopscreen += vis->shear.tan * vis->shear.offset; dc_iscale = FixedDiv(FRACUNIT, vis->scale); } @@ -942,31 +941,50 @@ static void R_DrawVisSprite(vissprite_t *vis) vis->x2--; #endif - for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale) + // Split drawing loops for paper and non-paper to reduce conditional checks per sprite + if (vis->scalestep) { - if (vis->scalestep) // currently papersprites only + // Papersprite drawing loop + for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, spryscale += vis->scalestep) { -#ifndef RANGECHECK - if ((frac>>FRACBITS) < 0 || (frac>>FRACBITS) >= SHORT(patch->width)) // if this doesn't work i'm removing papersprites - break; -#endif + angle_t angle = ((vis->centerangle + xtoviewangle[dc_x]) >> ANGLETOFINESHIFT) & 0xFFF; + texturecolumn = (vis->paperoffset - FixedMul(FINETANGENT(angle), vis->paperdistance)) / this_scale; + + if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) + continue; + + if (vis->xiscale < 0) // Flipped sprite + texturecolumn = SHORT(patch->width) - 1 - texturecolumn; + sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); dc_iscale = (0xffffffffu / (unsigned)spryscale); - spryscale += vis->scalestep; - } -#ifdef RANGECHECK - texturecolumn = frac>>FRACBITS; - if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) - I_Error("R_DrawSpriteRange: bad texturecolumn"); - column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn])); + column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn])); + + if (vis->cut & SC_VFLIP) + R_DrawFlippedMaskedColumn(column, patch->height); + else + R_DrawMaskedColumn(column); + } + } + else + { + // Non-paper drawing loop + for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan) + { +#ifdef RANGECHECK + texturecolumn = frac>>FRACBITS; + if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) + I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x); + column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn])); #else - column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS])); + column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS])); #endif - if (vis->cut & SC_VFLIP) - R_DrawFlippedMaskedColumn(column, patch->height); - else - R_DrawMaskedColumn(column); + if (vis->cut & SC_VFLIP) + R_DrawFlippedMaskedColumn(column, patch->height); + else + R_DrawMaskedColumn(column); + } } colfunc = basecolfunc; @@ -1138,6 +1156,278 @@ static void R_SplitSprite(vissprite_t *sprite) } } +// +// R_GetShadowZ(thing, shadowslope) +// Get the first visible floor below the object for shadows +// shadowslope is filled with the floor's slope, if provided +// +fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope) +{ + fixed_t z, floorz = INT32_MIN; + pslope_t *slope, *floorslope = NULL; + msecnode_t *node; + sector_t *sector; + ffloor_t *rover; + + for (node = thing->touching_sectorlist; node; node = node->m_sectorlist_next) + { + sector = node->m_sector; + + slope = (sector->heightsec != -1) ? NULL : sector->f_slope; + z = slope ? P_GetZAt(slope, thing->x, thing->y) : ( + (sector->heightsec != -1) ? sectors[sector->heightsec].floorheight : sector->floorheight + ); + + if (z < thing->z+thing->height/2 && z > floorz) + { + floorz = z; + floorslope = slope; + } + + if (sector->ffloors) + for (rover = sector->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES) || (rover->alpha < 90 && !(rover->flags & FF_SWIMMABLE))) + continue; + + z = *rover->t_slope ? P_GetZAt(*rover->t_slope, thing->x, thing->y) : *rover->topheight; + if (z < thing->z+thing->height/2 && z > floorz) + { + floorz = z; + floorslope = *rover->t_slope; + } + } + } + + if (thing->floorz > floorz + (!floorslope ? 0 : FixedMul(abs(floorslope->zdelta), thing->radius*3/2))) + { + floorz = thing->floorz; + floorslope = NULL; + } + +#if 0 // Unfortunately, this drops CEZ2 down to sub-17 FPS on my i7. +//#ifdef POLYOBJECTS + // Check polyobjects and see if floorz needs to be altered, for rings only because they don't update floorz + if (thing->type == MT_RING) + { + INT32 xl, xh, yl, yh, bx, by; + + xl = (unsigned)(thing->x - thing->radius - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(thing->x + thing->radius - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(thing->y - thing->radius - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(thing->y + thing->radius - bmaporgy)>>MAPBLOCKSHIFT; + + BMBOUNDFIX(xl, xh, yl, yh); + + validcount++; + + for (by = yl; by <= yh; by++) + for (bx = xl; bx <= xh; bx++) + { + INT32 offset; + polymaplink_t *plink; // haleyjd 02/22/06 + + if (bx < 0 || by < 0 || bx >= bmapwidth || by >= bmapheight) + continue; + + offset = by*bmapwidth + bx; + + // haleyjd 02/22/06: consider polyobject lines + plink = polyblocklinks[offset]; + + while (plink) + { + polyobj_t *po = plink->po; + + if (po->validcount != validcount) // if polyobj hasn't been checked + { + po->validcount = validcount; + + if (!P_MobjInsidePolyobj(po, thing) || !(po->flags & POF_RENDERPLANES)) + { + plink = (polymaplink_t *)(plink->link.next); + continue; + } + + // We're inside it! Yess... + z = po->lines[0]->backsector->ceilingheight; + + if (z < thing->z+thing->height/2 && z > floorz) + { + floorz = z; + floorslope = NULL; + } + } + plink = (polymaplink_t *)(plink->link.next); + } + } + } +#endif + + if (shadowslope != NULL) + *shadowslope = floorslope; + + return floorz; +} + +static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, fixed_t tx, fixed_t tz) +{ + vissprite_t *shadow; + patch_t *patch; + fixed_t xscale, yscale, shadowxscale, shadowyscale, shadowskew, x1, x2; + INT32 light = 0; + fixed_t scalemul; UINT8 trans; + fixed_t floordiff; + fixed_t floorz; + pslope_t *floorslope; + + floorz = R_GetShadowZ(thing, &floorslope); + + if (abs(floorz-viewz)/tz > 4) return; // Prevent stretchy shadows and possible crashes + + floordiff = abs(thing->z - floorz); + + trans = floordiff / (100*FRACUNIT) + 3; + if (trans >= 9) return; + + scalemul = FixedMul(FRACUNIT - floordiff/640, scale); + + if (thing->whiteshadow) + patch = W_CachePatchName("LSHADOW", PU_CACHE); + else + patch = W_CachePatchName("DSHADOW", PU_CACHE); + + xscale = FixedDiv(projection, tz); + yscale = FixedDiv(projectiony, tz); + shadowxscale = FixedMul(thing->radius*2, scalemul); + shadowyscale = FixedMul(FixedMul(thing->radius*2, scalemul), FixedDiv(abs(floorz - viewz), tz)); + shadowyscale = min(shadowyscale, shadowxscale) / patch->height; + shadowxscale /= patch->width; + shadowskew = 0; + + if (floorslope) + { + // haha let's try some dumb stuff + fixed_t xslope, zslope; + angle_t sloperelang = (R_PointToAngle(thing->x, thing->y) - floorslope->xydirection) >> ANGLETOFINESHIFT; + + xslope = FixedMul(FINESINE(sloperelang), floorslope->zdelta); + zslope = FixedMul(FINECOSINE(sloperelang), floorslope->zdelta); + + //CONS_Printf("Shadow is sloped by %d %d\n", xslope, zslope); + + if (viewz < floorz) + shadowyscale += FixedMul(FixedMul(thing->radius*2 / patch->height, scalemul), zslope); + else + shadowyscale -= FixedMul(FixedMul(thing->radius*2 / patch->height, scalemul), zslope); + + shadowyscale = abs(shadowyscale); + + shadowskew = xslope; + } + + tx -= patch->width * shadowxscale/2; + x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; + if (x1 >= viewwidth) return; + + tx += patch->width * shadowxscale; + x2 = ((centerxfrac + FixedMul(tx,xscale))>>FRACBITS); x2--; + if (x2 < 0 || x2 <= x1) return; + + if (shadowyscale < FRACUNIT/patch->height) return; // fix some crashes? + + shadow = R_NewVisSprite(); + + if (thing->whiteshadow) + shadow->patch = W_CheckNumForName("LSHADOW"); + else + shadow->patch = W_CheckNumForName("DSHADOW"); + + shadow->heightsec = vis->heightsec; + + shadow->thingheight = FRACUNIT; + shadow->pz = floorz; + shadow->pzt = shadow->pz + shadow->thingheight; + + shadow->mobjflags = 0; + shadow->sortscale = vis->sortscale; + shadow->dispoffset = vis->dispoffset - 5; + shadow->gx = thing->x; + shadow->gy = thing->y; + shadow->gzt = shadow->pz + patch->height * shadowyscale / 2; + shadow->gz = shadow->gzt - patch->height * shadowyscale; + shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewz, shadowyscale)); + if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) + shadow->texturemid = FixedMul(shadow->texturemid, ((skin_t *)thing->skin)->highresscale); + shadow->scalestep = 0; + shadow->shear.tan = shadowskew; // repurposed variable + + shadow->mobj = thing; // Easy access! Tails 06-07-2002 + + shadow->x1 = x1 < 0 ? 0 : x1; + shadow->x2 = x2 >= viewwidth ? viewwidth-1 : x2; + + // PORTAL SEMI-CLIPPING + if (portalrender) + { + if (shadow->x1 < portalclipstart) + shadow->x1 = portalclipstart; + if (shadow->x2 >= portalclipend) + shadow->x2 = portalclipend-1; + } + + shadow->xscale = FixedMul(xscale, shadowxscale); //SoM: 4/17/2000 + shadow->scale = FixedMul(yscale, shadowyscale); + shadow->sector = vis->sector; + shadow->szt = (INT16)((centeryfrac - FixedMul(shadow->gzt - viewz, yscale))>>FRACBITS); + shadow->sz = (INT16)((centeryfrac - FixedMul(shadow->gz - viewz, yscale))>>FRACBITS); + shadow->cut = SC_ISSCALED|SC_SHADOW; //check this + + shadow->startfrac = 0; + //shadow->xiscale = 0x7ffffff0 / (shadow->xscale/2); + shadow->xiscale = (patch->width<x1 > x1) + shadow->startfrac += shadow->xiscale*(shadow->x1-x1); + + // reusing x1 variable + x1 += (x2-x1)/2; + shadow->shear.offset = shadow->x1-x1; + + if (thing->subsector->sector->numlights) + { + INT32 lightnum; +#ifdef ESLOPE // R_GetPlaneLight won't work on sloped lights! + light = thing->subsector->sector->numlights - 1; + + for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) { + fixed_t h = thing->subsector->sector->lightlist[lightnum].slope ? P_GetZAt(thing->subsector->sector->lightlist[lightnum].slope, thing->x, thing->y) + : thing->subsector->sector->lightlist[lightnum].height; + if (h <= shadow->gzt) { + light = lightnum - 1; + break; + } + } +#else + light = R_GetPlaneLight(thing->subsector->sector, shadow->gzt, false); +#endif + } + + if (thing->subsector->sector->numlights) + shadow->extra_colormap = thing->subsector->sector->lightlist[light].extra_colormap; + else + shadow->extra_colormap = thing->subsector->sector->extra_colormap; + + shadow->transmap = transtables + (trans<whiteshadow) + shadow->colormap = scalelight[LIGHTLEVELS - 1][0]; // full bright! + else + shadow->colormap = scalelight[0][0]; // full dark! + + objectsdrawn++; +} + // // R_ProjectSprite // Generates a vissprite for a thing @@ -1168,7 +1458,11 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t iscale; fixed_t scalestep; // toast '16 fixed_t offset, offset2; - boolean papersprite = (thing->frame & FF_PAPERSPRITE); + + fixed_t basetx; // drop shadows + + boolean papersprite = !!(thing->frame & FF_PAPERSPRITE); + fixed_t paperoffset = 0, paperdistance = 0; angle_t centerangle = 0; //SoM: 3/17/2000 fixed_t gz, gzt; @@ -1176,8 +1470,6 @@ static void R_ProjectSprite(mobj_t *thing) INT32 light = 0; fixed_t this_scale = thing->scale; - fixed_t ang_scale = FRACUNIT; - // transform the origin point tr_x = thing->x - viewx; tr_y = thing->y - viewy; @@ -1188,15 +1480,15 @@ static void R_ProjectSprite(mobj_t *thing) tz = gxt-gyt; // thing is behind view plane? - if (!(papersprite) && (tz < FixedMul(MINZ, this_scale))) // papersprite clipping is handled later + if (!papersprite && (tz < FixedMul(MINZ, this_scale))) // papersprite clipping is handled later return; gxt = -FixedMul(tr_x, viewsin); gyt = FixedMul(tr_y, viewcos); - tx = -(gyt + gxt); + basetx = tx = -(gyt + gxt); // too far off the side? - if (abs(tx) > tz<<2) + if (!papersprite && abs(tx) > tz<<2) // papersprite clipping is handled later return; // aspect ratio stuff @@ -1249,8 +1541,6 @@ static void R_ProjectSprite(mobj_t *thing) ang = R_PointToAngle (thing->x, thing->y) - thing->player->frameangle; else ang = R_PointToAngle (thing->x, thing->y) - thing->angle; - if (papersprite) - ang_scale = abs(FINESINE(ang>>ANGLETOFINESHIFT)); } if (sprframe->rotate == SRF_SINGLE) @@ -1288,27 +1578,12 @@ static void R_ProjectSprite(mobj_t *thing) else offset = -spritecachedinfo[lump].offset; offset = FixedMul(offset, this_scale); - tx += FixedMul(offset, ang_scale); - x1 = (centerxfrac + FixedMul (tx,xscale)) >>FRACBITS; - - // off the right side? - if (x1 > viewwidth) - return; - offset2 = FixedMul(spritecachedinfo[lump].width, this_scale); - tx += FixedMul(offset2, ang_scale); - x2 = ((centerxfrac + FixedMul (tx,xscale)) >> FRACBITS) - 1; - - // off the left side - if (x2 < 0) - return; if (papersprite) { - fixed_t yscale2, cosmul, sinmul, tz2; - - if (x2 <= x1) - return; + fixed_t xscale2, yscale2, cosmul, sinmul, tx2, tz2; + INT32 range; if (ang >= ANGLE_180) { @@ -1325,7 +1600,23 @@ static void R_ProjectSprite(mobj_t *thing) gyt = -FixedMul(tr_y, viewsin); tz = gxt-gyt; yscale = FixedDiv(projectiony, tz); - if (yscale < 64) return; // Fix some funky visuals + //if (yscale < 64) return; // Fix some funky visuals + + gxt = -FixedMul(tr_x, viewsin); + gyt = FixedMul(tr_y, viewcos); + tx = -(gyt + gxt); + xscale = FixedDiv(projection, tz); + x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; + + // Get paperoffset (offset) and paperoffset (distance) + paperoffset = -FixedMul(tr_x, cosmul) - FixedMul(tr_y, sinmul); + paperdistance = -FixedMul(tr_x, sinmul) + FixedMul(tr_y, cosmul); + if (paperdistance < 0) + { + paperoffset = -paperoffset; + paperdistance = -paperdistance; + } + centerangle = viewangle - thing->angle; tr_x += FixedMul(offset2, cosmul); tr_y += FixedMul(offset2, sinmul); @@ -1333,13 +1624,52 @@ static void R_ProjectSprite(mobj_t *thing) gyt = -FixedMul(tr_y, viewsin); tz2 = gxt-gyt; yscale2 = FixedDiv(projectiony, tz2); - if (yscale2 < 64) return; // ditto + //if (yscale2 < 64) return; // ditto + + gxt = -FixedMul(tr_x, viewsin); + gyt = FixedMul(tr_y, viewcos); + tx2 = -(gyt + gxt); + xscale2 = FixedDiv(projection, tz2); + x2 = ((centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS); if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier return; - scalestep = (yscale2 - yscale)/(x2 - x1); - scalestep = scalestep ? scalestep : 1; + // Needs partially clipped + if (tz < FixedMul(MINZ, this_scale)) + { + fixed_t div = FixedDiv(tz2-tz, FixedMul(MINZ, this_scale)-tz); + tx += FixedDiv(tx2-tx, div); + tz = FixedMul(MINZ, this_scale); + yscale = FixedDiv(projectiony, tz); + xscale = FixedDiv(projection, tz); + x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; + } + else if (tz2 < FixedMul(MINZ, this_scale)) + { + fixed_t div = FixedDiv(tz-tz2, FixedMul(MINZ, this_scale)-tz2); + tx2 += FixedDiv(tx-tx2, div); + tz2 = FixedMul(MINZ, this_scale); + yscale2 = FixedDiv(projectiony, tz2); + xscale2 = FixedDiv(projection, tz2); + x2 = (centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS; + } + + // off the right side? + if (x1 > viewwidth) + return; + + // off the left side + if (x2 < 0) + return; + + if ((range = x2 - x1) <= 0) + return; + + range++; // fencepost problem + + scalestep = ((yscale2 - yscale)/range) ?: 1; + xscale = FixedDiv(range<>FRACBITS; - xscale = FixedMul(xscale, ang_scale); + // off the right side? + if (x1 > viewwidth) + return; + + tx += offset2; + x2 = ((centerxfrac + FixedMul(tx,xscale))>>FRACBITS); x2--; + + // off the left side + if (x2 < 0) + return; + } // PORTAL SPRITE CLIPPING if (portalrender) @@ -1445,6 +1786,11 @@ static void R_ProjectSprite(mobj_t *thing) vis->pzt = vis->pz + vis->thingheight; vis->texturemid = vis->gzt - viewz; vis->scalestep = scalestep; + vis->paperoffset = paperoffset; + vis->paperdistance = paperdistance; + vis->centerangle = centerangle; + vis->shear.tan = 0; + vis->shear.offset = 0; vis->mobj = thing; // Easy access! Tails 06-07-2002 @@ -1537,6 +1883,9 @@ static void R_ProjectSprite(mobj_t *thing) if (thing->subsector->sector->numlights) R_SplitSprite(vis); + if (thing->shadowscale && cv_shadow.value) + R_ProjectDropShadow(thing, vis, thing->shadowscale, basetx, tz); + // Debug ++objectsdrawn; } @@ -1639,14 +1988,10 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) // okay, we can't return now except for vertical clipping... this is a hack, but weather isn't networked, so it should be ok if (!(thing->precipflags & PCF_THUNK)) { - if (thing->precipflags & PCF_RAIN) - P_RainThinker(thing); - else - P_SnowThinker(thing); + P_PrecipThinker(thing); thing->precipflags |= PCF_THUNK; } - //SoM: 3/17/2000: Disregard sprites that are out of view.. gzt = thing->z + spritecachedinfo[lump].topoffset; gz = gzt - spritecachedinfo[lump].height; @@ -1670,6 +2015,9 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) vis->pzt = vis->pz + vis->thingheight; vis->texturemid = vis->gzt - viewz; vis->scalestep = 0; + vis->paperdistance = 0; + vis->shear.tan = 0; + vis->shear.offset = 0; vis->x1 = x1 < 0 ? 0 : x1; vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; diff --git a/src/r_things.h b/src/r_things.h index 4837b4aee..a50e0803d 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -50,6 +50,8 @@ void R_SortVisSprites(void); // (only sprites from namelist are added or replaced) void R_AddSpriteDefs(UINT16 wadnum); +fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope); + #ifdef DELFILE void R_DelSpriteDefs(UINT16 wadnum); #endif @@ -114,7 +116,8 @@ typedef enum SC_FULLBRIGHT = 1<<4, SC_SEMIBRIGHT = 1<<5, SC_VFLIP = 1<<6, - SC_ISSCALED = 1>>7, + SC_ISSCALED = 1<<7, + SC_SHADOW = 1<<8, // masks SC_CUTMASK = SC_TOP|SC_BOTTOM, SC_FLAGMASK = ~SC_CUTMASK @@ -139,8 +142,16 @@ typedef struct vissprite_s fixed_t startfrac; // horizontal position of x1 fixed_t scale, sortscale; // sortscale only differs from scale for flat sprites fixed_t scalestep; // only for flat sprites, 0 otherwise + fixed_t paperoffset, paperdistance; // for paper sprites, offset/dist relative to the angle fixed_t xiscale; // negative if flipped + angle_t centerangle; // for paper sprites + + struct { + fixed_t tan; // The amount to shear the sprite vertically per row + INT32 offset; // The center of the shearing location offset from x1 + } shear; + fixed_t texturemid; lumpnum_t patch; diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index e5f1c23fc..c900417ab 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1382,8 +1382,11 @@ void I_FinishUpdate(void) if (cv_ticrate.value) SCR_DisplayTicRate(); - if (cv_showping.value && netgame && consoleplayer != serverplayer) + if (cv_showping.value && netgame && + ( consoleplayer != serverplayer || ! server_lagless )) + { SCR_DisplayLocalPing(); + } } if (rendermode == render_soft && screens[0]) diff --git a/src/y_inter.c b/src/y_inter.c index f5380d565..ff168070c 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -435,6 +435,7 @@ void Y_IntermissionDrawer(void) INT32 y = 41, gutter = ((data.match.numplayers > NUMFORNEWCOLUMN) ? 0 : (BASEVIDWIDTH/2)); INT32 dupadjust = (vid.width/vid.dupx), duptweak = (dupadjust - BASEVIDWIDTH)/2; const char *timeheader; + int y2; if (data.match.rankingsmode) timeheader = "PWR.LV"; @@ -492,10 +493,41 @@ void Y_IntermissionDrawer(void) STRBUFCPY(strtime, data.match.name[i]); + y2 = y; + + if (data.match.num[i] == 0 && server_lagless) + { + static int alagles_timer = 0; + patch_t *alagles; + + y2 = ( y - 4 ); + + V_DrawScaledPatch(x + 36, y2, 0, W_CachePatchName(va("BLAGLES%d", (intertic / 3) % 6), PU_CACHE)); + // every 70 tics + if (( leveltime % 70 ) == 0) + { + alagles_timer = 9; + } + if (alagles_timer > 0) + { + alagles = W_CachePatchName(va("ALAGLES%d", alagles_timer), PU_CACHE); + V_DrawScaledPatch(x + 36, y2, 0, alagles); + if (( leveltime % 2 ) == 0) + alagles_timer--; + } + else + { + alagles = W_CachePatchName("ALAGLES0", PU_CACHE); + V_DrawScaledPatch(x + 36, y2, 0, alagles); + } + + y2 += SHORT (alagles->height) + 1; + } + if (data.match.numplayers > NUMFORNEWCOLUMN) - V_DrawThinString(x+36, y-1, ((data.match.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, strtime); + V_DrawThinString(x+36, y2-1, ((data.match.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, strtime); else - V_DrawString(x+36, y, ((data.match.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE, strtime); + V_DrawString(x+36, y2, ((data.match.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE, strtime); if (data.match.rankingsmode) {