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:
Alayan-stk-2 2018-04-30 00:27:03 +02:00 committed by auriamg
parent a2659f479c
commit 6a25384ed9
55 changed files with 837 additions and 307 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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"/>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View 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>

View 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>

View 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>

View 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>

View File

@ -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>

View File

@ -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>

View File

@ -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"/>

View File

@ -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" />

View File

@ -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>

View File

@ -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>

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
data/gui/mystery_unlock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -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>

View 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>

View File

@ -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

View File

@ -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

View File

@ -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";

View File

@ -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; }

View File

@ -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);

View File

@ -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; }
// ------------------------------------------------------------------------

View File

@ -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 */

View File

@ -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);

View File

@ -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()
{

View File

@ -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

View File

@ -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);
}
}

View File

@ -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
}
// ----------------------------------------------------------------------------

View File

@ -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
// ----------------------------------------------------------------------------

View File

@ -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

View File

@ -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();
}

View File

@ -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
//-----------------------------------------------------------------------------

View File

@ -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. */

View File

@ -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.",