Something like this would work:
const flip = effect("Flip")("Checkbox");
const stggr = effect("Stagger")("Slider");
const range = textTotal/2;
const offst = Math.round(textTotal/2 - textIndex);
const rO = offst/range;
const mod = Math.cos(Math.PI*2 + rO*2) + 1;
let sel = linear(textIndex, 1, textTotal, -100, 100);
sel = textIndex > textTotal/2 && flip == 1 ? -sel : sel;
if(stggr <= 0) {
easeL = sel * mod
v = ease(stggr, -100, 0, easeL, sel);
} else if(stggr >= 0) {
easeH = sel / mod/2
v = ease(stggr, 0, 100, sel, easeH);
}
pos = effect("Position")("Point");
delay = textIndex*thisComp.frameDuration*2;
p = pos.valueAtTime(time - delay);
p*v/1000;
The expression control Point – Effect named “Position” will determine the position of the animator (along with the funky easing function you wrote), if its value is keyframed, the letters will move with 2 frames delay. (you can also hook that up to a slider of course, or finetune it in another way).
Important: the value set in the position parameter of the animator needs to be fixed at 1000 (or something else like 100.000, but it needs to be the same as value the v/1000 in the last line of the expression) and it needs to be more than the maximum distance you would want to move the letters around.
This is what makes it possible to use the expression-selector as sort of an absolute positioner which is what we need here to do the delay.
If this value itself is keyframed, then it doesn’t work, because amount is limited form -100 to +100%, so say it becomes 50px, but 1 of the letters needs to be positioned still at 60 pixels because it is lagging, we can’t give it 120% to end up at 60.
Using a very high fixed number for the position-value and then using small amount-percentages gives us all the flexibility.