For some time now we do have some trouble with custom mods and switching between them in online games on dedicated servers. In online games using a dedicated UT3 server some unexpected behaviour can often be observed after switching from a legacy game type (DM, CTF, ...) to a custom game type (for example GaltanorsInvasion, BTFA,...):
- Missing custom game type HUD
- Number of bots is twice as high as before and can not be modified
- UT3 (linux) server crashes after some time of playing
- Voting menu is missing
- No movement or hit fire to begin the game possible
Those things seem only to happen in the first map after such a seamless server travel. In the second map within the same custom game type it seems fine again (if the server does not crash before).
I tried to pinpoint the cause of this behaviour and I think to have found it for the first three points (still trying to pinpoint the others :-). Also found some workarounds which could be successfully tested with GaltanorsInvasion and BTFA ... but it would need some coding.
Test-Setup:
- Dedicated UT3 linux server (version 3808)
- Windows Clients (version 2.1)
- UnrealScript Source (version 1.5)
- BTFA (Version 10)
- GaltanorsInvasion (Version 0.22)
1. Missing Custom Game Type HUD
Problem:
When switching the first time to a custom game type usually the game type specific HUD is missing. The only way to get the custom HUD displayed seems to be disconnecting from the server and reconnecting again.
Cause:
This seem to be a simple timing problem. When the UT3 server has switched to the new game type the reliable function is called on all clients:
SetHUD() --> ClientSetHUD()
But it seems that the client (at least our windows clients) needs some more time for switching to the new game type. When the server tries to set the new HUD on the clients the switching procedure to the new game type has not yet taken place on the clients and the new HUD can not be set.
Workaround:
The custom HUD of the new game type can be hardcoded in the derived 'PlayerController' class. In this way the custom HUD is set by the client by its own (independent of the server).
Code:
class <CustomMod>_PayerController extends UTPlayerController;
...
simulated event PostBeginPlay()
{
...
ClientSetHUD(Class'<CustomMod>.<CustomHUDClass>', none);
}
2. Number of bots twice as high as before
Problem:
When switching the first time to a custom game type the number of bots is usually twice as high as in the previous mod. Furthermore, the admin command 'killbots' does allow to kill all bots but they are instantly re-spawned. At last, the UT3 server crashes when playing the first map for some time.
Cause:
This issue is a little bit more complex... first of all, when switching to the custom game type the server transfers all bots from the previous game type to the new one. In doing so, the bot controller classes from the previous game type must be replaced by the customs game type controller class. During this process the number of transfered bots should be specified ... but it is not and this is causing the first problem.
Lets have a look at the source code:
Code:
0006: class UTGame extends GameInfo
0007: config(Game)
0008: abstract
0009: native;
...
3822: event HandleSeamlessTravelPlayer(out Controller C)
3823: {
...
3835: else if (B != None && B.Class != BotClass)
3826: {
3837: // re-create bot
3838: BotName = B.PlayerReplicationInfo.PlayerName;
3839: BotTeamIndex = B.GetTeamNum();
3840: B.Destroy();
3841: C = AddBot(BotName, (BotTeamIndex != 255), BotTeamIndex);
3842: }
...
3866: }
The else-block beginning from line 3835 is executed when the new game types bot class is different from the old one. The bot name and team number is stored, the old bot is destroyed and the same bot is spawned with the new bot class.
Looks good? Yeah ... but is not because the member variable 'NumBots' is not initialized. During server travel when setting up the new game type 'NumBots' is zero. What happens then:
Step-by-step(whatmighthappenandisnogood):
- NumBots == 0
- B.Destroy()->UTGame::Logout(B)::Numbots--
- NumBots == -1
- C = AddBot()::NumBots++
- NumBots == 0
So, we have a new bot but the number of bots is set to zero ... not good.
But there is also another side effect ... a second problem. The UTGame::Logout() method has a code block which adds automatically a new bot if the number of bots is less than the specified desired minimum:
Code:
0006: class UTGame extends GameInfo
0007: config(Game)
0008: abstract
0009: native;
...
1756: function Logout(controller Exiting)
1757: {
...
1800: else if ( NeedPlayers() )
1801: {
1802: AddBot();
1803: }
...
1814: }
I have no clue why this is done in Logout() as it is usually done within the state 'MatchInProgress'. This block causes the number of bots to be doubled.
Step-by-Step(whatreallyhappensandisevenworse):
- NumBots == 0
- B.Destroy()->UTGame::Logout(B)::NumBots--
- NumBots == -1
- UTGame::Logout(B)->Addbot()::NumBots++
- NumBots == 0
- C = AddBot()::NumBots++
- NumBots == 1
So, we have two bots spawned but the number of bots 'NumBots' is set to 1. This means for _each_ travelling bot there will be another one in the new game type.
I think (but not sure) that this wrong value for number of bots 'NumBots' might also cause the server crashes (point three from above) after some time of playing the first map ... need some more testing.
Workaround:
The only workaround I can think of is to re-write the method UTGame::HandleSeamlessTravelPlayer() in your base game type class. The above mentioned block should be exchanged by something like the following:
Code:
else if (B != None && B.Class != BotClass)
{
// re-create bot
BotName = B.PlayerReplicationInfo.PlayerName;
BotTeamIndex = B.GetTeamNum();
NumBots++; // because Destroy()->Logout() will decrement it
NumBots += DesiredPlayerCount; // prevent Destroy()->Logout() from auto adding new bots
B.Destroy(); // remove bot of class of previous game type
NumBots -= DesiredPlayerCount; // reset prevention of auto adding new bots
if ( NeedPlayers() ) // check if DesiredPlayerCount of new game types is less than of old one
C = AddBot(BotName, (BotTeamIndex != 255), BotTeamIndex); // add bot from class of new game type
}
Didnot find the causes for points 4 and 5
... yet
Bookmarks