diff --git a/src/deh_tables.c b/src/deh_tables.c index f113f6b19c8eb8b0a9c511406778db8bebd2e81d..15991a936199e0059d5082ef8b79f0b0b509ee43 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4483,6 +4483,8 @@ const char *const PLAYERFLAG_LIST[] = { "CANCARRY", // Can carry? "FINISHED", + "SHIELDDOWN", // Shield has been pressed. + NULL // stop loop here. }; diff --git a/src/filesrch.c b/src/filesrch.c index ea19e00cdc0abd38d3fd1b869751faad316b0b83..67a2e8976f88548c0f6f77b2143fbef6888d820f 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -444,12 +444,11 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name); #if defined(__linux__) || defined(__FreeBSD__) - if (dent->d_type == DT_UNKNOWN) - if (lstat(searchpath,&fsstat) == 0 && S_ISDIR(fsstat.st_mode)) + if (dent->d_type == DT_UNKNOWN || dent->d_type == DT_LNK) + if (stat(searchpath,&fsstat) == 0 && S_ISDIR(fsstat.st_mode)) dent->d_type = DT_DIR; // Linux and FreeBSD has a special field for file type on dirent, so use that to speed up lookups. - // FIXME: should we also follow symlinks? if (dent->d_type == DT_DIR && depthleft) #else if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 5dc0af89423547930e029503439b93154bde0473..87c5f8e328aa8e918d942cf9b1b506a0db9c2111 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -2880,7 +2880,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) } HWR_Lighting(&sSurf, 0, colormap); - sSurf.PolyColor.s.alpha = alpha; + sSurf.PolyColor.s.alpha = FixedMul(thing->alpha, alpha); if (HWR_UseShader()) { @@ -3054,11 +3054,16 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) // baseWallVerts is used to know the final shape to easily get the vertex // co-ordinates memcpy(wallVerts, baseWallVerts, sizeof(baseWallVerts)); + + fixed_t newalpha = spr->mobj->alpha; // if sprite has linkdraw, then dont write to z-buffer (by not using PF_Occlude) // this will result in sprites drawn afterwards to be drawn on top like intended when using linkdraw. if ((spr->mobj->flags2 & MF2_LINKDRAW) && spr->mobj->tracer) + { + newalpha = spr->mobj->tracer->alpha; occlusion = 0; + } else occlusion = PF_Occlude; @@ -3094,6 +3099,8 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) blend = HWR_GetBlendModeFlag(blendmode)|occlusion; if (!occlusion) use_linkdraw_hack = true; } + + Surf.PolyColor.s.alpha = FixedMul(newalpha, Surf.PolyColor.s.alpha); if (HWR_UseShader()) { @@ -3543,11 +3550,15 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) FBITFIELD blend = 0; FBITFIELD occlusion; boolean use_linkdraw_hack = false; + fixed_t newalpha = spr->mobj->alpha; // if sprite has linkdraw, then dont write to z-buffer (by not using PF_Occlude) // this will result in sprites drawn afterwards to be drawn on top like intended when using linkdraw. if ((spr->mobj->flags2 & MF2_LINKDRAW) && spr->mobj->tracer) + { occlusion = 0; + newalpha = spr->mobj->tracer->alpha; + } else occlusion = PF_Occlude; @@ -3583,6 +3594,8 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) blend = HWR_GetBlendModeFlag(blendmode)|occlusion; if (!occlusion) use_linkdraw_hack = true; } + + Surf.PolyColor.s.alpha = FixedMul(newalpha, Surf.PolyColor.s.alpha); if (spr->renderflags & RF_SHADOWEFFECTS) { diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index a1fbdaa14014da7ed48119ecddf29a4383f4f10a..2616d4085c4c9e8fa81e6ce82bfa2f30f072f68f 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1289,6 +1289,11 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) // Apparently people don't like jump frames like that, so back it goes //if (tics > durs) //durs = tics; + + // Make linkdraw objects use their tracer's alpha value + fixed_t newalpha = spr->mobj->alpha; + if ((spr->mobj->flags2 & MF2_LINKDRAW) && spr->mobj->tracer) + newalpha = spr->mobj->tracer->alpha; INT32 blendmode; if (spr->mobj->frame & FF_BLENDMASK) @@ -1303,6 +1308,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) Surf.PolyColor.s.alpha = (spr->mobj->flags2 & MF2_SHADOW) ? 0x40 : 0xff; Surf.PolyFlags = HWR_GetBlendModeFlag(blendmode); } + + Surf.PolyColor.s.alpha = FixedMul(newalpha, Surf.PolyColor.s.alpha); // don't forget to enable the depth test because we can't do this // like before: model polygons are not sorted diff --git a/src/hardware/hw_shaders.c b/src/hardware/hw_shaders.c index 36cbb5db949c7fae0e28c82b6c0fcb6bd1dd3a73..ee1e2acdf58cd73d810c1884cfc5ffe3e4797389 100644 --- a/src/hardware/hw_shaders.c +++ b/src/hardware/hw_shaders.c @@ -448,6 +448,101 @@ void HWR_LoadAllCustomShaders(void) HWR_LoadCustomShadersFromFile(i, W_FileHasFolders(wadfiles[i])); } +static const char version_directives[][14] = { + "#version 330\n", + "#version 150\n", + "#version 140\n", + "#version 130\n", + "#version 120\n", + "#version 110\n", +}; + +static boolean HWR_VersionDirectiveExists(const char* source) +{ + return strncmp(source, "#version", 8) == 0; +} + +static char* HWR_PrependVersionDirective(const char* source, UINT32 version_index) +{ + const UINT32 version_len = sizeof(version_directives[version_index]) - 1; + const UINT32 source_len = strlen(source); + + char* result = Z_Malloc(source_len + version_len + 1, PU_STATIC, NULL); + strcpy(result, version_directives[version_index]); + strcpy(result + version_len, source); + + return result; +} + +static void HWR_ReplaceVersionInplace(char* shader, UINT32 version_index) +{ + shader[9] = version_directives[version_index][9]; + shader[10] = version_directives[version_index][10]; + shader[11] = version_directives[version_index][11]; +} + +static boolean HWR_CheckVersionDirectives(const char* vert, const char* frag) +{ + return HWR_VersionDirectiveExists(vert) && HWR_VersionDirectiveExists(frag); +} + +static void HWR_TryToCompileShaderWithImplicitVersion(INT32 shader_index, INT32 shaderxlat_id) +{ + char* vert_shader = gl_shaders[shader_index].vertex; + char* frag_shader = gl_shaders[shader_index].fragment; + + boolean vert_shader_version_exists = HWR_VersionDirectiveExists(vert_shader); + boolean frag_shader_version_exists = HWR_VersionDirectiveExists(frag_shader); + + if(!vert_shader_version_exists) { + CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: vertex shader '%s' is missing a #version directive\n", HWR_GetShaderName(shaderxlat_id)); + } + + if(!frag_shader_version_exists) { + CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: fragment shader '%s' is missing a #version directive\n", HWR_GetShaderName(shaderxlat_id)); + } + + // try to compile as is + HWR_CompileShader(shader_index); + if (gl_shaders[shader_index].compiled) + return; + + // try each version directive + for(UINT32 i = 0; i < sizeof(version_directives) / sizeof(version_directives[0]); ++i) { + CONS_Alert(CONS_NOTICE, "HWR_TryToCompileShaderWithImplicitVersion: Trying %s\n", version_directives[i]); + + if(!vert_shader_version_exists) { + // first time reallocation would have to be made + + if(i == 0) { + void* old = (void*)gl_shaders[shader_index].vertex; + vert_shader = gl_shaders[shader_index].vertex = HWR_PrependVersionDirective(vert_shader, i); + Z_Free(old); + } else { + HWR_ReplaceVersionInplace(vert_shader, i); + } + } + + if(!frag_shader_version_exists) { + if(i == 0) { + void* old = (void*)gl_shaders[shader_index].fragment; + frag_shader = gl_shaders[shader_index].fragment = HWR_PrependVersionDirective(frag_shader, i); + Z_Free(old); + } else { + HWR_ReplaceVersionInplace(frag_shader, i); + } + } + + HWR_CompileShader(shader_index); + if (gl_shaders[shader_index].compiled) { + CONS_Alert(CONS_NOTICE, "HWR_TryToCompileShaderWithImplicitVersion: Compiled with %s\n", + version_directives[i]); + CONS_Alert(CONS_WARNING, "Implicit GLSL version is used. Correct behavior is not guaranteed\n"); + return; + } + } +} + void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3) { UINT16 lump; @@ -610,7 +705,13 @@ skip_field: gl_shaders[shader_index].fragment = Z_StrDup(gl_shadersources[i].fragment); if (!gl_shaders[shader_index].vertex) gl_shaders[shader_index].vertex = Z_StrDup(gl_shadersources[i].vertex); - HWR_CompileShader(shader_index); + + if(!HWR_CheckVersionDirectives(gl_shaders[shader_index].vertex, gl_shaders[shader_index].fragment)) { + HWR_TryToCompileShaderWithImplicitVersion(shader_index, i); + } else { + HWR_CompileShader(shader_index); + } + if (!gl_shaders[shader_index].compiled) CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: A compilation error occured for the %s shader in file %s. See the console messages above for more information.\n", shaderxlat[i].type, wadfiles[wadnum]->filename); } diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 6d2c8661ee977603dc0f4013bdfdb43ef153d5b4..304c866c9c9ee6c8fc78b0c860a8a0ed09d83cb3 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3878,7 +3878,7 @@ static int lib_gAddPlayer(lua_State *L) player_t *newplayer; SINT8 skinnum = 0, bot; - for (i = 0; i < MAXPLAYERS; i++) + for (i = 1; i < MAXPLAYERS; i++) { if (!playeringame[i]) break; diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index de7065790abb137e82f505c961215ca6acb10429..eadcbe33b0b676447f43f6479693046e507c02b6 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -69,6 +69,7 @@ enum mobj_e { mobj_color, mobj_translation, mobj_blendmode, + mobj_alpha, mobj_bnext, mobj_bprev, mobj_hnext, @@ -150,6 +151,7 @@ static const char *const mobj_opt[] = { "color", "translation", "blendmode", + "alpha", "bnext", "bprev", "hnext", @@ -354,6 +356,9 @@ static int mobj_get(lua_State *L) case mobj_blendmode: lua_pushinteger(L, mo->blendmode); break; + case mobj_alpha: + lua_pushfixed(L, mo->alpha); + break; case mobj_bnext: if (mo->blocknode && mo->blocknode->bnext) { LUA_PushUserdata(L, mo->blocknode->bnext->mobj, META_MOBJ); @@ -733,6 +738,16 @@ static int mobj_set(lua_State *L) mo->blendmode = blendmode; break; } + case mobj_alpha: + { + fixed_t alpha = luaL_checkfixed(L, 3); + if (alpha < 0) + alpha = 0; + else if (alpha > FRACUNIT) + alpha = FRACUNIT; + mo->alpha = alpha; + break; + } case mobj_bnext: return NOSETPOS; case mobj_bprev: diff --git a/src/m_menu.c b/src/m_menu.c index c4fccb372c376e72f15e54cc1410999f3648f878..7d4049df235adf33046a3883916e05ed41710ca9 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8610,7 +8610,7 @@ static void M_DrawLoadGameData(void) if (savegameinfo[savetodraw].lives == -42) col = 26; else if (savegameinfo[savetodraw].botskin == 3) // & knuckles - col = 105; + col = 106; else if (savegameinfo[savetodraw].botskin) // tailsbot or custom col = 134; else diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 2bf9d2dde7cb60266687282748142af5e676c917..d46e75c3f79dc475fa969cb6bdc48c06a4a938a8 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -114,6 +114,7 @@ static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, consvar_t cv_playbackspeed = CVAR_INIT ("playbackspeed", "1", 0, playbackspeed_cons_t, NULL); consvar_t cv_idletime = CVAR_INIT ("idletime", "0", CV_SAVE, CV_Unsigned, NULL); +consvar_t cv_idlespectate = CVAR_INIT ("idlespectate", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_dedicatedidletime = CVAR_INIT ("dedicatedidletime", "10", CV_SAVE, CV_Unsigned, NULL); consvar_t cv_httpsource = CVAR_INIT ("http_source", "", CV_SAVE, NULL, NULL); @@ -1362,7 +1363,7 @@ static void IdleUpdate(void) for (i = 1; i < MAXPLAYERS; i++) { - if (cv_idletime.value && playeringame[i] && playernode[i] != UINT8_MAX && !players[i].quittime && !players[i].spectator && !players[i].bot && !IsPlayerAdmin(i) && i != serverplayer && gamestate == GS_LEVEL) + if (cv_idletime.value && playeringame[i] && playernode[i] != UINT8_MAX && !players[i].quittime && !players[i].spectator && !players[i].bot && !IsPlayerAdmin(i) && i != serverplayer && gamestate == GS_LEVEL && !(players[i].pflags & PF_FINISHED)) { if (players[i].cmd.forwardmove || players[i].cmd.sidemove || players[i].cmd.buttons) players[i].lastinputtime = 0; @@ -1372,7 +1373,21 @@ static void IdleUpdate(void) if (players[i].lastinputtime > (tic_t)cv_idletime.value * TICRATE * 60) { players[i].lastinputtime = 0; - SendKick(i, KICK_MSG_IDLE | KICK_MSG_KEEP_BODY); + if (cv_idlespectate.value && G_GametypeHasSpectators()) + { + changeteam_union NetPacket; + UINT16 usvalue; + NetPacket.value.l = NetPacket.value.b = 0; + NetPacket.packet.newteam = 0; + NetPacket.packet.playernum = i; + NetPacket.packet.verification = true; // This signals that it's a server change + usvalue = SHORT(NetPacket.value.l|NetPacket.value.b); + SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue)); + } + else + { + SendKick(i, KICK_MSG_IDLE | KICK_MSG_KEEP_BODY); + } } } else diff --git a/src/netcode/d_clisrv.h b/src/netcode/d_clisrv.h index 5aac4693d2fdd166cee7a796166ba7c798e183c8..342173dff5bf575a762433a4cb2ad753a61685a0 100644 --- a/src/netcode/d_clisrv.h +++ b/src/netcode/d_clisrv.h @@ -73,7 +73,7 @@ extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS]; extern tic_t servermaxping; -extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed, cv_idletime, cv_dedicatedidletime; +extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed, cv_idletime, cv_idlespectate, cv_dedicatedidletime; extern consvar_t cv_httpsource; // Used in d_net, the only dependence diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c index f7b98c4dbaff55d58481b5c439623a92fcd4e4c4..4134c633e5a32e23e6be085a32300bb308a694df 100644 --- a/src/netcode/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -620,6 +620,7 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_blamecfail); CV_RegisterVar(&cv_dedicatedidletime); CV_RegisterVar(&cv_idletime); + CV_RegisterVar(&cv_idlespectate); CV_RegisterVar(&cv_httpsource); COM_AddCommand("ping", Command_Ping_f, COM_LUA); @@ -2510,11 +2511,11 @@ static void MutePlayer(boolean mute) if (COM_Argc() < 2) { - CONS_Printf(M_GetText("muteplayer <playernum>: mute a player\n")); + CONS_Printf(M_GetText("muteplayer <playername/playernum>: mute a player\n")); return; } - data[0] = atoi(COM_Argv(1)); + data[0] = nametonum(COM_Argv(1)); if (data[0] >= MAXPLAYERS || !playeringame[data[0]]) { CONS_Alert(CONS_NOTICE, M_GetText("There is no player %u!\n"), (unsigned int)data[0]); @@ -2603,11 +2604,11 @@ static void Command_ServerTeamChange_f(void) if (COM_Argc() < 3) { if (G_TagGametype()) - CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "it, notit, playing, or spectator"); + CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "it, notit, playing, or spectator"); else if (G_GametypeHasTeams()) - CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator"); + CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator"); else if (G_GametypeHasSpectators()) - CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "spectator or playing"); + CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "spectator or playing"); else CONS_Alert(CONS_NOTICE, M_GetText("This command cannot be used in this gametype.\n")); return; @@ -2655,19 +2656,19 @@ static void Command_ServerTeamChange_f(void) if (error) { if (G_TagGametype()) - CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "it, notit, playing, or spectator"); + CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "it, notit, playing, or spectator"); else if (G_GametypeHasTeams()) - CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator"); + CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator"); else if (G_GametypeHasSpectators()) - CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "spectator or playing"); + CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "spectator or playing"); return; } - NetPacket.packet.playernum = atoi(COM_Argv(1)); + NetPacket.packet.playernum = nametonum(COM_Argv(1)); - if (!playeringame[NetPacket.packet.playernum]) + if (NetPacket.packet.playernum == -1 || !playeringame[NetPacket.packet.playernum]) { - CONS_Alert(CONS_NOTICE, M_GetText("There is no player %d!\n"), NetPacket.packet.playernum); + CONS_Alert(CONS_NOTICE, M_GetText("There is no player %s!\n"), COM_Argv(1)); return; } @@ -3106,13 +3107,16 @@ static void Command_Verify_f(void) if (COM_Argc() != 2) { - CONS_Printf(M_GetText("promote <playernum>: give admin privileges to a player\n")); + CONS_Printf(M_GetText("promote <playername/playernum>: give admin privileges to a player\n")); return; } - strlcpy(buf, COM_Argv(1), sizeof (buf)); - - playernum = atoi(buf); + playernum = nametonum(COM_Argv(1)); + if (playernum == -1) + { + CONS_Alert(CONS_NOTICE, M_GetText("There is no player %s!\n"), COM_Argv(1)); + return; + } temp = buf; @@ -3156,13 +3160,16 @@ static void Command_RemoveAdmin_f(void) if (COM_Argc() != 2) { - CONS_Printf(M_GetText("demote <playernum>: remove admin privileges from a player\n")); + CONS_Printf(M_GetText("demote <playername/playernum>: remove admin privileges from a player\n")); return; } - strlcpy(buf, COM_Argv(1), sizeof(buf)); - - playernum = atoi(buf); + playernum = nametonum(COM_Argv(1)); + if (playernum == -1) + { + CONS_Alert(CONS_NOTICE, M_GetText("There is no player %s!\n"), COM_Argv(1)); + return; + } temp = buf; diff --git a/src/p_inter.c b/src/p_inter.c index e73cd1fce675ee17721e6236e7dc764ede8e9d69..cbd56183df855ed0d8afc9e308bea5e05a7d0fee 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3786,6 +3786,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (player->powers[pw_carry] == CR_NIGHTSMODE) // NiGHTS damage handling { + if (player->powers[pw_flashing]) + return false; if (!force) { if (source == target) @@ -3803,6 +3805,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (G_IsSpecialStage(gamemap) && !(damagetype & DMG_DEATHMASK)) { + if (player->powers[pw_flashing]) + return false; + if (LUA_HookMobjDamage(target, inflictor, source, damage, damagetype)) + return true; P_SpecialStageDamage(player, inflictor, source); return true; } diff --git a/src/p_map.c b/src/p_map.c index 668a8ab6413ccda17adccf994c18e7f2dc58f58d..b8584205b8082cd284a5aae81382882781d85ab6 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1258,8 +1258,9 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) if (tmthing->type != MT_SHELL && tmthing->target && tmthing->target->type == thing->type) { - // Don't hit same species as originator. - if (thing == tmthing->target) + // Don't hit yourself, and if a player, don't hit bots + if (thing == tmthing->target + || (thing->player && tmthing->target->player && (thing->player->bot == BOT_2PAI || thing->player->bot == BOT_2PHUMAN))) return CHECKTHING_IGNORE; if (thing->type != MT_PLAYER) @@ -3960,23 +3961,25 @@ papercollision: mo->momy = tmymove; } + const fixed_t tmradius = mo->radius > 8 ? mo->radius : 8; + do { - if (tmxmove > mo->radius) { - newx = mo->x + mo->radius; - tmxmove -= mo->radius; - } else if (tmxmove < -mo->radius) { - newx = mo->x - mo->radius; - tmxmove += mo->radius; + if (tmxmove > tmradius) { + newx = mo->x + tmradius; + tmxmove -= tmradius; + } else if (tmxmove < -tmradius) { + newx = mo->x - tmradius; + tmxmove += tmradius; } else { newx = mo->x + tmxmove; tmxmove = 0; } - if (tmymove > mo->radius) { - newy = mo->y + mo->radius; - tmymove -= mo->radius; - } else if (tmymove < -mo->radius) { - newy = mo->y - mo->radius; - tmymove += mo->radius; + if (tmymove > tmradius) { + newy = mo->y + tmradius; + tmymove -= tmradius; + } else if (tmymove < -tmradius) { + newy = mo->y - tmradius; + tmymove += tmradius; } else { newy = mo->y + tmymove; tmymove = 0; diff --git a/src/p_mobj.c b/src/p_mobj.c index 3ca6093906b3da9725cf95f6edb3ee5b78b9cae0..1ec09ab8582adea2716db0d817b670bf4aba0d2c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2246,7 +2246,7 @@ boolean P_ZMovement(mobj_t *mo) else if (!onground) P_SlopeLaunch(mo); } - + if (!mo->player && P_CheckDeathPitCollide(mo) && mo->health && !(mo->flags & MF_NOCLIPHEIGHT) && !(mo->flags2 & MF2_BOSSDEAD)) { @@ -2939,7 +2939,7 @@ boolean P_SceneryZMovement(mobj_t *mo) mo->eflags &= ~MFE_APPLYPMOMZ; } mo->z += mo->momz; - + if (!mo->player && P_CheckDeathPitCollide(mo) && mo->health && !(mo->flags & MF_NOCLIPHEIGHT) && !(mo->flags2 & MF2_BOSSDEAD)) { @@ -3782,7 +3782,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj) // always do the gravity bit now, that's simpler // BUT CheckPosition only if wasn't done before. - if (!(mobj->eflags & MFE_ONGROUND) || mobj->momz + if (mobj->momz || ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z + mobj->height != mobj->ceilingz) || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z != mobj->floorz) || P_IsObjectInGoop(mobj)) @@ -3795,17 +3795,6 @@ static void P_PlayerMobjThinker(mobj_t *mobj) } else { -#if 0 // i don't know why this is here, it's causing a few undesired state glitches, and disabling it doesn't appear to negatively affect the game, but i don't want it gone permanently just in case some obscure bug crops up - if (!(mobj->player->powers[pw_carry] == CR_NIGHTSMODE)) // used for drilling - mobj->player->pflags &= ~PF_STARTJUMP; - mobj->player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); - if (mobj->player->secondjump || mobj->player->powers[pw_tailsfly]) - { - mobj->player->secondjump = 0; - mobj->player->powers[pw_tailsfly] = 0; - P_SetMobjState(mobj, S_PLAY_WALK); - } -#endif mobj->eflags &= ~MFE_JUSTHITFLOOR; } @@ -10355,6 +10344,7 @@ void P_MobjThinker(mobj_t *mobj) case MT_GRENADEPICKUP: if (mobj->health == 0) // Fading tile { + // TODO: Maybe use mobj->alpha instead of messing with frame flags INT32 value = mobj->info->damage/10; value = mobj->fuse/value; value = 10-value; @@ -10700,6 +10690,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) // Sprite rendering mobj->blendmode = AST_TRANSLUCENT; + mobj->alpha = FRACUNIT; mobj->spritexscale = mobj->spriteyscale = mobj->scale; mobj->spritexoffset = mobj->spriteyoffset = 0; mobj->floorspriteslope = NULL; @@ -10744,7 +10735,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) // Set shadowscale here, before spawn hook so that Lua can change it mobj->shadowscale = P_DefaultMobjShadowScale(mobj); - + // A monitor can't respawn if we're not in multiplayer, // or if we're in co-op and it's score or a 1up if (mobj->flags & MF_MONITOR && (!(netgame || multiplayer) diff --git a/src/p_mobj.h b/src/p_mobj.h index 2f013a2f30fac7f7d117cb190fcbc5bd1db17e54..f281410f6ddc7ece41acc963afe63a6b23420269 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -313,6 +313,7 @@ typedef struct mobj_s UINT32 renderflags; // render flags INT32 blendmode; // blend mode + fixed_t alpha; // alpha fixed_t spritexscale, spriteyscale; fixed_t spritexoffset, spriteyoffset; fixed_t old_spritexscale, old_spriteyscale, old_spritexscale2, old_spriteyscale2; @@ -456,6 +457,7 @@ typedef struct precipmobj_s UINT32 renderflags; // render flags INT32 blendmode; // blend mode + fixed_t alpha; // alpha fixed_t spritexscale, spriteyscale; fixed_t spritexoffset, spriteyoffset; fixed_t old_spritexscale, old_spriteyscale, old_spritexscale2, old_spriteyscale2; diff --git a/src/p_saveg.c b/src/p_saveg.c index 5e4d6d0760441e6bc94c6815824b8b7e1ab38c80..219410bb63741e0ca0eb138cc57cf3323665e297 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1746,7 +1746,8 @@ typedef enum MD2_DISPOFFSET = 1<<23, MD2_DRAWONLYFORPLAYER = 1<<24, MD2_DONTDRAWFORVIEWMOBJ = 1<<25, - MD2_TRANSLATION = 1<<26 + MD2_TRANSLATION = 1<<26, + MD2_ALPHA = 1<<27 } mobj_diff2_t; typedef enum @@ -1989,6 +1990,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_DONTDRAWFORVIEWMOBJ; if (mobj->dispoffset != mobj->info->dispoffset) diff2 |= MD2_DISPOFFSET; + if (mobj->alpha != FRACUNIT) + diff2 |= MD2_ALPHA; if (diff2 != 0) diff |= MD_MORE; @@ -2172,6 +2175,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, mobj->dispoffset); if (diff2 & MD2_TRANSLATION) WRITEUINT16(save_p, mobj->translation); + if (diff2 & MD2_ALPHA) + WRITEFIXED(save_p, mobj->alpha); WRITEUINT32(save_p, mobj->mobjnum); } @@ -3238,6 +3243,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->dispoffset = mobj->info->dispoffset; if (diff2 & MD2_TRANSLATION) mobj->translation = READUINT16(save_p); + if (diff2 & MD2_ALPHA) + mobj->alpha = READFIXED(save_p); if (diff & MD_REDFLAG) { diff --git a/src/p_user.c b/src/p_user.c index 7ad5bccbb58db303a28c9b3fe438b7effdea3c90..ea68f9443cb4b7eb438f4992899683a1b5b7553b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -976,6 +976,9 @@ pflags_t P_GetJumpFlags(player_t *player) // boolean P_PlayerInPain(player_t *player) { + if (P_MobjWasRemoved(player->mo)) + return false; + // no silly, sliding isn't pain if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing]) return true; @@ -2078,6 +2081,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->renderflags = mobj->renderflags; ghost->blendmode = mobj->blendmode; + ghost->alpha = mobj->alpha; ghost->spritexscale = mobj->spritexscale; ghost->spriteyscale = mobj->spriteyscale; diff --git a/src/r_segs.c b/src/r_segs.c index 8e9368bafde86847e8b4ddca0bc25c5aef6fe52e..303de88807bcbbb7289b948e268c71c0d3a30914 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -1004,25 +1004,21 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { dc_iscale = 0xffffffffu / (unsigned)spryscale; - // Skip if texture is multipatch - if (textures[texnum]->transparency) + // Column has a single post and it matches the texture height, use regular column drawers + if (col->num_posts == 1 && col->posts[0].topdelta == 0 && col->posts[0].length == (unsigned)dc_texheight) { - // Column has a single post and it matches the texture height, use regular column drawers - if (col->num_posts == 1 && col->posts[0].topdelta == 0 && col->posts[0].length == (unsigned)dc_texheight) - { - if (fuzzy) - colfunc = colfuncs[COLDRAWFUNC_FUZZY]; - else - colfunc = colfuncs[BASEDRAWFUNC]; - } + if (fuzzy) + colfunc = colfuncs[COLDRAWFUNC_FUZZY]; else - { - // Otherwise use column drawers with extra checks - if (fuzzy) - colfunc = colfuncs[COLDRAWFUNC_CLAMPEDTRANS]; - else - colfunc = colfuncs[COLDRAWFUNC_CLAMPED]; - } + colfunc = colfuncs[BASEDRAWFUNC]; + } + else + { + // Otherwise use column drawers with extra checks + if (fuzzy) + colfunc = colfuncs[COLDRAWFUNC_CLAMPEDTRANS]; + else + colfunc = colfuncs[COLDRAWFUNC_CLAMPED]; } } diff --git a/src/r_things.c b/src/r_things.c index dc9cab99770817e5f05c6d13a281f3fa37668790..b32181670aa0ad9e3c5c59bcdc9f9fb2a810108d 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -996,6 +996,12 @@ UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 trans return NULL; } +// Based off of R_GetLinedefTransTable +transnum_t R_GetThingTransTable(fixed_t alpha, transnum_t transmap) +{ + return (20*(FRACUNIT - ((alpha * (10 - transmap))/10) - 1) + FRACUNIT) >> (FRACBITS+1); +} + // // R_DrawVisSprite // mfloorclip and mceilingclip should also be set. @@ -1501,6 +1507,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, floordiff = abs((isflipped ? interp.height : 0) + interp.z - groundz); trans = floordiff / (100*FRACUNIT) + 3; + trans = R_GetThingTransTable(thing->alpha, trans); if (trans >= 9) return; scalemul = FixedMul(FRACUNIT - floordiff/640, scale); @@ -2191,6 +2198,11 @@ static void R_ProjectSprite(mobj_t *thing) } else trans = 0; + + if ((oldthing->flags2 & MF2_LINKDRAW) && oldthing->tracer) + trans = R_GetThingTransTable(oldthing->tracer->alpha, trans); + else + trans = R_GetThingTransTable(oldthing->alpha, trans); // Check if this sprite needs to be rendered like a shadow shadowdraw = (!!(thing->renderflags & RF_SHADOWDRAW) && !(papersprite || splat)); @@ -3652,6 +3664,7 @@ boolean R_ThingVisible (mobj_t *thing) (thing->sprite == SPR_NULL) || // Don't draw null-sprites (thing->flags2 & MF2_DONTDRAW) || // Don't draw MF2_LINKDRAW objects (thing->drawonlyforplayer && thing->drawonlyforplayer != viewplayer) || // Don't draw other players' personal objects + (!R_BlendLevelVisible(thing->blendmode, R_GetThingTransTable(thing->alpha, 0))) || (!P_MobjWasRemoved(r_viewmobj) && ( (r_viewmobj == thing) || // Don't draw first-person players or awayviewmobj objects (r_viewmobj->player && r_viewmobj->player->followmobj == thing) || // Don't draw first-person players' followmobj diff --git a/src/r_things.h b/src/r_things.h index 3daf55c4235bc753aeb5f1c897856e6d9303338c..55ab71ec3847d5b85295904a18de516afa6f1b74 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -93,6 +93,7 @@ boolean R_ThingIsFullDark (mobj_t *thing); boolean R_ThingIsFlashing (mobj_t *thing); UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 translation); +transnum_t R_GetThingTransTable(fixed_t alpha, transnum_t transmap); void R_ThingOffsetOverlay (mobj_t *thing, fixed_t *outx, fixed_t *outy);