Author Topic: Lag between image animation and image state script  (Read 1204 times)

I'm making a weapon, after 6 shots it automatically reloads, and you can manually reload by pressing the light key. When I press the light key, everything works just fine, image reloads and everything is in sync. But when I fire 6 shots and the gun is empty, the image sequence is starting noticeably before the stateScript function is called

For example
The one on the left is synced (happens when pressing the reload key manually) whereas the gif on the right shows what happens when it happens automatically after firing
   

You can see that on the left, the first ~2 rounds go in before the function containing the %player.playThread(3, ShiftLeft); starts, and then after the rounds are already in, the animation is played twice out of sync. You can also see it happening when shiftRight is played half a second after the cylinder is already pushed back in, rather than at the same time.

Here's the stateSystem (I had to make 3 separate ready states and respective transitions, so that the cylinder could rotate seamlessly between shots)

Code: [Select]
  // Initial start up state
stateName[0]                                       = "Activate";
stateTimeoutValue[0]                               = 0.15;
stateTransitionOnTimeout[0]                = "ReadyA";
stateSound[0] = weaponSwitchSound;

// ANGLE 0-60 (A)
stateName[1]                                      = "ReadyA";
stateSequence[1] = "ReadyA";
stateTransitionOnTriggerDown[1]          = "FireA";
stateAllowImageChange[1]                  = true;
stateTransitionOnNoAmmo[1] = "Reload";

stateName[2]                                     = "FireA";
stateSequence[2]                                = "FireA";
stateTransitionOnTimeout[2]               = "SmokeA";
stateTimeoutValue[2] = 0.5;
stateFire[2]                                             = true;
stateAllowImageChange[2]                 = false;
stateScript[2]                                          = "onFire";
stateWaitForTimeout[2] = true;
stateEmitter[2] = HL1BulletFlashEmitter;
stateEmitterTime[2] = 0.05;
stateEmitterNode[2] = "muzzleNode";

stateName[3] = "SmokeA";
stateTransitionOnTimeout[3]              = "WaitForTriggerupA";
stateTimeoutValue[3] = 0.25;
stateTransitionOnNoAmmo[3] = "ReadyA";
stateEmitter[3] = HL1BulletSmokeEmitter;
stateEmitterTime[3] = 1;
stateEmitterNode[3] = "muzzleNode";
stateTimeoutValue[3]                            = 0.0;
stateWaitForTimeout[3] = true;

stateName[4] = "WaitForTriggerupA";
stateTransitionOnTriggerUp[4]         = "ReadyB";

// ANGLE 60-120 (B)
stateName[5]                                      = "ReadyB";
stateSequence[5] = "ReadyB";
stateTransitionOnTriggerDown[5]           = "FireB";
stateAllowImageChange[5]                   = true;
stateTransitionOnNoAmmo[5] = "Reload";

stateName[6]                                  = "FireB";
stateSequence[6]                             = "FireB";
stateTransitionOnTimeout[6]            = "SmokeB";
stateTimeoutValue[6] = 0.5;
stateFire[6]                                           = true;
stateAllowImageChange[6]                = false;
stateScript[6]                                         = "onFire";
stateWaitForTimeout[6] = true;
stateEmitter[6] = HL1BulletFlashEmitter;
stateEmitterTime[6] = 0.05;
stateEmitterNode[6] = "muzzleNode";

stateName[7] = "SmokeB";
stateTransitionOnTimeout[7]               = "WaitForTriggerupB";
stateTimeoutValue[7] = 0.25;
stateTransitionOnNoAmmo[7] = "ReadyA";
stateEmitter[7] = HL1BulletSmokeEmitter;
stateEmitterTime[7] = 1;
stateEmitterNode[7] = "muzzleNode";
stateTimeoutValue[7]                            = 0.0;
stateWaitForTimeout[7] = true;

stateName[8] = "WaitForTriggerupB";
stateTransitionOnTriggerUp[8]         = "ReadyC";

// ANGLE 120-180
stateName[9]                                     = "ReadyC";
stateSequence[9] = "ReadyC";
stateTransitionOnTriggerDown[9]              = "FireC";
stateAllowImageChange[9]                 = true;
stateTransitionOnNoAmmo[9]                = "Reload";

stateName[10]                                 = "FireC";
stateSequence[10]                             = "FireC";
stateTransitionOnTimeout[10]             = "SmokeC";
stateTimeoutValue[10] = 0.5;
stateFire[10]                                          = true;
stateAllowImageChange[10]              = false;
stateScript[10]                                = "onFire";
stateWaitForTimeout[10] = true;
stateEmitter[10] = HL1BulletFlashEmitter;
stateEmitterTime[10] = 0.05;
stateEmitterNode[10] = "muzzleNode";

stateName[11] = "SmokeC";
stateTransitionOnTimeout[11]                = "WaitForTriggerupC";
stateTimeoutValue[11] = 0.25;
stateTransitionOnNoAmmo[11] = "ReadyA";
stateEmitter[11] = HL1BulletSmokeEmitter;
stateEmitterTime[11] = 1;
stateEmitterNode[11] = "muzzleNode";
stateWaitForTimeout[11] = true;

stateName[12] = "WaitForTriggerupC";
stateTransitionOnTriggerUp[12]            = "ReadyA";

// RELOAD
stateName[13] = "Reload";
stateSequence[13] = "CylOut";
stateTimeoutValue[13] = 0.25;
stateTransitionOnTimeout[13]          = "Unload";
stateScript[13] = "CylOut";

stateName[14] = "Unload";
stateSequence[14] = "Unload";
stateTimeoutValue[14] = 0.1;
stateTransitionOnTimeout[14] = "Load";
stateScript[14] = "Unload";

stateName[15] = "Load";
stateSequence[15] = "Load";
stateTimeoutValue[15] = 1;
stateTransitionOnTimeout[15] = "CylIn";
stateScript[15] = "Load";

stateName[16] = "CylIn";
stateSequence[16] = "CylIn";
stateTransitionOnTimeout[16] = "ReadyA";
stateTimeoutValue[16] = 0.25;
stateScript[16] = "CylIn";
};

function HL1MagnumImage::CylOut(%this, %player, %slot){%player.playThread(2, shiftLeft);}
function HL1MagnumImage::CylIn(%this, %player, %slot){%player.playThread(2, shiftRight);}
function HL1MagnumImage::Unload(%this, %player, %slot){%player.playThread(2, plant);}
function HL1MagnumImage::Load(%this, %player, %slot)
{
%player.playThread(3, ShiftLeft);
%player.schedule(160, playThread, 3, ShiftLeft);
%player.schedule(160 * 2, playThread, 3, ShiftLeft);
%player.schedule(160 * 3, playThread, 3, ShiftLeft);
%player.schedule(160 * 4, playThread, 2, ShiftLeft);
%player.schedule(160 * 5, playThread, 2, ShiftLeft);

%player.HL1357Rounds = 6;
%player.setImageAmmo(0, 1);
}

I should probably mention: I noticed that setting the timeoutValue for the Fire states to 0.0 would eliminate the issue. But obviously that's not preferable because then you don't see the firing animation, and of course you're also able to fire the gun too fast lol

try setting smokea/b/c to timeout 0 maybe

try setting smokea/b/c to timeout 0 maybe

They actually were set to 0 but I had two timeoutValue definitions in many of the smoke states. It was really messy in general so I rewrote it

Okay, so now I'm really confused. I re-wrote the state system from scratch, to this:

Code: [Select]
  // Initial start up state
stateName[0]                     = "Activate";
stateTimeoutValue[0]             = 0.15;
stateTransitionOnTimeout[0]       = "ReadyA";
stateSound[0] = weaponSwitchSound;

// 0-60
stateName[1]                     = "ReadyA";
stateTransitionOnTriggerDown[1]   = "FireA";
stateTransitionOnNoAmmo[1] = "ImageReload";
stateAllowImageChange[1]         = true;
stateSequence[1] = "ReadyA";

stateName[2]                     = "FireA";
stateTransitionOnTimeout[2]     = "SmokeA";
stateTimeoutValue[2]             = 0.5;
stateFire[2]                     = true;
stateAllowImageChange[2]         = false;
stateSequence[2]                 = "FireA";
stateScript[2]                   = "onFire";
stateWaitForTimeout[2] = true;
stateEmitter[2] = HL1BulletFlashEmitter;
stateEmitterTime[2] = 0.05;
stateEmitterNode[2] = "muzzleNode";
stateSound[2] = HL1MagnumFireSound;
stateEjectShell[2]       = true;

stateName[3] = "SmokeA";
stateEmitter[3] = HL1BulletSmokeEmitter;
stateEmitterTime[3] = 0.2;
stateEmitterNode[3] = "muzzleNode";
stateTimeoutValue[3]             = 0.0;
stateTransitionOnTimeout[3]     = "WaitA";
stateTransitionOnNoAmmo[3] = "ImageReload";

stateName[4] = "WaitA";
stateTransitionOnTriggerUp[4] = "ReadyA";

// 60-120
stateName[5]                     = "ReadyB";
stateTransitionOnTriggerDown[5]   = "FireB";
stateTransitionOnNoAmmo[5] = "ImageReload";
stateAllowImageChange[5]         = true;
stateSequence[5] = "ReadyB";

stateName[6]                     = "FireB";
stateTransitionOnTimeout[6]     = "SmokeB";
stateTimeoutValue[6]             = 0.5;
stateFire[6]                     = true;
stateAllowImageChange[6]         = false;
stateSequence[6]                 = "FireB";
stateScript[6]                   = "onFire";
stateWaitForTimeout[6] = true;
stateEmitter[6] = HL1BulletFlashEmitter;
stateEmitterTime[6] = 0.05;
stateEmitterNode[6] = "muzzleNode";
stateSound[6] = HL1MagnumFireSound;
stateEjectShell[6]       = true;

stateName[7] = "SmokeB";
stateEmitter[7] = HL1BulletSmokeEmitter;
stateEmitterTime[7] = 0.2;
stateEmitterNode[7] = "muzzleNode";
stateTimeoutValue[7]             = 0.0;
stateTransitionOnTimeout[7]     = "WaitB";
stateTransitionOnNoAmmo[7] = "ImageReload";

stateName[8] = "WaitB";
stateTransitionOnTriggerUp[8] = "ReadyB";

// 120-180
stateName[9]                     = "ReadyC";
stateTransitionOnTriggerDown[9]   = "FireC";
stateTransitionOnNoAmmo[9] = "ImageReload";
stateAllowImageChange[9]         = true;
stateSequence[9] = "ReadyC";

stateName[10]                     = "FireC";
stateTransitionOnTimeout[10]     = "SmokeC";
stateTimeoutValue[10]             = 0.5;
stateFire[10]                     = true;
stateAllowImageChange[10]         = false;
stateSequence[10]                 = "FireC";
stateScript[10]                   = "onFire";
stateWaitForTimeout[10] = true;
stateEmitter[10] = HL1BulletFlashEmitter;
stateEmitterTime[10] = 0.05;
stateEmitterNode[10] = "muzzleNode";
stateSound[10] = HL1MagnumFireSound;
stateEjectShell[10]       = true;

stateName[11] = "SmokeC";
stateEmitter[11] = HL1BulletSmokeEmitter;
stateEmitterTime[11] = 0.2;
stateEmitterNode[11] = "muzzleNode";
stateTimeoutValue[11]             = 0.0;
stateTransitionOnTimeout[11]     = "WaitC";
stateTransitionOnNoAmmo[11] = "ImageReload";

stateName[12] = "WaitC";
stateTransitionOnTriggerUp[12] = "ReadyC";

// Reload effects
// Cyl Out
stateName[13] = "ImageReload";
stateScript[13] = "CylOut";
stateSequence[13] = "CylOut";
stateTimeoutValue[13] = 0.25;
stateTransitionOnTimeout[13] = "Unload";

// Unload
stateName[14] = "Unload";
stateScript[14] = "UnLoad";
stateSequence[14] = "UnLoad";
stateTimeoutValue[14] = 0.1;
stateTransitionOnTimeout[14] = "Load";

// Mag in
stateName[15] = "Load";
stateScript[15] = "Load";
stateSequence[15] = "Load";
stateTimeoutValue[15] = 1;
stateTransitionOnTimeout[15] = "CylIn";

// Chamber
stateName[16] = "CylIn";
stateScript[16] = "CylIn";
stateSequence[16] = "CylIn";
stateTimeoutValue[16] = 0.25;
stateTransitionOnTimeout[16] = "Activate";

So obviously it's not correct, as in, if stateTransitionOnTimeout[0] is set to ReadyA, it will constantly loop through A states instead of A->B->C, and the same applies if I set it to B or C. I did it for debugging purposes. What I found out was: ReadyA works, but ReadyB and ReadyC are broken. What I mean by this is that ReadyA produces correct results when automatically reloading when the gun is empty, but ReadyB and ReadyC states will create half a second of lag. This also means that if the states are set to loop through A->B->C, if you fire 5 shots, de-equip and then re-equip the weapon and fire again, it will be in the ReadyA/FireA state block, and produce correct results.

The state blocks are literally the same, they're copied and pasted and then I switched around the A/B/C values. I really don't understand why B and C are broken if A works since they should be interchangeable. So naturally I assumed there might be something wrong with the actual animations I made in Blender.

What's even more loving confusing is that to test it further, I went ahead and swapped out ReadyA/FireA's sequences with ReadyB/FireB's sequences, and ReadyA still works and B and C are still broken. So what this leads me to believe is that the animations I made in Blender are totally fine, the issue is, I'm assuming, caused by the index of the state. Because anything I plug into states 1-4 will work, but but the exact same state definitions in indexes 5-12 wont work. Any clarification how the state system actually works would be greatly appreciated.
« Last Edit: June 14, 2017, 10:40:56 PM by Rally »