The underpinnings for the function in modelanim.cpp were utterly broken, so here's a patch which makes it return sensible values. Due to how +acceleration works, which is a completely incomprehensible mess for seemingly no reason at all, it still won't return the correct value for animations which use +acceleration (it'll return a bigger value than it should), but it does for animations which don't use it. Possibly the animation's target angle divided by its velocity needs to equal its time*1000 as well, but I've never understood if there's any use case for doing it otherwise so whatever.
I'm not going to make the patch any fancier and cover the usage of +acceleration, because the design and implementation for that feature is simply so obnoxious that I can't even tell what it's supposed to do exactly, not to mention figuring out how the relevant code works (or rather, doesn't work). No offense to anyone. A comprehensible fix would likely entail a rewrite of those parts of the code and making +acceleration work in an entirely different way entirely.
For now, this patches things up so that getAnimationDoneTime() returns the right value in what I think is the most common use case.
Index: modelanim.cpp
===================================================================
--- modelanim.cpp (revision 7992)
+++ modelanim.cpp (working copy)
@@ -107,7 +107,7 @@
slow_angle.a1d[0], slow_angle.a1d[1], slow_angle.a1d[2]));
has_started = true;
- end_time = q->end_time;
+ end_time = timestamp(model_anim_instance_get_actual_time(q));
}
void triggered_rotation::set_to_end(queued_animation *q)
@@ -175,7 +175,7 @@
if (new_queue.start == 0) {
new_queue.start_time = timestamp();
- new_queue.end_time = timestamp( new_queue.end );
+ new_queue.end_time = timestamp( model_anim_instance_get_actual_time(&new_queue) );
// if there is no delay don't bother with the queue, just start the thing
start( &new_queue );
@@ -193,7 +193,7 @@
// so this means that there is some sort of delay that's getting fubared becase of other queue items getting removed due to reversal
// this animation needs to be started now!
new_queue.start_time = timestamp();
- new_queue.end_time = timestamp( new_queue.end );
+ new_queue.end_time = timestamp( model_anim_instance_get_actual_time(&new_queue) );
// if there is no delay don't bother with the queue, just start the thing
start( &new_queue );
@@ -515,9 +515,13 @@
int temp = 0;
for (int a = 0; a < 3; a++) {
- temp = fl2i( ((3.0f * properties->vel.a1d[a] * properties->vel.a1d[a]) + (2.0f * properties->accel.a1d[a] * fabs(properties->angle.a1d[a])))
+ if (properties->accel.a1d[a] > 0.0f) {
+ temp = fl2i( ((3.0f * properties->vel.a1d[a] * properties->vel.a1d[a]) + (2.0f * properties->accel.a1d[a] * fabs(properties->angle.a1d[a])))
/ (2.0f * properties->accel.a1d[a] * properties->vel.a1d[a]) * 1000.0f )
+ properties->start;
+ } else {
+ temp = properties->end;
+ }
if (temp > ret)
ret = temp;
@@ -643,16 +647,24 @@
for (int a = 0; a < 3; a++) {
triggered_rotation tr = pss->trigger;
- float end_angle = (tr.current_ang.a1d[a] + (((tr.rot_vel.a1d[a]*tr.rot_vel.a1d[a]) - (tr.current_vel.a1d[a]*tr.current_vel.a1d[a])) / (2*tr.rot_accel.a1d[a])));
- if (end_angle > tr.slow_angle.a1d[a]) {
- //T(total) = (2V(maximum) - V(initial))/a + (S(turnpoint) - S(initial) + (V(initial)^2 - V(maximum)^2)/2a) / V(maximum)
- a_time = fl2i(((((2*tr.rot_vel.a1d[a]) - tr.current_ang.a1d[a])/tr.rot_accel.a1d[a]) + tr.slow_angle.a1d[a] - tr.current_ang.a1d[a] + (((tr.current_vel.a1d[a]*tr.current_vel.a1d[a]) - (tr.rot_vel.a1d[a]*tr.rot_vel.a1d[a])) / (2*tr.rot_accel.a1d[a])))*1000.0f);
- if (ani_time < a_time)
- ani_time = a_time;
+ if (tr.rot_accel.a1d[a] > 0.0f) {
+ float end_angle = (tr.current_ang.a1d[a] + (((tr.rot_vel.a1d[a]*tr.rot_vel.a1d[a]) - (tr.current_vel.a1d[a]*tr.current_vel.a1d[a])) / (2*tr.rot_accel.a1d[a])));
+
+ if (end_angle > tr.slow_angle.a1d[a]) {
+ //T(total) = (2V(maximum) - V(initial))/a + (S(turnpoint) - S(initial) + (V(initial)^2 - V(maximum)^2)/2a) / V(maximum)
+ a_time = fl2i(((((2*tr.rot_vel.a1d[a]) - tr.current_ang.a1d[a])/tr.rot_accel.a1d[a]) + tr.slow_angle.a1d[a] - tr.current_ang.a1d[a] + (((tr.current_vel.a1d[a]*tr.current_vel.a1d[a]) - (tr.rot_vel.a1d[a]*tr.rot_vel.a1d[a])) / (2*tr.rot_accel.a1d[a])))*1000.0f);
+ if (ani_time < a_time)
+ ani_time = a_time;
+ } else {
+ //T(total) = 2 * sqrt((S(final) - S(initial))/a - ( (V(initial)/a)^2 ) / 2 ) - V(initial)/a
+ a_time = fl2i((2 * fl_sqrt(((tr.end_angle.a1d[a] - tr.current_ang.a1d[a])/tr.rot_accel.a1d[a]) - ((tr.current_vel.a1d[a] * tr.current_vel.a1d[a]) / (tr.rot_accel.a1d[a] * tr.rot_accel.a1d[a])) / 2) - (tr.current_vel.a1d[a] / tr.rot_accel.a1d[a]))*1000.0f);
+ if (ani_time < a_time)
+ ani_time = a_time;
+ }
} else {
- //T(total) = 2 * sqrt((S(final) - S(initial))/a - ( (V(initial)/a)^2 ) / 2 ) - V(initial)/a
- a_time = fl2i((2 * fl_sqrt(((tr.end_angle.a1d[a] - tr.current_ang.a1d[a])/tr.rot_accel.a1d[a]) - ((tr.current_vel.a1d[a] * tr.current_vel.a1d[a]) / (tr.rot_accel.a1d[a] * tr.rot_accel.a1d[a])) / 2) - (tr.current_vel.a1d[a] / tr.rot_accel.a1d[a]))*1000.0f);
+ a_time = tr.end_time - timestamp();
+
if (ani_time < a_time)
ani_time = a_time;
}
@@ -663,7 +675,7 @@
} else {
// if it isn't moving then it's trivial.
// no currently playing animation
- ani_time = psub->triggers[i].end + psub->triggers[i].start;
+ ani_time = 0;
}
if (ret < ani_time)
Index: modelanim.h
===================================================================
--- modelanim.h (revision 7992)
+++ modelanim.h (working copy)
@@ -145,6 +145,7 @@
bool model_anim_start_type(ship *shipp, int animation_type, int subtype, int direction); // for all valid subsystems
// how long until the animation is done
+int model_anim_instance_get_actual_time(queued_animation *properties);
int model_anim_get_time_type(ship_subsys *pss, int animation_type, int subtype); // for a specific subsystem
int model_anim_get_time_type(ship *shipp, int animation_type, int subtype); // for all valid subsystems