diff --git a/src/b_bot.c b/src/b_bot.c index af57d65ecf6e3c24e725ed38b9533b9ab6509763..6229cb1d61893b328e667ba357fbbefe333e51f4 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -387,7 +387,8 @@ void B_BuildTiccmd(player_t *player, ticcmd_t *cmd) } // Bot AI isn't programmed in analog. - CV_SetValue(&cv_analog[1], false); + if (!dedicated) + CV_SetValue(&cv_analog[1], false); // Let Lua scripts build ticcmds if (LUA_HookTiccmd(player, cmd, HOOK(BotTiccmd))) diff --git a/src/command.c b/src/command.c index a46cc98bcde4ad01557a31e439994135341a5c06..7947048ed986199816f5a9d9d9c1279bf5855b0b 100644 --- a/src/command.c +++ b/src/command.c @@ -1992,7 +1992,7 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth) if (var->flags & CV_NETVAR) { // send the value of the variable - UINT8 buf[128]; + UINT8 buf[512]; UINT8 *p = buf; // Loading from a config in a netgame? Set revert value. diff --git a/src/d_main.c b/src/d_main.c index 4904b6909c1b8b52e1e048a0e21293e410cc6fab..2405b01365ba8c47f4e54036839e7e704b6aaa4b 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -983,7 +983,7 @@ void D_StartTitle(void) emeralds = 0; memset(&luabanks, 0, sizeof(luabanks)); lastmaploaded = 0; - pickedchar = R_SkinAvailable(cv_defaultskin.string); + pickedchar = R_SkinAvailable(cv_skin.string); // In case someone exits out at the same time they start a time attack run, // reset modeattacking diff --git a/src/dedicated/i_system.c b/src/dedicated/i_system.c index 413b366b865c035a08ece29008c30004ea58666e..82dd51be0775a5ac0e4116391c24c5479481d2b6 100644 --- a/src/dedicated/i_system.c +++ b/src/dedicated/i_system.c @@ -1433,9 +1433,15 @@ static const char *locateWad(void) #ifndef NOHOME // find in $HOME - I_OutputMsg(",HOME"); + I_OutputMsg(",HOME/" DEFAULTDIR); if ((envstr = I_GetEnv("HOME")) != NULL) + { + char *tmp = malloc(strlen(envstr) + sizeof(DEFAULTDIR)); + strcpy(tmp, envstr); + strcat(tmp, DEFAULTDIR); SEARCHWAD(envstr); + free(tmp); + } #endif // search paths diff --git a/src/g_demo.c b/src/g_demo.c index 8d3e3563585e76ed9989c17373c835726a21eb90..cfa34fc7e76c7978a52603fdd05f3e55d19f3e17 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -551,6 +551,9 @@ void G_ConsGhostTic(void) testmo = players[0].mo; + if (P_MobjWasRemoved(testmo)) + return; // No valid mobj exists, probably because of unexpected quit + // Grab ghost data. ziptic = READUINT8(demo_p); if (ziptic & GZT_XYZ) diff --git a/src/g_game.c b/src/g_game.c index 8d19c9e7cb68df142e68e7d0277b2425153f9206..bf369d111bb2ea1da40514e1b2b6b5ad3845d0af 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1363,11 +1363,11 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) axis = PlayerJoyAxis(ssplayer, JA_FIRENORMAL); if (PLAYERINPUTDOWN(ssplayer, GC_FIRENORMAL) || (usejoystick && axis > 0)) cmd->buttons |= BT_FIRENORMAL; - + // Toss flag button if (PLAYERINPUTDOWN(ssplayer, GC_TOSSFLAG)) cmd->buttons |= BT_TOSSFLAG; - + // Shield button axis = PlayerJoyAxis(ssplayer, JA_SHIELD); if (PLAYERINPUTDOWN(ssplayer, GC_SHIELD) || (usejoystick && axis > 0)) @@ -1386,6 +1386,13 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if (PLAYERINPUTDOWN(ssplayer, GC_SPIN) || (usejoystick && axis > 0)) cmd->buttons |= BT_SPIN; + if (gamestate != GS_LEVEL) // not in a level, don't build anything else + { + cmd->angleturn = ticcmd_oldangleturn[forplayer]; + cmd->aiming = G_ClipAimingPitch(myaiming); + return; + } + // Centerview can be a toggle in simple mode! { static boolean last_centerviewdown[2], centerviewhold[2]; // detect taps for toggle behavior @@ -1420,7 +1427,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) ticcmd_centerviewdown[forplayer] = true; } - else if (ticcmd_centerviewdown[forplayer]) + else if (ticcmd_centerviewdown[forplayer] || (leveltime < 5)) { if (controlstyle == CS_SIMPLE) { @@ -1435,6 +1442,9 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { if ( P_MobjWasRemoved(ticcmd_ztargetfocus[forplayer]) || + (leveltime < 5) || + (player->playerstate != PST_LIVE) || + player->exiting || !ticcmd_ztargetfocus[forplayer]->health || (ticcmd_ztargetfocus[forplayer]->type == MT_EGGMOBILE3 && !ticcmd_ztargetfocus[forplayer]->movecount) // Sea Egg is moving around underground and shouldn't be tracked ) @@ -1466,7 +1476,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) P_SetTarget(&newtarget->target, ticcmd_ztargetfocus[forplayer]); newtarget->drawonlyforplayer = player; // Hide it from the other player in splitscreen, and yourself when spectating - if (player->mo && P_AproxDistance( + if (player->mo && R_PointToDist2(0, 0, player->mo->x - ticcmd_ztargetfocus[forplayer]->x, player->mo->y - ticcmd_ztargetfocus[forplayer]->y ) > 50*player->mo->scale) @@ -1714,7 +1724,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // At this point, cmd doesn't contain the final angle yet, // So we need to temporarily transform it so Lua scripters // don't need to handle it differently than in other hooks. - if (addedtogame && gamestate == GS_LEVEL) + if (addedtogame) { INT16 extra = ticcmd_oldangleturn[forplayer] - player->oldrelangleturn; INT16 origangle = cmd->angleturn; @@ -4018,7 +4028,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent) INT32 i; INT16 newmapnum; boolean spec = G_IsSpecialStage(gamemap); - + // go to next level // newmapnum is 0-based, unlike gamemap if (nextmapoverride != 0) @@ -4122,7 +4132,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent) if (spec && (!gottoken || ignoretokens) && !nextmapoverride) newmapnum = lastmap; // Exiting from a special stage? Go back to the game. Tails 08-11-2001 - + if (!(gametyperules & GTR_CAMPAIGN)) { if (cv_advancemap.value == 0) // Stay on same map. @@ -4130,7 +4140,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent) else if (cv_advancemap.value == 2) // Go to random map. newmapnum = RandMap(G_TOLFlag(gametype_to_use), prevmap); } - + return newmapnum; } @@ -4140,7 +4150,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent) static void G_DoCompleted(void) { INT32 i; - + tokenlist = 0; // Reset the list if (modeattacking && pausedelay) @@ -4168,7 +4178,7 @@ static void G_DoCompleted(void) //Get and set prevmap/nextmap prevmap = (INT16)(gamemap-1); nextmap = G_GetNextMap(false, false); - + automapactive = false; // We are committed to this map now. diff --git a/src/hu_stuff.c b/src/hu_stuff.c index d784c2358a82eecbff441d3e22d535b7b34ceaf5..8489e405837a9acbb1fd951792a2a155dcf6e3e4 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2463,53 +2463,20 @@ static inline void HU_DrawSpectatorTicker(void) { int i; int length = 0, height = 174; - int totallength = 0, templength = 0; + int totallength = 0; for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].spectator) totallength += (signed)strlen(player_names[i]) * 8 + 16; - length -= (leveltime % (totallength + BASEVIDWIDTH)); - length += BASEVIDWIDTH; + length -= (leveltime % (totallength + (vid.width / vid.dup))); + length += (vid.width / vid.dup); for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].spectator) { - char *pos; - char initial[MAXPLAYERNAME+1]; - char current[MAXPLAYERNAME+1]; - - strcpy(initial, player_names[i]); - pos = initial; - - if (length >= -((signed)strlen(player_names[i]) * 8 + 16) && length <= BASEVIDWIDTH) - { - if (length < 0) - { - UINT8 eatenchars = (UINT8)(abs(length) / 8 + 1); - - if (eatenchars <= strlen(initial)) - { - // Eat one letter off the left side, - // then compensate the drawing position. - pos += eatenchars; - strcpy(current, pos); - templength = length % 8 + 8; - } - else - { - strcpy(current, " "); - templength = length; - } - } - else - { - strcpy(current, initial); - templength = length; - } - - V_DrawString(templength, height + 8, V_TRANSLUCENT|V_ALLOWLOWERCASE, current); - } + if (length >= -((signed)strlen(player_names[i]) * 8 + 16) && length <= (vid.width / vid.dup)) + V_DrawString(length, height + 8, V_TRANSLUCENT|V_ALLOWLOWERCASE|V_SNAPTOLEFT, player_names[i]); length += (signed)strlen(player_names[i]) * 8 + 16; } diff --git a/src/lua_baselib.c b/src/lua_baselib.c index f6b8f462b5a41cee30c33145fd62fa28daa01e92..942963780a851db4ff914a6c8e292907eeb7e3c0 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -345,6 +345,18 @@ static int lib_reserveLuabanks(lua_State *L) return 1; } +static int lib_tofixed(lua_State *L) +{ + const char *arg = luaL_checkstring(L, 1); + char *end; + float f = strtof(arg, &end); + if (*end != '\0') + lua_pushnil(L); + else + lua_pushnumber(L, FLOAT_TO_FIXED(f)); + return 1; +} + // M_MENU ////////////// @@ -641,7 +653,7 @@ static int lib_pSpawnMobj(lua_State *L) NOHUD INLEVEL NOSPAWNNULL - LUA_PushUserdata(L, P_SpawnMobj(x, y, z, type), META_MOBJ); + LUA_PushUserdata(L, P_SpawnMobj(x, y, z, type, NULL), META_MOBJ); return 1; } @@ -4333,6 +4345,7 @@ static luaL_Reg lib[] = { {"userdataMetatable", lib_userdataMetatable}, {"IsPlayerAdmin", lib_isPlayerAdmin}, {"reserveLuabanks", lib_reserveLuabanks}, + {"tofixed", lib_tofixed}, // m_menu {"M_MoveColorAfter",lib_pMoveColorAfter}, diff --git a/src/lua_hudlib_drawlist.c b/src/lua_hudlib_drawlist.c index c518ba52540ff874480d7cda2c8314a31987e993..cb58e628ea005217c819ddea922f4952f70961f0 100644 --- a/src/lua_hudlib_drawlist.c +++ b/src/lua_hudlib_drawlist.c @@ -180,7 +180,8 @@ static const char *CopyString(huddrawlist_h list, const char* str) const char *old_offset = list->strbuf; size_t i; if (list->strbuf_capacity == 0) list->strbuf_capacity = 256; - else list->strbuf_capacity *= 2; + while (list->strbuf_capacity <= list->strbuf_len + lenstr + 1) + list->strbuf_capacity *= 2; list->strbuf = (char*) Z_Realloc(list->strbuf, sizeof(char) * list->strbuf_capacity, PU_STATIC, NULL); // align the string pointers to make sure old pointers don't point towards invalid addresses diff --git a/src/m_menu.c b/src/m_menu.c index 7ba5fa12f5f88a891d6c3ae5e44e7bea21cf8ecb..38165472e53459d93dc3f3cffa2a81ecce2d9de7 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7000,7 +7000,10 @@ static void M_LevelSelectWarp(INT32 choice) if (currentMenu == &SP_LevelSelectDef || currentMenu == &SP_PauseLevelSelectDef) { if (cursaveslot > 0) // do we have a save slot to load? + { + CV_StealthSet(&cv_skin, DEFAULTSKIN); // already handled by loadgame so we don't want this G_LoadGame((UINT32)cursaveslot, startmap); // reload from SP save data: this is needed to keep score/lives/continues from reverting to defaults + } else // no save slot, start new game but keep the current skin { M_ClearMenus(true); @@ -8649,9 +8652,14 @@ static void M_LoadSelect(INT32 choice) M_NewGame(); } else if (savegameinfo[saveSlotSelected-1].gamemap & 8192) // Completed + { M_LoadGameLevelSelect(0); + } else + { + CV_StealthSet(&cv_skin, DEFAULTSKIN); // already handled by loadgame so we don't want this G_LoadGame((UINT32)saveSlotSelected, 0); + } cursaveslot = saveSlotSelected; } @@ -9510,6 +9518,8 @@ static void M_ChoosePlayer(INT32 choice) //lastmapsaved = 0; gamecomplete = 0; + CV_StealthSet(&cv_skin, skins[skinnum]->name); + G_DeferedInitNew(ultmode, G_BuildMapName(startmap), skinnum, false, fromlevelselect); COM_BufAddText("dummyconsvar 1\n"); // G_DeferedInitNew doesn't do this @@ -10201,9 +10211,12 @@ void M_DrawNightsAttackMenu(void) color = skins[skinnumber]->prefcolor; angle_t fa = (FixedAngle(((FixedInt(ntsatkdrawtimer * 4)) % 360)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK; + fixed_t scale = skins[skinnumber]->highresscale; + if (skins[skinnumber]->shieldscale) + scale = FixedDiv(scale, skins[skinnumber]->shieldscale); V_DrawFixedPatch(270<<FRACBITS, (186<<FRACBITS) - 8*FINESINE(fa), - FixedDiv(skins[skinnumber]->highresscale, skins[skinnumber]->shieldscale), + scale, (sprframe->flip & 1<<6) ? V_FLIP : 0, natksprite, R_GetTranslationColormap(TC_BLINK, color, GTC_CACHE)); @@ -12290,7 +12303,9 @@ static void M_DrawSetupMultiPlayerMenu(void) if (multi_frame >= sprdef->numframes) multi_frame = 0; - scale = FixedDiv(skins[setupm_fakeskin]->highresscale, skins[setupm_fakeskin]->shieldscale); + scale = skins[setupm_fakeskin]->highresscale; + if (skins[setupm_fakeskin]->shieldscale) + scale = FixedDiv(scale, skins[setupm_fakeskin]->shieldscale); #define chary (y+64) @@ -12323,7 +12338,7 @@ static void M_DrawSetupMultiPlayerMenu(void) V_DrawFixedPatch( x<<FRACBITS, chary<<FRACBITS, - FixedDiv(skins[setupm_fakeskin]->highresscale, skins[setupm_fakeskin]->shieldscale), + scale, flags, patch, colormap); goto colordraw; diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c index 91635cf308529ebf17d8a99bc3e2ebd6a9afcd7e..f7b98c4dbaff55d58481b5c439623a92fcd4e4c4 100644 --- a/src/netcode/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -1309,7 +1309,7 @@ static void SendNameAndColor(void) SetColorLocal(consoleplayer, cv_playercolor.value); - if (splitscreen) + if (splitscreen || (!pickedchar && stricmp(cv_skin.string, skins[consoleplayer]->name) != 0)) SetSkinLocal(consoleplayer, R_SkinAvailable(cv_skin.string)); else SetSkinLocal(consoleplayer, pickedchar); @@ -4609,7 +4609,7 @@ static void Command_ExitLevel_f(void) SendNetXCmd(XD_EXITLEVEL, NULL, 0); return; } - + // Allow exiting without cheating if at least one player beat the level // Consistent with just setting playersforexit to one if (splitscreen || multiplayer) @@ -4623,7 +4623,7 @@ static void Command_ExitLevel_f(void) continue; if (players[i].lives <= 0) continue; - + if ((players[i].pflags & PF_FINISHED) || players[i].exiting) { SendNetXCmd(XD_EXITLEVEL, NULL, 0); @@ -4631,7 +4631,7 @@ static void Command_ExitLevel_f(void) } } } - + // Only consider it a cheat if we're not allowed to go to the next map if (M_CampaignWarpIsCheat(gametype, G_GetNextMap(true, true) + 1, serverGamedata)) CONS_Alert(CONS_NOTICE, M_GetText("Cheats must be enabled to force exit to a locked level!\n")); @@ -4770,7 +4770,7 @@ static void Command_Cheats_f(void) G_SetUsedCheats(false); return; } - + if (usedCheats) CONS_Printf(M_GetText("Cheats are enabled, the game cannot be saved.\n")); else @@ -4942,6 +4942,8 @@ static boolean Skin2_CanChange(const char *valstr) */ static void Skin_OnChange(void) { + pickedchar = R_SkinAvailable(cv_skin.string); + if (!Playing()) return; diff --git a/src/netcode/http-mserv.c b/src/netcode/http-mserv.c index b8c662a51e215965470310d758331236359378b7..4a080498455234f234655f505e4bf0df956dd9a6 100644 --- a/src/netcode/http-mserv.c +++ b/src/netcode/http-mserv.c @@ -486,20 +486,23 @@ int HMS_unlist (void) { struct HMS_buffer *hms; - int ok; + int ok = 0; - hms = HMS_connect(PROTO_V4, "servers/%s/unlist", hms_server_token); + if (hms_server_token) + { + hms = HMS_connect(PROTO_V4, "servers/%s/unlist", hms_server_token); - if (! hms) - return 0; + if (! hms) + return 0; - curl_easy_setopt(hms->curl, CURLOPT_POST, 1); - curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDSIZE, 0); + curl_easy_setopt(hms->curl, CURLOPT_POST, 1); + curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDSIZE, 0); - ok = HMS_do(hms); - HMS_end(hms); + ok = HMS_do(hms); + HMS_end(hms); - free(hms_server_token); + free(hms_server_token); + } #ifndef NO_IPV6 if (hms_server_token_ipv6 && hms_allow_ipv6) @@ -526,18 +529,13 @@ int HMS_update (void) { struct HMS_buffer *hms; - int ok; + int ok = 0; char post[256]; char *title; - hms = HMS_connect(PROTO_V4, "servers/%s/update", hms_server_token); - - if (! hms) - return 0; - - title = curl_easy_escape(hms->curl, cv_servername.string, 0); + title = curl_easy_escape(NULL, cv_servername.string, 0); snprintf(post, sizeof post, "title=%s", @@ -546,10 +544,18 @@ HMS_update (void) curl_free(title); - curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDS, post); + if (hms_server_token) + { + hms = HMS_connect(PROTO_V4, "servers/%s/update", hms_server_token); - ok = HMS_do(hms); - HMS_end(hms); + if (! hms) + return 0; + + curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDS, post); + + ok = HMS_do(hms); + HMS_end(hms); + } #ifndef NO_IPV6 if (hms_server_token_ipv6 && hms_allow_ipv6) diff --git a/src/netcode/mserv.c b/src/netcode/mserv.c index 3acacd24c164471057ca3ffa7a6225f8ba95d2f3..74ee120f96e17ed6641adb48e0dc29f35d46c0c8 100644 --- a/src/netcode/mserv.c +++ b/src/netcode/mserv.c @@ -50,6 +50,8 @@ static void Command_Listserv_f(void); #endif/*MASTERSERVER*/ +static boolean ServerName_CanChange (const char*); + static void Update_parameters (void); static void MasterServer_OnChange(void); @@ -61,7 +63,7 @@ static CV_PossibleValue_t masterserver_update_rate_cons_t[] = { }; consvar_t cv_masterserver = CVAR_INIT ("masterserver", "https://ds.ms.srb2.org/MS/0", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange); -consvar_t cv_servername = CVAR_INIT ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Update_parameters); +consvar_t cv_servername = CVAR_INIT_WITH_CALLBACKS ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Update_parameters, ServerName_CanChange); consvar_t cv_masterserver_update_rate = CVAR_INIT ("masterserver_update_rate", "15", CV_SAVE|CV_CALL|CV_NOINIT, masterserver_update_rate_cons_t, Update_parameters); @@ -497,6 +499,15 @@ Set_api (const char *api) #endif/*MASTERSERVER*/ +static boolean ServerName_CanChange(const char* newvalue) +{ + if (strlen(newvalue) < MAXSERVERNAME) + return true; + + CONS_Alert(CONS_NOTICE, "The server name must be shorter than %d characters\n", MAXSERVERNAME); + return false; +} + static void Update_parameters (void) { diff --git a/src/p_enemy.c b/src/p_enemy.c index e779489fb7409c745511416d3af85d0ef57cbcb5..59934aa40d01291d7686097fca5c6ad2da1e2193 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -4865,7 +4865,7 @@ void A_AttractChase(mobj_t *actor) else actor->flags2 &= ~MF2_DONTDRAW; - // Turn flingrings back into regular rings if attracted. + // Turn rings into flingrings if shield is lost or out of range if (actor->tracer && actor->tracer->player && !(actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC) && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime) { @@ -4897,8 +4897,9 @@ void A_AttractChase(mobj_t *actor) // If a FlingRing gets attracted by a shield, change it into a normal ring. if (actor->type == (mobjtype_t)actor->info->reactiontime) { - P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->painchance); - P_RemoveMobj(actor); + actor->type = mobjinfo[actor->type].painchance; // Become the regular version of the fling object. + actor->flags = mobjinfo[actor->type].flags; // Reset actor flags. + P_SetMobjState(actor, actor->info->spawnstate); // Go to regular object's spawn state. return; } diff --git a/src/p_maputl.c b/src/p_maputl.c index 5da7839f3119abf554fa59340ec499add4c7f49d..200b89cff93c815bac281c8b270ae4975de219c6 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -502,6 +502,19 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (texnum) { fixed_t scaley = abs(side->scaley_mid); fixed_t offsetvalue = FixedDiv(side->rowoffset + side->offsety_mid, scaley); + fixed_t midopentop, midopenbottom; + + if (linedef->flags & ML_NOSKEW) + { + // Use the sector's actual heights if the midtexture is not skewed + midopentop = min(front->ceilingheight, back->ceilingheight); + midopenbottom = max(front->floorheight, back->floorheight); + } + else + { + midopentop = opentop; + midopenbottom = openbottom; + } // Get the midtexture's height texheight = FixedDiv(textureheight[texnum], scaley); @@ -525,13 +538,13 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) #endif { if (linedef->flags & ML_WRAPMIDTEX && !side->repeatcnt) { // "infinite" repeat - texbottom = openbottom + offsetvalue; - textop = opentop + offsetvalue; + texbottom = midopenbottom + offsetvalue; + textop = midopentop + offsetvalue; } else if (linedef->flags & ML_MIDPEG) { - texbottom = openbottom + offsetvalue; + texbottom = midopenbottom + offsetvalue; textop = texbottom + texheight*(side->repeatcnt+1); } else { - textop = opentop + offsetvalue; + textop = midopentop + offsetvalue; texbottom = textop - texheight*(side->repeatcnt+1); } } @@ -545,7 +558,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (opentop > texbottom) { opentop = texbottom; if (linedef->flags & ML_NOSKEW) - opentopslope = NULL; + opentopslope = NULL; // Object is not actually on a slope else opentopslope = linedef->midtexslope; } @@ -553,7 +566,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (openbottom < textop) { openbottom = textop; if (linedef->flags & ML_NOSKEW) - openbottomslope = NULL; + openbottomslope = NULL; // Object is not actually on a slope else openbottomslope = linedef->midtexslope; } diff --git a/src/p_mobj.c b/src/p_mobj.c index fbbae5a1e4b5cb122ff353591b037a91f284ceef..3ca6093906b3da9725cf95f6edb3ee5b78b9cae0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6662,8 +6662,21 @@ static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield) thing->flags |= MF_NOCLIPHEIGHT; thing->eflags = (thing->eflags & ~MFE_VERTICALFLIP)|(thing->target->eflags & MFE_VERTICALFLIP); - P_SetScale(thing, FixedMul(thing->target->scale, thing->target->player->shieldscale), true); - thing->old_scale = FixedMul(thing->target->old_scale, thing->target->player->shieldscale); + //Set the shield's scale based on shieldscale, hide it if we're too small! + fixed_t scale = FixedMul(thing->target->scale, thing->target->player->shieldscale); + if (scale < 1) { + P_SetScale(thing, thing->target->scale, true); + thing->old_scale = thing->target->old_scale; + + thing->flags2 |= (MF2_DONTDRAW|MF2_JUSTATTACKED); //Hide and indicate we're hidden + } else { + P_SetScale(thing, scale, true); + thing->old_scale = FixedMul(thing->target->old_scale, thing->target->player->shieldscale); + + //Only unhide if we were hidden by the above code + if (thing->flags2 & MF2_JUSTATTACKED) + thing->flags2 &= ~(MF2_DONTDRAW|MF2_JUSTATTACKED); + } #define NewMH(mobj) mobj->height // Ugly mobj-height and player-height defines, for the sake of prettier code #define NewPH(player) P_GetPlayerHeight(player) @@ -10747,7 +10760,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) // when spawning MT_PLAYER, set mobj->player before calling MobjSpawn hook to prevent P_RemoveMobj from succeeding on player mobj. va_start(args, type); mobj->player = va_arg(args, player_t *); - mobj->player->mo = mobj; + if (mobj->player) + mobj->player->mo = mobj; va_end(args); } @@ -14289,7 +14303,8 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo yofs = FixedMul(yofs, mobj->scale); zofs = FixedMul(zofs, mobj->scale); - newmobj = P_SpawnMobj(mobj->x + xofs, mobj->y + yofs, mobj->z + zofs, type); + newmobj = P_SpawnMobj(mobj->x + xofs, mobj->y + yofs, mobj->z + zofs, type, NULL); + if (!newmobj) return NULL; diff --git a/src/p_setup.c b/src/p_setup.c index c4b4a35b3610beeb973624035a4d5454f69f49db..f4b7f96a3446c9a2dc7e4e706c10b822749ba086 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1554,11 +1554,41 @@ static void P_LoadThings(UINT8 *data) } // Stores positions for relevant map data spread through a TEXTMAP. -UINT32 mapthingsPos[UINT16_MAX]; -UINT32 linesPos[UINT16_MAX]; -UINT32 sidesPos[UINT16_MAX]; -UINT32 vertexesPos[UINT16_MAX]; -UINT32 sectorsPos[UINT16_MAX]; +typedef struct textmap_block_s +{ + UINT32 *pos; + size_t capacity; +} textmap_block_t; + +static textmap_block_t mapthingBlocks; +static textmap_block_t linedefBlocks; +static textmap_block_t sidedefBlocks; +static textmap_block_t vertexBlocks; +static textmap_block_t sectorBlocks; + +static void TextmapStorePos(textmap_block_t *blocks, size_t *count) +{ + size_t locCount = (*count) + 1; + + if (blocks->pos == NULL) + { + // Initial capacity (half of the former one.) + blocks->capacity = UINT16_MAX / 2; + + Z_Calloc(sizeof(blocks->pos) * blocks->capacity, PU_LEVEL, &blocks->pos); + } + else if (locCount >= blocks->capacity) + { + // If we hit the list's capacity, make space for 1024 more blocks + blocks->capacity += 1024; + + Z_Realloc(blocks->pos, sizeof(blocks->pos) * blocks->capacity, PU_LEVEL, &blocks->pos); + } + + blocks->pos[locCount - 1] = M_TokenizerGetEndPos(); + + (*count) = locCount; +} // Determine total amount of map data in TEXTMAP. static boolean TextmapCount(size_t size) @@ -1602,15 +1632,15 @@ static boolean TextmapCount(size_t size) brackets++; // Check for valid fields. else if (fastcmp(tkn, "thing")) - mapthingsPos[nummapthings++] = M_TokenizerGetEndPos(); + TextmapStorePos(&mapthingBlocks, &nummapthings); else if (fastcmp(tkn, "linedef")) - linesPos[numlines++] = M_TokenizerGetEndPos(); + TextmapStorePos(&linedefBlocks, &numlines); else if (fastcmp(tkn, "sidedef")) - sidesPos[numsides++] = M_TokenizerGetEndPos(); + TextmapStorePos(&sidedefBlocks, &numsides); else if (fastcmp(tkn, "vertex")) - vertexesPos[numvertexes++] = M_TokenizerGetEndPos(); + TextmapStorePos(&vertexBlocks, &numvertexes); else if (fastcmp(tkn, "sector")) - sectorsPos[numsectors++] = M_TokenizerGetEndPos(); + TextmapStorePos(§orBlocks, &numsectors); else CONS_Alert(CONS_NOTICE, "Unknown field '%s'.\n", tkn); } @@ -2944,7 +2974,7 @@ static void P_LoadTextmap(void) vt->floorzset = vt->ceilingzset = false; vt->floorz = vt->ceilingz = 0; - TextmapParse(vertexesPos[i], i, ParseTextmapVertexParameter); + TextmapParse(vertexBlocks.pos[i], i, ParseTextmapVertexParameter); if (vt->x == INT32_MAX) I_Error("P_LoadTextmap: vertex %s has no x value set!\n", sizeu1(i)); @@ -3001,7 +3031,7 @@ static void P_LoadTextmap(void) textmap_planefloor.defined = 0; textmap_planeceiling.defined = 0; - TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter); + TextmapParse(sectorBlocks.pos[i], i, ParseTextmapSectorParameter); P_InitializeSector(sc); if (textmap_colormap.used) @@ -3050,7 +3080,7 @@ static void P_LoadTextmap(void) ld->sidenum[0] = NO_SIDEDEF; ld->sidenum[1] = NO_SIDEDEF; - TextmapParse(linesPos[i], i, ParseTextmapLinedefParameter); + TextmapParse(linedefBlocks.pos[i], i, ParseTextmapLinedefParameter); if (!ld->v1) I_Error("P_LoadTextmap: linedef %s has no v1 value set!\n", sizeu1(i)); @@ -3077,7 +3107,7 @@ static void P_LoadTextmap(void) sd->sector = NULL; sd->repeatcnt = 0; - TextmapParse(sidesPos[i], i, ParseTextmapSidedefParameter); + TextmapParse(sidedefBlocks.pos[i], i, ParseTextmapSidedefParameter); if (!sd->sector) I_Error("P_LoadTextmap: sidedef %s has no sector value set!\n", sizeu1(i)); @@ -3101,7 +3131,7 @@ static void P_LoadTextmap(void) memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); mt->mobj = NULL; - TextmapParse(mapthingsPos[i], i, ParseTextmapThingParameter); + TextmapParse(mapthingBlocks.pos[i], i, ParseTextmapThingParameter); } } @@ -3502,7 +3532,6 @@ static boolean P_LoadExtraVertices(UINT8 **data) UINT32 xtrvrtx = READUINT32((*data)); line_t* ld = lines; vertex_t *oldpos = vertexes; - ssize_t offset; size_t i; if (numvertexes != origvrtx) // If native vertex count doesn't match node original vertex count, bail out (broken data?). @@ -3517,12 +3546,11 @@ static boolean P_LoadExtraVertices(UINT8 **data) // If extra vertexes were generated, reallocate the vertex array and fix the pointers. numvertexes += xtrvrtx; vertexes = Z_Realloc(vertexes, numvertexes*sizeof(*vertexes), PU_LEVEL, NULL); - offset = (size_t)(vertexes - oldpos); for (i = 0, ld = lines; i < numlines; i++, ld++) { - ld->v1 += offset; - ld->v2 += offset; + ld->v1 = &vertexes[ld->v1 - oldpos]; + ld->v2 = &vertexes[ld->v2 - oldpos]; } // Read extra vertex data. diff --git a/src/p_user.c b/src/p_user.c index 5d2930bd96e35133cdfb1afbdfdda8b63dc6abab..7ad5bccbb58db303a28c9b3fe438b7effdea3c90 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -915,7 +915,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) player->textvar = NTV_BONUSTIMEEND; // Score and grades player->finishedspheres = (INT16)(player->spheres); player->finishedrings = (INT16)(player->rings); - + // Add score to temp leaderboards player->lastmaretime = leveltime - player->marebegunat; G_AddTempNightsRecords(player, player->marescore, player->lastmaretime, (UINT8)(oldmare + 1)); @@ -2379,7 +2379,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) if (dorollstuff) { if ((player->charability2 == CA2_SPINDASH) && !((player->pflags & (PF_SPINNING|PF_THOKKED)) == PF_THOKKED) && !(player->charability == CA_THOK && player->secondjump) - && (player->cmd.buttons & BT_SPIN) && (FixedHypot(player->mo->momx, player->mo->momy) > (5*player->mo->scale))) + && (player->cmd.buttons & BT_SPIN) && (FixedHypot(player->mo->momx, player->mo->momy) >= (5*player->mo->scale))) player->pflags = (player->pflags|PF_SPINNING) & ~PF_THOKKED; else if (!(player->pflags & PF_STARTDASH)) player->pflags &= ~PF_SPINNING; @@ -4735,7 +4735,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) // Revving else if ((cmd->buttons & BT_SPIN) && (player->pflags & PF_STARTDASH)) { - if (player->speed > 5*player->mo->scale) + if (player->speed >= 5*player->mo->scale) { player->pflags &= ~PF_STARTDASH; P_SetMobjState(player->mo, S_PLAY_ROLL); @@ -4775,9 +4775,8 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) if (!player->spectator) S_StartSound(player->mo, sfx_spin); } - else // Catapult the player from a spindash rev! - if (onground && !(player->pflags & PF_SPINDOWN) && (player->pflags & PF_STARTDASH) && (player->pflags & PF_SPINNING)) + else if (onground && !(player->pflags & PF_SPINDOWN) && (player->pflags & PF_STARTDASH) && (player->pflags & PF_SPINNING)) { player->pflags &= ~PF_STARTDASH; if (player->powers[pw_carry] == CR_BRAKGOOP) @@ -8780,7 +8779,7 @@ void P_MovePlayer(player_t *player) if (!(player->mo->momz || player->mo->momx || player->mo->momy) && !(player->mo->eflags & MFE_GOOWATER) && player->panim == PA_IDLE && !(player->powers[pw_carry])) P_DoTeeter(player); - + // Toss a flag if (G_GametypeHasTeams() && (cmd->buttons & BT_TOSSFLAG) && !(player->powers[pw_super]) && !(player->tossdelay)) { diff --git a/src/r_things.c b/src/r_things.c index fb9757a9ae077703433b2ad4bc8a3a1fc166d12b..dc9cab99770817e5f05c6d13a281f3fa37668790 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1774,6 +1774,10 @@ static void R_ProjectSprite(mobj_t *thing) } this_scale = interp.scale; + + if (this_scale < 1) + return; + radius = interp.radius; // For drop shadows height = interp.height; // Ditto diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 8bae550b0b12c1cc40fa166d6dc9963946a4c11d..e28fbd34abd5e17a322adad41e9068ae25935a00 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2987,7 +2987,7 @@ static void pathonly(char *s) */ static const char *searchWad(const char *searchDir) { - static char tempsw[256] = ""; + static char tempsw[MAX_WADPATH] = ""; filestatus_t fstemp; strcpy(tempsw, WADKEYWORD1); @@ -3050,9 +3050,15 @@ static const char *locateWad(void) #ifndef NOHOME // find in $HOME - I_OutputMsg(",HOME"); + I_OutputMsg(",HOME/" DEFAULTDIR); if ((envstr = I_GetEnv("HOME")) != NULL) + { + char *tmp = malloc(strlen(envstr) + sizeof(DEFAULTDIR)); + strcpy(tmp, envstr); + strcat(tmp, DEFAULTDIR); SEARCHWAD(envstr); + free(tmp); + } #endif // search paths