Jump to content
Sign in to follow this  
clydefrog

What is the best way to measure time since start of mission?

Recommended Posts

Hi, for the mission I'm working on I want it to work so that if Blufor fail to kill an enemy unit within one hour then they fail. I simple have a trigger with

time > 3600 && alive VIP

inside it, but I have heard this can be unreliable if there is server lag. Is there another more reliable way to do something like this?

Share this post


Link to post
Share on other sites
Hi, for the mission I'm working on I want it to work so that if Blufor fail to kill an enemy unit within one hour then they fail. I simple have a trigger with

time > 3600 && alive VIP

inside it, but I have heard this can be unreliable if there is server lag. Is there another more reliable way to do something like this?

hi

i believe that there is nothing better then the time command

you should look at it from the other side... do not overload your server :cool:

Share this post


Link to post
Share on other sites
hi

i believe that there is nothing better then the time command

you should look at it from the other side... do not overload your server :cool:

It's not my server, so I'll just have to hope it is running well with a decent framerate when the mission is played.

Share this post


Link to post
Share on other sites

I think time is the best way.

you could start a loop at the mission start which updates a PublicVariable on each iteration. But i dunno if that'd be any better.

Share this post


Link to post
Share on other sites

I personally use diag_ticktime.

If you have heavy scripts the time command will eventually slow down. The difference in time 100->101 could in real life take 2 seconds.

Diag_ticktime does not have this problem.

I use this piece of code to sync a time var from my server to all my clients:

START_TIME = diag_tickTime;
while {true} do
{
ELAPSED_TIME = diag_tickTime - START_TIME;
publicVariable "ELAPSED_TIME";
sleep 1;
};

Edit: You can place this in the init.sqf but make sure to wrap it in a if(isServer)

Share this post


Link to post
Share on other sites
I personally use diag_ticktime.

If you have heavy scripts the time command will eventually slow down. The difference in time 100->101 could in real life take 2 seconds.

Diag_ticktime does not have this problem.

I use this piece of code to sync a time var from my server to all my clients:

START_TIME = diag_tickTime;
while {true} do
{
ELAPSED_TIME = diag_tickTime - START_TIME;
publicVariable "ELAPSED_TIME";
sleep 1;
};

Edit: You can place this in the init.sqf but make sure to wrap it in a if(isServer)

Is that all I need to do? And then I have my trigger condition as normal shown in the first post? Also would I need to use spawn. e.g.

[] spawn {

                if (isServer) then {
                                             START_TIME = diag_tickTime;
                                             while {true} do 
                                             {
                                              ELAPSED_TIME = diag_tickTime - START_TIME;
                                              publicVariable "ELAPSED_TIME";
                                              sleep 1;
                                             };
                                   };

        };


Edited by clydefrog

Share this post


Link to post
Share on other sites

Yes, the spawn is indeed a good idea. Your example is perfect.

You can put the condition of the ending trigger to:

ELAPSED_TIME => 3600 && alive VIP

Just test it with 10 or something to be sure.

Share this post


Link to post
Share on other sites

Use time and use it on the server. If the server is lagging time will be delayed, but then again so is the entire mission. The only thing that isn't slowed down is player-controlled units (since they will just warp from the server's perspective and in ArmA the server allows it to happen), but it shouldn't be a big deal if the server isn't lagging badly. If the server is lagging badly then poor time counting is the least of your worries - You'll have other much bigger problems really.

As long as you use the server time, at least it's the same time for everyone.

Share this post


Link to post
Share on other sites

Thanks mindstorm.

Use time and use it on the server. If the server is lagging time will be delayed, but then again so is the entire mission. The only thing that isn't slowed down is player-controlled units (since they will just warp from the server's perspective and in ArmA the server allows it to happen), but it shouldn't be a big deal if the server isn't lagging badly. If the server is lagging badly then poor time counting is the least of your worries - You'll have other much bigger problems really.

As long as you use the server time, at least it's the same time for everyone.

so you suggest the trigger condition to be, for example:

isServer && time > 3600 && alive VIP

?

Share this post


Link to post
Share on other sites

uf uf i hate errors.. i just lost my reply so i will short it..

you are mixing two differen things together..

first of all, time is local, each machine compute time on its own..

facts:

time is synced only once per client (on connection)

time can "run slower"

example:

you are connecting to the server

server givs you time (computed by server)

since that your machine compute time by its own...

scenario one:

server have performance problems..

server time runs slower

your time runs normally

scenario two:

you have performance probmes..

server time runs normally

your time runs slower

so.. this code...

START_TIME = diag_tickTime;
while {true} do
{
   ELAPSED_TIME = diag_tickTime - START_TIME;
   publicVariable "ELAPSED_TIME";
   sleep 1;
};

is theoretically useful if u need same "time value" on each machine........

my suggestion....... never use that... its useless... im sorry... :o

so... yeah... lets say that you care about performance of your scripts (in fact you always should :) )

triggers checks for their conditions twice per second.. you dont have to do that so "fast" when your time limit is one hour..

suggested solution:

init.sqf

if isServer then
{
 private ["_delay", "_timeLimit"];

 _timeLimit = 3600;

 _delay = 2;

 [_timeLimit, _delay] spawn
 {
   private ["_continue", "_delay", "_timeLimit"];

   _timeLimit = [_this, 0, 3600, [0]] call BIS_fnc_param;
   _delay = [_this, 1, 2, [0]] call BIS_fnc_param;

   _timeLimit = _timeLimit - _delay;

   _continue = true;

   waitUntil { time > 0 };

   while { _continue } do
   {
     if (time > _timeLimit) then
     {
       [["EndName", true, true], "BIS_fnc_endMission", true, true] call BIS_fnc_MP;
       _continue = false;
     };

     sleep _delay;
   };
 };
};

Edited by Tatar

Share this post


Link to post
Share on other sites
uf uf i hate errors.. i just lost my reply so i will short it..

you are mixing two differen things together..

first of all, time is local, each machine compute time on its own..

facts:

time is synced only once per client (on connection)

time can "run slower"

example:

you are connecting to the server

server givs you time (computed by server)

since that your machine compute time by its own...

scenario one:

server have performance problems..

server time runs slower

your time runs normally

scenario two:

you have performance probmes..

server time runs normally

your time runs slower

so.. this code...

START_TIME = diag_tickTime;
while {true} do
{
   ELAPSED_TIME = diag_tickTime - START_TIME;
   publicVariable "ELAPSED_TIME";
   sleep 1;
};

is theoretically useful if u need same "time value" on each machine........

my suggestion....... never use that... its useless... im sorry... :o

so... yeah... lets say that you care about performance of your scripts (in fact you always should :) )

triggers checks for their conditions twice per second.. you dont have to do that so "fast" when your time limit is one hour..

suggested solution:

init.sqf

if isServer then
{
 private ["_delay", "_timeLimit"];

 _timeLimit = 3600;

 _delay = 2;

 [_timeLimit, _delay] spawn
 {
   private ["_continue", "_delay", "_timeLimit"];

   _timeLimit = [_this, 0, 3600, [0]] call BIS_fnc_param;
   _delay = [_this, 1, 2, [0]] call BIS_fnc_param;

   _timeLimit = _timeLimit - _delay;

   _continue = true;

   waitUntil { time > 0 };

   while { _continue } do
   {
     if (time > _timeLimit) then
     {
       [["EndName", true, true], "BIS_fnc_endMission", true, true] call BIS_fnc_MP;
       _continue = false;
     };

     sleep _delay;
   };
 };
};

Hmm, I take it I need to put something in that loop to exit it so it doesn't keep just looping the Mission Failed endmission thing?

I've done this:


if isServer then
{
 private ["_delay", "_timeLimit"];

 _timeLimit = 60;

 _delay = 2;

 [_timeLimit, _delay] spawn
 {
   private ["_delay", "_timeLimit"];

   _timeLimit = [_this, 0, 60, [0]] call BIS_fnc_param;
   _delay = [_this, 1, 2, [0]] call BIS_fnc_param;

   _timeLimit = _timeLimit - _delay;

   while { true } do
   {
     if (time > _timeLimit && alive vip) then
     {
       [["End2", false, true], "BIS_fnc_endMission", west, false] call BIS_fnc_MP;
[["End3", true, true], "BIS_fnc_endMission", east, false] call BIS_fnc_MP;
     };

     if (time > _timeLimit && alive vip) exitWith {};

     sleep _delay;
   };
 };
};

Share this post


Link to post
Share on other sites
Hmm, I take it I need to put something in that loop to exit it so it doesn't keep just looping the Mission Failed endmission thing?

here is how i did mine if it helps, i used to have the endless loop on mission end too. but this fixed mine:

[color="#FF0000"]EndisNear = true;[/color]

	 while {EndisNear} do {


	  if (waves_east == AIWaveCount)then {

	  _CntEast = {side _x == opfor} count allUnits;

          if (_CntEast == 0)then {

             ["End1","BIS_fnc_endMission",west] call BIS_fnc_MP;
      ["End1","BIS_fnc_endMission",independent] call BIS_fnc_MP;

		[color="#FF0000"][color="#FF0000"]EndisNear = false;[/color][/color]

	};
};
   sleep 10;	

    };

Share this post


Link to post
Share on other sites
Hmm, I take it I need to put something in that loop to exit it so it doesn't keep just looping the Mission Failed endmission thing?

description.ext

class CfgDebriefing
{
 class myOwnEndName1
 {
   title = "title";
   subtitle = "subtitle";
   description = "description";
   picture = "b_inf";
   pictureBackground = "";
   pictureColor[] = { 1.0, 1.0, 1.0, 1 };
 };

 class myOwnEndName2
 {
   title = "title";
   subtitle = "subtitle";
   description = "description";
   picture = "b_inf";
   pictureBackground = "";
   pictureColor[] = { 1.0, 1.0, 1.0, 1 };
 };
};

if (time > _timeLimit) then
{
 private "_end";

 _end = "myOwnEndName1";

 if (alive VIP) then
 {
   _end = "myOwnEndName2";
 };

 [[_end, true, true], "BIS_fnc_endMission", true, true] call BIS_fnc_MP;
 _continue = false;
};

note that second argument for BIS_fnc_endMission isnt victory/loose but completed/failed

its not a "graphic" function, it actually can change the text what you can see on debriefing if you dont define "what the end is" but its main feature is that it keeps or deletes the actual mission proggres.. if mission fails progress is saved and you can continue from last save, but if the mission is completed the saved progress is deleted... because mission was completed........

btw.. im sorry i didnt notice that you posted your reply so fast.. look at the code again i edited it little bit...

Edited by Tatar

Share this post


Link to post
Share on other sites

Don't forget though that even sleep checks every frame if enough time has passed, so don't worry too much about checking a condition very often, as long as it's not some crazy ass condition. Especially if the condition is simply time > endTime or something of that sort, you can check it every frame and the performance will be about the same as checking it every 60 seconds (because the sleep itself is tested every frame anyway). Even an iteration of all units (for example counting if all enemies are dead) is something you should feel free to do very often.

Share this post


Link to post
Share on other sites

You will be perfectly fine using my piece of code and a trigger.

Use this piece of code. Don't wrap it in a isServer because else the trigger will give an error on clients.

START_TIME = diag_tickTime;
while {true} do
{
   ELAPSED_TIME = diag_tickTime - START_TIME;
   sleep 1;
};

Then in the tirgger put the condition to:

isServer && ELAPSED_TIME => 3600 && alive VIP

And set the trigger to end1 or whatever ending. You can also make another one with end2 with is the failing trigger if !alive vip.

It is absolutely bogus to say that this is performance hungry. It it far from performance hungry. Even if this code was called onEachFrame then you would still have no visible performance los / fps los.

And clydefrog, you actually swap my solution for a more performance hungry solution (and even your solution is that much of a deal) which only runs once each 2 seconds.... Not to mention the fact that you still use the time var which is prone to delay. In any case I suggest never using that var for time based calculations, it's too unreliable... Especially in early beta's and not to mention the fact that you can be running mods who could be totally out of your "performance optimization ideology".

calling diag_tickTime has no extra overhead instead of calling time so why on earth wouldn't you wanna use it....

Share this post


Link to post
Share on other sites

Even if you run an insane amount of scripts, as long as they don't spam anything crazy (like diag_log, createVehicle or nearObjects with a very large radius), they won't cause any FPS drops. They'll just eat runtime from other scripts that need to run. Exception is of course non-scheduled scripts (code of event handlers, init lines and trigger conditions/activations, or functions called from any of those).

In any case, just doing a comparison and 2 logical operations every 0.5 sconds (or even 10 times every frame) is really nothing. Same for updating a variable with a simple arithmetic operation.

Share this post


Link to post
Share on other sites
You will be perfectly fine using my piece of code and a trigger.

Use this piece of code. Don't wrap it in a isServer because else the trigger will give an error on clients.

START_TIME = diag_tickTime;
while {true} do
{
   ELAPSED_TIME = diag_tickTime - START_TIME;
   sleep 1;
};

Then in the tirgger put the condition to:

isServer && ELAPSED_TIME => 3600 && alive VIP

And set the trigger to end1 or whatever ending. You can also make another one with end2 with is the failing trigger if !alive vip.

It is absolutely bogus to say that this is performance hungry. It it far from performance hungry. Even if this code was called onEachFrame then you would still have no visible performance los / fps los.

And clydefrog, you actually swap my solution for a more performance hungry solution (and even your solution is that much of a deal) which only runs once each 2 seconds.... Not to mention the fact that you still use the time var which is prone to delay. In any case I suggest never using that var for time based calculations, it's too unreliable... Especially in early beta's and not to mention the fact that you can be running mods who could be totally out of your "performance optimization ideology".

calling diag_tickTime has no extra overhead instead of calling time so why on earth wouldn't you wanna use it....

I never said I'm not going to use it, I've been given a load of options so I don't know what to use at the moment. By the way I have already tried your code (the bit you posted on page 1) along with the spawn and isServer stuff in the init and ELAPSED_TIME > 60 in the trigger, and nothing happened. Any idea why?

Edited by clydefrog

Share this post


Link to post
Share on other sites

Works fine here. Try setting up an onAct hint and test it with 10 seconds or so.

Share this post


Link to post
Share on other sites
Works fine here. Try setting up an onAct hint and test it with 10 seconds or so.

well I had it with my endmission code in it which I know works as it did with time, and had it set to 60 seconds. I'll give it another try. Should I be using the code from the first page or the new one without the publicVariable?

Edited by clydefrog

Share this post


Link to post
Share on other sites

Do a quick test (with sideChat, hint or diag_log) to see that your end mission script even starts running. If it does, then the trigger is working and you should debug the script :)

Share this post


Link to post
Share on other sites

Ok mindstorm it's working. So to be clear I don't need the publicVariable "ELAPSED_TIME"; line that was in there originally, and I shouldn't run the code on the server but just run the trigger condition on the server, and I should still use spawn for that code in the init.sqf right?

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
Sign in to follow this  

×