Revisión | 88b99ea5632e5ec30de61a3c2bbe3ac5c5ecf61b (tree) |
---|---|
Tiempo | 2022-03-08 23:19:49 |
Autor | Léonard <hobbax3@gmai...> |
Commiter | Léonard |
Merged with 3.1-alpha-211205-2031.
@@ -432,7 +432,7 @@ | ||
432 | 432 | CLIENT_MOVE_COMMAND_s moveCMD = clientcommand_CreateMoveCommand( ); |
433 | 433 | |
434 | 434 | // [AK] If we don't want to send backup commands, send only this one and that's it. |
435 | - if (( sv_smoothplayers == 0 ) || ( cl_backupcommands == 0 )) | |
435 | + if ( cl_backupcommands == 0 ) | |
436 | 436 | { |
437 | 437 | CLIENT_GetLocalBuffer( )->ByteStream.WriteByte( CLC_CLIENTMOVE ); |
438 | 438 | clientcommand_WriteMoveCommandToBuffer( moveCMD ); |
@@ -3496,7 +3496,7 @@ | ||
3496 | 3496 | const BYTE oldPlayerClass = pPlayer->CurrentPlayerClass; |
3497 | 3497 | |
3498 | 3498 | // Set up the player class. |
3499 | - pPlayer->CurrentPlayerClass = playerClass; | |
3499 | + pPlayer->CurrentPlayerClass = clamp<int>( playerClass, 0, PlayerClasses.Size() -1 ); | |
3500 | 3500 | pPlayer->cls = PlayerClasses[pPlayer->CurrentPlayerClass].Type; |
3501 | 3501 | |
3502 | 3502 | if ( isMorphed ) |
@@ -5798,7 +5798,7 @@ | ||
5798 | 5798 | UCVarValue Value; |
5799 | 5799 | |
5800 | 5800 | // Read in the gameskill setting, and set gameskill to this setting. |
5801 | - Value.Int = pByteStream->ReadByte(); | |
5801 | + Value.Int = clamp<int>( pByteStream->ReadByte(), 0, AllSkills.Size() - 1); | |
5802 | 5802 | gameskill.ForceSet( Value, CVAR_Int ); |
5803 | 5803 | |
5804 | 5804 | // Do the same for botskill. |
@@ -543,7 +543,7 @@ | ||
543 | 543 | ULONG ulTimeLeft = MIN( g_lRespawnDelay, 1 + ( g_lRespawnGametic - level.time ) / TICRATE ); |
544 | 544 | |
545 | 545 | bottomString += "\n" TEXTCOLOR_GREEN; |
546 | - bottomString.AppendFormat( "Ready to respawn in %d second%s", ulTimeLeft, ulTimeLeft != 1 ? "s" : "" ); | |
546 | + bottomString.AppendFormat( "Ready to respawn in %lu second%s", ulTimeLeft, ulTimeLeft != 1 ? "s" : "" ); | |
547 | 547 | } |
548 | 548 | } |
549 | 549 |
@@ -1123,6 +1123,7 @@ | ||
1123 | 1123 | return true; |
1124 | 1124 | |
1125 | 1125 | const GAMEEVENT_e DamageEvent = bBeforeArmor ? GAMEEVENT_ACTOR_ARMORDAMAGED : GAMEEVENT_ACTOR_DAMAGED; |
1126 | + const int originalDamage = damage; | |
1126 | 1127 | |
1127 | 1128 | // [AK] We somehow need to pass all the actor pointers into the script itself. A simple way |
1128 | 1129 | // to do this is temporarily spawn a temporary actor and change its actor pointers to the target, |
@@ -1141,7 +1142,8 @@ | ||
1141 | 1142 | temp->Destroy( ); |
1142 | 1143 | |
1143 | 1144 | // [AK] If the new damage is zero, that means the target shouldn't take damage in P_DamageMobj. |
1144 | - return ( damage != 0 ); | |
1145 | + // Allow P_DamageMobj to execute anyways if the original damage was zero (i.e. NODAMAGE flag). | |
1146 | + return ( originalDamage == 0 || damage != 0 ); | |
1145 | 1147 | } |
1146 | 1148 | |
1147 | 1149 | //***************************************************************************** |
@@ -1445,6 +1447,10 @@ | ||
1445 | 1447 | case GAMELIMIT_WAVES: |
1446 | 1448 | wavelimit.ForceSet( Val, CVAR_Int ); |
1447 | 1449 | break; |
1450 | + | |
1451 | + default: | |
1452 | + I_Error( "GAMEMODE_SetLimit: Unhandled GameLimit\n." ); | |
1453 | + break; | |
1448 | 1454 | } |
1449 | 1455 | } |
1450 | 1456 |
@@ -9510,7 +9510,7 @@ | ||
9510 | 9510 | int capacity, offset, a, c; |
9511 | 9511 | if (CharArrayParms(capacity, offset, a, Stack, sp, pcd == PCD_PRINTMAPCHRANGE)) |
9512 | 9512 | { |
9513 | - while (capacity-- && (c = activeBehavior->GetArrayVal (a, offset)) != '\0') | |
9513 | + while (capacity-- && (c = activeBehavior->GetArrayVal (*activeBehavior->MapVars[a], offset)) != '\0') | |
9514 | 9514 | { |
9515 | 9515 | work += (char)c; |
9516 | 9516 | offset++; |
@@ -4670,6 +4670,11 @@ | ||
4670 | 4670 | // a "map" map change during possessions hold countdown to a CTF/ST map, the counter would stay |
4671 | 4671 | // on the screen of the clients after the map change. |
4672 | 4672 | { |
4673 | + // [AK] In case we changed levels in the middle of a duel's win sequence, just start a new duel | |
4674 | + // so the loser still gets sent to spectators. | |
4675 | + if (( DUEL_GetState( ) == DS_WINSEQUENCE ) && ( DUEL_GetStartNextDuelOnLevelLoad( ) == false )) | |
4676 | + DUEL_SetStartNextDuelOnLevelLoad( true ); | |
4677 | + | |
4673 | 4678 | DUEL_SetState( DS_WAITINGFORPLAYERS ); |
4674 | 4679 | LASTMANSTANDING_SetState( LMSS_WAITINGFORPLAYERS ); |
4675 | 4680 | POSSESSION_SetState( PSNS_WAITINGFORPLAYERS ); |
@@ -4680,6 +4685,16 @@ | ||
4680 | 4685 | // [BB] We have to reset the state though when this is a new game. |
4681 | 4686 | if ( ( SURVIVAL_GetState( ) == SURVS_COUNTDOWN ) || ( gameaction == ga_newgame ) ) |
4682 | 4687 | SURVIVAL_SetState( SURVS_WAITINGFORPLAYERS ); |
4688 | + | |
4689 | + // [AK] If we still advanced to the next map when the mission failed, then either the countdown | |
4690 | + // if there's still people playing, or reset the state entirely. | |
4691 | + if ( SURVIVAL_GetState( ) == SURVS_MISSIONFAILED ) | |
4692 | + { | |
4693 | + if ( SERVER_CalcNumNonSpectatingPlayers( MAXPLAYERS ) < 1 ) | |
4694 | + SURVIVAL_SetState( SURVS_WAITINGFORPLAYERS ); | |
4695 | + else | |
4696 | + SURVIVAL_StartCountdown(( sv_survivalcountdowntime > 0 ? sv_survivalcountdowntime : 20 ) * TICRATE - 1 ); | |
4697 | + } | |
4683 | 4698 | } |
4684 | 4699 | |
4685 | 4700 | if ( NETWORK_InClientMode() == false ) |
@@ -3380,9 +3380,17 @@ | ||
3380 | 3380 | if ( pActor == NULL ) |
3381 | 3381 | return; |
3382 | 3382 | |
3383 | - // [AK] If the actor is a player, don't tell clients to play the sound while we're backtracing their movement. | |
3383 | + // [AK] There's a few sounds that we shouldn't play if it originated from a player who we're backtracing. | |
3384 | 3384 | if (( pActor->player ) && ( SERVER_IsBacktracingPlayer( pActor->player - players ))) |
3385 | - return; | |
3385 | + { | |
3386 | + static const char *pszRestrictedSounds[7] = { "*grunt", "*land", "*falling", "*jump", "*dive", "*surface", "*gasp" }; | |
3387 | + | |
3388 | + for ( unsigned int i = 0; i < 7; i++ ) | |
3389 | + { | |
3390 | + if ( stricmp( pszSound, pszRestrictedSounds[i] ) == 0 ) | |
3391 | + return; | |
3392 | + } | |
3393 | + } | |
3386 | 3394 | |
3387 | 3395 | // [BB] If the actor doesn't have a NetID, we have to instruct the clients differently how to play the sound. |
3388 | 3396 | if ( pActor->NetID == -1 ) |
@@ -172,7 +172,7 @@ | ||
172 | 172 | static bool server_InfoCheat( BYTESTREAM_s* pByteStream ); |
173 | 173 | static bool server_CheckLogin( const ULONG ulClient ); |
174 | 174 | static void server_PrintWithIP( FString message, const NETADDRESS_s &address ); |
175 | -static void server_PerformBacktrace( ULONG ulClient ); | |
175 | +static void server_PerformBacktrace( ULONG ulClient, ULONG ulNumLateMoveCMDs ); | |
176 | 176 | static bool server_ShouldPerformBacktrace( ULONG ulClient ); |
177 | 177 | static void server_FixZFromBacktrace( APlayerPawn *pmo, fixed_t oldFloorZ ); |
178 | 178 |
@@ -2038,6 +2038,10 @@ | ||
2038 | 2038 | // should be able to go back is the gametic they connected with. |
2039 | 2039 | g_aClients[lClient].lLastServerGametic = gametic; |
2040 | 2040 | |
2041 | + // [AK] Clear any recent command gametics from the client. | |
2042 | + g_aClients[lClient].recentMoveCMDs.clear(); | |
2043 | + g_aClients[lClient].recentSelectCMDs.clear(); | |
2044 | + | |
2041 | 2045 | // [AK] Reset the client's tic buffer. |
2042 | 2046 | SERVER_ResetClientTicBuffer( lClient ); |
2043 | 2047 |
@@ -5200,56 +5204,61 @@ | ||
5200 | 5204 | const ULONG ulClientTic = cmd->getClientTic( ); |
5201 | 5205 | const bool bIsMoveCMD = cmd->isMoveCmd( ); |
5202 | 5206 | |
5203 | - // [AK] Ignore commands that arrived too late or are duplicates of commands we already processed, | |
5204 | - // neither of which we can account for anymore. This way, we aren't processing the same commands | |
5205 | - // again, or that happened too far into the past. | |
5206 | - if (( ulClientTic != 0 ) && ( ulClientTic <= g_aClients[g_lCurrentClient].ulClientGameTic )) | |
5207 | - { | |
5208 | - delete cmd; | |
5209 | - return false; | |
5207 | + // [AK] Ignore commands that are duplicates of commands we already received and/or processed. | |
5208 | + // This way, we won't process the exact same commands multiple times. | |
5209 | + if ( ulClientTic != 0 ) | |
5210 | + { | |
5211 | + RingBuffer<ULONG, MAX_RECENT_COMMANDS> *recentCMDs; | |
5212 | + | |
5213 | + // [AK] Move commands and weapon select commands each have their own ring buffers, since | |
5214 | + // a movement and weapon select commands with the same gametic can co-exist. | |
5215 | + recentCMDs = bIsMoveCMD ? &g_aClients[g_lCurrentClient].recentMoveCMDs : &g_aClients[g_lCurrentClient].recentSelectCMDs; | |
5216 | + | |
5217 | + for ( unsigned int i = 0; i < MAX_RECENT_COMMANDS; i++ ) | |
5218 | + { | |
5219 | + if ( recentCMDs->getOldestEntry( i ) == ulClientTic ) | |
5220 | + { | |
5221 | + delete cmd; | |
5222 | + return false; | |
5223 | + } | |
5224 | + } | |
5225 | + | |
5226 | + // [AK] Save this gametic into the ring buffer for later use. | |
5227 | + recentCMDs->put( ulClientTic ); | |
5210 | 5228 | } |
5211 | 5229 | |
5212 | 5230 | if ( sv_useticbuffer ) |
5213 | 5231 | { |
5214 | 5232 | if ( ulClientTic != 0 ) |
5215 | 5233 | { |
5216 | - if ( sv_smoothplayers ) | |
5234 | + // [AK] It's possible that we were extrapolating this player's movement. If that's the case, | |
5235 | + // then we're going to store any incoming commands into a separate buffer until we receive | |
5236 | + // as many of them as we emulated during extrapolation. Once that happens, we'll use them to | |
5237 | + // backtrace the player's actual movement. | |
5238 | + if (( sv_smoothplayers ) && ( g_aClients[g_lCurrentClient].ulExtrapolatedTics > 0 )) | |
5217 | 5239 | { |
5218 | - // [AK] It's possible this was a command that arrived late and we already extrapolated | |
5219 | - // the player's movement at this tic. In this case, we'll store these commands into a | |
5220 | - // separate buffer so we can backtrace the player's actual movement. | |
5221 | - if (( g_aClients[g_lCurrentClient].LastMoveCMD != NULL ) && ( g_aClients[g_lCurrentClient].ulExtrapolatedTics > 0 )) | |
5240 | + ULONG ulNumLateMoveCMDs = 0; | |
5241 | + | |
5242 | + // [AK] Only count how many movement commands are in the buffer, weapon select command don't matter. | |
5243 | + for ( unsigned int i = 0; i < g_aClients[g_lCurrentClient].LateMoveCMDs.Size( ); i++ ) | |
5222 | 5244 | { |
5223 | - // [AK] We want to try filling this buffer only when the client is suffering from a ping | |
5224 | - // spike, not when they're experiencing packet loss. | |
5225 | - if ( ulClientTic <= g_aClients[g_lCurrentClient].ulClientGameTic + g_aClients[g_lCurrentClient].ulExtrapolatedTics ) | |
5226 | - buffer = &g_aClients[g_lCurrentClient].LateMoveCMDs; | |
5245 | + if ( g_aClients[g_lCurrentClient].LateMoveCMDs[i]->isMoveCmd( )) | |
5246 | + ulNumLateMoveCMDs++; | |
5227 | 5247 | } |
5248 | + | |
5249 | + if ( ulNumLateMoveCMDs < g_aClients[g_lCurrentClient].ulExtrapolatedTics ) | |
5250 | + buffer = &g_aClients[g_lCurrentClient].LateMoveCMDs; | |
5228 | 5251 | } |
5229 | 5252 | |
5230 | 5253 | for ( unsigned int i = 0; i < buffer->Size( ); i++ ) |
5231 | 5254 | { |
5232 | 5255 | ULONG ulBufferClientTic = (*buffer)[i]->getClientTic( ); |
5233 | 5256 | |
5234 | - if ( ulBufferClientTic != 0 ) | |
5257 | + // [AK] Reorganize the commands in case they arrived in the wrong order. | |
5258 | + if (( ulBufferClientTic != 0 ) && ( ulClientTic < ulBufferClientTic )) | |
5235 | 5259 | { |
5236 | - // [AK] Double-check to make sure we don't already have this command stored anywhere in the buffer. | |
5237 | - // If it's not a late command, we also need to make sure there aren't any newer move commands already | |
5238 | - // in the tic buffer. If any of these conditions fail, we have to ignore this command. | |
5239 | - // Movement and weapon select commands with the same gametic can co-exist in the tic buffer, as | |
5240 | - // they're not the same command, but two movement or weapon select commands cannot. | |
5241 | - if (( ulBufferClientTic == ulClientTic ) && ( bIsMoveCMD == (*buffer)[i]->isMoveCmd( ))) | |
5242 | - { | |
5243 | - delete cmd; | |
5244 | - return false; | |
5245 | - } | |
5246 | - | |
5247 | - // [AK] Reorganize the commands in case they arrived in the wrong order. | |
5248 | - if ( ulClientTic < ulBufferClientTic ) | |
5249 | - { | |
5250 | - buffer->Insert( i, cmd ); | |
5251 | - return false; | |
5252 | - } | |
5260 | + buffer->Insert( i, cmd ); | |
5261 | + return false; | |
5253 | 5262 | } |
5254 | 5263 | } |
5255 | 5264 | } |
@@ -5386,8 +5395,8 @@ | ||
5386 | 5395 | |
5387 | 5396 | // [AK] If we have enough late commands in the buffer, process them all immediately, so as long |
5388 | 5397 | // as they hadn't morphed or unmorphed at any point during extrapolation. |
5389 | - if (( ulNumLateMoveCMDs > 0 ) && ( ulNumMoveCMDs > 0 || ulNumLateMoveCMDs == pClient->ulExtrapolatedTics ) && ( pClient->OldData != NULL )) | |
5390 | - server_PerformBacktrace( ulClient ); | |
5398 | + if (( pClient->OldData != NULL ) && ( pClient->ulExtrapolatedTics > 0 ) && ( pClient->ulExtrapolatedTics == ulNumLateMoveCMDs )) | |
5399 | + server_PerformBacktrace( ulClient, ulNumLateMoveCMDs ); | |
5391 | 5400 | |
5392 | 5401 | // [AK] If there are no movement commands left in the client's tic buffer then we'll keep processing |
5393 | 5402 | // the last movement command we received from them, but we won't extrapolate more than we should. |
@@ -5407,15 +5416,6 @@ | ||
5407 | 5416 | |
5408 | 5417 | pClient->LastMoveCMD->process( ulClient ); |
5409 | 5418 | } |
5410 | - | |
5411 | - // [AK] Reset the client's extrapolation data if necessary. | |
5412 | - if (( ulNumMoveCMDs > 0 ) && ( pClient->ulExtrapolatedTics > 0 )) | |
5413 | - { | |
5414 | - if ( sv_smoothplayers_debuginfo ) | |
5415 | - Printf( "%d: resetting extrapolation data for %s.\n", gametic, players[ulClient].userinfo.GetName( )); | |
5416 | - | |
5417 | - SERVER_ResetClientExtrapolation( ulClient ); | |
5418 | - } | |
5419 | 5419 | } |
5420 | 5420 | else if ( pClient->ulExtrapolatedTics > 0 ) |
5421 | 5421 | { |
@@ -5467,14 +5467,7 @@ | ||
5467 | 5467 | |
5468 | 5468 | // [AK] Clear all stored commands in the tic buffer. |
5469 | 5469 | for ( unsigned int i = 0; i < g_aClients[ulClient].MoveCMDs.Size( ); i++ ) |
5470 | - { | |
5471 | - // [AK] Set the client's gametic to the last command in their tic buffer that has a non-zero | |
5472 | - // gametic. This way, any old and therefore invalid backup commands will be rejected. | |
5473 | - if ( g_aClients[ulClient].MoveCMDs[i]->getClientTic( ) != 0 ) | |
5474 | - g_aClients[ulClient].ulClientGameTic = g_aClients[ulClient].MoveCMDs[i]->getClientTic( ); | |
5475 | - | |
5476 | 5470 | delete g_aClients[ulClient].MoveCMDs[i]; |
5477 | - } | |
5478 | 5471 | |
5479 | 5472 | g_aClients[ulClient].MoveCMDs.Clear( ); |
5480 | 5473 |
@@ -5504,12 +5497,9 @@ | ||
5504 | 5497 | // to the last late command we received from them and update their gametic. |
5505 | 5498 | if ( bUpdatedLastMoveCMD == false ) |
5506 | 5499 | { |
5507 | - ULONG ulNewClientGametic = g_aClients[ulClient].LastMoveCMD->getClientTic( ) + g_aClients[ulClient].ulExtrapolatedTics; | |
5508 | - | |
5509 | 5500 | delete g_aClients[ulClient].LastMoveCMD; |
5510 | 5501 | g_aClients[ulClient].LastMoveCMD = static_cast<ClientMoveCommand *>( g_aClients[ulClient].LateMoveCMDs[i] ); |
5511 | 5502 | |
5512 | - g_aClients[ulClient].LastMoveCMD->setClientTic( ulNewClientGametic ); | |
5513 | 5503 | bUpdatedLastMoveCMD = true; |
5514 | 5504 | continue; |
5515 | 5505 | } |
@@ -7447,7 +7437,7 @@ | ||
7447 | 7437 | |
7448 | 7438 | //***************************************************************************** |
7449 | 7439 | // |
7450 | -static void server_PerformBacktrace( ULONG ulClient ) | |
7440 | +static void server_PerformBacktrace( ULONG ulClient, ULONG ulNumLateMoveCMDs ) | |
7451 | 7441 | { |
7452 | 7442 | CLIENT_s *pClient = &g_aClients[ulClient]; |
7453 | 7443 | APlayerPawn *pmo = players[ulClient].mo; |
@@ -7477,39 +7467,25 @@ | ||
7477 | 7467 | // [AK] Check if the player hasn't moved into a spot that's blocking them or something else. |
7478 | 7468 | if ( P_TestMobjLocation( players[ulClient].mo )) |
7479 | 7469 | { |
7480 | - ULONG ulExtrapolateStartTic = pClient->LastMoveCMD->getClientTic( ); | |
7481 | - ULONG ulNumExtrapolatedTics = pClient->ulExtrapolatedTics; | |
7470 | + ULONG ulNumProcessedMoveCMDs = 0; | |
7482 | 7471 | fixed_t oldFloorZ = 0; |
7483 | 7472 | |
7484 | 7473 | pClient->bIsBacktracing = true; |
7485 | 7474 | pClient->ulExtrapolatedTics = 0; |
7486 | 7475 | |
7487 | - // [AK] Ideally, we want to have as many late move commands in the buffer as the number of tics we | |
7488 | - // extrapolated this player for. If that's not the case, however, then we'll try "filling in the gaps" | |
7489 | - // by re-processing the command we last processed until every tic is accounted for. | |
7490 | - for ( ULONG ulTic = 1; ulTic <= ulNumExtrapolatedTics; ulTic++ ) | |
7476 | + for ( int tic = 0; tic < static_cast<int>( pClient->LateMoveCMDs.Size( )); tic++ ) | |
7491 | 7477 | { |
7492 | - if (( pClient->LateMoveCMDs.Size( ) > 0 ) && ( pClient->LateMoveCMDs[0]->getClientTic( ) == ulExtrapolateStartTic + ulTic )) | |
7478 | + // [AK] If this is a weapon select command, just process it and move onto the next late command. | |
7479 | + if ( pClient->LateMoveCMDs[tic]->isMoveCmd( ) == false ) | |
7493 | 7480 | { |
7494 | - // [AK] If this is a weapon select command, just process it and move onto the next late command. | |
7495 | - if ( pClient->LateMoveCMDs[0]->isMoveCmd( ) == false ) | |
7496 | - { | |
7497 | - pClient->LateMoveCMDs[0]->process( ulClient ); | |
7498 | - | |
7499 | - delete pClient->LateMoveCMDs[0]; | |
7500 | - pClient->LateMoveCMDs.Delete( 0 ); | |
7501 | - | |
7502 | - ulTic--; | |
7503 | - continue; | |
7504 | - } | |
7505 | - | |
7506 | - delete pClient->LastMoveCMD; | |
7507 | - pClient->LastMoveCMD = new ClientMoveCommand( *static_cast<ClientMoveCommand *>( pClient->LateMoveCMDs[0] )); | |
7508 | - | |
7509 | - delete pClient->LateMoveCMDs[0]; | |
7510 | - pClient->LateMoveCMDs.Delete( 0 ); | |
7481 | + pClient->LateMoveCMDs[tic]->process( ulClient ); | |
7482 | + continue; | |
7511 | 7483 | } |
7512 | 7484 | |
7485 | + // [AK] This becomes the last movement command we received from the client. | |
7486 | + delete pClient->LastMoveCMD; | |
7487 | + pClient->LastMoveCMD = new ClientMoveCommand( *static_cast<ClientMoveCommand *>( pClient->LateMoveCMDs[tic] )); | |
7488 | + | |
7513 | 7489 | pClient->LastMoveCMD->process( ulClient ); |
7514 | 7490 | |
7515 | 7491 | // [AK] Now we have to tick this player's body and set the proper psprite settings. |
@@ -7521,7 +7497,7 @@ | ||
7521 | 7497 | |
7522 | 7498 | // [AK] Adjust the sector ceiling/floor heights for the next tic that we extrapolated the player. |
7523 | 7499 | // We don't have to do this on the last tic that we extrapolated the player. |
7524 | - if ( ulTic < ulNumExtrapolatedTics ) | |
7500 | + if ( ++ulNumProcessedMoveCMDs < ulNumLateMoveCMDs ) | |
7525 | 7501 | { |
7526 | 7502 | unlaggedIndex = ( unlaggedIndex + 1 ) % UNLAGGEDTICS; |
7527 | 7503 |
@@ -7546,8 +7522,6 @@ | ||
7546 | 7522 | // [AK] As a final measure, fix the player's floorz/ceilingz and to ensure that they don't |
7547 | 7523 | // get stuck in the floor/ceiling of whatever sector they're supposed to be in. |
7548 | 7524 | server_FixZFromBacktrace( pmo, oldFloorZ ); |
7549 | - | |
7550 | - pClient->LastMoveCMD->setClientTic( ulExtrapolateStartTic + ulNumExtrapolatedTics ); | |
7551 | 7525 | debugMessage += "accepted"; |
7552 | 7526 | } |
7553 | 7527 | else |
@@ -7619,7 +7593,7 @@ | ||
7619 | 7593 | { |
7620 | 7594 | pmo->z = pmo->floorz; |
7621 | 7595 | } |
7622 | - else | |
7596 | + else if ( oldFloorZ != pmo->floorz ) | |
7623 | 7597 | { |
7624 | 7598 | // [AK] Check if the player should move with the floor if it moved, similarly to PIT_FloorDrop. |
7625 | 7599 | if (( pmo->velz == 0 ) && (!( pmo->flags & MF_NOGRAVITY ) || ( pmo->z == oldFloorZ && !( pmo->flags & MF_NOLIFTDROP )))) |
@@ -82,6 +82,9 @@ | ||
82 | 82 | // Amount of time the client has to report his checksum of the level. |
83 | 83 | #define CLIENT_CHECKSUM_WAITTIME ( 15 * TICRATE ) |
84 | 84 | |
85 | +// [AK] Maximum amount of gametics of recent commands from a client that we can store. | |
86 | +#define MAX_RECENT_COMMANDS 15 | |
87 | + | |
85 | 88 | // This is for the server console, but since we normally can't include that (win32 stuff), |
86 | 89 | // we can just put it here. |
87 | 90 | #define UDF_NAME 0x00000001 |
@@ -392,6 +395,12 @@ | ||
392 | 395 | // [BB] A record of the gametics the client called protected minor commands, e.g. toggleconsole. |
393 | 396 | RingBuffer<LONG, 100> minorCommandInstances; |
394 | 397 | |
398 | + // [AK] A list of gametics of the last few movement commands the client sent us. | |
399 | + RingBuffer<ULONG, MAX_RECENT_COMMANDS> recentMoveCMDs; | |
400 | + | |
401 | + // [AK] A list of (non-zero) gametics of the last few weapon select commands the client sent us. | |
402 | + RingBuffer<ULONG, MAX_RECENT_COMMANDS> recentSelectCMDs; | |
403 | + | |
395 | 404 | // A record of the gametic the client spoke at. We store the last MAX_CHATINSTANCE_STORAGE |
396 | 405 | // times the client chatted. This is used to chat spam protection. |
397 | 406 | LONG lChatInstances[MAX_CHATINSTANCE_STORAGE]; |
@@ -1243,7 +1243,8 @@ | ||
1243 | 1243 | // |
1244 | 1244 | player_t *TEAM_GetCarrier( ULONG ulTeamIdx ) |
1245 | 1245 | { |
1246 | - if ( TEAM_CheckIfValid( ulTeamIdx )) | |
1246 | + // [AK] Also make sure that this team's carrier is still valid. | |
1247 | + if (( TEAM_CheckIfValid( ulTeamIdx )) && ( PLAYER_IsValidPlayerWithMo( teams[ulTeamIdx].g_pCarrier - players ))) | |
1247 | 1248 | return ( teams[ulTeamIdx].g_pCarrier ); |
1248 | 1249 | |
1249 | 1250 | return ( NULL ); |
@@ -512,8 +512,7 @@ | ||
512 | 512 | RECT ThisWindowRect; |
513 | 513 | ANIMATIONINFO AnimationInfo; |
514 | 514 | NOTIFYICONDATA NotifyIconData; |
515 | - UCVarValue Val; | |
516 | - char szString[64]; | |
515 | + FString uncolorizedHostname; | |
517 | 516 | |
518 | 517 | AnimationInfo.cbSize = sizeof( AnimationInfo ); |
519 | 518 | SystemParametersInfo( SPI_GETANIMATION, sizeof( AnimationInfo ), &AnimationInfo, 0 ); |
@@ -547,10 +546,12 @@ | ||
547 | 546 | NotifyIconData.uCallbackMessage = UWM_TRAY_TRAYID; |
548 | 547 | NotifyIconData.hIcon = g_hSmallIcon; |
549 | 548 | |
550 | - Val = sv_hostname.GetGenericRep( CVAR_String ); | |
551 | - strncpy( szString, Val.String, 63 ); | |
552 | - szString[63] = 0; | |
553 | - lstrcpy( NotifyIconData.szTip, szString ); | |
549 | + // [AK] Remove any color codes in the server name before sending it off. | |
550 | + uncolorizedHostname = sv_hostname.GetGenericRep( CVAR_String ).String; | |
551 | + V_ColorizeString( uncolorizedHostname ); | |
552 | + V_RemoveColorCodes( uncolorizedHostname ); | |
553 | + | |
554 | + lstrcpy( NotifyIconData.szTip, uncolorizedHostname.GetChars( )); | |
554 | 555 | |
555 | 556 | Shell_NotifyIcon( NIM_ADD, &NotifyIconData ); |
556 | 557 | break; |