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

Users who are viewing this thread

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?
 
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.
 
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.
 
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?
 
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 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
 
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?
 
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.
 
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.
 
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.
 
Back
Top Bottom