B Info Module System Delays & Mission Template Triggers: A Study

Currently viewing this thread:

Caba`drin

Count
M&BWBWF&SNWVC
Best answers
0
After a recent exchange in the Q&A thread about mission template triggers and their various delay and check intervals, I just so happened to have a PM exchange with motomataru and he pointed out something I wasn't aware of when dealing with delays and mission templates triggers:
motomataru said:
Simple check: an n-second trigger with an n/2 delay, display_message the mission clock. It'll show the trigger firing every n+n/2 seconds.
So, I ran a test with the following debug trigger:
Code:
(4, 2, 0, [(store_mission_timer_a_msec,reg0),(display_message, "str_reg0"),],
[(store_mission_timer_a_msec,reg0),(display_message, "str_reg0")]),
I both included and did not include a conditional test (eq, 1, 1) in the conditions block; the inclusion of such an operation had no effect. The result was exactly as moto had indicated--the trigger fired every 6 seconds after its initial firing somewhere in second 1, typically around 600 milliseconds.

However, the delay between the two blocks worked correctly in that the second millisecond report was always 2 seconds following the first...it was just that the first did not appear every 4 seconds, but every 6.

Out of curiosity I included a re-arm delay. The re-arm delay works correctly.
I tested the following trigger:
Code:
 (4, 2, 5, [(store_mission_timer_a_msec,reg0),(display_message, "str_reg0"),],
[(store_mission_timer_a_msec,reg0),(display_message, "str_reg0")]),
And the screen displayed the following:
Code:
600
2625

11656
13682

22714
24715

33747
35748
So the delay was always 2 seconds and the call interval was always 11 seconds 4+2+5.

But now here's the crazy thing...if the conditions block fails, the check interval is correct.

With this trigger, where the conditions block should fail 50% of the time:
Code:
(4, 2, 5, [(store_mission_timer_a_msec,reg0),(display_message, "str_reg0"),(store_random_in_range, reg0, 0, 2),(eq, reg0, 0)],
[(store_mission_timer_a_msec,reg0),(display_message, "str_reg0")]),
I got the following pattern:
Code:
521

4522
6535

15556

19570
21576

30601

34606
36609
So, the re-arm delay definitely works correctly, but the "problem" with the delay interval only comes in when it is actually used...which leads me to think that it is less a "bug" and more a very strange idea on the dev's part of what would be useful...

Also, I've done numerous checks on timed triggers and when they initialize themselves on mission-start. The above checks confirm what my other tests have demonstrated--the check interval does not affect when a trigger will first fire in the mission. All timed triggers, regardless of call interval, will be initialized in the first second of the mission. I had previously been under the mistaken assumption that they would begin X seconds into the mission...with X as whatever their check interval was.

Has any one else noticed these things? Had I either missed the boat or misunderstood the intention of these values?
 

xenoargh

Grandmaster Knight
Best answers
0
Hmm.  Never used that, I just use strict timers.  I never presume anything will happen during the very first part of a scenario properly unless it's a Presentation (they're realtime wherever they're allowed to be, up to the frame limiter).

Sounds like it's N1+N2 for the first delay... maybe because so much stuff is happening on 0 that anywhere they could, they shoved it out a repetition and during the first pass it auto-gives false?

Try printing the logical state in the conditions block.
 

Computica

Grandmaster Knight
M&BWBWF&S
Best answers
0
This is a very good observation and test with conclusion on the mission trigger mechanics. I haven't noticed this myself but I have been working in the mission_templates.py a lot lately. Thanks for this information.
 

Caba`drin

Count
M&BWBWF&SNWVC
Best answers
0
And just checked with standard long/old-form triggers in module_triggers on the game map with the following:
Code:
(2, 1, 3, [(store_current_hours,reg0),(display_message, "str_reg0"),(store_random_in_range, reg0, 0, 2),(eq, reg0, 0)],
[(store_current_hours,reg0),(display_message, "str_reg0")]),
The pattern is identical to the mission_template_triggers (at least there is consistency).

The data gathered were as follows (in game hours):
Code:
323

325
326

331
332

337

339
341

346

348

350
351
xenoargh said:
Sounds like it's N1+N2 for the first delay... maybe because so much stuff is happening on 0
I also checked the mission_timer in milliseconds for ti_after_mission_start and an every frame trigger, check interval 0.
The mission timer always read exactly "200" milliseconds both for ti_after_mission_start and the trigger with check interval 0.

xenoargh said:
Try printing the logical state in the conditions block.
I'm uncertain how I would do this other than having the display_message call following a conditional check...which I've done to the same result. Unless I'm missing your meaning?
 

xenoargh

Grandmaster Knight
Best answers
0
I was thinking to set a Troop register on one of the dummies.  Something non-message-like and fast.
 

cmpxchg8b

Count
M&BWBWF&SNW
Best answers
0
How a trigger works internally:
Code:
// executed on event for named triggers, executed every frame for timed triggers
// context = trigger number (negative) for named triggers, current context (positive) for timed triggers
// timer.set = set timer start time to current frame time
// timer.get_time_elapsed = get time elapsed since timer start time
// conditions.execute and consequences.execute = self explanatory, return false on operation block failure (cf), true on success
void trigger::execute(int context)
{
	if (status == ts_rearm && rearm_interval <= rearm_interval_timer.get_time_elapsed())
	{
		check_interval_timer.set();
		status = ts_check;
	}
	if (status == ts_check)
	{
		if (check_interval > -0.1f)
		{
			if (context >= 0)
			{
				if (check_interval <= check_interval_timer.get_time_elapsed())
				{
					check_interval_timer.set();
					if (conditions.execute(context))
					{
						delay_interval_timer.set();
						status = ts_delay;
					}
				}
			}
		}
		else
		{
			if (round(check_interval) == context && conditions.execute(context))
			{
				rearm_interval_timer.set();
				status = ts_rearm;
				consequences.execute(context);
			}
		}
	}
	if (status == ts_delay && delay_interval <= delay_interval_timer.get_time_elapsed())
	{
		rearm_interval_timer.set();
		status = ts_rearm;
		consequences.execute(context);
	}
}
Totally just pseudocode derived from observations. Goes without saying.
 

Computica

Grandmaster Knight
M&BWBWF&S
Best answers
0
So is it possible to speed up the internal checks? I wouldn't mind it if the engine could handle it.
 

cmpxchg8b

Count
M&BWBWF&SNW
Best answers
0
Computica said:
So is it possible to speed up the internal checks? I wouldn't mind it if the engine could handle it.
Apart from the fact that that's not the issue, how do you speed up something that's checked on every frame?

Caba`drin said:
Out of curiosity I included a re-arm delay. The re-arm delay works correctly.
I tested the following trigger:
Code:
 (4, 2, 5, [(store_mission_timer_a_msec,reg0),(display_message, "str_reg0"),],
[(store_mission_timer_a_msec,reg0),(display_message, "str_reg0")]),
And the screen displayed the following:
Code:
600
2625

11656
13682

22714
24715

33747
35748
So the delay was always 2 seconds and the call interval was always 11 seconds 4+2+5.

But now here's the crazy thing...if the conditions block fails, the check interval is correct.
I gave a look to the examples, I think you guys are making the wrong assumption that the check interval is really an interval (who knows why, nice wording there TaleWorlds), while it's actually a check delay.
I'd say it's working as the devs intended, if not, they really fail hard.
Code:
600
- delay 2 sec
2625
- rearm 5 sec
- check 4 sec
11656
- delay 2 sec
13682
- rearm 5 sec
- check 4 sec
22714
- delay 2 sec
24715
- rearm 5 sec
- check 4 sec
33747
- delay 2 sec
35748
 

dunde

Count
WB
Best answers
0
So the game won't start the check interval countdown before it finished the delayed execution and rearming of successful trigger. Do I catch your explanation corrrectly?
 

cmpxchg8b

Count
M&BWBWF&SNW
Best answers
0
dunde said:
So the game won't start the check interval countdown before it finished the delayed execution and rearming of successful trigger. Do I catch your explanation corrrectly?
Yes. If you look at the code I posted above, it's a simple state machine with fixed delays.
 

Caba`drin

Count
M&BWBWF&SNWVC
Best answers
0
Aye, your explanation makes sense based on everything I've seen cmp. And follows your psuedo code.
As I stated
Caba`drin said:
So, the re-arm delay definitely works correctly, but the "problem" with the delay interval only comes in when it is actually used...which leads me to think that it is less a "bug" and more a very strange idea on the dev's part of what would be useful...
though it probably would have behooved me to summarize/note things as you did.

But yes, I think the key sticking point is "check interval" implies "put a number here and your trigger will be checked every this many seconds" not the "check delay" that it actually turns out to be. So, now I (we?) know.
 

Swyter

Grandmaster Knight
M&BWBWF&S
Best answers
0
Caba`drin said:
Aye, your explanation makes sense based on everything I've seen cmp. And follows your psuedo code.
Trust him, he knows the game better than the developers themselves.
Cool pseudo code by the way. :wink:
 

motomataru

Squire
M&BWBVC
Best answers
0
cmpxchg8b said:
Computica said:
So is it possible to speed up the internal checks? I wouldn't mind it if the engine could handle it.
Apart from the fact that that's not the issue, how do you speed up something that's checked on every frame?
I think he means how to turn the trigger into a true check interval with delay...

I did just that: effectively sped up the checks by running the trigger more often, then throwing out all but the ones that "matched" what I calculated the delay to be by the system clock.

I think that's right: the dev's were only looking at delaying the consequence block relative to whenever the check block fired.