Jump to content
austin_medic

[CODE SNIPPET] Countdown Timer

Recommended Posts

So BIS has a countdown module, though it doesn't have any on screen timer, and a rather puny little icon that displays the number of minutes left, though some people might want something that stands out a bit more.

description.ext:

#define CT_STATIC 0
#define ST_LEFT  0x00

class RscTitles 
{ 
	class RscText 
	{
		  type = CT_STATIC;
		  idc = -1;
		  style = ST_LEFT;
		  colorBackground[] = {0, 0, 0, 1};
		  colorText[] = {1, 1, 1, 1};
		  font = FontM;
		  sizeEx = 0.04;
		  h = 0.04;
		  text = "";
	};
	class  AUSMD_Timer   
	{
		idd = 10000; 
           onload ="uiNamespace setVariable [""AUSMD_Timer"", _this select 0];"; 
           duration = 10000000; 
		class Controls 
		{
			class timer_text: RscText
			{
				idc = -1;
				colorBackground[] = {0,0,0,0};
				x = 0.434375 * safezoneW + safezoneX;
				y = 0.164 * safezoneH + safezoneY;
				w = 0.124687 * safezoneW;
				h = 0.042 * safezoneH;
			};
		};
	};
};

init.sqf:

disableSerialization;
cutRsc["AUSMD_Timer","PLAIN"];
_Display = uiNamespace getVariable "AUSMD_Timer"; 
_textBar = _display displayCtrl -1;
_timer = 500;
while{_timer > 1} do
{
_textBar ctrlsetText (format["%1",[_timer,"HH:MM:SS",false] call BIS_fnc_secondstoString]);
_timer = _timer - 1;
uiSleep 1;
};

add code to the right files as stated above then go ingame and you should see a timer for about 8 Minutes popup. You can change the time that will display with the obvious timer variable above the while loop. NOTE: I attempted to use the 'safezone' for the display so if you have a lower resolution or a higher one it will scale the text to the right position on the screen so its visible rather than being off screen and therefore being useless.

Edited by austin_medic
  • Like 1

Share this post


Link to post
Share on other sites

Looks good from what I can tell, however, it may be more beneficial to try out a pure code solution in this case:

[] spawn
{
disableSerialization;
sleep 1;
_control = (findDisplay 46) ctrlCreate ["RscText", 1234];
_control ctrlSetText "TEST";
_control ctrlSetPosition [0.4, 0, 0.4, 0.1];
_control ctrlCommit 0;
hintSilent "Control created";
while {true} do
{
	_control ctrlSetText (format ["Time since mission start: %1", time]);
};
};

One small piece of advice, use uiSleep instead of sleep for multiplayer/other places where synchronization is critical. Apparently it uses system time and is unaffected by low fps

Share this post


Link to post
Share on other sites

Hello

Sorry for bringing this old thread up,  but I really like design of this timer and I decided to use this in SP mission.

However whenever I load saved game, timer doesn't appear.

Any ideas how to display timer when mission is loaded?

 

Thanks

Share this post


Link to post
Share on other sites
4 hours ago, resistance-rat said:

However whenever I load saved game, timer doesn't appear.

Couple of reasons...

The script has disableSerialization so its progress is not saved when the mission is saved. Due to the way the above script is written disableSerialization is needed as it has variables that reference UI controls, UI controls can not be serialised so cannot be saved hence the use of disableSerialization.

So you need to remove any variables that reference controls, this then enables you to remove disableSerialization.

Once the above is fixed that then leaves you with.. when the script is loaded from a save where the timer was running then the script will start within the while loop. As UI resource states are not saved(i.e cutRsc having initialised its display) you will need to add something in the while loop to cutRsc if the resource is not present.

 

Spoiler

description.ext


//Pixel Grid defines
#define SCALE_FACTOR ( getNumber( configFile >> "uiScaleFactor" ))
#define GRID_SCALE 2
#define GRID_X( num ) ( pixelW * pixelGridNoUIScale * (( num * GRID_SCALE ) / SCALE_FACTOR ))
#define GRID_Y( num ) ( pixelH * pixelGridNoUIScale * (( num * GRID_SCALE ) / SCALE_FACTOR ))

#define CT_STATIC 0
#define ST_CENTER 0x02

class RscText
{
	deletable = 0;
	fade = 0;
	access = 0;
	type = CT_STATIC;
	idc = -1;
	colorBackground[] = {0,0,0,0};
	colorText[] = {1,1,1,1};
	text = "";
	fixedWidth = 0;
	colorShadow[] = {0,0,0,0.5};
	tooltipColorText[] = {1,1,1,1};
	tooltipColorBox[] = {1,1,1,1};
	tooltipColorShade[] = {0,0,0,0.65};
	x = 0;
	y = 0;
	h = 0.037;
	w = 0.3;
	style = ST_CENTER;
	shadow = 1;
	font = "RobotoCondensed";
	linespacing = 1;
};

class RscTitles {

	class  AUSMD_Timer {
		idd = 10000;
		duration = 10000000;

		class Controls {

			class timer_text: RscText {
				idc = 10;

				x = ( safeZoneX + ( safeZoneW / 2 )) - GRID_X( 10 );
				y = safeZoneY + GRID_Y( 16 );
				w = GRID_X( 20 );
				h = GRID_Y( 3 );

				sizeEx = GRID_Y( 3 );
				colorBackground[] = {0,0,0,0};

				//Add reference to control in uiNamespace when it loads
				onload ="uiNamespace setVariable [ 'AUSMD_TimerCtrl', _this select 0 ];";
			};
		};
	};
};

initPlayerLocal.sqf



//Always access the timer control directly, removing the need for disableSerialization
#define TIMER_CTRL uiNamespace getVariable [ "AUSMD_TimerCtrl", controlNull ]

AUSMD_fnc_timer = {
	//If there is already a timer running
	if !( isNull ( TIMER_CTRL ) ) exitWith {
		"There is a timer currently running" call BIS_fnc_error;
	};

	//Make sure we can suspend
	if !( canSuspend ) exitWith{
		_this spawn AUSMD_fnc_timer;
	};

	params[
		[ "_timer", 500, [ 0 ] ],
		[ "_code", {}, [ {}, "" ] ],
		[ "_args", [] ]
	];

	if ( _code isEqualType "" ) then {
		_code = compile _code;
	};

	while{_timer > 0} do {
		//If the timer control is not present
		if ( isNull ( TIMER_CTRL ) ) then {
			//Initialise display
			( "AUSMD_Timer" call BIS_fnc_rscLayer ) cutRsc["AUSMD_Timer","PLAIN"];
			//Make sure its fully initialised before accessing
			waitUntil{ !( isNull ( TIMER_CTRL ) ) };
		};
		 TIMER_CTRL ctrlSetText format[ "%1", [ _timer, "HH:MM:SS", false ] call BIS_fnc_secondsToString ];
		_timer = _timer - 1;
		uiSleep 1;
	};

	//Remove timer display
	( "AUSMD_Timer" call BIS_fnc_rscLayer ) cutText["","PLAIN"];

	_args call _code;
};

//Wait for mission to start
waitUntil{ time > 0 };

//Start a timer
[
	120,
	{ hint _this },
	"Timer Finished"
] spawn AUSMD_fnc_timer;

 

Added some extra bits so the timer removes its display when finished and has the ability to call some code.

TEST_MISSION

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites

@Larrow
Really well done, a few questions?
#1 How do I stop the game if the clock goes to zero?
#2 how do i get time to change colors  e.g total time 1h = white / 0.45 = green / 0.30 = yellow / 0.15 = Orange / 0.05 = red

Share this post


Link to post
Share on other sites

AUSMD_timer_V2

Added warning time parameter( see example call below )

 

Put through very limited testing: MP( dedicated & JIP ), SP( with save/resume )

 

Example:

//Wait for mission to start
waitUntil{ time > 0 };

//Start a timer
[
	//Total timer time in seconds
	120,
	//Code called when timer ends( both server and non headless clients in MP )
	{
		if ( isServer ) then {
			[ "end1" ] call BIS_fnc_endMissionServer;
		};
	},
	//Any arguments to pass to the end code
	[],
	//Warning time in seconds
	//from this time-left onwards the displays text color will gradually go through...
	// Green -> Yellow -> Orange -> and finally Red
	//If not supplied will automatically be a quarter of total timer time
	//Supply 0 if not needed.
	100
] spawn AUSMD_fnc_timer;

 

18 hours ago, Casio91Fin said:

#1 How do I stop the game if the clock goes to zero?

See passed code in above example or in test missions initServer.sqf

 

18 hours ago, Casio91Fin said:

how do i get time to change colors  e.g total time 1h = white / 0.45 = green / 0.30 = yellow / 0.15 = Orange / 0.05 = red

Although I have not implemented these exact times, I have implemented a gradual color variation. See _warningTime parameter.

 

  • Like 2

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×