supertuxkart / stk-code

The code base of supertuxkart
Other
4.47k stars 1.05k forks source link

Grand Prix finish scenes don’t show unlocked karts #3671

Closed Flakebi closed 4 months ago

Flakebi commented 5 years ago

Description

If one finishes a grand prix in story mode and afterwards the amount of points is higher than 190, the first kart (Amanda) gets unlocked, but it is not shown in the trophy screen.

Now when I start the next grand prix and win the first race, the trophy screen with the unlocked Amanda is shown. When clicking continue I get reset to the story mode, so the grand prix is aborted.

Steps to reproduce

  1. Mark all challenges as solved="hard" except gp1, gp2 and gp4. The unlock_… should also be marked as solved="none".
  2. Now win the 'Penguin Playground' grand prix (gp1). The trophy screen for 24 points or so gets shown.
  3. Now finish the first track of 'Off the beaten track' (gp2). Now the trophy screen is shown again and the grand prix is aborted.

Notes

If you are too lazy to finish the whole grand prix every time, this function proved helpful. It can be inserted into scripting/script_kart.cpp:

        /** Finish the race for this kart */
        void finish(int idKart)
        {
            AbstractKart* kart = World::getWorld()->getKart(idKart);
            // Swap place with the first kart
            int pos = kart->getPosition();
            for (auto k : World::getWorld()->getKarts()) {
                if (k->getPosition() == 1) {
                    k->setPosition(pos);
                    break;
                }
            }
            kart->setPosition(1);
            kart->finishedRace(20.0, false);
        }

and into the registerScriptFunctions function in the same file:

            r = engine->RegisterGlobalFunction("void finish(int id)",
                                               mp ? WRAP_FN(finish) : asFUNCTION(finish),
                                               call_conv); assert(r >= 0);

Now in the artist debug mode, open the scripting console and write Kart::finish(<id>); and you win the race. In the first race in gp1 you start last so your id is 5. In the next races you should be first so your id is 0.

Alayan-stk-2 commented 5 years ago

In testing, I encountered several weird issues when it comes to unlock display at the end of races.

The correct things were unlocked once back in the overworld, but e.g. some unlock notifications were delayed (only happened a challenge too late)

hiker commented 5 years ago

It seems to be difficult to show the unlock-screen during a GP, since the unlock screen is itself a race (so race mode is getting reset to single race, and likely things like tracks, track number etc as well). While of course fixable, this would be a bit of work. So my suggestion: The following patch only tests for unlocks and shows unlocks after the last race in a GP:

diff --git a/src/states_screens/race_result_gui.cpp b/src/states_screens/race_result_gui.cpp
index b0a874cb7..2831f44dd
--- a/src/states_screens/race_result_gui.cpp
+++ b/src/states_screens/race_result_gui.cpp
@@ -182,7 +182,8 @@ void RaceResultGUI::enableAllButtons()
     // If something was unlocked
     // -------------------------
     int n = (int)PlayerManager::getCurrentPlayer()->getRecentlyCompletedChallenges().size();
-    if (n > 0)
+    if (n > 0 && ( race_manager->getMajorMode()!=RaceManager::MAJOR_MODE_GRAND_PRIX ||
+                   race_manager->getTrackNumber()+1 == race_manager->getNumOfTracks() ) )
     {
         top->setText(n == 1 ? _("You completed a challenge!")
             : _("You completed challenges!"));
@@ -289,7 +290,8 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget,
     // ---------------------------------------------------------
     int n = (int)PlayerManager::getCurrentPlayer()
         ->getRecentlyCompletedChallenges().size();
-    if (n>0)
+    if (n > 0 && (race_manager->getMajorMode() != RaceManager::MAJOR_MODE_GRAND_PRIX ||
+                  race_manager->getTrackNumber() + 1 == race_manager->getNumOfTracks()))
     {
         if (name == "top")
         {

Is that ok? That seems to work for a simple test. Alayan, can you try this with your other tests?

Note that I would recommend the following: change all GPs to have 0 laps (modify data/grandprix/*.grandpix), and in skidding_ai.cpp do

diff --git a/src/karts/controller/skidding_ai.cpp b/src/karts/controller/skidding_ai.cpp
index a2d330b79..ceb818a6c
--- a/src/karts/controller/skidding_ai.cpp
+++ b/src/karts/controller/skidding_ai.cpp
@@ -285,7 +285,7 @@ void SkiddingAI::update(int ticks)

     // Having a non-moving AI can be useful for debugging, e.g. aiming
     // or slipstreaming.
-#undef AI_DOES_NOT_MOVE_FOR_DEBUGGING
+#define AI_DOES_NOT_MOVE_FOR_DEBUGGING
 #ifdef AI_DOES_NOT_MOVE_FOR_DEBUGGING
     m_controls->setAccel(0);
     m_controls->setSteer(0);

This way the AI does not drive, so you just need to cross the start line to win each race.

Alayan-stk-2 commented 5 years ago

It seems to be difficult to show the unlock-screen during a GP, since the unlock screen is itself a race (so race mode is getting reset to single race, and likely things like tracks, track number etc as well). While of course fixable, this would be a bit of work.

The core issue here is that the unlock is sometimes delayed.

E.g., challenge A unlocks kart X. But in the end screen of challenge A, kart X is not shown. However, at the end of the next race (even if going back to single player non story mode iirc, and also in the middle of GPs as reported here) the unlock of kart X is shown.

Blocking unlock screen except at the last race of GP is doable but it would only serve to hide the effect of another bug, not to resolve it.

But once the other issue is tracked down and patched, this patch could serve as a safeguard to limit damage in case a similar bug resurface.

The non-moving AI trick is nice, I will remember it for faster testing !

hiker commented 5 years ago

The work around has been committed for the RC, postponing the root cause fix till later.

Alayan-stk-2 commented 5 years ago

With the workaround, the Grand Prix doesn't get interrupted... But when you finish the GP challenge afterwards, the win is NOT registered.

Benau commented 4 years ago

maybe just use if (n > 0 && race_manager->getMajorMode() != RaceManager::MAJOR_MODE_GRAND_PRIX) because the feature unlocked screen can be pushed in enterRaceOverState too?

Alayan-stk-2 commented 3 years ago

Still a bug.