From 175b932b13f3b9fc97a1abdf8f590d2e202eaf03 Mon Sep 17 00:00:00 2001 From: Alayan-stk-2 Date: Tue, 22 May 2018 00:12:16 +0200 Subject: [PATCH] Correct finish time for egg hunt ghosts (#3263) * Use replay data for ghost karts finish time * Compute correct finish time for egg hunts replays --- src/karts/ghost_kart.cpp | 67 +++++++++++++++++++++++++++++++++-- src/karts/ghost_kart.hpp | 5 +++ src/modes/easter_egg_hunt.cpp | 9 ++++- src/modes/easter_egg_hunt.hpp | 1 + 4 files changed, 79 insertions(+), 3 deletions(-) diff --git a/src/karts/ghost_kart.cpp b/src/karts/ghost_kart.cpp index 9a1fc5af9..5e2d74a8b 100644 --- a/src/karts/ghost_kart.cpp +++ b/src/karts/ghost_kart.cpp @@ -242,7 +242,10 @@ void GhostKart::computeFinishTime() // In egg hunts, the finish time is the moment at which all egs are collected if (race_manager->isEggHuntMode()) { - m_finish_time = 0; //FIXME : do a real computation + EasterEggHunt *world = dynamic_cast(World::getWorld()); + assert(world); + int max_eggs = world->numberOfEggsToFind(); + m_finish_time = getTimeForEggs(max_eggs); } else // linear races { @@ -328,4 +331,64 @@ float GhostKart::getTimeForDistance(float distance) +gc->getTimeAtIndex(upper_frame_index)*(upper_ratio); return ghost_time; -} +} // getTimeForDIstance + +// ---------------------------------------------------------------------------- +/** Returns the smallest time at which the kart had the required number of eggs + * Returns -1.0f if none */ +float GhostKart::getTimeForEggs(int egg_number) +{ + const GhostController* gc = + dynamic_cast(getController()); + + int current_index = gc->getCurrentReplayIndex(); + + // Second, get the current egg number + int current_eggs = m_all_bonus_info[current_index].m_special_value; + + // This determines in which direction we will search a matching frame + bool search_forward = (current_eggs < egg_number); + + // This used to compute the time + int lower_frame_index = current_index-1; + unsigned int upper_frame_index = current_index; + + // Third, search frame by frame in the good direction + // A modified binary search would be an optimization + while (1) + { + // If we have reached the end of the replay file without finding the + // searched distance, break + if (upper_frame_index >= m_all_bonus_info.size() || + lower_frame_index < 0 ) + break; + + // The target distance was reached between those two frames + if (m_all_bonus_info[lower_frame_index].m_special_value < egg_number && + m_all_bonus_info[upper_frame_index].m_special_value == egg_number) + { + break; + } + + if (search_forward) + { + lower_frame_index++; + upper_frame_index++; + } + else + { + lower_frame_index--; + upper_frame_index--; + } + } + + float ghost_time; + + if (upper_frame_index >= m_all_bonus_info.size() || + lower_frame_index < 0 ) + ghost_time = -1.0f; + else + ghost_time = gc->getTimeAtIndex(upper_frame_index); + + return ghost_time; +} // getTimeForEggs diff --git a/src/karts/ghost_kart.hpp b/src/karts/ghost_kart.hpp index 04106076c..47a2f086b 100644 --- a/src/karts/ghost_kart.hpp +++ b/src/karts/ghost_kart.hpp @@ -95,6 +95,11 @@ public: * Returns -1.0f if none */ float getTimeForDistance(float distance); + // ---------------------------------------------------------------------------- + /** Returns the smallest time at which the kart had the required number of eggs + * Returns -1.0f if none */ + float getTimeForEggs(int egg_number); + // ------------------------------------------------------------------------ virtual void kartIsInRestNow() OVERRIDE {}; // ------------------------------------------------------------------------ diff --git a/src/modes/easter_egg_hunt.cpp b/src/modes/easter_egg_hunt.cpp index ec1e171da..8dda34a65 100644 --- a/src/modes/easter_egg_hunt.cpp +++ b/src/modes/easter_egg_hunt.cpp @@ -248,9 +248,16 @@ void EasterEggHunt::terminateRace() } //----------------------------------------------------------------------------- /** In Easter Egg mode the finish time is just the time the race is over, - * since there are no AI karts. + * since there are no AI karts and no other players, except for ghosts. */ float EasterEggHunt::estimateFinishTimeForKart(AbstractKart* kart) { + // For ghost karts, use the replay data + if (kart->isGhostKart()) + { + GhostKart* gk = dynamic_cast(kart); + return gk->getGhostFinishTime(); + } + return getTime(); } // estimateFinishTimeForKart diff --git a/src/modes/easter_egg_hunt.hpp b/src/modes/easter_egg_hunt.hpp index 1c42216bd..647451e13 100644 --- a/src/modes/easter_egg_hunt.hpp +++ b/src/modes/easter_egg_hunt.hpp @@ -64,6 +64,7 @@ public: std::vector *info) OVERRIDE; const int numberOfEggsFound() { return m_eggs_found; } + const int numberOfEggsToFind() { return m_number_of_eggs; } void updateKartRanks(); void collectedEasterEgg(const AbstractKart *kart);