Results 1 to 4 of 4
  1. #1

    Default Using Timer functions in HUD class? / How to implement game time limit?

    Morning folks!
    I'd like to have a time limit on my game, and i tried to get a timer counting down in my class that extends UTHUD like so:
    Code:
    function DrawGameHud()
    {
        local string timerText;
    
    SetTimer(60, false, 'GameOverTimer'); //after a minute it'll be game over atm
    Canvas.SetPos(Canvas.ClipX/2,Canvas.ClipY/6);
    Canvas.SetDrawColor(255,60,210,255);
    Canvas.Font = class'Engine'.static.GetSmallFont();
    
    //total time - current time = time remaining
    
    timerText = "Remaining time: "$(string((GetTimerRate('GameOverTimer') - GetTimerCount('GameOverTimer')))); 
    
    Canvas.DrawText(timerText);
    And then the separate function..
    Code:
    function GameOverTimer()
    {
    	Canvas.SetPos(Canvas.ClipX/2,Canvas.ClipY/2);
        Canvas.SetDrawColor(55,200,210,255);
        Canvas.Font = class'Engine'.static.GetLargeFont();
        Canvas.DrawText("Game Over");
    }
    While the text displays on screen as expected it does not countdown, it just stays at 60, also i've waited 60 seconds in the game and the "Game Over" text is not drawn.

    I thought maybe the HUD wasn't the best place for a game over timer anyway and that perhaps it should be in the game type? but then i'm not sure how i would get the value from there and display it in the HUD..

    I should probably mention that i've JUST started learning so my mistakes could be monumentally obvious, really appreciate any help you could give me.

  2. #2
    MSgt. Shooter Person
    Join Date
    Feb 2009
    Location
    Germany / NRW
    Posts
    189

    Default

    You're doing several mistakes here and it shows you haven't understood some things about HUD and timing in UDK. Let me help you out:

    http://wiki.beyondunreal.com/UE3:Act...unctions_(UDK)
    SetTimer
    native(280) final function SetTimer (float InRate, optional bool inbLoop, optional name inTimerFunc, optional Object inObj)
    Sets a timer to call the given function at a set interval. Defaults to calling the 'Timer' event if no function is specified. If InRate is set to 0.f it will effectively disable the previous timer.
    NOTE: Functions with parameters are not supported!
    So it just calls your GameOverTimer() function after 60 seconds, however, DrawGameHud() gets called by DrawHUD() inside UTHUD.uc ever Tick ( I think) and so you are setting the timer over and over again. I do not know if it resets the timer or how that works though, I'm a total beginner myself.
    You should not extend UTHUD.uc if you do not want to basically make UT with a new game mode, because it will draw tons of UT related stuff unless you overwrite it but then you have to make sure that you do it proper and don't miss anything (it's a ~2500 lines file so that's what I think anyways).
    You should not set a TimeLimit in your HUD because it "doesn't have a say" in the actual game since it's just running locally on the client. You should use the GameInfo for that stuff.
    Have a look at UTGame.uc:

    Code:
    function InitGameReplicationInfo()
    {	
    	...
    	local UTGameReplicationInfo GRI;	
    	Super.InitGameReplicationInfo();
    	GRI = UTGameReplicationInfo(GameReplicationInfo);
    	GRI.GoalScore = GoalScore;
    	GRI.TimeLimit = TimeLimit;
    	GameReplicationInfo.RemainingTime = 60 * TimeLimit;
    	...
    }
    
    ...
    
    state MatchInProgress
    {
    	...
    	function Timer()
    	{
    		Global.Timer();
    		if ( TimeLimit > 0 )
    		{
    			GameReplicationInfo.bStopCountDown = false;
    			if ( GameReplicationInfo.RemainingTime <= 0 )
    			{
    				EndGame(None,"TimeLimit");
    			}
    		}
    	}
    	...
    }
    So what happens here?
    TimeLimit is a config variable, set inside "C:\UDK\UDK-2012-03\UDKGame\Config\UDKGame.ini" in the [UTGame.UTGame] section.
    Then it gets assigned to GRI.TimeLimit. GameReplicationInfo comes with this definition:
    Every GameInfo.uc creates a GameReplicationInfo.uc, which is always relevant, to replicate important game data to clients (as the GameInfo is not replicated).
    In this case replication means that the server will send the information about the TimeLimit to all connected players.
    Then you have game states. You see the Timer() function. This is automatically called by the engine every second. Here in UTGame.uc it just checks if the TimeLimit is reached
    (if ( GameReplicationInfo.RemainingTime <= 0 )). The actual decreasing of the time that is left is done in GameReplicationInfo.uc itself:

    Code:
    if ( RemainingTime > 0)
    {
    	RemainingTime--;
    	if ( WorldInfo.NetMode != NM_Client )
    	{
    		if ( RemainingTime % 60 == 0 )
    		{
    			RemainingMinute = RemainingTime;
    		}
    	}
    }
    What you want now is to display this time on your HUD so you do this:

    Code:
    function DrawGameHud()
    {
    ...
    DisplayTime();
    ...
    }
    
    function DisplayClock()
    {
    	...
    	Canvas.DrawText(WorldInfo.GRI.TimeLimit);
    	...
    }
    -> The HUD has a reference to the GameReplicationInfo.uc so you can display anything you want on your HUD that is replicated.

    I hope this helps and that I didn't get anything completely wrong If so, I'm sure one of the pros will correct me

    Have fun!
    Last edited by saiboat; 04-08-2012 at 05:34 AM.
    Working on a spiritual successor to Unreal II's eXpanded MultiPlayer: UDK:XMP

  3. #3

    Default Thanks! One last question..

    Quote Originally Posted by saiboat View Post
    Here in UTGame.uc it just checks if the TimeLimit is reached....
    Have fun!
    First thank you so much for the fantastic response! Very informative and i've now got the game time limit function and displaying just as i'd like.


    The only thing i really need to do now is is change the win conditions, right now the player gets the "you have won the match" voice-over regardless. I would like to be able to set whether the player won or lost based on a variable i created in my own PlayerReplicationInfo. I'm pretty sure i can access it like so if i'm not mistaken..

    l
    Code:
    ocal myPlayerReplicationInfo PRI; 
    PRI = myPlayerReplicationInfo( (GetALocalPlayerController().Pawn).PlayerReplicationInfo );
    if ( PRI.myvariableforwin == ect..
    However I've been scrolling through the sourcecode for UTGame and UTDeathmatch (what my own gametype extends) and i'm having trouble figuring out exactly where this win condition is defined..
    right at the end of the match over state i see..

    Code:
    State MatchOver
    {
    ...
    		// play end-of-match message for winner/losers (for single and muli-player)
    		EndMessageCounter++;
    		if ( EndMessageCounter == EndMessageWait )
    		{
    			PlayEndOfMatchMessage();
    		}
    	}
    However PlayEndOfMatchMessage SEEMS to only apply for victories, i keep backtracking but i just can't find were a victory or loss is decided.. If someone could help me figure out what functions i would need to change that would be just great! I'll keep looking in the mean time, but i hope that its common knowledge to seasoned udk'ers

  4. #4
    MSgt. Shooter Person
    Join Date
    Feb 2009
    Location
    Germany / NRW
    Posts
    189

    Thumbs up

    Code:
    inside Pawn.uc
    WorldInfo.Game.Killed(Killer, Controller, self, damageType);
    
    inside UTGame.uc
    function Killed
    {
    	...
    	if ( class<UTDamageType>(DamageType) != None )
    		{
    			class<UTDamageType>(DamageType).static.ScoreKill(KillerPRI, KilledPRI, KilledPawn);
    		}
    	...
    }
    
    inside UTTeamGame.uc;
    function ScoreKill(Controller Killer, Controller Other)
    {
    	...
    	if ( !Other.bIsPlayer || ((Killer != None) && (!Killer.bIsPlayer || (Killer.PlayerReplicationInfo == None))) )
    	{
    		Super.ScoreKill(Killer, Other);
    		if ( !bScoreTeamKills && (Killer != None) && Killer.bIsPlayer && (MaxLives > 0) )
    			CheckScore(Killer.PlayerReplicationInfo);
    		return;
    	}
    	...
    }
    
    inside UTGame.uc:
    function bool CheckScore(PlayerReplicationInfo Scorer)
    {
    	...
    	if ( (GoalScore > 0) && (Scorer.Score >= GoalScore) )
    	{
    		EndGame(Scorer,"fraglimit");
    	}
    	...
    }
    All you need to do is something like
    WorldInfo.Game.increaseMyVariableFTW(Scorer.Player ReplicationInfo);

    and then inside your GameInfo
    function increaseMyVariableFTW(PlayerReplicationInfo Scorer)
    {
    Scorer.myvariableforwin++;
    CheckScore(..)
    }

    You can put the call to WorldInfo.Game in any class you want. What you have to keep in mind is that it works like this: everytime something happens that could cause a win, check if the game has ended.
    Working on a spiritual successor to Unreal II's eXpanded MultiPlayer: UDK:XMP


 

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Copyright ©2009-2011 Epic Games, Inc. All Rights Reserved.
Digital Point modules: Sphinx-based search vBulletin skin by CompletevB.com.