Jump to content

Times and what those magic numbers mean


WizWom

Recommended Posts

OK, having explored various and sundry things:

 

A round is 90 display frames. The [Program Options] Maximum Frame Rate= option sets the target; it can vary from that some, for instance, I usually see 31 or 32 FPS with a '30' setting, '45' gives me 44 to 47. If the AI is overloaded, it will slow the frame rate.

 

A round has 6 AI updates. That is, a StartTimer(n,6) will be a 1-round delay until the timer expires.

 

A VVC display Rate of 15 updates at 1 frame from the animation per display frame.

 

Your character's base speed is 9 - this is 10 display frames to move 1 unit. This is why the walking animations (like CHFC4G11.BAM) have 10 frames per pace.

 

A Spell duration is also frame rate/10. Thus, Bless, with a 4-round duration, has '36'

 

I was not entirely sure, but it seemed a SmallWait(30) gave me a 1-round delay. I did not get my expected results any of these blocks:

 

IF
!CombatCounter(0)
THEN
RESPONSE #100
	DisplayStringHead(Myself,4592)
	StartTimer(1,6)
	SmallWait(60)
END

IF
TimerExpired(1)
THEN
RESPONSE #100
	DisplayStringHead(Myself,4392)
	StartTimer(1,6)
END

Link to comment
A round has 6 AI updates. That is, a StartTimer(n,6) will be a 1-round delay until the timer expires.

 

 

 

IF
!CombatCounter(0)
THEN
RESPONSE #100
	DisplayStringHead(Myself,4592)
	StartTimer(1,6)
	SmallWait(60)
END

 

I think you got that wrong. A round is 6 seconds with 15 AI updates every second. That comes to 90 AI updates in a round. So SmallWait(90) would equal a round.

 

You would have to wrap it up in "SetInterrupt's" though, unless every other block in your script starts with "ActionListEmpty()", otherwise your "SmallWait", will be cut off as soon as the script finds something else to do.

Link to comment
You would have to wrap it up in "SetInterrupt's" though, unless every other block in your script starts with "ActionListEmpty()", otherwise your "SmallWait", will be cut off as soon as the script finds something else to do.

Did you test it?

I am certain that it is 6 AI updates per round, and that it is 15 frames per update. I am also certain that those frames are timed based on a "best attempt" to meet the selected Frame rate per second.

I mean, I can go in and look at the timing again... Better yet, I'll make a 90 frame sequence which displays the frame number. and then I'll run windowed with a clock next to the screen.

 

Results later this morning.

Link to comment

Well, I made a counter animation, counting from 0 to 14. I made a VVC to run it at speed 15

I set the frame rate to 15 fps (actual frame rate, by ^D, 16 fps.

Round Autopause on frame 5 to start

Round Autopause on frame 10 after cycling 6 times after ~12 seconds.

Round Autopause on frame 5 after cycling 6 times after ~12 seconds.

 

So, yes, my timing was off. I'm going to try to increase the VVC speed, and see what happens.

Chance the VVC speed to 30.

Round Autopuse on frame 12 to start

Round AutoPause on frame 7 after cycling 6 times.

 

It appears that speed 15 is the maximum for a VVC, and that a round is 100 frames, not 90.

 

It seems to take 4-5 animation frames to walk across the distance of a target circle.

Link to comment

OK, a new timing script:

IF
!CombatCounter(0)
THEN
RESPONSE #100
	MakeUnselectable(6)
	StartTimer(1,6)
END

IF
TimerExpired(1)
THEN
RESPONSE #100
	MakeUnselectable(6)
	DisplayStringHead(Myself,4392) // evening
	StartTimer(1,6)
END

 

Results (after setting everyone in the party to this script):

Party AI turned on, fram 0 - no activity.

Attack Minsc with PC on frame 0:

0f4: Aerie (Player4, I think) purple; Autopause Round end (PC in contact with Minsc)

1f5: rest of group now has purple circle, except PC

2f15: PC now gets purple circle

4f?: Aerie green for a moment (no text)

4f13: Jan turns green

5f2: Anomen G

5f3: Minsc G

5f4: Jan Purple (no text)

[Minsc & Jaheira display "evening"]

8f8: Pc green

8f12: PC purple, display "Evening"

No autopause, combat stopped by display.

Characters continue to have a 90%+ cycle of purple circle time.

 

The "Unselectable" time and the timer seem to be 10 frames per, like spells, If I'm interpreting this correctly. So I will test using 9 and see if that gives me the whole round.

 

OK, changing 6s to 9s:

after a cylce, on frame 13 PC turns Green

1f4: turn purple

1f6: display "evening"

8f9: PC turns green

8f14 PC turns purple

9f1: display "evening"

 

so, '9' gave me roughly 115 frames.

I still did not get in a second attack.

So, I shall make a script which attacks Minsc and starts the timer at 10.

 

OK: 0f0 order attack minsc

0f5-11: NPCs turn purple

4f13: Pc Pur, "Attacks Minsc" message

6f14: Pause R.E.

8f10-9f4: NPC cycle green->purple

13f4: PC Green, Pause R.E.

16f6-12: NPC cycle green->purple

17f5: PC green, Pause R.E. (does not turn purple again)

23f0: pause R.E.

25f10-26f8: NPCs Cycle G->P

 

So, uniquivocably, the timer runs through 6 cycles per round.

The AI timer is not quite synced with a player's round.

The same count is used for MakeUnselectable() and a SetTimer

 

Owing to the AI running scripts in randomized order, it seems, you get a bit of randomization each cycle.

Link to comment

Don't know why you link frames per second to AI updates Wizdom. Why should those be related in any way. One is the CPU working, the other the GPU. Changing the framerate in a shooter game doesn't make the enemy AI better or worse..but maybe there's something I don't know about the inner workings of PCs here - probably a lot.

 

I got my information from the IESDP, which states:

 

"RunAwayFrom(O:Creature*,I:Time*)"

Is a very nice command to use to escape your enemies when your hitpoints get low, provided there is somewhere to run to. The Time parameter is measured in AI updates. Since, by default, there are 15 AI updates per second, it is usually a rule of thumb to use multiples of 15, such as 90, 120, or 180.

 

Which makes perfect sense. Try scripting a RunAwayFromNoInterrupt(O:Creature*,90), it should come to 6 seconds. Doesn't matter what your frame rate is. "90" refers to the number of times the script should skip a "runthrough" checking for new actions. Doing that 90 times with 15 checks per second will take 6 seconds.

 

The way I understand it, the script will update every 6.67 ms (100/15), which means going through the "IFs" to see if anything checks true. In that case whatever is on the actionlist is deleted, unless it's a Continue()'ed action, and replaced with the current actions. (Which is why you use ActionListEmpty as a trigger - whatever is on the ActionList will be completed first and not replaced.)

 

If your action isn't an instant one (Shout, SetGlobalTimer and so on), but takes time (Attack,MoveToObject,Wait,RunAwayFrom) and isn't wrapped in SetInterrupts, it will be deleted as soon as something else checks true, which could be 6.67 ms later.

 

IF
 Hotkey(D)
 See(NearestEnemyOf())
THEN
RESPONSE #100
	  RunAwayFromNoInterrupt(NearestEnemyOf(),90)		 
END

IF
 ActionListEmpty()
THEN
RESPONSE #100
		 DisplayStringHead(Myself,27405)// "Stop."
END

 

It seems however that actions are only executed once every 1 second, which means that your script has 15 chances every second to decide what to do next. This is why you will see the character move in 6 distinctly separate moves if you run the code above. But I'm not entirely sure about this.

Link to comment

The game has a fixed limit on how many scripting actions and trigger blocks it will do per AI tick; there was noticable delay between the actions in a single action block, let alone between the checking of trigger blocks.

 

MakeUnselectable() completes the current script pass, and then stops AI for the sprite. So, there was no further scripting from that sprite until the MakeUnselectable() has expired. There was then a very noticable, but variable, delay until the next AI cycle kicked in, and the MakeUnselectable() was run again.

 

But, there are 15 AI updates per second. I had a counter runing with 15 ticks per second. Everyone's AI was staggered. But each script is not run every AI update. I think that is how the engine simulates initiative.

 

Which you could have noticed if you had tried that code.

 

You also seem to be forgetting that an executed block with no Continue() end processing of that script for that run. It won't restart until it gets another chance at the queue. SetInterrupt(FALSE) keeps other scripts from interfering; that is, if I have both a General script and a class script, the class script needs to do a SetInterrupt(FALSE) to make sure it gets to perform an action list. I have not tested SetInterrupt(), so I'm not sure what the results of that would be.

Link to comment
Don't know why you link frames per second to AI updates Wizdom. Why should those be related in any way. One is the CPU working, the other the GPU. Changing the framerate in a shooter game doesn't make the enemy AI better or worse..but maybe there's something I don't know about the inner workings of PCs here - probably a lot.

 

I never did address this.

 

In your configuration options, you get the option "Frame Rate" in AI options. This changes [Program Options] Maximum Frame Rate=n in baldur.ini

 

This is not the video Frame Rate, technically. Like most good games, the screen update is synced to the video refresh, to happen between them. This is an automatic feature of Windows DirectX. But both the animations and scripts are sped up if you increase the Frame Rate, and slowed down if you decrease it. Heavy script loading will slow it during play, heavy animation loading will not, but WILL cause skipped frames.

Link to comment

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...