-
Notifications
You must be signed in to change notification settings - Fork 1
Time Events
Time events seem to be a system that schedules callbacks for ToEE subsystems in a very flexible way.
Directly above the subsystem table are these three strings:
- Real-Time
- Game-Time
- Game-Time2 (Animations)
Which leads me to believe that these are the clock types supported by the game and are referenced as clock types 0 to 2.
Time generally seems to be stored as a number of days and the current time of day in milliseconds.
struct GameTime {
uint32_t day;
uint32_t timeOfDayInMs;
};
Clock Type | Time stored at | Remarks |
---|---|---|
Real-Time | 0x10AA83B8 | Always increased every timestep. |
Game-Time | 0x10AA83C0 | Only advances while out of combat, [0x10AA83D8] is 0 and the dialog UI is not visible. |
Game-Time2 (Anims) | 0x10AA83C8 | Advances as long as the dialog UI is not visible |
Each clock type has two queues of timed events. The events are sorted earliest to latest. The secondary queue for each type seems to be used for map initialization, but details are still not known.
The queued events contain the GameTime
when they will expire. Whenever game time is advanced, each queue is checked for expired events. The system will expire at most 500 events at once before suspecting an infinite loop and breaking out of the function. Infinite loops can happen when expiring an event immediately adds another event that is also expired immediately.
Each event is associated with a subsystem (see table below), which defines the function to be called for expired events. The function is passed a pointer to the expired event as an argument so it can read it's own arguments from the event.
When an event is added to the timer system, the following structure is used:
struct TimeEvent {
uint32_t inDays;
uint32_t inMilliseconds;
uint32_t subsystem;
uint32_t padding;
TimeEventArg args[4];
};
struct TimeEventArgs {
uint32_t value0;
uint32_t value1;
uint32_t value2;
uint32_t value3;
}
Each subsystem applies only to a single clock type and any event scheduled for a subsystem will be enqueued in the queue for the specified clock type.
If the event type is associated with object handles, it will only be called upon expiry if that object handle is still valid. This restriction does not apply to the "Expire Always Callback", which will even be called if object handles are no longer valid.
Id | Name | Persistent | Arg1 | Arg2 | Arg3 | Arg4 | Clock Type | Expired Callback | Expire Always Callback --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- 0 | Debug | No | int32 | int32 | | | 0 | 0x10061250 | 0x0 1 | Anim | Yes | int32 | | | | 2 | 0x1001b830 | 0x0 2 | Bkg Anim | No | int32 | int32 | int32 | | 0 | 0x101f5850 | 0x0 3 | Fidget Anim | No | | | | | 0 | 0x100144c0 | 0x0 4 | Script | Yes | int32 | int32 | obj | obj | 1 | 0x1000bea0 | 0x0 5 | PythonScript | Yes | pythonObj | pythonObj | | | 1 | 0x100ad560 | 0x0 6 | Poison | Yes | int32 | obj | int32 | | 1 | 0x101f5850 | 0x0 7 | Normal Healing | Yes | obj | int32 | | | 1 | 0x1007efb0 | 0x0 8 | Subdual Healing | Yes | obj | int32 | | | 1 | 0x1007eca0 | 0x0 9 | Aging | Yes | | | | | 1 | 0x101f5850 | 0x0 10 | AI | No | obj | int32 | | | 1 | 0x1005f090 | 0x0 11 | AI Delay | Yes | obj | | | | 1 | 0x100584b0 | 0x0 12 | Combat | Yes | | | | | 1 | 0x101f5850 | 0x0 13 | TB Combat | Yes | | | | | 0 | 0x101f5850 | 0x0 14 | Ambient Lighting | Yes | | | | | 1 | 0x101f5850 | 0x0 15 | WorldMap | Yes | | | | | 0 | 0x101f5850 | 0x0 16 | Sleeping | No | int32 | | | | 0 | 0x101f5850 | 0x0 17 | Clock | Yes | | | | | 1 | 0x101f5850 | 0x0 18 | NPC Wait Here | Yes | obj | | | | 1 | 0x100579a0 | 0x0 19 | MainMenu | No | int32 | | | | 0 | 0x101f5850 | 0x0 20 | Light | No | int32 | int32 | | | 2 | 0x100a8010 | 0x0 21 | Lock | Yes | obj | | | | 1 | 0x10021230 | 0x0 22 | NPC Respawn | Yes | obj | | | | 1 | 0x1006deb0 | 0x0 23 | Decay Dead Bodies | Yes | obj | int32 | | | 1 | 0x1007f230 | 0x0 24 | Item Decay | Yes | obj | int32 | | | 1 | 0x101f5850 | 0x0 25 | Combat-Focus Wipe | Yes | obj | int32 | | | 1 | 0x10080510 | 0x0 26 | Fade | Yes | int32 | int32 | float | int32 | 1 | 0x10051c10 | 0x0 27 | GFadeControl | Yes | | | | | 0 | 0x101f5850 | 0x0 28 | Teleported | No | obj | | | | 1 | 0x10025250 | 0x0 29 | Scenery Respawn | Yes | obj | | | | 1 | 0x101f5850 | 0x0 30 | Random Encounters | Yes | | | | | 1 | 0x1009a610 | 0x0 31 | objfade | Yes | int32 | obj | | | 2 | 0x1004c490 | 0x1004c570 32 | Action Queue | Yes | obj | int32 | | | 1 | 0x100151f0 | 0x0 33 | Search | Yes | obj | | | | 1 | 0x10046f00 | 0x0 34 | intgame_turnbased | No | int32 | int32 | | | 0 | 0x1009a880 | 0x0 35 | python_dialog | Yes | obj | obj | int32 | | 0 | 0x100acc60 | 0x0 36 | encumbered complain | Yes | obj | | | | 1 | 0x10037df0 | 0x0 37 | PythonRealtime | Yes | pythonObj | pythonObj | | | 0 | 0x100ad560 | 0x0