I search for solutions in this order: Past Code, Unreal Source, Wiki, BUF, groups.yahoo, google, screaming at monitor. – RegularX

Difference between revisions of "User:Rejecht"

From Unreal Wiki, The Unreal Engine Documentation Site
Jump to: navigation, search
(About)
(Where)
Line 5: Line 5:
 
=== Where ===
 
=== Where ===
  
* rejecht on the [http://forums.beyondunreal.com/member.php?u=59753 Beyond Unreal Forums]
+
'''Fora'''
* rejecht on the [http://forums.epicgames.com/members/1358276-rejecht Epic Games Forums]
+
 
 +
* rejecht on the [http://forums.beyondunreal.com/member.php?u=59753 Beyond Unreal Forum]
 +
* rejecht on the [http://forums.epicgames.com/members/1358276-rejecht Epic Games Forum]
 +
* rejecht on [http://www.tcpclan.net/phpforum/profile.php?mode=viewprofile&u=566 The Clan Punishers' Forum]
 +
* rejecht on [http://ut2004.titaninternet.co.uk/forums/member.php?u=1901 Titan Onslaught Forum]
 +
 
 +
'''Other'''
 +
 
 +
* rejecht on [https://twitter.com/#!/rejecht Twitter]
 +
 
 +
'''Websites'''
 +
 
 
* rejecht on [https://sites.google.com/site/rejecht/ Google Sites - rejecht's notes]
 
* rejecht on [https://sites.google.com/site/rejecht/ Google Sites - rejecht's notes]
 
** rejecht's notes is poorly maintained.  It is what it is.
 
** rejecht's notes is poorly maintained.  It is what it is.
* rejecht on [http://ut2004.titaninternet.co.uk/forums/member.php?u=1901 Titan Onslaught Forums]
 
* rejecht on [https://twitter.com/#!/rejecht Twitter]
 
  
 
== Experience ==
 
== Experience ==

Revision as of 16:06, 8 March 2012

About

Haphazard hobbyist programming sessions.

Where

Fora

Other

Websites

Experience

Nice to know

NumLives is not the number of lives

NumLives is the number of deaths (the number of lives used).

Errors found in Unreal Engine 2.5 may also be present in the UDK

Unreal Tournament 2004 Bugs || Errors

Players who are out can sometimes respawn

Triggers for this error:

  • It must be a TeamGame.
  • (MaxLives > 0) - Assume that this example has (MaxLives == 1)
  • TeamGame.ScoreKill has the errors.

By design?

  • Team kills are not counted as deaths, thus giving the player another chance. This might be desirable in some game types, however, a simple solution is to track the NumLives of the killed player before and after the TeamGame.ScoreKill call; if NumLives is unchanged, decide whether to call Super(DeathMatch).ScoreKill to deal with this, depending on whether this behavior is wanted.

Consequences:

  • The player can respawn despite having died the allotted MaxLives.

Cause:

  • The ScoreKill logic in TeamGame does not always call Super.ScoreKill, which is the one handling the NumLives count and sets bOutofLives accordingly. This is by design, but not necessarily desirable.

First attempt:

  • OK, so let's just override ScoreKill and increment NumLives ourselves, before calling ScoreKill, since the DeathMatch implementation expects (NumLives >= MaxLives) and sets bOutofLives accordingly.

First consequence of the first attempt: While this solved the original problem, it also introduced another problem:

  • This triggers LateEntryLives (which defaults to 1), forcing latecomers to become spectators (bOnlySpectator) at login, and some people losing their hair because they now have a new unwanted behaviour.

This is because some players now get (NumLives == 2), and others get (NumLives == 1), depending on the circumstances in TeamGame.ScoreKill. Login checks LateEntryLives against all players and boots the player to a spectator slot when it finds (NumLives (2) > LateEntryLives (1)).

Other possible approaches to solve the first consequence:

  1. Bad: Set LateEntryLives to MAXINT in InitGame to override any ini setting, unless you want to use LateEntryLives.
  2. Bad: Preincrement NumLives before Super.ScoreKill and clamp the value postcall (the first attempt).

The best solution is to track changes in NumLives and act accordingly after a Super.ScoreKill call to the TeamGame implementation. Also, add a choice whether to trigger this behavior, in case someone actually wants the default behavior.

AskforPawn and ClientGotoState

AskforPawn insists on calling ClientGotoState ('Spectating', 'Begin'), but there is no Begin: label in the Spectating state, which leads to an error.

The UDK solves this in the ClientGotoState function, but this code base also gets rid of the logic forcing the client to a spectating state.

Sometimes a player pawn spawns and gets possessed, but immediately gets destroyed again

(First, figuring out how to reproduce the error took some time, then the technique to trigger it again during testing. This one took 3/4 of a day to figure out and solve; logging/tracing client-side and server-side state changes step by effing step.)

So, sometimes, when a player presses the Fire button, just right after a controller enters one of the Player* states (PlayerWalking), ServerSpectate gets called, which destroys the pawn, enters a spectating state, and then ignores ClientRestart calls.

The first solution is simply to ignore ServerSpectate in the Player* states in PlayerController; such as PlayerWaiting, PlayerWalking, WaitingforPawn.

InitTeamSymbols may sometimes give both teams the same team symbol

DeathMatch.InitTeamSymbols is replaced with the following implementation.

Instead of getting in trouble with more random numbers, it just picks the next team symbol in the array, wrapping around to zero.

(Index_MaxTeams == 2)

The (Count_TeamSymbols < 10) check is an early warning system for someone who managed to change the team symbols--this implementation is adapted for at least ten different team symbols.

// *UT2004Fix*
// (Replaces) DeathMatch.InitTeamSymbols
// - Sometimes both teams would get the same team symbol.
 
event InitTeamSymbols ()
{
    local array<string> Group_Text_TeamSymbol;
    local int Count_TeamSymbols;
    local int Index_TeamSymbol[Index_MaxTeams];
    local Texture Texture_TeamSymbol;
 
    // ** Attempt to get a list of team symbols.
 
    if
    (
        (GameReplicationInfo.TeamSymbols[0] != None)
        &&
        (GameReplicationInfo.TeamSymbols[1] != None)
    )
    {
        return; // Already loaded.
    }
 
    // ** Team Symbol Names
 
    Class'CacheManager'.Static.GetTeamSymbolList (Group_Text_TeamSymbol, true);
 
    Count_TeamSymbols = Group_Text_TeamSymbol.Length;
 
    if (Count_TeamSymbols < 10)
    {
        Warn ("(Count_TeamSymbols < 10)");
 
        return;
    }
 
    // ** Randomization
 
    Index_TeamSymbol[0] = Rand (Group_Text_TeamSymbol.Length - 1);
    Index_TeamSymbol[1] = Rand (Group_Text_TeamSymbol.Length - 9);
 
    // **
    // - Handle Equality
 
    if (Index_TeamSymbol[0] == Index_TeamSymbol[1])
    {
        ++Index_TeamSymbol[1];
 
        if (Index_TeamSymbol[1] >= Count_TeamSymbols)
        {
            Index_TeamSymbol[1] = 0;
        }
    }
 
    // ** Red Team
 
    Texture_TeamSymbol = Texture(DynamicLoadObject (Group_Text_TeamSymbol[Index_TeamSymbol[0]], Class'Texture'));
 
    if (Texture_TeamSymbol != None)
    {
        GameReplicationInfo.TeamSymbols[0] = Texture_TeamSymbol;
    }
    else
    {
        Warn ("(Texture_TeamSymbol[0] == None)"@Group_Text_TeamSymbol[Index_TeamSymbol[0]]);
    }
 
    // ** Blue Team
 
    Texture_TeamSymbol = Texture(DynamicLoadObject (Group_Text_TeamSymbol[Index_TeamSymbol[1]], Class'Texture'));
 
    if (Texture_TeamSymbol != None)
    {
        GameReplicationInfo.TeamSymbols[1] = Texture_TeamSymbol;
    }
    else
    {
        Warn ("(Texture_TeamSymbol[1] == None)"@Group_Text_TeamSymbol[Index_TeamSymbol[1]]);
    }
 
    // ** Replication
 
    GameReplicationInfo.TeamSymbolNotify ();
}

ToggleScreenShotMode does not restore a variety of state

Scope:

  • PlayerController.ToggleScreenShotMode

Type:

  • Save/Restore

Fix:

  1. Remember and restore Handedness, bHideVehicleNoEntryIndicator.

TakeDrowningDamage

Triggers:

  • Pawn is in a water volume and the match has entered the MatchOver state.

Scope:

  • Pawn.TakeDrowningDamage

Type:

  • Access Error

Fix:

  1. Check (Controller != None) before calling Super.TakeDrowningDamage in a subclass of pawn.

PlayTakeHit never played drowning sound

Scope:

  • xPawn.PlayTakeHit

Type:

  • Class Check Error

Corrections:

  1. Find: DamageType.IsA('Drowned')
  2. Replace With: DamageType == Class'Drowned'

Reminder:

  • Do not use IsA with a class object (Class<DamageType> Class_DamageType).
  • Use IsA with an instance of a class object.

Trivia:

  • I don't think the actual drowning sounds were included anyway.

(...) more to come.