Jump to content

Recommended Posts

Hey fellow forumgoers!
 

People have been very helpful. I try to give some back to the newer forum members, but I notice that my lack of programming experience is really biting me. This feature I am designing was sort of meant to practice the basics. It also, believe it or not, will be included in a mission.

Aim: Basically, to recreate an object that does this-
https://www.youtube.com/watch?v=6ZeD5BrQYXo

Only instead of telling the time, it tells how much is left of a timer. Example: 12:57 will be read out as " one - two - five - seven ".

The setup is simple. Some recorded sounds for the numbers 1 through 10. A timer countdown script. A function to couple the four digits to four sounds being played. A " clock " object. And an addaction on the clock object to execute the coupling function. 
The sounds work great (.ogg format). I can play them using " Say3D " without problems.

The timer script, very simply, starts counting down when it is started via execVM:


timer = 58; // length of timer

while {timer > 0} do  
{
    timer = timer - 1;   
    sleep 1; 
};

An ingame object named " clock " will get an addaction in its init:

this addAction [(""<t color='#FFFFFF'>"" + (""Switch on Clock"") + ""</t>""),{[clock,timer] call MeM_fnc_ClockSpeak;},"""",1,true,true,"""",""(_target distance _this) < 3""]; 


But I am stuck on the most difficult part, which is the function (fn_ClockSpeak) that parses the time into four digits, couples each digit with the correct sound file, then plays them correctly in order. This is what I came up with:

private ["_clock", "_time"];
_clock = [_this, 0, objNull, [objNull]] call BIS_fnc_param;
_time = [_this, 1, 0, [0]] call BIS_fnc_param;

_timestring = [((_time)/60)+.01,"HH:MM"] call BIS_fnc_timetostring;

_firstnum  = _timestring select [0,1] ;
_secondnum = _timestring select [1,1] ;
_thirdnum  = _timestring select [3,1] ;
_fourthnum = _timestring select [4,1] ;

//hintC format ["Time is %1 %2 : %3 %4", _firstnum, _secondnum, _thirdnum, _fourthnum]; // Testing parsing

	{ if (_x isequalto "1") then {_clock say3D ["01", 70, 1];} ;
	  if (_x isequalto "2") then {_clock say3D ["02", 70, 1];} ;
	  if (_x isequalto "3") then {_clock say3D ["03", 70, 1];} ;
	  if (_x isequalto "4") then {_clock say3D ["04", 70, 1];} ;
	  if (_x isequalto "5") then {_clock say3D ["05", 70, 1];} ;
	  if (_x isequalto "6") then {_clock say3D ["06", 70, 1];} ;
	  if (_x isequalto "7") then {_clock say3D ["07", 70, 1];} ;
	  if (_x isequalto "8") then {_clock say3D ["08", 70, 1];} ;
	  if (_x isequalto "9") then {_clock say3D ["09", 70, 1];} ;
	  if (_x isequalto "0") then {_clock say3D ["00", 70, 1];} ;
	sleep 5;  
	}  
	forEach [ _firstnum, _secondnum, _thirdnum, _fourthnum] ;


Notice that I commented out a hintC. This was to check that the parsing of _num 's went correctly, which it did. My idea was to have a series of " if () " statements match the digit to playing the correct audio file, for each digit, with a pause in between digits. Seemed reasonably straightforward to me.
 
But no audio is played with this script. The game doesn't give an error, so I don't know what I'm missing. My guess is that the _x is out of scope.

Anyone have any ideas?

Share this post


Link to post
Share on other sites

I just looked your script roughly, so might wrong, but aren't _firstnum ... _fourthnum string but not scalar? Try if (_x isequalto "1") ... instead.

  • Like 1

Share this post


Link to post
Share on other sites

Holy cow! That was it. 

I have edited the script to its correct form. 
 

Thank you !

Share this post


Link to post
Share on other sites

Few things:

You can avoid this:

{ if (_x isequalto "1") then {_clock say3D ["01", 70, 1];} ;
	  if (_x isequalto "2") then {_clock say3D ["02", 70, 1];} ;
	  if (_x isequalto "3") then {_clock say3D ["03", 70, 1];} ;
	  if (_x isequalto "4") then {_clock say3D ["04", 70, 1];} ;
	  if (_x isequalto "5") then {_clock say3D ["05", 70, 1];} ;
	  if (_x isequalto "6") then {_clock say3D ["06", 70, 1];} ;
	  if (_x isequalto "7") then {_clock say3D ["07", 70, 1];} ;
	  if (_x isequalto "8") then {_clock say3D ["08", 70, 1];} ;
	  if (_x isequalto "9") then {_clock say3D ["09", 70, 1];} ;
	  if (_x isequalto "0") then {_clock say3D ["00", 70, 1];} ;
	sleep 5;  
	}  
	forEach [ _firstnum, _secondnum, _thirdnum, _fourthnum] ;

By doing that:

{
	_clock say3D ["0" + _x, 70, 1]
	sleep 5;  
} forEach [ _firstnum, _secondnum, _thirdnum, _fourthnum];

Since you want to say single digit numbers and it's a finite amount of known strings ("00" -> "09") this should do fine.

You could even rename all sound cfgs to "0"->"9" to avoid the "0" + _x entirely.

 

From what I know, last time I checked say3D uses some kind of queue, you could try ditching the sleep inside the foreach, all sounds should still play in order, might have changed though.

 

Also don't use sleep for your timer, build it around time instead, for guaranteed accuracy, since sleep can suspend for more than the given duration, depending on scheduler load.

 

Cheers

 

  • Like 4
  • Thanks 1

Share this post


Link to post
Share on other sites

Also thanks!

I had to add a ; to the end of " _clock say3D [_x, 70, 1] ". But this also works fine. 

Unfortunately the sleep seems necessary to prevent the sounds from playing simultaneously. 

A few questions.
What does adding "0" + do to the variable? 
How much difference can I expect between client "time" and "serverTime" with, let's say, an hour gameplay of 10 players without mods? 
And does it generate a lot of network traffic to base the timer on "serverTime" for each client?

Share this post


Link to post
Share on other sites

There are already sound files available for numbers in vanilla Arma 3.

Spoiler


[ 60 * 60 * 1.99 ] call BIS_fnc_countdown;
addMissionEventHandler[ "EachFrame", {
	hintSilent str ( [ [ 0 ] call BIS_fnc_countdown, "HH:MM:SS" ] call BIS_fnc_secondsToString );
}];
player addAction[ "Tell Time", {

	[] spawn {

		_timeRemaining = [ 0 ] call BIS_fnc_countdown;
		systemChat format[ "Time now: %1", [ _timeRemaining, "HH:MM:SS" ] call BIS_fnc_secondsToString ];
		
		_soundPath = "A3\Dubbing_Radio_F\data\ENG\Male01ENG\RadioProtocolENG\Normal\025_Numbers\";
				
		{
			_tenths = floor ( _x / 10 );
			_units = _x - ( _tenths * 10 );
			
			if ( _tenths > 1 ) then {
				_tenthsSound = [ "", "", "twenty.ogg", "thirty.ogg", "forty.ogg", "fifty.ogg" ] select _tenths;
				playSound3D[ _soundPath + _tenthsSound, player ];
				uiSleep 0.5;
			}else{
				_units = _units + ( _tenths * 10 );
			};
			
			if ( _forEachIndex > 0 && { _tenths isEqualTo 0 && _units < 10 } ) then {
				playSound3D[ _soundPath + "zero.ogg", player ];
				uiSleep 0.5;
			};
			
			_unitsSound = [ 
				"zero.ogg", "one.ogg", "two.ogg", "three.ogg", "four.ogg", 
				"five.ogg", "six.ogg", "seven.ogg", "eight.ogg", "nine.ogg", 
				"ten.ogg", "eleven.ogg", "twelve.ogg", "thirteen.ogg", "fourteen.ogg", 
				"fifteen.ogg", "sixteen.ogg", "seventeen.ogg", "eighteen.ogg", "nineteen.ogg"
			] select _units;

			if !( _tenths > 1 && _units isEqualTo 0 ) then {
				playSound3D[ _soundPath + _unitsSound, player ];
			};
			uiSleep 0.5;

		}forEach ( [ _timeRemaining, "HH:MM:SS", true ] call BIS_fnc_secondsToString apply{ parseNumber _x } );
	};

}];

Example to run from the debug console in a mission preview. Use the addAction to make the player say the time.

 

  • Like 5

Share this post


Link to post
Share on other sites
18 hours ago, Melody_Mike said:

A few questions.
What does adding "0" + do to the variable? 
How much difference can I expect between client "time" and "serverTime" with, let's say, an hour gameplay of 10 players without mods? 
And does it generate a lot of network traffic to base the timer on "serverTime" for each client?

"0" + _x simply adds a leading zero to the string, so if _x is "5" it will turn into "05".

serverTime is global and automatically synced every 5 minutes, so no manual sync needed.

 

Cheers

  • Like 1

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

×