summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/build_vehicle_gui.cpp42
1 files changed, 28 insertions, 14 deletions
diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp
index 2778ccd55..7e8eea4c5 100644
--- a/src/build_vehicle_gui.cpp
+++ b/src/build_vehicle_gui.cpp
@@ -269,20 +269,34 @@ static bool EnginePowerVsRunningCostSorter(const EngineID &a, const EngineID &b)
{
const Engine *e_a = Engine::Get(a);
const Engine *e_b = Engine::Get(b);
-
- /* Here we are using a few tricks to get the right sort.
- * We want power/running cost, but since we usually got higher running cost than power and we store the result in an int,
- * we will actually calculate cunning cost/power (to make it more than 1).
- * Because of this, the return value have to be reversed as well and we return b - a instead of a - b.
- * Another thing is that both power and running costs should be doubled for multiheaded engines.
- * Since it would be multiplying with 2 in both numerator and denominator, it will even themselves out and we skip checking for multiheaded. */
- Money va = (e_a->GetRunningCost()) / max(1U, (uint)e_a->GetPower());
- Money vb = (e_b->GetRunningCost()) / max(1U, (uint)e_b->GetPower());
- int r = ClampToI32(vb - va);
-
- /* Use EngineID to sort instead since we want consistent sorting */
- if (r == 0) return EngineNumberSorter(a, b);
- return _engine_sort_direction ? r > 0 : r < 0;
+ uint p_a = e_a->GetPower();
+ uint p_b = e_b->GetPower();
+ Money r_a = e_a->GetRunningCost();
+ Money r_b = e_b->GetRunningCost();
+ /* Check if running cost is zero in one or both engines.
+ * If only one of them is zero then that one has higher value,
+ * else if both have zero cost then compare powers. */
+ if (r_a == 0) {
+ if (r_b == 0) {
+ /* If it is ambiguous which to return go with their ID */
+ if (p_a == p_b) return EngineNumberSorter(a, b);
+ return _engine_sort_direction != (p_a < p_b);
+ }
+ return !_engine_sort_direction;
+ }
+ if (r_b == 0) return _engine_sort_direction;
+ /* Using double for more precision when comparing close values.
+ * This shouldn't have any major effects in performance nor in keeping
+ * the game in sync between players since it's used in GUI only in client side */
+ double v_a = (double)p_a / (double)r_a;
+ double v_b = (double)p_b / (double)r_b;
+ /* Use EngineID to sort if both have same power/running cost,
+ * since we want consistent sorting.
+ * Also if both have no power then sort with reverse of running cost to simulate
+ * previous sorting behaviour for wagons. */
+ if (v_a == 0 && v_b == 0) return !EngineRunningCostSorter(a, b);
+ if (v_a == v_b) return EngineNumberSorter(a, b);
+ return _engine_sort_direction != (v_a < v_b);
}
/* Train sorting functions */