I don't need to test my programs. I have an error-correcting modem.
Difference between revisions of "User:Rejecht"
(→Nice to know) |
(→Players who are out can sometimes respawn) |
||
Line 34: | Line 34: | ||
Other possible approaches to solve the first consequence: | Other possible approaches to solve the first consequence: | ||
− | # | + | # Preincrement NumLives before Super.ScoreKill and clamp the value postcall. |
# Set LateEntryLives to MAXINT in InitGame to override any ini setting, unless you want to use LateEntryLives. | # Set LateEntryLives to MAXINT in InitGame to override any ini setting, unless you want to use LateEntryLives. | ||
+ | |||
+ | ==== 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. | ||
+ | |||
+ | <uscript> | ||
+ | // *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 (); | ||
+ | } | ||
+ | |||
+ | </uscript> | ||
==== ToggleScreenShotMode does not restore Handedness ==== | ==== ToggleScreenShotMode does not restore Handedness ==== |
Revision as of 17:40, 26 February 2012
About
Haphazard hobbyist programming sessions.
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
Game mechanical errors discovered in Unreal Tournament 2004
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.
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.
First attempt:
- OK, so let's just override ScoreKill and increment NumLives ourselves, before or after calling ScoreKill, since it expects (NumLives >= MaxLives).
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 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:
- Preincrement NumLives before Super.ScoreKill and clamp the value postcall.
- Set LateEntryLives to MAXINT in InitGame to override any ini setting, unless you want to use LateEntryLives.
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.
// *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 Handedness
Scope:
- PlayerController.ToggleScreenShotMode
Type:
- Save/Restore
Fix:
- Remember and restore Handedness.
TakeDrowningDamage
Scope:
- Pawn.TakeDrowningDamage
Type:
- Access Error
Fix:
- 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:
- Find: DamageType.IsA('Drowned')
- 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.
(...) more to come.