SuperTux in Story Mode (and other improvements) (#3207)
* Add SuperTux difficulty & update number of karts Also make the expert challenge slightly easier to match more the difficulty of other challenges. * Add SuperTux difficulty & update number of karts & points required Also give some more time margin in easier difficulties, as it is a hard challenge compared to most. * Add SuperTux difficulty & update number of karts & points required Also change the lap count to 4 as it is a very short track (sub 30s) * Add SuperTux difficulty Also tweak the expert challenge to have a more appropriate difficulty * Add SuperTux difficulty & update number of karts * Add SuperTux difficulty & update number of karts & points required * Add SuperTux difficulty & update number of karts & points required Also correct the requirement position, since this is not a FTL race anymore. * Add SuperTux difficulty & update number of karts & points required Also slight balancing improvements for the usual difficulties. * Add SuperTux difficulty & update number of karts & points required Also adds a position requirement in expert * Add SuperTux difficulty & update number of karts & points required * Add SuperTux difficulty & update number of karts & points required * Add SuperTux difficulty & update number of karts & points required Also change the number of laps to 5, as this is a very short track. The time requirements for easier difficulties have been kept proportionally similar to before. * Add SuperTux difficulty & update number of karts & points required Also change the number of laps to 4. * Add SuperTux difficulty & update number of karts & points required Also add a position requirement to expert and intermediate. * Add SuperTux difficulty & update number of karts & points required Also change the number of laps to 4, as a lap often is 30s or less in expert/supertux * Add SuperTux difficulty & update number of karts & points required * Add SuperTux difficulty & update number of karts & points required * Rename islandtrack.challenge to gran_paradiso.challenge * Rename challenge file * Add SuperTux difficulty & update number of karts & points required Also makes the time limit in expert less easy and tweak position requirement. * Add SuperTux difficulty & update number of karts * Add SuperTux difficulty & update number of karts & points required * Add SuperTux difficulty & update number of karts & points required * Add SuperTux difficulty & update number of karts & points required * Add SuperTux difficulty & update number of karts & points required Doesn't unlock the SuperTux difficulty anymore - it's managed elsewhere. * Add SuperTux difficulty & update number of karts & points required * Add SuperTux difficulty & update number of karts & points required * Add new unlock challenges, for difficulty and karts * Add a lap to oliver's math class * Replace Northern Resort by Volcano Island * Replace Volcano Island by Candela City Candela City was in no (official) GP before this. Also sets Green Valley to 3 laps. * Add Northern Resort and remove Fort Magma In 0.9.3, this GP has only 4 races in Story Mode (5 for the other GPs) because Fort Magma is locked. Of all the tracks outside this GP before, Northern Resort is one of the hardest, the AI being rather good there. * Temporary cup for SuperTux challenges Recolored version of the gold cup * Update challenge selection UI for the SuperTux challenges * GUI used before SuperTux difficulty unlocking This is the old select_challenge.stkgui * Swap the two sara * Replace Kiki by another kart to unlock on Benau's demand * Update for improved Story Mode * Update for improved Story Mode * Add support for SuperTux challenges * Add support for SuperTux challenges * Add support for SuperTux challenges * Add support for SuperTux challenges * Update for SuperTux ; also adds the ability to unlock a challenge by points * Update for unlocking by points * Add support for SuperTux challenges * Add support for SuperTux challenges * Add support for SuperTux challenges * Minor changes to function calls * Update for SuperTux challenges * Add support for SuperTux challenges * Update for Story Mode GP changes * Allows to display the correct number of points for GP challenges * Set the unlock of the 1st bonus kart to correct non-test value * Add support for SuperTux challenges Including a bigger challenge selection diaolg * Add default value * Icon to indicate that there is an unlockable The number of points needed to unlock it are displayed next to it. * Changed format : the point requirements is now specified in the file * Changed format : the point requirements is now specified in the file * Changed format : the point requirements is now specified in the file * Function for unlock by points UI * Add default for unlock list node and use requirements node for all * Make unlockByPoints simpler and more flexible Now the code will iterate in StoryModeStatus and send the unlock_list challenges for treatment here. The question of getting the right challenge statuses beings solved, it allows for a great simplification and much more flexibility * Update unlockByPoints declaration * Adds support for next unlockable UI * Improve call of unlockByPoints Also calculations for displaying in the UI how many point the next unlockable by points requires. * Add icon for next unlockable * Displays icon/number to make the player aware of the next unlockable Also displays the number below the icon rather than on the side, for more clarity. * Changes to display karts in the unlock scene * Update unlock functions declarations * New function to clarify code and more logical recently unlocked list management In the previous version, everything was added to the recently unlocked list at some point, necessitating a clearing at the end of computeActive, which also removed from the list the non-race challenges. Checking if the feature is newly unlocked to add it to the list remove the need of that clearing. * Declaration for unlockFeatureByList * Display newly unlocked karts * Display newly unlocked karts * Clear the list of recently unlocked features at the end * Update testing code * Update unlocks finding function call * Improve UI scaling * Fixes indentation * Update the number of points before checking for unlock by points * Add const to declarations * Remove const_cast * Remove a const_cast There are other const_cast in the menu debug items (but they are unrelated to this PR) * Fix menu being bolder
This commit is contained in:
parent
a2659f479c
commit
6a25384ed9
@ -1,15 +1,20 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="abyss" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="0"/>
|
||||
|
||||
<best>
|
||||
<karts number="7"/>
|
||||
<requirements position="1" time="150"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<requirements position="1" time="160"/>
|
||||
<karts number="6"/>
|
||||
<requirements position="1" time="165"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<karts number="5"/>
|
||||
<requirements time="197"/>
|
||||
</medium>
|
||||
<easy>
|
||||
|
@ -1,21 +1,26 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="candela_city" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="70"/>
|
||||
<requirements trophies="75"/>
|
||||
|
||||
<best>
|
||||
<karts number="9"/>
|
||||
<requirements position="1"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<karts number="8"/>
|
||||
<requirements position="1"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<karts number="7"/>
|
||||
<requirements position="1"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="3"/>
|
||||
<karts number="6"/>
|
||||
<requirements position="1"/>
|
||||
</easy>
|
||||
|
||||
<unlock kart="sara_the_wizard"/>
|
||||
<unlock kart="sara_the_racer"/>
|
||||
</challenge>
|
@ -1,19 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="cocoa_temple" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="5"/>
|
||||
|
||||
|
||||
<best>
|
||||
<karts number="8"/>
|
||||
<requirements position="1" time="140"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<karts number="7"/>
|
||||
<requirements position="1" time="170"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<karts number="6"/>
|
||||
<requirements time="210"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="4"/>
|
||||
<karts number="5"/>
|
||||
<requirements time="300"/>
|
||||
</easy>
|
||||
</challenge>
|
@ -1,15 +1,20 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="cornfield_crossing" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="0"/>
|
||||
|
||||
<best>
|
||||
<karts number="7"/>
|
||||
<requirements position="1" time="140"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<karts number="6"/>
|
||||
<requirements position="1" time="165"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<karts number="5"/>
|
||||
<requirements time="195"/>
|
||||
</medium>
|
||||
<easy>
|
||||
|
@ -1,9 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="fortmagma" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="180"/>
|
||||
<requirements trophies="190"/>
|
||||
|
||||
<best>
|
||||
<karts number="2" aiIdent="nolok" superPower="nolokBoss"/>
|
||||
<requirements position="1"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="2" aiIdent="nolok" superPower="nolokBoss"/>
|
||||
<requirements position="1"/>
|
||||
@ -19,6 +24,5 @@
|
||||
|
||||
<unlock kart="gnu"/>
|
||||
<unlock kart="nolok"/>
|
||||
<unlock difficulty="difficulty_best"/>
|
||||
<unlock track="fortmagma"/>
|
||||
</challenge>
|
||||
|
@ -1,19 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<grandprix id="1_penguinplayground"/>
|
||||
<mode major="grandprix" minor="quickrace"/>
|
||||
<requirements trophies="40"/>
|
||||
<requirements trophies="30"/>
|
||||
|
||||
<best>
|
||||
<karts number="7"/>
|
||||
<requirements position="1"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<karts number="6"/>
|
||||
<requirements position="1"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<karts number="5"/>
|
||||
<requirements position="1"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="3"/>
|
||||
<karts number="4"/>
|
||||
<requirements position="1"/>
|
||||
</easy>
|
||||
</challenge>
|
||||
|
@ -1,19 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<grandprix id="2_offthebeatentrack"/>
|
||||
<mode major="grandprix" minor="quickrace"/>
|
||||
<requirements trophies="85"/>
|
||||
<requirements trophies="70"/>
|
||||
|
||||
<best>
|
||||
<karts number="8"/>
|
||||
<requirements position="1"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<karts number="7"/>
|
||||
<requirements position="1"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<karts number="6"/>
|
||||
<requirements position="1"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="3"/>
|
||||
<karts number="5"/>
|
||||
<requirements position="1"/>
|
||||
</easy>
|
||||
</challenge>
|
||||
|
@ -1,19 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<grandprix id="3_tothemoonandback"/>
|
||||
<mode major="grandprix" minor="quickrace"/>
|
||||
<requirements trophies="125"/>
|
||||
<requirements trophies="120"/>
|
||||
|
||||
<best>
|
||||
<karts number="9"/>
|
||||
<requirements position="1"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<karts number="8"/>
|
||||
<requirements position="1"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<karts number="7"/>
|
||||
<requirements position="1"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="3"/>
|
||||
<karts number="6"/>
|
||||
<requirements position="1"/>
|
||||
</easy>
|
||||
</challenge>
|
||||
|
@ -1,19 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<grandprix id="4_atworldsend"/>
|
||||
<mode major="grandprix" minor="quickrace"/>
|
||||
<requirements trophies="165"/>
|
||||
|
||||
<best>
|
||||
<karts number="10"/>
|
||||
<requirements position="1"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<karts number="9"/>
|
||||
<requirements position="1"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<karts number="8"/>
|
||||
<requirements position="1"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="3"/>
|
||||
<karts number="7"/>
|
||||
<requirements position="1"/>
|
||||
</easy>
|
||||
</challenge>
|
||||
|
@ -1,20 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="gran_paradiso_island" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="95"/>
|
||||
<requirements trophies="80"/>
|
||||
|
||||
<best>
|
||||
<karts number="9"/>
|
||||
<requirements position="1"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<karts number="8"/>
|
||||
<requirements position="1"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<karts number="7"/>
|
||||
<requirements position="1"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="3"/>
|
||||
<karts number="6"/>
|
||||
<requirements position="1"/>
|
||||
</easy>
|
||||
</challenge>
|
||||
|
@ -1,19 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="greenvalley" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="95"/>
|
||||
<requirements trophies="90"/>
|
||||
|
||||
<best>
|
||||
<karts number="9"/>
|
||||
<requirements position="1"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<karts number="8"/>
|
||||
<requirements position="1"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<karts number="7"/>
|
||||
<requirements position="1"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="4"/>
|
||||
<karts number="6"/>
|
||||
<requirements position="1"/>
|
||||
</easy>
|
||||
</challenge>
|
@ -1,19 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="hacienda" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="45"/>
|
||||
<requirements trophies="25"/>
|
||||
|
||||
<best>
|
||||
<karts number="8"/>
|
||||
<requirements position="1" time="130"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<requirements position="2" time="170"/>
|
||||
<karts number="7"/>
|
||||
<requirements position="1" time="160"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<requirements time="187"/>
|
||||
<karts number="6"/>
|
||||
<requirements position="2" time="187"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="4"/>
|
||||
<karts number="5"/>
|
||||
<requirements time="260"/>
|
||||
</easy>
|
||||
</challenge>
|
||||
|
@ -1,20 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<track id="lighthouse" laps="3"/>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="lighthouse" laps="4"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="135"/>
|
||||
<requirements trophies="125"/>
|
||||
|
||||
<best>
|
||||
<karts number="10"/>
|
||||
<requirements position="1" time="120"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<requirements time="110" position="1"/>
|
||||
<karts number="9"/>
|
||||
<requirements position="1" time="140"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<requirements time="145" position="1"/>
|
||||
<karts number="8"/>
|
||||
<requirements position="1" time="190"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="3"/>
|
||||
<requirements time="185"/>
|
||||
<karts number="7"/>
|
||||
<requirements time="250"/>
|
||||
</easy>
|
||||
</challenge>
|
||||
|
||||
|
@ -1,18 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="mansion" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="110"/>
|
||||
<requirements trophies="100"/>
|
||||
|
||||
<best>
|
||||
<karts number="9"/>
|
||||
<requirements position="1" time="100"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<requirements time="110"/>
|
||||
<karts number="8"/>
|
||||
<requirements position="1" time="115"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<requirements time="130"/>
|
||||
<karts number="7"/>
|
||||
<requirements time="140"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="4"/>
|
||||
<requirements time="160"/>
|
||||
<karts number="6"/>
|
||||
<requirements time="180"/>
|
||||
</easy>
|
||||
</challenge>
|
||||
|
@ -1,19 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="mines" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="150"/>
|
||||
<requirements trophies="140"/>
|
||||
|
||||
<best>
|
||||
<karts number="10"/>
|
||||
<requirements position="1" time="140"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="4"/>
|
||||
<requirements time="160"/>
|
||||
<karts number="9"/>
|
||||
<requirements position="1" time="160"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<requirements time="190"/>
|
||||
<karts number="8"/>
|
||||
<requirements position="2" time="190"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="4"/>
|
||||
<karts number="7"/>
|
||||
<requirements time="255"/>
|
||||
</easy>
|
||||
</challenge>
|
||||
|
@ -1,19 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<track id="minigolf" laps="3"/>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="minigolf" laps="4"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="150"/>
|
||||
<requirements trophies="130"/>
|
||||
|
||||
<best>
|
||||
<karts number="10"/>
|
||||
<requirements position="1"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<karts number="9"/>
|
||||
<requirements position="1"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<karts number="8"/>
|
||||
<requirements position="1"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="3"/>
|
||||
<karts number="7"/>
|
||||
<requirements position="1"/>
|
||||
</easy>
|
||||
</challenge>
|
||||
|
@ -1,20 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<track id="olivermath" laps="3"/>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="olivermath" laps="5"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="0"/>
|
||||
|
||||
|
||||
<best>
|
||||
<karts number="7"/>
|
||||
<requirements position="1" time="95"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<requirements position="1" time="65"/>
|
||||
<karts number="6"/>
|
||||
<requirements position="1" time="110"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="5"/>
|
||||
<requirements position="1" time="85"/>
|
||||
<requirements position="1" time="140"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="5"/>
|
||||
<requirements position="1" time="130"/>
|
||||
<karts number="4"/>
|
||||
<requirements position="1" time="210"/>
|
||||
</easy>
|
||||
</challenge>
|
||||
|
||||
|
@ -1,12 +1,17 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="sandtrack" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="0"/>
|
||||
|
||||
<best>
|
||||
<karts number="1"/>
|
||||
<requirements energy="20" time="135"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="1"/>
|
||||
<requirements energy="18" time="167"/>
|
||||
<requirements energy="18" time="165"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="1"/>
|
||||
|
@ -1,15 +1,20 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="scotland" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="0"/>
|
||||
|
||||
<best>
|
||||
<karts number="7"/>
|
||||
<requirements position="1" time="140"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<karts number="6"/>
|
||||
<requirements position="1" time="165"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<karts number="5"/>
|
||||
<requirements time="185"/>
|
||||
</medium>
|
||||
<easy>
|
||||
|
@ -1,18 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="snowmountain" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="60"/>
|
||||
<requirements trophies="115"/>
|
||||
|
||||
<best>
|
||||
<karts number="10"/>
|
||||
<requirements position="1" time="120"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<requirements time="145"/>
|
||||
<karts number="9"/>
|
||||
<requirements position="2" time="145"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<karts number="8"/>
|
||||
<requirements time="187"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="4"/>
|
||||
<karts number="7"/>
|
||||
<requirements time="250"/>
|
||||
</easy>
|
||||
</challenge>
|
||||
|
@ -1,19 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="snowtuxpeak" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="60"/>
|
||||
<requirements trophies="45"/>
|
||||
|
||||
<best>
|
||||
<karts number="8"/>
|
||||
<requirements position="1" time="120"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<requirements position="1" time="145"/>
|
||||
<karts number="7"/>
|
||||
<requirements position="1" time="140"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<karts number="6"/>
|
||||
<requirements time="170"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="4"/>
|
||||
<requirements time="195"/>
|
||||
<karts number="5"/>
|
||||
<requirements time="210"/>
|
||||
</easy>
|
||||
</challenge>
|
||||
|
@ -1,19 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<track id="stk_enterprise" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="110"/>
|
||||
|
||||
<hard>
|
||||
<karts number="6"/>
|
||||
<requirements position="2"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="6"/>
|
||||
<requirements position="2"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="5"/>
|
||||
<requirements position="2"/>
|
||||
</easy>
|
||||
</challenge>
|
24
data/challenges/stk_enterprise.challenge
Normal file
24
data/challenges/stk_enterprise.challenge
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="stk_enterprise" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="105"/>
|
||||
|
||||
<best>
|
||||
<karts number="9"/>
|
||||
<requirements position="1"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="8"/>
|
||||
<requirements position="1"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="7"/>
|
||||
<requirements position="1"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="6"/>
|
||||
<requirements position="1"/>
|
||||
</easy>
|
||||
</challenge>
|
8
data/challenges/unlock_bonus_kart1.challenge
Normal file
8
data/challenges/unlock_bonus_kart1.challenge
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="true"/>
|
||||
<!-- This is the (rounded) point equivalent of finishing all challenges
|
||||
in easy, except the final challenge -->
|
||||
<requirements trophies="190"/>
|
||||
<unlock kart="amanda"/>
|
||||
</challenge>
|
8
data/challenges/unlock_bonus_kart2.challenge
Normal file
8
data/challenges/unlock_bonus_kart2.challenge
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="true"/>
|
||||
<!-- This is the point equivalent of finishing the
|
||||
story mode with 8 supertux challenges and the rest in gold -->
|
||||
<requirements trophies="280"/>
|
||||
<unlock kart="sara_the_wizard"/>
|
||||
</challenge>
|
8
data/challenges/unlock_supertux.challenge
Normal file
8
data/challenges/unlock_supertux.challenge
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="true"/>
|
||||
<!-- This is the point equivalent of finishing the
|
||||
story mode with all gold except 14 silver challenges -->
|
||||
<requirements trophies="250"/>
|
||||
<unlock difficulty="difficulty_best"/>
|
||||
</challenge>
|
@ -1,19 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="volcano_island" laps="2"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="15"/>
|
||||
|
||||
<best>
|
||||
<karts number="8"/>
|
||||
<requirements position="1"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<karts number="7"/>
|
||||
<requirements position="1"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<karts number="6"/>
|
||||
<requirements position="1"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="4"/>
|
||||
<karts number="5"/>
|
||||
<requirements position="1"/>
|
||||
</easy>
|
||||
</challenge>
|
||||
|
@ -1,12 +1,17 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="xr591" laps="2"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="135"/>
|
||||
|
||||
<best>
|
||||
<karts number="1"/>
|
||||
<requirements energy="20" time="100"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="1"/>
|
||||
<requirements energy="18" time="120"/>
|
||||
<requirements energy="18" time="115"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="1"/>
|
||||
@ -17,5 +22,3 @@
|
||||
<requirements energy="12" time="180"/>
|
||||
</easy>
|
||||
</challenge>
|
||||
|
||||
|
||||
|
@ -1,9 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<track id="zengarden" laps="3"/>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="zengarden" laps="4"/>
|
||||
<mode major="single" minor="timetrial"/>
|
||||
<requirements trophies="45"/>
|
||||
<requirements trophies="35"/>
|
||||
|
||||
<best>
|
||||
<karts number="3"/>
|
||||
<requirements position="1"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="2"/>
|
||||
<requirements position="1"/>
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
<track id="sandtrack" laps="3" reverse="false" />
|
||||
<track id="cornfield_crossing" laps="3" reverse="false" />
|
||||
<track id="olivermath" laps="4" reverse="false" />
|
||||
<track id="olivermath" laps="5" reverse="false" />
|
||||
<track id="abyss" laps="3" reverse="false" />
|
||||
<track id="scotland" laps="3" reverse="false" />
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
|
||||
<supertuxkart_grand_prix name="Off the beaten track">
|
||||
|
||||
<track id="cocoa_temple" laps="3" reverse="false" />
|
||||
<track id="snowmountain" laps="3" reverse="false" />
|
||||
<track id="hacienda" laps="3" reverse="false" />
|
||||
<track id="zengarden" laps="4" reverse="false" />
|
||||
<track id="snowtuxpeak" laps="3" reverse="false" />
|
||||
<track id="cocoa_temple" laps="3" reverse="false" />
|
||||
<track id="hacienda" laps="3" reverse="false" />
|
||||
<track id="zengarden" laps="4" reverse="false" />
|
||||
<track id="volcano_island" laps="2" reverse="false" />
|
||||
<track id="snowtuxpeak" laps="3" reverse="false" />
|
||||
|
||||
</supertuxkart_grand_prix>
|
||||
|
@ -2,10 +2,9 @@
|
||||
<supertuxkart_grand_prix name="To the moon and back">
|
||||
|
||||
<track id="gran_paradiso_island" laps="3" reverse="false" />
|
||||
<track id="greenvalley" laps="2" reverse="false" />
|
||||
<track id="greenvalley" laps="3" reverse="false" />
|
||||
<track id="mansion" laps="3" reverse="false" />
|
||||
<track id="stk_enterprise" laps="3" reverse="false" />
|
||||
<track id="volcano_island" laps="2" reverse="false" />
|
||||
<track id="candela_city" laps="3" reverse="false" />
|
||||
|
||||
</supertuxkart_grand_prix>
|
||||
|
||||
|
@ -1,11 +1,10 @@
|
||||
|
||||
<supertuxkart_grand_prix name="At World's End">
|
||||
|
||||
<track id="fortmagma" laps="3" reverse="false" />
|
||||
<track id="minigolf" laps="3" reverse="false" />
|
||||
<track id="lighthouse" laps="4" reverse="false" />
|
||||
<track id="snowmountain" laps="3" reverse="false" />
|
||||
<track id="minigolf" laps="4" reverse="false" />
|
||||
<track id="xr591" laps="3" reverse="false" />
|
||||
<track id="mines" laps="3" reverse="false" />
|
||||
<track id="lighthouse" laps="4" reverse="false" />
|
||||
|
||||
</supertuxkart_grand_prix>
|
||||
|
||||
|
BIN
data/gui/cup_platinum.png
Normal file
BIN
data/gui/cup_platinum.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
data/gui/mystery_unlock.png
Normal file
BIN
data/gui/mystery_unlock.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.8 KiB |
@ -21,7 +21,7 @@
|
||||
<label id="novice_label" proportion="1" height="100%"/>
|
||||
</div>
|
||||
|
||||
<spacer height="8%" width="1"/>
|
||||
<spacer height="6%" width="1"/>
|
||||
|
||||
<div width="100%" proportion="1" layout="horizontal-row">
|
||||
<icon-button id="intermediate" icon="gui/difficulty_medium.png"
|
||||
@ -30,7 +30,7 @@
|
||||
<label id="intermediate_label" proportion="1" height="100%"/>
|
||||
</div>
|
||||
|
||||
<spacer height="8%" width="1"/>
|
||||
<spacer height="6%" width="1"/>
|
||||
|
||||
<div width="100%" proportion="1" layout="horizontal-row">
|
||||
<icon-button id="expert" icon="gui/difficulty_hard.png"
|
||||
@ -39,7 +39,16 @@
|
||||
<label id="difficult_label" proportion="1" height="100%"/>
|
||||
</div>
|
||||
|
||||
<spacer height="8%" width="1"/>
|
||||
<spacer height="6%" width="1"/>
|
||||
|
||||
<div width="100%" proportion="1" layout="horizontal-row">
|
||||
<icon-button id="supertux" icon="gui/difficulty_best.png"
|
||||
I18N="Difficulty" text="SuperTux" height="100%"/>
|
||||
<spacer width="5%" height="1"/>
|
||||
<label id="supertux_label" proportion="1" height="100%"/>
|
||||
</div>
|
||||
|
||||
<spacer height="2%" width="1"/>
|
||||
|
||||
</div>
|
||||
</stkgui>
|
||||
|
46
data/gui/select_challenge_nobest.stkgui
Normal file
46
data/gui/select_challenge_nobest.stkgui
Normal file
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<stkgui>
|
||||
<div x="5%" y="5%" width="90%" height="90%" layout="vertical-row" >
|
||||
|
||||
<header id="title" width="100%" text="Race Setup" align="center" text_align="center" />
|
||||
|
||||
<spacer height="2%" width="1"/>
|
||||
|
||||
<div width="100%" layout="horizontal-row" height="fit">
|
||||
<label id="race_type" text="Type:" I18N="Type of race, in a challenge"/>
|
||||
<spacer width="5" height="1"/>
|
||||
<label id="race_type_val" proportion="1"/>
|
||||
</div>
|
||||
|
||||
<spacer height="2%" width="1"/>
|
||||
|
||||
<div width="100%" proportion="1" layout="horizontal-row">
|
||||
<icon-button id="novice" icon="gui/difficulty_easy.png"
|
||||
I18N="Difficulty" text="Novice" height="100%"/>
|
||||
<spacer width="5%" height="1"/>
|
||||
<label id="novice_label" proportion="1" height="100%"/>
|
||||
</div>
|
||||
|
||||
<spacer height="8%" width="1"/>
|
||||
|
||||
<div width="100%" proportion="1" layout="horizontal-row">
|
||||
<icon-button id="intermediate" icon="gui/difficulty_medium.png"
|
||||
I18N="Difficulty" text="Intermediate" height="100%"/>
|
||||
<spacer width="5%" height="1"/>
|
||||
<label id="intermediate_label" proportion="1" height="100%"/>
|
||||
</div>
|
||||
|
||||
<spacer height="8%" width="1"/>
|
||||
|
||||
<div width="100%" proportion="1" layout="horizontal-row">
|
||||
<icon-button id="expert" icon="gui/difficulty_hard.png"
|
||||
I18N="Difficulty" text="Expert" height="100%"/>
|
||||
<spacer width="5%" height="1"/>
|
||||
<label id="difficult_label" proportion="1" height="100%"/>
|
||||
</div>
|
||||
|
||||
<spacer height="8%" width="1"/>
|
||||
|
||||
</div>
|
||||
</stkgui>
|
||||
|
@ -43,6 +43,7 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
m_gp_id = "";
|
||||
m_version = 0;
|
||||
m_num_trophies = 0;
|
||||
m_is_unlock_list = false;
|
||||
m_is_ghost_replay = false;
|
||||
|
||||
for (int d=0; d<RaceManager::DIFFICULTY_COUNT; d++)
|
||||
@ -66,7 +67,7 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
throw std::runtime_error(msg.str());
|
||||
}
|
||||
|
||||
setId(StringUtils::removeExtension(StringUtils::getBasename(filename)));
|
||||
setChallengeId(StringUtils::removeExtension(StringUtils::getBasename(filename)));
|
||||
|
||||
root->get("version", &m_version);
|
||||
// No need to get the rest of the data if this challenge
|
||||
@ -79,7 +80,48 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
return;
|
||||
}
|
||||
|
||||
m_is_unlock_list = false;
|
||||
const XMLNode* unlock_list_node = root->getNode("unlock_list");
|
||||
if (unlock_list_node != NULL)
|
||||
{
|
||||
std::string list;
|
||||
unlock_list_node->get("list", &list);
|
||||
m_is_unlock_list = (list=="true");
|
||||
}
|
||||
|
||||
std::vector<XMLNode*> unlocks;
|
||||
root->getNodes("unlock", unlocks);
|
||||
for(unsigned int i=0; i<unlocks.size(); i++)
|
||||
{
|
||||
std::string s;
|
||||
if(unlocks[i]->get("kart", &s))
|
||||
setUnlocks(s, ChallengeData::UNLOCK_KART);
|
||||
else if(unlocks[i]->get("track", &s))
|
||||
addUnlockTrackReward(s);
|
||||
else if(unlocks[i]->get("gp", &s))
|
||||
setUnlocks(s, ChallengeData::UNLOCK_GP);
|
||||
else if(unlocks[i]->get("mode", &s))
|
||||
setUnlocks(s, ChallengeData::UNLOCK_MODE);
|
||||
else if(unlocks[i]->get("difficulty", &s))
|
||||
setUnlocks(s, ChallengeData::UNLOCK_DIFFICULTY);
|
||||
else
|
||||
{
|
||||
Log::warn("ChallengeData", "Unknown unlock entry. Must be one of kart, track, gp, mode, difficulty.");
|
||||
throw std::runtime_error("Unknown unlock entry");
|
||||
}
|
||||
}
|
||||
|
||||
const XMLNode* requirements_node = root->getNode("requirements");
|
||||
if (requirements_node == NULL)
|
||||
{
|
||||
throw std::runtime_error("Challenge file " + filename +
|
||||
" has no <requirements> node!");
|
||||
}
|
||||
requirements_node->get("trophies", &m_num_trophies);
|
||||
|
||||
//Don't check further if this is an unlock list
|
||||
if(m_is_unlock_list)
|
||||
return;
|
||||
|
||||
const XMLNode* mode_node = root->getNode("mode");
|
||||
if (mode_node == NULL)
|
||||
@ -149,27 +191,19 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
}
|
||||
}
|
||||
|
||||
const XMLNode* requirements_node = root->getNode("requirements");
|
||||
if (requirements_node == NULL)
|
||||
{
|
||||
throw std::runtime_error("Challenge file " + filename +
|
||||
" has no <requirements> node!");
|
||||
}
|
||||
requirements_node->get("trophies", &m_num_trophies);
|
||||
|
||||
const XMLNode* difficulties[RaceManager::DIFFICULTY_COUNT];
|
||||
difficulties[0] = root->getNode("easy");
|
||||
difficulties[1] = root->getNode("medium");
|
||||
difficulties[2] = root->getNode("hard");
|
||||
difficulties[3] = root->getNode("best");
|
||||
|
||||
// Note that the challenges can only be done in three difficulties
|
||||
if (difficulties[0] == NULL || difficulties[1] == NULL ||
|
||||
difficulties[2] == NULL)
|
||||
difficulties[2] == NULL || difficulties[3] == NULL)
|
||||
{
|
||||
error("<easy> or <medium> or <hard>");
|
||||
error("<easy> or <medium> or <hard> or <best>");
|
||||
}
|
||||
|
||||
for (int d=0; d<=RaceManager::DIFFICULTY_HARD; d++)
|
||||
for (int d=0; d<=RaceManager::DIFFICULTY_BEST; d++)
|
||||
{
|
||||
const XMLNode* karts_node = difficulties[d]->getNode("karts");
|
||||
if (karts_node == NULL) error("<karts .../>");
|
||||
@ -229,28 +263,6 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
if (requirements_node->get("energy", &energy)) m_energy[d] = energy;
|
||||
|
||||
}
|
||||
|
||||
std::vector<XMLNode*> unlocks;
|
||||
root->getNodes("unlock", unlocks);
|
||||
for(unsigned int i=0; i<unlocks.size(); i++)
|
||||
{
|
||||
std::string s;
|
||||
if(unlocks[i]->get("kart", &s))
|
||||
setUnlocks(s, ChallengeData::UNLOCK_KART);
|
||||
else if(unlocks[i]->get("track", &s))
|
||||
addUnlockTrackReward(s);
|
||||
else if(unlocks[i]->get("gp", &s))
|
||||
setUnlocks(s, ChallengeData::UNLOCK_GP);
|
||||
else if(unlocks[i]->get("mode", &s))
|
||||
setUnlocks(s, ChallengeData::UNLOCK_MODE);
|
||||
else if(unlocks[i]->get("difficulty", &s))
|
||||
setUnlocks(s, ChallengeData::UNLOCK_DIFFICULTY);
|
||||
else
|
||||
{
|
||||
Log::warn("ChallengeData", "Unknown unlock entry. Must be one of kart, track, gp, mode, difficulty.");
|
||||
throw std::runtime_error("Unknown unlock entry");
|
||||
}
|
||||
}
|
||||
} // ChallengeData
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -486,7 +498,7 @@ bool ChallengeData::isChallengeFulfilled() const
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns true if this GP challenge is fulfilled.
|
||||
*/
|
||||
bool ChallengeData::isGPFulfilled() const
|
||||
ChallengeData::GPLevel ChallengeData::isGPFulfilled() const
|
||||
{
|
||||
int d = race_manager->getDifficulty();
|
||||
|
||||
@ -496,14 +508,25 @@ bool ChallengeData::isGPFulfilled() const
|
||||
race_manager->getMinorMode() != m_minor ||
|
||||
race_manager->getGrandPrix().getId() != m_gp_id ||
|
||||
race_manager->getNumberOfKarts() < (unsigned int)m_default_num_karts[d] ||
|
||||
race_manager->getNumPlayers() > 1) return false;
|
||||
race_manager->getNumPlayers() > 1) return GP_NONE;
|
||||
|
||||
// check if the player came first.
|
||||
// rank == 0 if first, 1 if second, etc.
|
||||
const int rank = race_manager->getLocalPlayerGPRank(0);
|
||||
|
||||
if (rank != 0) return false;
|
||||
|
||||
return true;
|
||||
// In superior difficulty levels, losing a place means
|
||||
// getting a cup of the inferior level rather than
|
||||
// nothing at all
|
||||
int unlock_level = d - rank;
|
||||
if (unlock_level == 3)
|
||||
return GP_BEST;
|
||||
if (unlock_level == 2)
|
||||
return GP_HARD;
|
||||
if (unlock_level == 1)
|
||||
return GP_MEDIUM;
|
||||
if (unlock_level == 0)
|
||||
return GP_EASY;
|
||||
return GP_NONE;
|
||||
} // isGPFulfilled
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -641,4 +664,3 @@ void ChallengeData::addUnlockKartReward(const std::string &internal_name,
|
||||
feature.m_user_name = user_name;
|
||||
m_feature.push_back(feature);
|
||||
} // addUnlockKartReward
|
||||
|
||||
|
@ -44,6 +44,17 @@ public:
|
||||
UNLOCK_KART,
|
||||
UNLOCK_DIFFICULTY
|
||||
};
|
||||
|
||||
/** The level of completion of a GP challenge
|
||||
*/
|
||||
enum GPLevel
|
||||
{
|
||||
GP_NONE,
|
||||
GP_EASY,
|
||||
GP_MEDIUM,
|
||||
GP_HARD,
|
||||
GP_BEST
|
||||
};
|
||||
// ------------------------------------------------------------------------
|
||||
class UnlockableFeature
|
||||
{
|
||||
@ -95,6 +106,7 @@ private:
|
||||
std::string m_filename;
|
||||
/** Version number of the challenge. */
|
||||
int m_version;
|
||||
bool m_is_unlock_list;
|
||||
bool m_is_ghost_replay;
|
||||
|
||||
void setUnlocks(const std::string &id,
|
||||
@ -120,7 +132,7 @@ public:
|
||||
|
||||
virtual void check() const;
|
||||
virtual bool isChallengeFulfilled() const;
|
||||
virtual bool isGPFulfilled() const;
|
||||
virtual GPLevel isGPFulfilled() const;
|
||||
void addUnlockTrackReward(const std::string &track_name);
|
||||
void addUnlockModeReward(const std::string &internal_mode_name,
|
||||
const irr::core::stringw &user_mode_name);
|
||||
@ -142,11 +154,11 @@ public:
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the id of the challenge. */
|
||||
const std::string &getId() const { return m_id; }
|
||||
const std::string &getChallengeId() const { return m_id; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the id of this challenge. */
|
||||
void setId(const std::string& s) { m_id = s; }
|
||||
void setChallengeId(const std::string& s) { m_id = s; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the track associated with this challenge. */
|
||||
@ -185,6 +197,9 @@ public:
|
||||
/** Returns if this challenge is using ghost replay. */
|
||||
bool isGhostReplay() const { return m_is_ghost_replay; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns if this challenge is an unlock list. */
|
||||
bool isUnlockList() const { return m_is_unlock_list; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the challenge mode of this challenge. */
|
||||
ChallengeModeType getMode() const { return m_mode; }
|
||||
// ------------------------------------------------------------------------
|
||||
@ -196,9 +211,9 @@ public:
|
||||
const irr::core::stringw getChallengeDescription() const;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the minimum position the player must have in order to win.
|
||||
/** Returns the maximum position the player must have in order to win.
|
||||
*/
|
||||
int getPosition(RaceManager::Difficulty difficulty) const
|
||||
int getMaxPosition(RaceManager::Difficulty difficulty) const
|
||||
{
|
||||
return m_position[difficulty];
|
||||
} // getPosition
|
||||
|
@ -35,18 +35,19 @@
|
||||
*/
|
||||
void ChallengeStatus::load(const XMLNode* challenges_node)
|
||||
{
|
||||
const XMLNode* node = challenges_node->getNode( m_data->getId() );
|
||||
const XMLNode* node = challenges_node->getNode( m_data->getChallengeId() );
|
||||
if(node == NULL)
|
||||
{
|
||||
Log::info("ChallengeStatus", "Couldn't find node <%s> in challenge list."
|
||||
"(If this is the first time you play this is normal)\n",
|
||||
m_data->getId().c_str());
|
||||
m_data->getChallengeId().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
m_state[0] = CH_INACTIVE;
|
||||
m_state[1] = CH_INACTIVE;
|
||||
m_state[2] = CH_INACTIVE;
|
||||
m_state[3] = CH_INACTIVE;
|
||||
|
||||
std::string solved;
|
||||
if (node->get("solved", &solved))
|
||||
@ -64,6 +65,13 @@ void ChallengeStatus::load(const XMLNode* challenges_node)
|
||||
m_state[1] = CH_SOLVED;
|
||||
m_state[2] = CH_SOLVED;
|
||||
}
|
||||
else if (solved == "best")
|
||||
{
|
||||
m_state[0] = CH_SOLVED;
|
||||
m_state[1] = CH_SOLVED;
|
||||
m_state[2] = CH_SOLVED;
|
||||
m_state[3] = CH_SOLVED;
|
||||
}
|
||||
} // if has 'solved' attribute
|
||||
|
||||
} // load
|
||||
@ -78,14 +86,28 @@ void ChallengeStatus::setSolved(RaceManager::Difficulty d)
|
||||
{
|
||||
m_state[curr] = CH_SOLVED;
|
||||
}
|
||||
}
|
||||
} // setSolved
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
bool ChallengeStatus::isUnlockList()
|
||||
{
|
||||
return m_data->isUnlockList();
|
||||
} // isUnlockList
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
bool ChallengeStatus::isGrandPrix()
|
||||
{
|
||||
return m_data->isGrandPrix();
|
||||
} // isUnlockList
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ChallengeStatus::save(UTFWriter& writer)
|
||||
{
|
||||
writer << L" <" << m_data->getId();
|
||||
if (isSolved(RaceManager::DIFFICULTY_HARD))
|
||||
writer << L" <" << m_data->getChallengeId();
|
||||
if (isSolved(RaceManager::DIFFICULTY_BEST))
|
||||
writer << L" solved=\"best\"/>\n";
|
||||
else if (isSolved(RaceManager::DIFFICULTY_HARD))
|
||||
writer << L" solved=\"hard\"/>\n";
|
||||
else if (isSolved(RaceManager::DIFFICULTY_MEDIUM))
|
||||
writer << L" solved=\"medium\"/>\n";
|
||||
|
@ -57,6 +57,7 @@ private:
|
||||
enum {CH_INACTIVE, // challenge not yet possible
|
||||
CH_ACTIVE, // challenge possible, but not yet solved
|
||||
CH_SOLVED} // challenge was solved
|
||||
|
||||
m_state[RaceManager::DIFFICULTY_COUNT];
|
||||
|
||||
/** Pointer to the original challenge data. */
|
||||
@ -69,6 +70,7 @@ public:
|
||||
m_state[RaceManager::DIFFICULTY_EASY] = CH_INACTIVE;
|
||||
m_state[RaceManager::DIFFICULTY_MEDIUM] = CH_INACTIVE;
|
||||
m_state[RaceManager::DIFFICULTY_HARD] = CH_INACTIVE;
|
||||
m_state[RaceManager::DIFFICULTY_BEST] = CH_INACTIVE;
|
||||
}
|
||||
virtual ~ChallengeStatus() {};
|
||||
void load(const XMLNode* config);
|
||||
@ -88,7 +90,7 @@ public:
|
||||
bool isSolvedAtAnyDifficulty() const
|
||||
{
|
||||
return m_state[0]==CH_SOLVED || m_state[1]==CH_SOLVED ||
|
||||
m_state[2]==CH_SOLVED;
|
||||
m_state[2]==CH_SOLVED || m_state[3]==CH_SOLVED;
|
||||
} // isSolvedAtAnyDifficulty
|
||||
// ------------------------------------------------------------------------
|
||||
/** True if this challenge is active at the given difficulty.
|
||||
@ -105,6 +107,13 @@ public:
|
||||
m_state[d] = CH_ACTIVE;
|
||||
} // setActive
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns if this challenge is only an unlock list */
|
||||
bool isUnlockList();
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns if this challenge is a grand prix */
|
||||
bool isGrandPrix();
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a pointer to the actual Challenge data.
|
||||
*/
|
||||
const ChallengeData* getData() const { return m_data; }
|
||||
|
@ -30,12 +30,14 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
StoryModeStatus::StoryModeStatus(const XMLNode *node)
|
||||
{
|
||||
m_points = 0;
|
||||
m_first_time = true;
|
||||
m_easy_challenges = 0;
|
||||
m_medium_challenges = 0;
|
||||
m_hard_challenges = 0;
|
||||
m_current_challenge = NULL;
|
||||
m_points = 0;
|
||||
m_next_unlock_points = 0;
|
||||
m_first_time = true;
|
||||
m_easy_challenges = 0;
|
||||
m_medium_challenges = 0;
|
||||
m_hard_challenges = 0;
|
||||
m_best_challenges = 0;
|
||||
m_current_challenge = NULL;
|
||||
|
||||
// If there is saved data, load it
|
||||
if(node)
|
||||
@ -62,7 +64,7 @@ StoryModeStatus::~StoryModeStatus()
|
||||
*/
|
||||
void StoryModeStatus::addStatus(ChallengeStatus *cs)
|
||||
{
|
||||
m_challenges_state[cs->getData()->getId()] = cs;
|
||||
m_challenges_state[cs->getData()->getChallengeId()] = cs;
|
||||
} // addStatus
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -78,9 +80,11 @@ bool StoryModeStatus::isLocked(const std::string& feature)
|
||||
void StoryModeStatus::computeActive()
|
||||
{
|
||||
m_points = 0;
|
||||
m_next_unlock_points = 0;
|
||||
m_easy_challenges = 0;
|
||||
m_medium_challenges = 0;
|
||||
m_hard_challenges = 0;
|
||||
m_best_challenges = 0;
|
||||
|
||||
m_locked_features.clear(); // start afresh
|
||||
|
||||
@ -111,20 +115,32 @@ void StoryModeStatus::computeActive()
|
||||
unlockFeature(i->second, RaceManager::DIFFICULTY_HARD,
|
||||
/*save*/ false);
|
||||
}
|
||||
|
||||
if (i->second->isSolved(RaceManager::DIFFICULTY_HARD))
|
||||
if (i->second->isSolved(RaceManager::DIFFICULTY_BEST))
|
||||
{
|
||||
m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_HARD];
|
||||
unlockFeature(i->second, RaceManager::DIFFICULTY_BEST,
|
||||
/*save*/ false);
|
||||
}
|
||||
|
||||
int gp_factor = i->second->isGrandPrix() ? GP_FACTOR : 1;
|
||||
|
||||
if (i->second->isSolved(RaceManager::DIFFICULTY_BEST) && !i->second->isUnlockList())
|
||||
{
|
||||
m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_BEST]*gp_factor;
|
||||
m_best_challenges++;
|
||||
}
|
||||
else if (i->second->isSolved(RaceManager::DIFFICULTY_HARD) && !i->second->isUnlockList())
|
||||
{
|
||||
m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_HARD]*gp_factor;
|
||||
m_hard_challenges++;
|
||||
}
|
||||
else if (i->second->isSolved(RaceManager::DIFFICULTY_MEDIUM))
|
||||
else if (i->second->isSolved(RaceManager::DIFFICULTY_MEDIUM) && !i->second->isUnlockList())
|
||||
{
|
||||
m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_MEDIUM];
|
||||
m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_MEDIUM]*gp_factor;
|
||||
m_medium_challenges++;
|
||||
}
|
||||
else if (i->second->isSolved(RaceManager::DIFFICULTY_EASY))
|
||||
else if (i->second->isSolved(RaceManager::DIFFICULTY_EASY) && !i->second->isUnlockList())
|
||||
{
|
||||
m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_EASY];
|
||||
m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_EASY]*gp_factor;
|
||||
m_easy_challenges++;
|
||||
}
|
||||
}
|
||||
@ -135,29 +151,40 @@ void StoryModeStatus::computeActive()
|
||||
lockFeature(i->second);
|
||||
}
|
||||
|
||||
if (i->second->isSolved(RaceManager::DIFFICULTY_HARD))
|
||||
if (i->second->isSolved(RaceManager::DIFFICULTY_BEST))
|
||||
{
|
||||
// challenge beaten at hardest, nothing more to do here
|
||||
continue;
|
||||
}
|
||||
else if (i->second->isSolved(RaceManager::DIFFICULTY_HARD))
|
||||
{
|
||||
i->second->setActive(RaceManager::DIFFICULTY_BEST);
|
||||
}
|
||||
else if (i->second->isSolved(RaceManager::DIFFICULTY_MEDIUM))
|
||||
{
|
||||
i->second->setActive(RaceManager::DIFFICULTY_BEST);
|
||||
i->second->setActive(RaceManager::DIFFICULTY_HARD);
|
||||
}
|
||||
else if (i->second->isSolved(RaceManager::DIFFICULTY_EASY))
|
||||
{
|
||||
i->second->setActive(RaceManager::DIFFICULTY_BEST);
|
||||
i->second->setActive(RaceManager::DIFFICULTY_HARD);
|
||||
i->second->setActive(RaceManager::DIFFICULTY_MEDIUM);
|
||||
}
|
||||
else
|
||||
{
|
||||
i->second->setActive(RaceManager::DIFFICULTY_BEST);
|
||||
i->second->setActive(RaceManager::DIFFICULTY_HARD);
|
||||
i->second->setActive(RaceManager::DIFFICULTY_MEDIUM);
|
||||
i->second->setActive(RaceManager::DIFFICULTY_EASY);
|
||||
}
|
||||
} // for i
|
||||
|
||||
// now we have the number of points. Actually lock the tracks
|
||||
// now we have the number of points.
|
||||
|
||||
unlockFeatureByList();
|
||||
|
||||
//Actually lock the tracks
|
||||
for (i = m_challenges_state.begin(); i != m_challenges_state.end(); i++)
|
||||
{
|
||||
if (m_points < i->second->getData()->getNumTrophies())
|
||||
@ -173,12 +200,37 @@ void StoryModeStatus::computeActive()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clearUnlocked();
|
||||
|
||||
|
||||
} // computeActive
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void StoryModeStatus::unlockFeatureByList()
|
||||
{
|
||||
// test if we have unlocked a feature requiring a certain number of points
|
||||
std::map<std::string, ChallengeStatus*>::const_iterator i;
|
||||
for(i = m_challenges_state.begin();
|
||||
i != m_challenges_state.end(); i++)
|
||||
{
|
||||
if (i->second->isUnlockList())
|
||||
{
|
||||
if (i->second->isSolvedAtAnyDifficulty())
|
||||
continue;
|
||||
|
||||
bool newly_solved = unlock_manager->unlockByPoints(m_points,i->second);
|
||||
|
||||
// Add to list of recently unlocked features
|
||||
if(newly_solved)
|
||||
m_unlocked_features.push_back(i->second->getData());
|
||||
|
||||
//Retrieve the smallest number of points for the next unlockable
|
||||
if (i->second->getData()->getNumTrophies() > m_points && (m_next_unlock_points == 0
|
||||
|| i->second->getData()->getNumTrophies() < m_next_unlock_points) )
|
||||
m_next_unlock_points = i->second->getData()->getNumTrophies();
|
||||
}
|
||||
}
|
||||
} //unlockFeatureByList
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void StoryModeStatus::lockFeature(ChallengeStatus *challenge_status)
|
||||
@ -216,8 +268,10 @@ void StoryModeStatus::unlockFeature(ChallengeStatus* c, RaceManager::Difficulty
|
||||
m_locked_features.erase(p);
|
||||
}
|
||||
|
||||
// Add to list of recently unlocked features
|
||||
m_unlocked_features.push_back(c->getData());
|
||||
// Add to list of recently unlocked features if the challenge is newly completed
|
||||
if (!c->isSolvedAtAnyDifficulty())
|
||||
m_unlocked_features.push_back(c->getData());
|
||||
|
||||
c->setSolved(d); // reset isActive flag
|
||||
|
||||
// Save the new unlock information
|
||||
@ -250,6 +304,10 @@ void StoryModeStatus::raceFinished()
|
||||
unlockFeature(const_cast<ChallengeStatus*>(m_current_challenge),
|
||||
race_manager->getDifficulty());
|
||||
} // if isActive && challenge solved
|
||||
|
||||
//This updates the number of points.
|
||||
//It then calls unlockFeatureByList which checks the specially unlocked features (by points, etc)
|
||||
computeActive();
|
||||
} // raceFinished
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -259,11 +317,33 @@ void StoryModeStatus::raceFinished()
|
||||
void StoryModeStatus::grandPrixFinished()
|
||||
{
|
||||
if(m_current_challenge &&
|
||||
m_current_challenge->isActive(race_manager->getDifficulty()) &&
|
||||
m_current_challenge->getData()->isGPFulfilled() )
|
||||
m_current_challenge->isActive(race_manager->getDifficulty()) )
|
||||
{
|
||||
unlockFeature(const_cast<ChallengeStatus*>(m_current_challenge),
|
||||
race_manager->getDifficulty());
|
||||
ChallengeData::GPLevel unlock_level = m_current_challenge->getData()->isGPFulfilled();
|
||||
|
||||
RaceManager::Difficulty difficulty = RaceManager::DIFFICULTY_EASY;
|
||||
|
||||
switch (unlock_level)
|
||||
{
|
||||
case ChallengeData::GP_NONE:
|
||||
race_manager->setCoinTarget(0);
|
||||
return; //No cup unlocked
|
||||
case ChallengeData::GP_EASY:
|
||||
difficulty = RaceManager::DIFFICULTY_EASY;
|
||||
break;
|
||||
case ChallengeData::GP_MEDIUM:
|
||||
difficulty = RaceManager::DIFFICULTY_MEDIUM;
|
||||
break;
|
||||
case ChallengeData::GP_HARD:
|
||||
difficulty = RaceManager::DIFFICULTY_HARD;
|
||||
break;
|
||||
case ChallengeData::GP_BEST:
|
||||
difficulty = RaceManager::DIFFICULTY_BEST;
|
||||
break;
|
||||
}
|
||||
|
||||
race_manager->setDifficulty(difficulty);
|
||||
unlockFeature(const_cast<ChallengeStatus*>(m_current_challenge), difficulty);
|
||||
} // if isActive && challenge solved
|
||||
|
||||
race_manager->setCoinTarget(0);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#ifndef GAME_SLOT_HPP
|
||||
#define GAME_SLOT_HPP
|
||||
|
||||
#include "challenges/challenge_data.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
|
||||
#include <irrString.h>
|
||||
@ -33,7 +34,8 @@ class ChallengeStatus;
|
||||
class UTFWriter;
|
||||
class XMLNode;
|
||||
|
||||
const int CHALLENGE_POINTS[] = { 8, 9, 10 };
|
||||
const int CHALLENGE_POINTS[] = { 6, 7, 8, 10 };
|
||||
const int GP_FACTOR = 3;
|
||||
|
||||
/** This class contains the progression through challenges for the story mode.
|
||||
* It maintains a list of all challenges in a mapping of challenge id to
|
||||
@ -60,6 +62,7 @@ private:
|
||||
const ChallengeStatus *m_current_challenge;
|
||||
|
||||
int m_points;
|
||||
int m_next_unlock_points;
|
||||
|
||||
/** Set to false after the initial stuff (intro, select kart, etc.) */
|
||||
bool m_first_time;
|
||||
@ -67,6 +70,7 @@ private:
|
||||
int m_easy_challenges;
|
||||
int m_medium_challenges;
|
||||
int m_hard_challenges;
|
||||
int m_best_challenges;
|
||||
|
||||
public:
|
||||
|
||||
@ -75,6 +79,7 @@ public:
|
||||
|
||||
void computeActive();
|
||||
bool isLocked (const std::string& feature);
|
||||
void unlockFeatureByList();
|
||||
void lockFeature (ChallengeStatus *challenge);
|
||||
void unlockFeature (ChallengeStatus* c, RaceManager::Difficulty d,
|
||||
bool do_save=true);
|
||||
@ -96,15 +101,21 @@ public:
|
||||
/** Returns the number of points accumulated. */
|
||||
int getPoints () const { return m_points; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of points needed by the next unlockable. 0 if none. */
|
||||
int getNextUnlockPoints () const { return m_next_unlock_points; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of fulfilled challenges at easy level. */
|
||||
int getNumEasyTrophies () const { return m_easy_challenges; }
|
||||
// ------------------------------------------------------------------------
|
||||
/* Returns the number of fulfilled challenges at medium level. */
|
||||
int getNumMediumTrophies() const { return m_medium_challenges; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of fulfilled challenges at har level. */
|
||||
/** Returns the number of fulfilled challenges at hard level. */
|
||||
int getNumHardTrophies () const { return m_hard_challenges; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of fulfilled challenges at best level. */
|
||||
int getNumBestTrophies () const { return m_best_challenges; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets if this is the first time the intro is shown. */
|
||||
void setFirstTime(bool ft) { m_first_time = ft; }
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "audio/sfx_manager.hpp"
|
||||
#include "challenges/challenge_data.hpp"
|
||||
#include "challenges/challenge_status.hpp"
|
||||
#include "challenges/story_mode_status.hpp"
|
||||
#include "config/player_manager.hpp"
|
||||
#include "config/player_profile.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
@ -142,19 +143,30 @@ void UnlockManager::addOrFreeChallenge(ChallengeData *c)
|
||||
{
|
||||
if(isSupportedVersion(*c))
|
||||
{
|
||||
m_all_challenges[c->getId()]=c;
|
||||
m_all_challenges[c->getChallengeId()]=c;
|
||||
if (c->isUnlockList())
|
||||
addListChallenge(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::warn("Challenge", "Challenge '%s' is not supported - ignored.",
|
||||
c->getId().c_str());
|
||||
c->getChallengeId().c_str());
|
||||
delete c;
|
||||
}
|
||||
} // addOrFreeChallenge
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Add a challenge to the unlock challenges list
|
||||
* \param c The challenge that is either stored or freed.
|
||||
*/
|
||||
void UnlockManager::addListChallenge(ChallengeData *c)
|
||||
{
|
||||
m_list_challenges[c->getChallengeId()]=c;
|
||||
} // addListChallenge
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Reads a challenge from the given filename. The challenge will then either
|
||||
* be stored, or (if the challenge version is not supported anymore
|
||||
* be stored, or (if the challenge version is not supported anymore, freed)
|
||||
* \param filename Name of the challenge file to read.
|
||||
*/
|
||||
void UnlockManager::addChallenge(const std::string& filename)
|
||||
@ -228,20 +240,25 @@ bool UnlockManager::isSupportedVersion(const ChallengeData &challenge)
|
||||
{
|
||||
// Test if challenge version number is in between minimum
|
||||
// and maximum supported version.
|
||||
return (challenge.getVersion()>=2 && challenge.getVersion()<=2);
|
||||
return (challenge.getVersion()>=3 && challenge.getVersion()<=3);
|
||||
} // isSupportedVersion
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** This functions finds what new tracks, GP and karts have been unlocked
|
||||
*/
|
||||
void UnlockManager::findWhatWasUnlocked(int points_before, int points_now,
|
||||
std::vector<std::string>& tracks,
|
||||
std::vector<std::string>& gps)
|
||||
std::vector<std::string>& gps,
|
||||
std::vector<std::string>& karts,
|
||||
std::vector<const ChallengeData*>& unlocked)
|
||||
{
|
||||
ChallengeData* c = NULL;
|
||||
|
||||
for (AllChallengesType::iterator it = m_all_challenges.begin();
|
||||
it != m_all_challenges.end(); it++)
|
||||
{
|
||||
ChallengeData* c = it->second;
|
||||
c = it->second;
|
||||
if (c->getNumTrophies() > points_before &&
|
||||
c->getNumTrophies() <= points_now )
|
||||
{
|
||||
@ -257,4 +274,36 @@ void UnlockManager::findWhatWasUnlocked(int points_before, int points_now,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int n = 0; n < unlocked.size(); n++)
|
||||
{
|
||||
std::vector<ChallengeData::UnlockableFeature> features = unlocked[n]->getFeatures();
|
||||
|
||||
for (unsigned int i = 0; i < features.size(); i++)
|
||||
{
|
||||
if( features[i].m_type == ChallengeData::UNLOCK_KART )
|
||||
karts.push_back(features[i].m_name);
|
||||
}
|
||||
}
|
||||
|
||||
//std::vector<const ChallengeData*>
|
||||
// getRecentlyCompletedChallenges()
|
||||
} // findWhatWasUnlocked
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This functions sets as completed the "challenges" requiring a certain number
|
||||
* of points, to unlock features.
|
||||
* Returns true if the challenge has been completed
|
||||
*/
|
||||
bool UnlockManager::unlockByPoints(int points, ChallengeStatus* unlock_list)
|
||||
{
|
||||
//TODO : add support for other conditions (achievements...) for alternative unlock paths
|
||||
if( unlock_list!=NULL && unlock_list->getData()->getNumTrophies() <= points)
|
||||
{
|
||||
unlock_list->setSolved(RaceManager::DIFFICULTY_BEST);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} // unlockByPoints
|
||||
|
||||
/* EOF */
|
||||
|
@ -44,12 +44,16 @@ private:
|
||||
typedef std::map<std::string, ChallengeData*> AllChallengesType;
|
||||
AllChallengesType m_all_challenges;
|
||||
|
||||
/* The challenges who don't have a race, only unlockables */
|
||||
AllChallengesType m_list_challenges;
|
||||
|
||||
void readAllChallengesInDirs(const std::vector<std::string>* all_dirs);
|
||||
|
||||
public:
|
||||
UnlockManager ();
|
||||
~UnlockManager ();
|
||||
void addOrFreeChallenge(ChallengeData *c);
|
||||
void addListChallenge(ChallengeData *c);
|
||||
void addChallenge (const std::string& filename);
|
||||
|
||||
const ChallengeData *getChallengeData(const std::string& id);
|
||||
@ -61,7 +65,10 @@ public:
|
||||
|
||||
void findWhatWasUnlocked(int pointsBefore, int pointsNow,
|
||||
std::vector<std::string>& tracks,
|
||||
std::vector<std::string>& gps);
|
||||
std::vector<std::string>& gps,
|
||||
std::vector<std::string>& karts,
|
||||
std::vector<const ChallengeData*>& unlocked);
|
||||
bool unlockByPoints(int points, ChallengeStatus* unlock_list);
|
||||
|
||||
StoryModeStatus *createStoryModeStatus(const XMLNode *node=NULL);
|
||||
|
||||
|
@ -230,6 +230,8 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
unsigned int getPoints() const { return m_story_mode_status->getPoints(); }
|
||||
// ------------------------------------------------------------------------
|
||||
unsigned int getNextUnlockPoints() const { return m_story_mode_status->getNextUnlockPoints(); }
|
||||
// ------------------------------------------------------------------------
|
||||
void setFirstTime(bool b) { m_story_mode_status->setFirstTime(b); }
|
||||
// ------------------------------------------------------------------------
|
||||
bool isFirstTime() const { return m_story_mode_status->isFirstTime(); }
|
||||
@ -263,7 +265,11 @@ public:
|
||||
unsigned int getNumHardTrophies() const
|
||||
{
|
||||
return m_story_mode_status->getNumHardTrophies();
|
||||
} // getNumHardTropies
|
||||
} // getNumHardTrophies
|
||||
unsigned int getNumBestTrophies() const
|
||||
{
|
||||
return m_story_mode_status->getNumBestTrophies();
|
||||
} // getNumBestTrophies
|
||||
// ------------------------------------------------------------------------
|
||||
AchievementsStatus* getAchievementsStatus()
|
||||
{
|
||||
|
@ -422,11 +422,14 @@ void CutsceneWorld::enterRaceOverState()
|
||||
// un-set the GP mode so that after unlocking, it doesn't try to continue the GP
|
||||
race_manager->setMajorMode(RaceManager::MAJOR_MODE_SINGLE);
|
||||
|
||||
//TODO : this code largely duplicate a similar code present in raceResultGUI.
|
||||
// Try to reduce duplication
|
||||
std::vector<const ChallengeData*> unlocked =
|
||||
PlayerManager::getCurrentPlayer()->getRecentlyCompletedChallenges();
|
||||
|
||||
if (unlocked.size() > 0)
|
||||
{
|
||||
//PlayerManager::getCurrentPlayer()->clearUnlocked();
|
||||
PlayerManager::getCurrentPlayer()->clearUnlocked();
|
||||
|
||||
StateManager::get()->enterGameState();
|
||||
race_manager->setMinorMode(RaceManager::MINOR_MODE_CUTSCENE);
|
||||
@ -441,8 +444,8 @@ void CutsceneWorld::enterRaceOverState()
|
||||
((CutsceneWorld*)World::getWorld())->setParts(parts);
|
||||
|
||||
assert(unlocked.size() > 0);
|
||||
scene->addTrophy(race_manager->getDifficulty());
|
||||
scene->findWhatWasUnlocked(race_manager->getDifficulty());
|
||||
scene->addTrophy(race_manager->getDifficulty(),true);
|
||||
scene->findWhatWasUnlocked(race_manager->getDifficulty(),unlocked);
|
||||
|
||||
StateManager::get()->replaceTopMostScreen(scene, GUIEngine::INGAME_MENU);
|
||||
}
|
||||
@ -476,9 +479,10 @@ void CutsceneWorld::enterRaceOverState()
|
||||
|
||||
std::vector<const ChallengeData*> unlocked =
|
||||
PlayerManager::getCurrentPlayer()->getRecentlyCompletedChallenges();
|
||||
|
||||
if (unlocked.size() > 0)
|
||||
{
|
||||
//PlayerManager::getCurrentPlayer()->clearUnlocked();
|
||||
PlayerManager::getCurrentPlayer()->clearUnlocked();
|
||||
|
||||
StateManager::get()->enterGameState();
|
||||
race_manager->setMinorMode(RaceManager::MINOR_MODE_CUTSCENE);
|
||||
@ -492,8 +496,8 @@ void CutsceneWorld::enterRaceOverState()
|
||||
parts.push_back("featunlocked");
|
||||
((CutsceneWorld*)World::getWorld())->setParts(parts);
|
||||
|
||||
scene->addTrophy(race_manager->getDifficulty());
|
||||
scene->findWhatWasUnlocked(race_manager->getDifficulty());
|
||||
scene->addTrophy(race_manager->getDifficulty(),true);
|
||||
scene->findWhatWasUnlocked(race_manager->getDifficulty(),unlocked);
|
||||
|
||||
StateManager::get()->replaceTopMostScreen(scene, GUIEngine::INGAME_MENU);
|
||||
}
|
||||
@ -594,4 +598,3 @@ void CutsceneWorld::createRaceGUI()
|
||||
m_race_gui = new CutsceneGUI();
|
||||
} // createRaceGUI
|
||||
|
||||
|
||||
|
@ -65,7 +65,15 @@ void OverWorld::enterOverWorld()
|
||||
race_manager->setMinorMode (RaceManager::MINOR_MODE_OVERWORLD);
|
||||
race_manager->setNumKarts( 1 );
|
||||
race_manager->setTrack( "overworld" );
|
||||
race_manager->setDifficulty(RaceManager::DIFFICULTY_HARD);
|
||||
|
||||
if (PlayerManager::getCurrentPlayer()->isLocked("difficulty_best"))
|
||||
{
|
||||
race_manager->setDifficulty(RaceManager::DIFFICULTY_HARD);
|
||||
}
|
||||
else
|
||||
{
|
||||
race_manager->setDifficulty(RaceManager::DIFFICULTY_BEST);
|
||||
}
|
||||
|
||||
// Use keyboard 0 by default (FIXME: let player choose?)
|
||||
InputDevice* device = input_manager->getDeviceManager()->getKeyboard(0);
|
||||
@ -255,7 +263,7 @@ void OverWorld::onFirePressed(Controller* who)
|
||||
if (unlocked)
|
||||
{
|
||||
race_manager->setKartLastPositionOnOverworld(kart_xyz);
|
||||
new SelectChallengeDialog(0.8f, 0.8f,
|
||||
new SelectChallengeDialog(0.9f, 0.9f,
|
||||
challenges[n].m_challenge_id);
|
||||
}
|
||||
}
|
||||
|
@ -43,9 +43,9 @@ core::stringw getLabel(RaceManager::Difficulty difficulty, const ChallengeData*
|
||||
{
|
||||
core::stringw label;
|
||||
|
||||
if (c->getPosition(difficulty) != -1)
|
||||
if (c->getMaxPosition(difficulty) != -1)
|
||||
{
|
||||
int r = c->getPosition(difficulty);
|
||||
int r = c->getMaxPosition(difficulty);
|
||||
if (c->getMinorMode() == RaceManager::MINOR_MODE_FOLLOW_LEADER) r--;
|
||||
|
||||
if (label.size() > 0) label.append(L"\n");
|
||||
@ -80,7 +80,10 @@ SelectChallengeDialog::SelectChallengeDialog(const float percentWidth,
|
||||
std::string challenge_id) :
|
||||
ModalDialog(percentWidth, percentHeight)
|
||||
{
|
||||
loadFromFile("select_challenge.stkgui");
|
||||
if (PlayerManager::getCurrentPlayer()->isLocked("difficulty_best"))
|
||||
loadFromFile("select_challenge_nobest.stkgui");
|
||||
else
|
||||
loadFromFile("select_challenge.stkgui");
|
||||
m_challenge_id = challenge_id;
|
||||
World::getWorld()->schedulePause(WorldStatus::IN_GAME_MENU_PHASE);
|
||||
|
||||
@ -95,6 +98,14 @@ SelectChallengeDialog::SelectChallengeDialog(const float percentWidth,
|
||||
case 2:
|
||||
getWidget("expert")->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
if(PlayerManager::getCurrentPlayer()->isLocked("difficulty_best"))
|
||||
getWidget("expert")->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
|
||||
else
|
||||
getWidget("supertux")->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const ChallengeStatus* c = PlayerManager::getCurrentPlayer()
|
||||
@ -121,6 +132,14 @@ SelectChallengeDialog::SelectChallengeDialog(const float percentWidth,
|
||||
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
|
||||
}
|
||||
|
||||
if (c->isSolved(RaceManager::DIFFICULTY_BEST)
|
||||
&& !PlayerManager::getCurrentPlayer()->isLocked("difficulty_best"))
|
||||
{
|
||||
IconButtonWidget* btn = getWidget<IconButtonWidget>("supertux");
|
||||
btn->setImage(file_manager->getAsset(FileManager::GUI,"cup_platinum.png"),
|
||||
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
|
||||
}
|
||||
|
||||
|
||||
LabelWidget* novice_label = getWidget<LabelWidget>("novice_label");
|
||||
LabelWidget* medium_label = getWidget<LabelWidget>("intermediate_label");
|
||||
@ -130,6 +149,12 @@ SelectChallengeDialog::SelectChallengeDialog(const float percentWidth,
|
||||
medium_label->setText( getLabel(RaceManager::DIFFICULTY_MEDIUM, c->getData()), false );
|
||||
expert_label->setText( getLabel(RaceManager::DIFFICULTY_HARD, c->getData()), false );
|
||||
|
||||
if (!PlayerManager::getCurrentPlayer()->isLocked("difficulty_best"))
|
||||
{
|
||||
LabelWidget* supertux_label = getWidget<LabelWidget>("supertux_label");
|
||||
supertux_label->setText( getLabel(RaceManager::DIFFICULTY_BEST, c->getData()), false );
|
||||
}
|
||||
|
||||
if (c->getData()->isGrandPrix())
|
||||
{
|
||||
const GrandPrixData* gp = grand_prix_manager->getGrandPrix(c->getData()->getGPId());
|
||||
@ -167,7 +192,7 @@ GUIEngine::EventPropagation SelectChallengeDialog::processEvent(const std::strin
|
||||
{
|
||||
std::string eventSource = eventSourceParam;
|
||||
if (eventSource == "novice" || eventSource == "intermediate" ||
|
||||
eventSource == "expert")
|
||||
eventSource == "expert" || eventSource == "supertux")
|
||||
{
|
||||
const ChallengeData* challenge = unlock_manager->getChallengeData(m_challenge_id);
|
||||
|
||||
@ -229,6 +254,11 @@ GUIEngine::EventPropagation SelectChallengeDialog::processEvent(const std::strin
|
||||
challenge->setRace(RaceManager::DIFFICULTY_HARD);
|
||||
UserConfigParams::m_difficulty = 2;
|
||||
}
|
||||
else if (eventSource == "supertux")
|
||||
{
|
||||
challenge->setRace(RaceManager::DIFFICULTY_BEST);
|
||||
UserConfigParams::m_difficulty = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("SelectChallenge", "Unknown widget <%s>\n",
|
||||
@ -250,4 +280,3 @@ GUIEngine::EventPropagation SelectChallengeDialog::processEvent(const std::strin
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
@ -81,7 +81,7 @@ FeatureUnlockedCutScene::UnlockedThing::UnlockedThing(std::string model,
|
||||
// -------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
FeatureUnlockedCutScene::UnlockedThing::UnlockedThing(KartProperties* kart,
|
||||
FeatureUnlockedCutScene::UnlockedThing::UnlockedThing(const KartProperties* kart,
|
||||
irr::core::stringw msg)
|
||||
{
|
||||
m_unlocked_kart = kart;
|
||||
@ -202,7 +202,7 @@ void FeatureUnlockedCutScene::onCutsceneEnd()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void FeatureUnlockedCutScene::findWhatWasUnlocked(RaceManager::Difficulty difficulty)
|
||||
void FeatureUnlockedCutScene::findWhatWasUnlocked(RaceManager::Difficulty difficulty,std::vector<const ChallengeData*>& unlocked)
|
||||
{
|
||||
PlayerProfile *player = PlayerManager::getCurrentPlayer();
|
||||
int points_before = player->getPoints();
|
||||
@ -210,9 +210,10 @@ void FeatureUnlockedCutScene::findWhatWasUnlocked(RaceManager::Difficulty diffic
|
||||
|
||||
std::vector<std::string> tracks;
|
||||
std::vector<std::string> gps;
|
||||
std::vector<std::string> karts;
|
||||
|
||||
player->computeActive();
|
||||
unlock_manager->findWhatWasUnlocked(points_before, points_now, tracks, gps);
|
||||
unlock_manager->findWhatWasUnlocked(points_before, points_now, tracks, gps, karts, unlocked);
|
||||
|
||||
for (unsigned int i = 0; i < tracks.size(); i++)
|
||||
{
|
||||
@ -222,26 +223,41 @@ void FeatureUnlockedCutScene::findWhatWasUnlocked(RaceManager::Difficulty diffic
|
||||
{
|
||||
addUnlockedGP(grand_prix_manager->getGrandPrix(gps[i]));
|
||||
}
|
||||
for (unsigned int i = 0; i < karts.size(); i++)
|
||||
{
|
||||
addUnlockedKart(kart_properties_manager->getKart(karts[i]));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void FeatureUnlockedCutScene::addTrophy(RaceManager::Difficulty difficulty)
|
||||
void FeatureUnlockedCutScene::addTrophy(RaceManager::Difficulty difficulty, bool is_grandprix)
|
||||
{
|
||||
core::stringw msg;
|
||||
|
||||
int gp_factor = is_grandprix ? GP_FACTOR : 1;
|
||||
RaceManager::Difficulty max_unlocked_difficulty = RaceManager::DIFFICULTY_BEST;
|
||||
|
||||
if (PlayerManager::getCurrentPlayer()->isLocked("difficulty_best"))
|
||||
max_unlocked_difficulty = RaceManager::DIFFICULTY_HARD;
|
||||
|
||||
switch (difficulty)
|
||||
{
|
||||
case RaceManager::DIFFICULTY_EASY:
|
||||
msg = _("You completed the easy challenge! Points earned on this level: %i/%i",
|
||||
CHALLENGE_POINTS[RaceManager::DIFFICULTY_EASY], CHALLENGE_POINTS[RaceManager::DIFFICULTY_HARD]);
|
||||
CHALLENGE_POINTS[RaceManager::DIFFICULTY_EASY]*gp_factor, CHALLENGE_POINTS[max_unlocked_difficulty]*gp_factor);
|
||||
break;
|
||||
case RaceManager::DIFFICULTY_MEDIUM:
|
||||
msg = _("You completed the intermediate challenge! Points earned on this level: %i/%i",
|
||||
CHALLENGE_POINTS[RaceManager::DIFFICULTY_MEDIUM], CHALLENGE_POINTS[RaceManager::DIFFICULTY_HARD]);
|
||||
CHALLENGE_POINTS[RaceManager::DIFFICULTY_MEDIUM]*gp_factor, CHALLENGE_POINTS[max_unlocked_difficulty]*gp_factor);
|
||||
break;
|
||||
case RaceManager::DIFFICULTY_HARD:
|
||||
msg = _("You completed the difficult challenge! Points earned on this level: %i/%i",
|
||||
CHALLENGE_POINTS[RaceManager::DIFFICULTY_HARD], CHALLENGE_POINTS[RaceManager::DIFFICULTY_HARD]);
|
||||
CHALLENGE_POINTS[RaceManager::DIFFICULTY_HARD]*gp_factor, CHALLENGE_POINTS[max_unlocked_difficulty]*gp_factor);
|
||||
break;
|
||||
case RaceManager::DIFFICULTY_BEST:
|
||||
msg = _("You completed the SuperTux challenge! Points earned on this level: %i/%i",
|
||||
CHALLENGE_POINTS[RaceManager::DIFFICULTY_BEST]*gp_factor, CHALLENGE_POINTS[max_unlocked_difficulty]*gp_factor);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
@ -259,6 +275,9 @@ void FeatureUnlockedCutScene::addTrophy(RaceManager::Difficulty difficulty)
|
||||
case RaceManager::DIFFICULTY_HARD:
|
||||
model = file_manager->getAsset(FileManager::MODEL,"trophy_gold.spm");
|
||||
break;
|
||||
case RaceManager::DIFFICULTY_BEST:
|
||||
model = file_manager->getAsset(FileManager::MODEL,"trophy_platinum.spm");
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
return;
|
||||
@ -269,12 +288,15 @@ void FeatureUnlockedCutScene::addTrophy(RaceManager::Difficulty difficulty)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// unused for now, maybe will be useful later?
|
||||
|
||||
void FeatureUnlockedCutScene::addUnlockedKart(KartProperties* unlocked_kart,
|
||||
irr::core::stringw msg)
|
||||
void FeatureUnlockedCutScene::addUnlockedKart(const KartProperties* unlocked_kart)
|
||||
{
|
||||
assert(unlocked_kart != NULL);
|
||||
if (unlocked_kart == NULL)
|
||||
{
|
||||
Log::error("FeatureUnlockedCutScene::addUnlockedKart", "Unlocked kart does not exist");
|
||||
return;
|
||||
}
|
||||
irr::core::stringw msg = _("You unlocked %s!", unlocked_kart->getName());
|
||||
m_unlocked_stuff.push_back( new UnlockedThing(unlocked_kart, msg) );
|
||||
} // addUnlockedKart
|
||||
|
||||
@ -426,8 +448,6 @@ void FeatureUnlockedCutScene::init()
|
||||
Log::error("FeatureUnlockedCutScene::init", "Malformed unlocked goody");
|
||||
}
|
||||
}
|
||||
|
||||
PlayerManager::getCurrentPlayer()->clearUnlocked();
|
||||
} // init
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -54,7 +54,7 @@ class FeatureUnlockedCutScene : public GUIEngine::CutsceneScreen, public GUIEngi
|
||||
struct UnlockedThing
|
||||
{
|
||||
/** Will be non-null if this unlocked thing is a kart */
|
||||
KartProperties* m_unlocked_kart;
|
||||
const KartProperties* m_unlocked_kart;
|
||||
|
||||
std::string m_unlock_model;
|
||||
|
||||
@ -80,7 +80,7 @@ class FeatureUnlockedCutScene : public GUIEngine::CutsceneScreen, public GUIEngi
|
||||
|
||||
UnlockedThing(std::string model, irr::core::stringw msg);
|
||||
|
||||
UnlockedThing(KartProperties* kart, irr::core::stringw msg);
|
||||
UnlockedThing(const KartProperties* kart, irr::core::stringw msg);
|
||||
|
||||
/**
|
||||
* Creates a 'picture' reward.
|
||||
@ -141,11 +141,11 @@ public:
|
||||
void eventCallback(GUIEngine::Widget* widget, const std::string& name,
|
||||
const int playerID) OVERRIDE;
|
||||
|
||||
void findWhatWasUnlocked(RaceManager::Difficulty difficulty);
|
||||
void findWhatWasUnlocked(RaceManager::Difficulty difficulty,std::vector<const ChallengeData*>& unlocked);
|
||||
|
||||
/** Call before showing up the screen to make a kart come out of the chest.
|
||||
'addUnlockedThings' will invoke this, so you generally don't need to call this directly. */
|
||||
void addUnlockedKart(KartProperties* unlocked_kart, irr::core::stringw msg);
|
||||
void addUnlockedKart(const KartProperties* unlocked_kart);
|
||||
|
||||
/** Call before showing up the screen to make a picture come out of the chest
|
||||
'addUnlockedThings' will invoke this, so you generally don't need to call this directly. */
|
||||
@ -166,7 +166,7 @@ public:
|
||||
void addUnlockedThings(const std::vector<const ChallengeData*> unlocked);
|
||||
*/
|
||||
|
||||
void addTrophy(RaceManager::Difficulty difficulty);
|
||||
void addTrophy(RaceManager::Difficulty difficulty, bool is_grandprix);
|
||||
|
||||
/** override from base class to handle escape press */
|
||||
virtual bool onEscapePressed() OVERRIDE;
|
||||
@ -175,4 +175,3 @@ public:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -318,18 +318,11 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
parts.push_back("featunlocked");
|
||||
((CutsceneWorld*)World::getWorld())->setParts(parts);
|
||||
|
||||
scene->addTrophy(RaceManager::DIFFICULTY_EASY);
|
||||
scene->addTrophy(RaceManager::DIFFICULTY_EASY, false);
|
||||
|
||||
if (selection == "test_unlocked")
|
||||
{
|
||||
// the passed kart will not be modified, that's why I allow myself
|
||||
// to use const_cast
|
||||
scene->addUnlockedKart(
|
||||
const_cast<KartProperties*>(
|
||||
kart_properties_manager->getKart("tux")
|
||||
),
|
||||
L"You unlocked <actual text would go here...>"
|
||||
);
|
||||
scene->addUnlockedKart(kart_properties_manager->getKart("tux"));
|
||||
scene->addUnlockedTrack(track_manager->getTrack("lighthouse"));
|
||||
scene->push();
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ const int OPEN = 1;
|
||||
const int COMPLETED_EASY = 2;
|
||||
const int COMPLETED_MEDIUM = 3;
|
||||
const int COMPLETED_HARD = 4;
|
||||
const int COMPLETED_BEST = 5;
|
||||
|
||||
/** The constructor is called before anything is attached to the scene node.
|
||||
* So rendering to a texture can be done here. But world is not yet fully
|
||||
@ -83,6 +84,7 @@ RaceGUIOverworld::RaceGUIOverworld()
|
||||
m_trophy1 = irr_driver->getTexture(FileManager::GUI, "cup_bronze.png");
|
||||
m_trophy2 = irr_driver->getTexture(FileManager::GUI, "cup_silver.png");
|
||||
m_trophy3 = irr_driver->getTexture(FileManager::GUI, "cup_gold.png" );
|
||||
m_trophy4 = irr_driver->getTexture(FileManager::GUI, "cup_platinum.png" );
|
||||
|
||||
float scaling = irr_driver->getFrameSize().Height / 420.0f;
|
||||
const float map_size = 250.0f;
|
||||
@ -122,6 +124,7 @@ RaceGUIOverworld::RaceGUIOverworld()
|
||||
|
||||
|
||||
// special case : when 3 players play, use available 4th space for such things
|
||||
// TODO : determine if there are plans for multiplayer in story mode in the future
|
||||
if (race_manager->getIfEmptyScreenSpaceExists())
|
||||
{
|
||||
m_map_left = irr_driver->getActualScreenSize().Width - m_map_width;
|
||||
@ -152,12 +155,15 @@ RaceGUIOverworld::RaceGUIOverworld()
|
||||
|
||||
m_lock = irr_driver->getTexture(FileManager::GUI,"gui_lock.png");
|
||||
m_open_challenge = irr_driver->getTexture(FileManager::GUI,"challenge.png");
|
||||
m_locked_bonus = irr_driver->getTexture(FileManager::GUI,"mystery_unlock.png");
|
||||
|
||||
m_icons[0] = m_lock;
|
||||
m_icons[1] = m_open_challenge;
|
||||
m_icons[2] = m_trophy1;
|
||||
m_icons[3] = m_trophy2;
|
||||
m_icons[4] = m_trophy3;
|
||||
m_icons[5] = m_trophy4;
|
||||
m_icons[6] = m_locked_bonus;
|
||||
} // RaceGUIOverworld
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -179,6 +185,7 @@ void RaceGUIOverworld::renderGlobal(float dt)
|
||||
|
||||
// Special case : when 3 players play, use 4th window to display such
|
||||
// stuff (but we must clear it)
|
||||
//TODO : remove if no story mode multiplayer plans
|
||||
if (race_manager->getIfEmptyScreenSpaceExists() &&
|
||||
!GUIEngine::ModalDialog::isADialogActive())
|
||||
{
|
||||
@ -257,8 +264,11 @@ void RaceGUIOverworld::drawTrophyPoints()
|
||||
#ifndef SERVER_ONLY
|
||||
PlayerProfile *player = PlayerManager::getCurrentPlayer();
|
||||
const int points = player->getPoints();
|
||||
const int next_unlock_points = player->getNextUnlockPoints();
|
||||
std::string s = StringUtils::toString(points);
|
||||
std::string s_goal = StringUtils::toString(next_unlock_points);
|
||||
core::stringw sw(s.c_str());
|
||||
core::stringw swg(s_goal.c_str());
|
||||
|
||||
static video::SColor time_color = video::SColor(255, 255, 255, 255);
|
||||
|
||||
@ -274,7 +284,7 @@ void RaceGUIOverworld::drawTrophyPoints()
|
||||
const int size = irr_driver->getActualScreenSize().Width/20;
|
||||
core::rect<s32> dest(size, pos.UpperLeftCorner.Y,
|
||||
size*2, pos.UpperLeftCorner.Y + size);
|
||||
core::rect<s32> source(core::position2di(0, 0), m_trophy3->getSize());
|
||||
core::rect<s32> source(core::position2di(0, 0), m_trophy4->getSize());
|
||||
|
||||
font->setShadow(video::SColor(255,0,0,0));
|
||||
|
||||
@ -321,17 +331,62 @@ void RaceGUIOverworld::drawTrophyPoints()
|
||||
font->draw(hardTrophiesW.c_str(), dest, time_color, false, vcenter, NULL, true /* ignore RTL */);
|
||||
}
|
||||
|
||||
dest = core::rect<s32>(pos.UpperLeftCorner.X - size - 5, pos.UpperLeftCorner.Y,
|
||||
pos.UpperLeftCorner.X - 5, pos.UpperLeftCorner.Y + size);
|
||||
dest += core::position2di(size*2, 0);
|
||||
if (!m_close_to_a_challenge && !PlayerManager::getCurrentPlayer()->isLocked("difficulty_best"))
|
||||
{
|
||||
draw2DImage(m_trophy4, dest, source, NULL, NULL, true /* alpha */);
|
||||
}
|
||||
dest += core::position2di((int)(size*1.5f), 0);
|
||||
std::string bestTrophies = StringUtils::toString(player->getNumBestTrophies());
|
||||
core::stringw bestTrophiesW(bestTrophies.c_str());
|
||||
if (!m_close_to_a_challenge && !PlayerManager::getCurrentPlayer()->isLocked("difficulty_best"))
|
||||
{
|
||||
font->draw(bestTrophiesW.c_str(), dest, time_color, false, vcenter, NULL, true /* ignore RTL */);
|
||||
}
|
||||
|
||||
dest = core::rect<s32>(pos.UpperLeftCorner.X - size, pos.UpperLeftCorner.Y,
|
||||
pos.UpperLeftCorner.X, pos.UpperLeftCorner.Y + size);
|
||||
|
||||
draw2DImage(m_open_challenge, dest, source, NULL,
|
||||
NULL, true /* alpha */);
|
||||
|
||||
pos.LowerRightCorner.Y = dest.LowerRightCorner.Y;
|
||||
pos.UpperLeftCorner.X += 5;
|
||||
core::dimension2du area = font->getDimension(L"9");
|
||||
int small_width = area.Width;
|
||||
area = font->getDimension(L"99");
|
||||
int middle_width = area.Width;
|
||||
area = font->getDimension(L"999");
|
||||
int large_width = area.Width;
|
||||
|
||||
int number_width;
|
||||
|
||||
if (points < 9) number_width = small_width;
|
||||
else if (points <99) number_width = middle_width;
|
||||
else number_width = large_width;
|
||||
|
||||
pos.LowerRightCorner.Y = dest.LowerRightCorner.Y + 1.5f*size;
|
||||
pos.UpperLeftCorner.X -= (0.5f*size + number_width*0.5f);
|
||||
|
||||
font->draw(sw.c_str(), pos, time_color, false, vcenter, NULL, true /* ignore RTL */);
|
||||
|
||||
pos.UpperLeftCorner.X += (0.5f*size + number_width*0.5f);
|
||||
|
||||
if (next_unlock_points > points && (points + 80) >= next_unlock_points)
|
||||
{
|
||||
if (next_unlock_points < 9) number_width = small_width;
|
||||
else if (next_unlock_points <99) number_width = middle_width;
|
||||
else number_width = large_width;
|
||||
|
||||
dest = core::rect<s32>(pos.UpperLeftCorner.X - 2.5f*size, pos.UpperLeftCorner.Y,
|
||||
pos.UpperLeftCorner.X - 1.5f*size, pos.UpperLeftCorner.Y + size);
|
||||
|
||||
draw2DImage(m_locked_bonus, dest, source, NULL,
|
||||
NULL, true /* alpha */);
|
||||
|
||||
pos.UpperLeftCorner.X -= (2*size + number_width*0.5f);
|
||||
|
||||
font->draw(swg.c_str(), pos, time_color, false, vcenter, NULL, true /* ignore RTL */);
|
||||
}
|
||||
|
||||
font->disableShadow();
|
||||
#endif
|
||||
} // drawTrophyPoints
|
||||
@ -468,7 +523,8 @@ void RaceGUIOverworld::drawGlobalMiniMap()
|
||||
|
||||
const ChallengeStatus* c = PlayerManager::getCurrentPlayer()
|
||||
->getChallengeStatus(challenges[n].m_challenge_id);
|
||||
if (c->isSolved(RaceManager::DIFFICULTY_HARD)) state = COMPLETED_HARD;
|
||||
if (c->isSolved(RaceManager::DIFFICULTY_BEST)) state = COMPLETED_BEST;
|
||||
else if (c->isSolved(RaceManager::DIFFICULTY_HARD)) state = COMPLETED_HARD;
|
||||
else if (c->isSolved(RaceManager::DIFFICULTY_MEDIUM)) state = COMPLETED_MEDIUM;
|
||||
else if (c->isSolved(RaceManager::DIFFICULTY_EASY)) state = COMPLETED_EASY;
|
||||
|
||||
@ -622,4 +678,3 @@ void RaceGUIOverworld::drawGlobalMiniMap()
|
||||
} // drawGlobalMiniMap
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
@ -65,10 +65,13 @@ private:
|
||||
video::ITexture *m_trophy1;
|
||||
video::ITexture *m_trophy2;
|
||||
video::ITexture *m_trophy3;
|
||||
video::ITexture *m_trophy4;
|
||||
video::ITexture *m_lock;
|
||||
video::ITexture *m_open_challenge;
|
||||
video::ITexture *m_locked_bonus;
|
||||
|
||||
video::ITexture* m_icons[5];
|
||||
|
||||
video::ITexture* m_icons[7];
|
||||
|
||||
/** The size of a single marker on the screen for AI karts,
|
||||
* need not be a power of 2. */
|
||||
|
@ -298,15 +298,13 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget,
|
||||
bool gameCompleted = false;
|
||||
for (unsigned int n = 0; n < unlocked.size(); n++)
|
||||
{
|
||||
if (unlocked[n]->getId() == "fortmagma")
|
||||
if (unlocked[n]->getChallengeId() == "fortmagma")
|
||||
{
|
||||
gameCompleted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PlayerManager::getCurrentPlayer()->clearUnlocked();
|
||||
|
||||
if (gameCompleted)
|
||||
{
|
||||
// clear the race
|
||||
@ -343,8 +341,8 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget,
|
||||
FeatureUnlockedCutScene* scene =
|
||||
FeatureUnlockedCutScene::getInstance();
|
||||
|
||||
scene->addTrophy(race_manager->getDifficulty());
|
||||
scene->findWhatWasUnlocked(race_manager->getDifficulty());
|
||||
scene->addTrophy(race_manager->getDifficulty(),false);
|
||||
scene->findWhatWasUnlocked(race_manager->getDifficulty(),unlocked);
|
||||
scene->push();
|
||||
race_manager->setAIKartOverride("");
|
||||
|
||||
@ -352,6 +350,9 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget,
|
||||
parts.push_back("featunlocked");
|
||||
((CutsceneWorld*)World::getWorld())->setParts(parts);
|
||||
}
|
||||
|
||||
PlayerManager::getCurrentPlayer()->clearUnlocked();
|
||||
|
||||
return;
|
||||
}
|
||||
Log::warn("RaceResultGUI", "Incorrect event '%s' when things are unlocked.",
|
||||
|
Loading…
Reference in New Issue
Block a user