C:/DevKitPro/!MDuel/source/menuBottom.cpp

Go to the documentation of this file.
00001 /*
00002  * Marshmallow Duel DS v2
00003  * Copyright © 2007 Sam Pospischil http://pospi.spadgos.com
00004  * 
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  * 
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  * GNU General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
00018  */
00019 
00020 #include "menuBottom.h"
00021 #include "spriteObject.h"
00022 #include "gameManager.h"
00023 
00024 const char *menuBottom::_SRAMID = "MDUEL";
00025 
00031 menuBottom::menuBottom(u8 newScreen) : spriteManager(newScreen), menuTop(NULL), gameBottom(NULL), gameTop(NULL), 
00032         playerPallete1(NULL), playerPallete2(NULL), playerPallete3(NULL), playerPallete4(NULL), 
00033         playerSprite1(NULL), playerSprite2(NULL), playerSprite3(NULL),
00034         navFunction(NULL), renderFunction(NULL), actionFunction(NULL),
00035         playerPal1(0), playerPal2(0), playerPal3(0), playerPal4(0),
00036         editingName(0), selectedItem(0), menuColSize(0), cursor(NULL), selectedItem2(0), settingsPlayer(0), 
00037         settingsPage(0), menuRepeater(0)
00038 {
00039         
00040 }
00041         
00042 menuBottom::~menuBottom()
00043 {
00044         
00045 }
00046 
00056 void menuBottom::gameTick()
00057 {
00058         spriteManager::gameTick();
00059 
00060         #ifdef __WITHSOUND
00061         u8 oldSelItem = selectedItem;
00062         #endif
00063         
00064         //stylus input
00065         bool stylusActivated = false;
00066         bool stylusTouched = false;
00067         
00068         if (Stylus.Newpress)
00069         {
00070                 s8 touchedItem = touchingWhichItem(Stylus.X, Stylus.Y);
00071                 if (touchedItem == selectedItem) {
00072                         stylusActivated = true;
00073                 }
00074                 if (touchedItem != -1) {
00075                         selectedItem = touchedItem;
00076                                 //selectedItem2 for stats can suck my balls
00077                         stylusTouched = true;
00078                 }
00079         }
00080         
00081         //button navigation
00082         if (navFunction != NULL)
00083                 (this->*navFunction)();
00084 
00085         #ifdef __WITHSOUND
00086         if (oldSelItem != selectedItem)
00087                 playSound(menuMove.data, menuMove.size);
00088         #endif
00089         
00090         //cursor display
00091         if (cursor != NULL)
00092         {
00093                 cursor->setPos(menuItems[selectedItem].cursorx, menuItems[selectedItem].cursory);
00094                 if (selectedItem > menuColSize-1 && menuColSize != 0)
00095                         cursor->setFrame(2);
00096                 else
00097                         cursor->setFrame(1);
00098         }
00099         //rendering
00100         for (u8 i=0; i < menuItems.size(); ++i)
00101         {
00102                 normalRender(i);
00103                 if (renderFunction != NULL)
00104                         (this->*renderFunction)(i);
00105         }
00106         
00107         //actions
00108         if (actionFunction != NULL)
00109                 (this->*actionFunction)(stylusTouched, stylusActivated);
00110         
00111         if (menuRepeater == 0)
00112                 menuRepeater = menuRepeatDelay;
00113         menuRepeater--;
00114 }
00115 
00116 //========================================================================================================
00117 //========================================================================================================
00118 
00120 void menuBottom::normalNav()
00121 {
00122         if (Pad.Newpress.Up)
00123                 --selectedItem;
00124         else if (Pad.Newpress.Down)
00125                 ++selectedItem;
00126         else if (Pad.Newpress.Left && menuColSize > 0)
00127                 selectedItem -= menuColSize;
00128         else if (Pad.Newpress.Right && menuColSize > 0)
00129                 selectedItem += menuColSize;
00130         if (selectedItem < 0)
00131                 (menuColSize > 0 ? selectedItem += menuColSize*2 : selectedItem = menuItems.size()-1);
00132         selectedItem %= menuItems.size();
00133 }
00135 void menuBottom::statsNav()
00136 {
00137         #ifdef __WITHSOUND
00138         u8 oldSelectedItem2 = selectedItem2;
00139         #endif
00140 
00141         if (Pad.Newpress.Up)
00142                 --selectedItem;
00143         else if (Pad.Newpress.Down)
00144                 ++selectedItem;
00145         else if (Pad.Newpress.Left)
00146                 --selectedItem2;
00147         else if (Pad.Newpress.Right)
00148                 ++selectedItem2;
00149         //hacked at 6 'cos we only want that column 'navigable'
00150         if (selectedItem < 0)
00151                 selectedItem = 6;
00152         else if (selectedItem > 6)
00153                 selectedItem = 0;                       
00154         //hacked at 4 'cos we only want that much 'navigable'. ITS A BIG HACK ANYWAY GAWD
00155         if (selectedItem2 < 0)
00156                 selectedItem2 = 3;
00157         else if (selectedItem2 > 3)
00158                 selectedItem2 = 0;
00159         //general stats has no 4th selectedItem2
00160         if (selectedItem == 0 && selectedItem2 == 3)
00161                 selectedItem2 = 0;
00162         drawStatsFor(selectedItem, selectedItem2);
00163 
00164         #ifdef __WITHSOUND
00165         if (oldSelectedItem2 != selectedItem2)
00166                 playSound(menuMove.data, menuMove.size);
00167         #endif
00168 }
00170 void menuBottom::miscNav()
00171 {
00172         if (Pad.Newpress.Up)
00173                 --selectedItem;
00174         else if (Pad.Newpress.Down)
00175                 ++selectedItem;
00176         if (selectedItem < 0)
00177                 (menuColSize > 0 ? selectedItem += menuColSize*2 : selectedItem = menuItems.size()-1);
00178         selectedItem %= menuItems.size();
00179 }
00181 void menuBottom::charNav()
00182 {
00183         if (Pad.Newpress.Up)
00184                 --selectedItem;
00185         else if (Pad.Newpress.Down)
00186                 ++selectedItem;
00187         else if (Pad.Newpress.Left)
00188         {
00189                 #ifdef __WITHSOUND
00190                 playSound(menuMove.data, menuMove.size);
00191                 #endif
00192                 selectPlayer(selectedItem, 1);
00193         } else if (Pad.Newpress.Right)
00194         {
00195                 #ifdef __WITHSOUND
00196                 playSound(menuMove.data, menuMove.size);
00197                 #endif
00198                 selectPlayer(selectedItem, 2);
00199         }
00200         if (selectedItem < 0)
00201                 (menuColSize > 0 ? selectedItem += menuColSize*2 : selectedItem = menuItems.size()-1);
00202         selectedItem %= menuItems.size();
00203         
00204         if (playerPals[player1id-1] == playerPals[player2id-1])         //stops same colour happening for both characters
00205                 playerColorCycle(selectedItem);
00206 }
00208 void menuBottom::charNameNav()
00209 {
00210         if (Pad.Held.Up && menuRepeater == 0 || Pad.Newpress.Up)
00211         {
00212                 #ifdef __WITHSOUND
00213                 playSound(menuMove.data, menuMove.size);
00214                 #endif
00215                 alterPlayerName(editingName, selectedItem, -1);
00216         } else if (Pad.Held.Down && menuRepeater == 0 || Pad.Newpress.Down)
00217         {
00218                 #ifdef __WITHSOUND
00219                 playSound(menuMove.data, menuMove.size);
00220                 #endif
00221                 alterPlayerName(editingName, selectedItem, 1);
00222         }
00223         else if (Pad.Newpress.Left)
00224                 --selectedItem;
00225         else if (Pad.Newpress.Right)
00226                 ++selectedItem;
00227         if (selectedItem < 0)
00228                 selectedItem = menuItems.size()-1;
00229         selectedItem %= menuItems.size();
00230         PA_OutputText(screen, 12, 9, "________\n%s\n--------", macros::getPlayerName(editingName, playerNames, false).c_str());
00231 }
00233 void menuBottom::roundsNav()
00234 {
00235         if ((Pad.Held.Up && menuRepeater == 0 || Pad.Newpress.Up) && roundNum < 50)
00236         {
00237                 #ifdef __WITHSOUND
00238                 playSound(menuMove.data, menuMove.size);
00239                 #endif
00240                 ++roundNum;
00241         } else if ((Pad.Held.Down && menuRepeater == 0 || Pad.Newpress.Down) && roundNum > 1)
00242         {
00243                 #ifdef __WITHSOUND
00244                 playSound(menuMove.data, menuMove.size);
00245                 #endif
00246                 --roundNum;
00247         }
00248         PA_OutputText(screen, 14, 10, "-%d-  ", roundNum);
00249         gameTop->pointsToWin = roundNum;
00250 }
00251 
00256 void menuBottom::normalRender(u8 i)
00257 {
00258         if (menuItems[i].text != "")
00259                 PA_OutputSimpleText(screen, menuItems[i].textx, menuItems[i].texty, const_cast<char*>(menuItems[i].text.c_str()));
00260         if (menuItems[i].obj != NULL)
00261                 menuItems[i].obj->setPos(menuItems[i].objx, menuItems[i].objy);
00262 }
00267 void menuBottom::statsRender(u8 i)
00268 {
00269         if (i > 6)              //first six are normal menu items
00270         {
00271                 if (selectedItem == 0 && i==10)         //no player, dont show deaths
00272                         PA_OutputSimpleText(screen, menuItems[i].textx, menuItems[i].texty, "      ");
00273                 if (selectedItem2 == i-7)
00274                         menuItems[i].obj->setPos(menuItems[i].objx, menuItems[i].objy); //show cursor
00275                 else
00276                         menuItems[i].obj->setPos(OFFX, OFFY);   //hide cursor
00277         }
00278 }
00283 void menuBottom::pickupsRender(u8 i)
00284 {
00285         //cursor points the opposite way in the pickups menu.
00286         //this need only be executed once but this is really the best way to do it anyway.
00287         if (cursor != NULL)
00288         {
00289                 if (selectedItem > menuColSize-1 && menuColSize != 0)
00290                         cursor->setFrame(1);
00291                 else
00292                         cursor->setFrame(2);
00293         }
00294 
00295         if (pickupSelected(i))
00296                 menuItems[i].obj2->setPos(menuItems[i].objx, menuItems[i].objy);
00297         else
00298                 menuItems[i].obj2->setPos(OFFX, OFFY);
00299 }
00304 void menuBottom::charRender(u8 i)
00305 {
00306         if (i == (u8)(player1id-1))
00307         {
00308                 menuItems[i].obj->setFrame(0);
00309                 menuItems[i].obj->setPos(120, menuItems[i].obj->gety());
00310         } else if (i == (u8)(player2id-1))
00311         {
00312                 menuItems[i].obj->setFrame(0);
00313                 menuItems[i].obj->setPos(224, menuItems[i].obj->gety());
00314         } else
00315         {
00316                 menuItems[i].obj->setFrame(6);
00317                 menuItems[i].obj->setPos(172, menuItems[i].obj->gety());
00318         }
00319 }
00324 void menuBottom::charNameRender(u8 i)
00325 {
00326         if (cursor != NULL && cursor->getFrame() != 0)
00327                 cursor->setFrame(0);
00328 }
00329 
00335 void menuBottom::mainAction(bool stylusTouched, bool stylusActivated)
00336 {
00337         #ifdef __WITHSOUND
00338         if (Pad.Released.A || stylusTouched)
00339                 playSound(menuOk.data, menuOk.size);
00340         #endif
00341         switch (selectedItem)
00342         {
00343                 case 0:         //start 2P game
00344                         #ifdef __MDDEBUG //file logging seems to slow the menu down to the point where button hits dont register
00345                         if (Pad.Held.A || stylusTouched)
00346                         #else
00347                         if (Pad.Released.A || stylusTouched)
00348                         #endif
00349                         {
00350                                 menuTop->deactivate();
00351                                 deactivate();
00352                                 PA_WaitForVBL();
00353                                 gameTop->activate();
00354                                 for (u8 i=0; i < _NUMPICKUPS; ++i)
00355                                 {
00356                                         if (pickupSelected(i))
00357                                                 gameTop->pickupMask.push_back(i);
00358                                 }
00359                                 gameTop->pointsToWin = roundNum;
00360                                 loadPlayerGFX(player1id, 1);
00361                                 loadPlayerGFX(player2id, 2);
00362                                 gameBottom->activate();
00363                         }
00364                 break;
00365                 case 1:         //select characters
00366                         if (Pad.Released.A || stylusTouched)
00367                                 characterMenu();
00368                 break;
00369                 case 2:         //choose pickups
00370                         if (Pad.Released.A || stylusTouched)
00371                                 pickupMenu();
00372                 break;
00373                 case 3:         //set kill limit
00374                         if (Pad.Released.A || stylusTouched)
00375                                 roundsMenu();
00376                 break;
00377                 case 4:         //misc options
00378                         if (Pad.Released.A || stylusTouched)
00379                                 miscMenu();
00380                 break;
00381                 case 5:         //statistics
00382                         if (Pad.Released.A || stylusTouched)
00383                                 statsMenu();
00384                 break;
00385                 case 6:         //view controls
00386                         if (Pad.Released.A || stylusTouched)
00387                                 controlsMenu();
00388                 break;
00389                 case 7:         //credits
00390                         if (Pad.Released.A || stylusTouched)
00391                                 creditsMenu();
00392                 break;
00393                 default:
00394                 break;
00395         }
00396 }
00402 void menuBottom::charAction(bool stylusTouched, bool stylusActivated)
00403 {
00404         if (Pad.Released.A)
00405         {
00406                 #ifdef __WITHSOUND
00407                 playSound(menuOk.data, menuOk.size);
00408                 #endif
00409                 saveSRAM(false, 1);
00410         } else if (Pad.Released.B) {
00411                 #ifdef __WITHSOUND
00412                 playSound(menuCancel.data, menuCancel.size);
00413                 #endif
00414                 loadSRAM();
00415                 mainMenu(1);
00416         } else if (Pad.Released.X || stylusActivated) {
00417                 #ifdef __WITHSOUND
00418                 playSound(menuOk.data, menuOk.size);
00419                 #endif
00420                 editingName = selectedItem+1;   //used by renameMenu to work out which name to modify
00421                 playerRenameMenu(selectedItem);
00422         } else if (Pad.Released.R) {
00423                 #ifdef __WITHSOUND
00424                 playSound(menuMove.data, menuMove.size);
00425                 #endif
00426                 playerColorCycle(selectedItem);
00427         } else if (Pad.Released.L) {
00428                 #ifdef __WITHSOUND
00429                 playSound(menuMove.data, menuMove.size);
00430                 #endif
00431                 playerGFXCycle(selectedItem);
00432         }
00433 }
00439 void menuBottom::pickupsAction(bool stylusTouched, bool stylusActivated)
00440 {
00441         if (Pad.Released.A)
00442         {
00443                 #ifdef __WITHSOUND
00444                 playSound(menuOk.data, menuOk.size);
00445                 #endif
00446                 saveSRAM(false, 2);
00447         } else if (Pad.Released.B) {
00448                 #ifdef __WITHSOUND
00449                 playSound(menuCancel.data, menuCancel.size);
00450                 #endif
00451                 loadSRAM();
00452                 mainMenu(2);
00453         } else if (Pad.Released.X || stylusTouched) {
00454                 #ifdef __WITHSOUND
00455                 playSound(menuMove.data, menuMove.size);
00456                 #endif
00457                 pickupToggle(selectedItem);
00458         }
00459 }
00465 void menuBottom::roundsAction(bool stylusTouched, bool stylusActivated)
00466 {
00467         if (Pad.Released.A)
00468         {
00469                 #ifdef __WITHSOUND
00470                 playSound(menuOk.data, menuOk.size);
00471                 #endif
00472                 saveSRAM(false, 3);
00473         } else if (Pad.Released.B) {
00474                 #ifdef __WITHSOUND
00475                 playSound(menuCancel.data, menuCancel.size);
00476                 #endif
00477                 loadSRAM();
00478                 mainMenu(3);
00479         }
00480 }
00486 void menuBottom::sramAction(bool stylusTouched, bool stylusActivated)
00487 {
00488         if (Pad.Released.A || Stylus.Newpress)
00489         {
00490                 #ifdef __WITHSOUND
00491                 playSound(menuOk.data, menuOk.size);
00492                 #endif
00493                 saveSRAM(true);
00494         } else if (Pad.Released.B) {
00495                 #ifdef __WITHSOUND
00496                 playSound(menuCancel.data, menuCancel.size);
00497                 #endif
00498                 mainMenu(0);
00499         }
00500 }
00506 void menuBottom::controlsAction(bool stylusTouched, bool stylusActivated)
00507 {
00508         if (Pad.Released.A || Stylus.Newpress)
00509         {
00510                 #ifdef __WITHSOUND
00511                 playSound(menuCancel.data, menuCancel.size);
00512                 #endif
00513                 resetBackground();
00514                 resetText();
00515                 mainMenu(6);
00516         }
00517 }
00523 void menuBottom::charNameAction(bool stylusTouched, bool stylusActivated)
00524 {
00525         if (Pad.Released.A)
00526         {
00527                 #ifdef __WITHSOUND
00528                 playSound(menuOk.data, menuOk.size);
00529                 #endif
00530                 erasePlayer(editingName);
00531                 characterMenu();
00532         } else if (Pad.Released.B) {
00533                 #ifdef __WITHSOUND
00534                 playSound(menuCancel.data, menuCancel.size);
00535                 #endif
00536                 loadSRAM();
00537                 characterMenu();
00538         }
00539 }
00545 void menuBottom::creditsAction(bool stylusTouched, bool stylusActivated)
00546 {
00547         if (Pad.Released.A || Stylus.Newpress)
00548         {
00549                 #ifdef __WITHSOUND
00550                 playSound(menuCancel.data, menuCancel.size);
00551                 #endif
00552                 mainMenu(7);
00553         }
00554 }
00560 void menuBottom::miscAction(bool stylusTouched, bool stylusActivated)
00561 {
00562         s8 temp;
00563 
00564         if (Pad.Newpress.Left || Pad.Newpress.Right)
00565         {
00566                 #ifdef __WITHSOUND
00567                 playSound(menuMove.data, menuMove.size);
00568                 #endif
00569                 switch (selectedItem)
00570                 {
00571                         case 0:
00572                                 temp = numPickups;
00573                                 temp += Pad.Newpress.Right-Pad.Newpress.Left;
00574                                 numPickups = temp > MAXPICKUPSONSCREEN ? MAXPICKUPSONSCREEN : (temp < 0 ? 0 : temp);
00575                                 char data[24];
00576                                 sprintf(data, "Max pickups: %d  ", numPickups);
00577                                 menuItems[selectedItem].text = data;
00578                         break;
00579                         case 1:
00580                                 showPickups = !showPickups;
00581                                 strcpy(data, "Pre-show pickups: ");
00582                                 strcat(data, (showPickups ? "ON " : "OFF"));
00583                                 menuItems[selectedItem].text = data;
00584                         break;
00585                         case 2:
00586                                 dieWhileDancing = !dieWhileDancing;
00587                                 strcpy(data, "Die while dancing: ");
00588                                 strcat(data, (dieWhileDancing ? "ON " : "OFF"));
00589                                 menuItems[selectedItem].text = data;
00590                         break;
00591                 }
00592         }
00593         if (Pad.Released.A)
00594         {
00595                 #ifdef __WITHSOUND
00596                 playSound(menuOk.data, menuOk.size);
00597                 #endif
00598                 saveSRAM(false, 4);
00599         }
00600         else if (Pad.Released.B) {
00601                 #ifdef __WITHSOUND
00602                 playSound(menuCancel.data, menuCancel.size);
00603                 #endif
00604                 loadSRAM();
00605                 mainMenu(4);
00606         }
00607 }
00613 void menuBottom::statsAction(bool stylusTouched, bool stylusActivated)
00614 {
00615         if (Pad.Released.A)
00616         {
00617                 #ifdef __WITHSOUND
00618                 playSound(menuCancel.data, menuCancel.size);
00619                 #endif
00620                 mainMenu(5);
00621         }
00622 }
00623 
00624 //========================================================================================================
00625 //========================================================================================================
00626 
00630 void menuBottom::loadBackground()
00631 {
00632         PA_EasyBgLoad(screen, 3, ::menuBGbottom);
00633 }
00634 
00639 void menuBottom::clearOutSprites(bool keepSound)
00640 {
00641         cursorSprite.palleteID = -1;
00642         pickupSprite.palleteID = -1;
00643         menuSprite.palleteID = -1;
00644         spriteManager::clearOutSprites(keepSound);
00645 }
00646 
00647 //============================================================================
00648 
00650 void menuBottom::loadCursorSpriteSet(const unsigned short *p, const unsigned char *s)
00651 {
00652         loadSpriteSet(&cursorSprite, p, s);
00653 }
00654 
00656 void menuBottom::loadPickupSpriteSet(const unsigned short *p, const unsigned char *s)
00657 {
00658         loadSpriteSet(&pickupSprite, p, s);
00659 }
00660 
00662 void menuBottom::loadMenuSpriteSet(const unsigned short *p, const unsigned char *s)
00663 {
00664         loadSpriteSet(&menuSprite, p, s);
00665 }
00666 
00667 //============================================================================
00668 
00674 void menuBottom::clearMenus()
00675 {
00676         menuItems.clear();
00677         PA_WaitForVBL();
00678         //PA_ClearTextBg(screen);
00679         clearOutSprites(true);
00680         PA_WaitForVBL();
00681         resetText();
00682         PA_WaitForVBL();
00683         loadBackground();
00684         loadCursorSpriteSet(cursorSprite.palleteData, cursorSprite.spriteData);
00685         loadMenuSpriteSet(menuSprite.palleteData, menuSprite.spriteData);
00686         PA_WaitForVBL();
00687         makeCursor();
00688         selectedItem = 0;
00689         selectedItem2 = 0;
00690         navFunction = &menuBottom::normalNav;
00691         renderFunction = NULL;
00692         actionFunction = NULL;
00693 }
00694 
00698 void menuBottom::makeCursor()
00699 {
00700         cursor = new spriteObject(this);
00701         cursor->setPallete(cursorSprite.palleteID);
00702         cursor->giveSprite(cursorSprite.spriteData, OBJ_SIZE_16X16, 8, 8);
00703         cursor->setLayer(0);
00704         cursor->setFrame(1);
00705 }
00706 
00707 //============================================================================
00708 
00714 void menuBottom::mainMenu(u8 prevScreen)
00715 {
00716         clearMenus();
00717         actionFunction = &menuBottom::mainAction;
00718         menuColSize = 0;
00719         selectedItem = prevScreen;
00720         struct menuItem temp1 = {60, 28, 9, 3, "Start 2P Game", 0,0,NULL,NULL};
00721         menuItems.push_back(temp1);
00722         struct menuItem temp2 = {44, 52, 7, 6, "Select Characters", 0,0,NULL,NULL};
00723         menuItems.push_back(temp2);
00724         struct menuItem temp3 = {60, 68, 9, 8, "Choose Pickups", 0,0,NULL,NULL};
00725         menuItems.push_back(temp3);
00726         struct menuItem temp4 = {60, 84, 9, 10, "Set Kill Limit", 0,0,NULL,NULL};
00727         menuItems.push_back(temp4);
00728         struct menuItem temp7 = {68, 100, 10, 12, "Misc Options", 0,0,NULL,NULL};
00729         menuItems.push_back(temp7);
00730         struct menuItem temp8 = {76, 124, 11, 15, "Statistics", 0,0,NULL,NULL};
00731         menuItems.push_back(temp8);
00732         struct menuItem temp5 = {60, 140, 9, 17, "View Controls", 0,0,NULL,NULL};
00733         menuItems.push_back(temp5);
00734         struct menuItem temp6 = {68, 156, 10, 19, "View Credits", 0,0,NULL,NULL};
00735         menuItems.push_back(temp6);
00736         
00737         autoMenuClickRegions();
00738         
00739         //instructions
00740         makeInstructions(0, 128);
00741 }
00742 
00744 void menuBottom::characterMenu()
00745 {
00746         clearMenus();
00747         navFunction = &menuBottom::charNav;
00748         renderFunction = &menuBottom::charRender;
00749         actionFunction = &menuBottom::charAction;
00750         menuColSize = 0;
00751         
00752         playerPal1 = loadPallete((void*)playerPallete1);
00753         playerPal2 = loadPallete((void*)playerPallete2);
00754         playerPal3 = loadPallete((void*)playerPallete3);
00755         playerPal4 = loadPallete((void*)playerPallete4);
00756                 
00757         spriteObject *playerSpr1 = new spriteObject(this);
00758         playerSpr1->setPallete(getPlayerPalleteID(playerPals[0]));
00759         playerSpr1->giveSprite(getPlayerSpriteData(playerSprs[0]), OBJ_SIZE_32X32, 16, 16);
00760         spriteObject *playerSpr2 = new spriteObject(this);
00761         playerSpr2->setPallete(getPlayerPalleteID(playerPals[1]));
00762         playerSpr2->giveSprite(getPlayerSpriteData(playerSprs[1]), OBJ_SIZE_32X32, 16, 16);
00763         spriteObject *playerSpr3 = new spriteObject(this);
00764         playerSpr3->setPallete(getPlayerPalleteID(playerPals[2]));
00765         playerSpr3->giveSprite(getPlayerSpriteData(playerSprs[2]), OBJ_SIZE_32X32, 16, 16);
00766         spriteObject *playerSprA = new spriteObject(this);
00767         playerSprA->setPallete(getPlayerPalleteID(playerPals[3]));
00768         playerSprA->giveSprite(getPlayerSpriteData(playerSprs[3]), OBJ_SIZE_32X32, 16, 16);
00769         //playerSprA->setFlipped(true);
00770         spriteObject *playerSprB = new spriteObject(this);
00771         playerSprB->setPallete(getPlayerPalleteID(playerPals[4]));
00772         playerSprB->giveSprite(getPlayerSpriteData(playerSprs[4]), OBJ_SIZE_32X32, 16, 16);
00773         //playerSprB->setFlipped(true);
00774         spriteObject *playerSprC = new spriteObject(this);
00775         playerSprC->setPallete(getPlayerPalleteID(playerPals[5]));
00776         playerSprC->giveSprite(getPlayerSpriteData(playerSprs[5]), OBJ_SIZE_32X32, 16, 16);
00777         //playerSprC->setFlipped(true);
00778         
00779         struct menuItem temp1 = {12, 36, 3, 4, macros::getPlayerName(1, playerNames, false).c_str(), 172, 36, playerSpr1, NULL};
00780         menuItems.push_back(temp1);
00781         struct menuItem temp2 = {12, 60, 3, 7, macros::getPlayerName(2, playerNames, false).c_str(), 172, 60, playerSpr2, NULL};
00782         menuItems.push_back(temp2);
00783         struct menuItem temp3 = {12, 84, 3, 10, macros::getPlayerName(3, playerNames, false).c_str(), 172, 84, playerSpr3, NULL};
00784         menuItems.push_back(temp3);
00785         struct menuItem tempA = {12, 108, 3, 13, macros::getPlayerName(4, playerNames, false).c_str(), 172, 108, playerSprA, NULL};
00786         menuItems.push_back(tempA);
00787         struct menuItem tempB = {12, 132, 3, 16, macros::getPlayerName(5, playerNames, false).c_str(), 172, 132, playerSprB, NULL};
00788         menuItems.push_back(tempB);
00789         struct menuItem tempC = {12, 156, 3, 19, macros::getPlayerName(6, playerNames, false).c_str(), 172, 156, playerSprC, NULL};
00790         menuItems.push_back(tempC);
00791         
00792         autoMenuClickRegions();
00793         
00794         //heading
00795         PA_OutputSimpleText(screen, 14, 1, "P1    OFF    P2");
00796         
00797         //instructions
00798         makeInstructions(5, 32);
00799         makeInstructions(1, 96);
00800         makeInstructions(2, 160);
00801         makeInstructions(3, 224);
00802 }
00803 
00805 void menuBottom::pickupMenu()
00806 {
00807         clearMenus();
00808         renderFunction = &menuBottom::pickupsRender;
00809         actionFunction = &menuBottom::pickupsAction;
00810         menuColSize = 9;
00811         loadPickupSpriteSet(pickupSprite.palleteData, pickupSprite.spriteData);
00812         
00813         makePickupIcon("Skull", 0, 84, 12);
00814         makePickupIcon("1000V", 1, 84, 28);
00815         makePickupIcon("Invisibility", 2, 140, 44);
00816         makePickupIcon("Mine", 3, 76, 60);
00817         makePickupIcon("Gun", 4, 68, 76);
00818         makePickupIcon("TNT", 5, 68, 92);
00819         makePickupIcon("Boots", 6, 84, 108);
00820         makePickupIcon("Grenade", 7, 100, 124);
00821         makePickupIcon("Puck", 8, 76, 140);
00822         makePickupIcon("Parachut", 9, 148, 12);
00823         makePickupIcon("Hook", 10, 180, 28);
00824         makePickupIcon("Warp", 11, 180, 44);
00825         makePickupIcon("Magnet", 12, 164, 60);
00826         makePickupIcon("Net", 13, 188, 76);
00827         makePickupIcon("Shield", 14, 164, 92);
00828         makePickupIcon("Dunce Hat", 15, 140, 108);      
00829         makePickupIcon("Weasel", 16, 164, 124); 
00830         makePickupIcon("Boomerang", 17, 140, 140);
00831         
00832         autoMenuClickRegions();
00833         
00834         //instructions
00835         makeInstructions(5, 96);
00836         makeInstructions(4, 160);
00837 }
00838 
00847 void menuBottom::makePickupIcon(string text, u8 num, u16 curx, u16 cury)
00848 {
00849         spriteObject *icon = new spriteObject(this);
00850         icon->setPallete(pickupSprite.palleteID);
00851         icon->giveSprite(pickupSprite.spriteData, OBJ_SIZE_16X16, 8, 8);
00852         icon->setFrame(num+3);
00853         spriteObject *icons = new spriteObject(this);
00854         icons->setPallete(pickupSprite.palleteID);
00855         icons->giveSprite(pickupSprite.spriteData, OBJ_SIZE_16X16, 8, 8);
00856         icons->setAnim(0,2,spriteObject::ANIMSPEED);
00857         
00858         if (num < 9)
00859         {
00860                 struct menuItem temp = {curx, cury, 4, 1+num*2, text, 20, ((num+1)*16)-4, icon, icons};
00861                 menuItems.push_back(temp);
00862         }
00863         else {
00864                 struct menuItem temp = {curx, cury, 28-text.length(), 1+(num-9)*2, text, 236, ((num-8)*16)-4, icon, icons};
00865                 menuItems.push_back(temp);
00866         }
00867 }
00868 
00875 void menuBottom::makeInstructions(u8 frame, u8 xpos)
00876 {
00877         spriteObject *temp = new spriteObject(this);
00878         temp->setPallete(menuSprite.palleteID);
00879         temp->giveSprite(menuSprite.spriteData, OBJ_SIZE_64X32, 32, 16, 0, xpos, 192-8);
00880         temp->setLayer(0);
00881         temp->setFrame(frame);
00882         temp->makeStatic();
00883 }
00884 
00892 bool menuBottom::pickupSelected(u8 pickupID)
00893 {
00894         u32 pickupNum = 1<<pickupID;
00895         return pickupMask & pickupNum;
00896 }
00897 
00899 void menuBottom::roundsMenu()
00900 {
00901         clearMenus();
00902         navFunction = &menuBottom::roundsNav;
00903         actionFunction = &menuBottom::roundsAction;
00904         menuColSize = 0;
00905         
00906         PA_OutputText(screen, 4, 4, "First player to reach\nthis many points wins:");
00907         
00908         cursor->destroy();
00909         cursor = NULL;
00910         
00911         //instructions
00912         makeInstructions(5, 96);
00913         makeInstructions(6, 160);
00914 }
00915 
00917 void menuBottom::saveWarningMenu()
00918 {
00919         clearMenus();
00920         actionFunction = &menuBottom::sramAction;
00921         menuColSize = 0;
00922         PA_OutputText(screen, 2, 4, " WARNING: SRAM has not been\n\nformatted for this game yet.\n\n\n\n\n\n\n  Overwrite SRAM Save Data?");
00923         
00924         cursor->destroy();
00925         cursor = NULL;
00926         
00927         //instructions
00928         makeInstructions(0, 128);
00929 }
00930 
00932 void menuBottom::controlsMenu()
00933 {
00934         resetBackground();
00935         clearMenus();
00936         actionFunction = &menuBottom::controlsAction;
00937         menuColSize = 0;
00938         
00939         cursor->destroy();
00940         cursor = NULL;
00941         
00942         //dont need to set video mode for this one :D
00943         PA_EasyBgLoad(screen, 3, ::controlsBG);
00944         
00945         //instructions
00946         makeInstructions(7, 224);
00947 }
00948 
00950 void menuBottom::creditsMenu()
00951 {
00952         clearMenus();
00953         actionFunction = &menuBottom::creditsAction;
00954         menuColSize = 0;
00955         
00956         cursor->destroy();
00957         cursor = NULL;
00958         
00959         PA_OutputText(screen, 2, 2, "    Marshmallow Duel DS\n\nby pospi - pospi.spadgos.com\n\n\n Based on Marshmallow Duel\n     created in 1996\n  by Duncan and Roger Gill\n\n     Sounds and music by\n       Liam Alexander\n\n Special thanks to Sam and\nMoles for their beta-testing\n      help and support.");
00960         
00961         //instructions
00962         makeInstructions(7, 128);
00963 }
00964 
00970 void menuBottom::playerRenameMenu(u8 playerID)
00971 {
00972         clearMenus();
00973         navFunction = &menuBottom::charNameNav;
00974         renderFunction = &menuBottom::charNameRender;
00975         actionFunction = &menuBottom::charNameAction;
00976         menuColSize = 0;
00977         
00978         struct menuItem temp1 = {100, 84, 0, 0, "", 0, 0, NULL, NULL};
00979         menuItems.push_back(temp1);
00980         struct menuItem temp2 = {108, 84, 0, 0, "", 0, 0, NULL, NULL};
00981         menuItems.push_back(temp2);
00982         struct menuItem temp3 = {116, 84, 0, 0, "", 0, 0, NULL, NULL};
00983         menuItems.push_back(temp3);
00984         struct menuItem temp4 = {124, 84, 0, 0, "", 0, 0, NULL, NULL};
00985         menuItems.push_back(temp4);
00986         struct menuItem temp5 = {132, 84, 0, 0, "", 0, 0, NULL, NULL};
00987         menuItems.push_back(temp5);
00988         struct menuItem temp6 = {140, 84, 0, 0, "", 0, 0, NULL, NULL};
00989         menuItems.push_back(temp6);
00990         struct menuItem temp7 = {148, 84, 0, 0, "", 0, 0, NULL, NULL};
00991         menuItems.push_back(temp7);
00992         struct menuItem temp8 = {156, 84, 0, 0, "", 0, 0, NULL, NULL};
00993         menuItems.push_back(temp8);
00994         
00995         PA_OutputText(screen, 1, 3, "    Pressing A will erase \n     this player's stats.\n\nPRESS B IF YOU DON'T WANT THIS");
00996         
00997         //instructions
00998         makeInstructions(0, 96);
00999         makeInstructions(6, 160);
01000 }
01001 
01003 void menuBottom::miscMenu()
01004 {
01005         clearMenus();
01006         navFunction = &menuBottom::miscNav;
01007         actionFunction = &menuBottom::miscAction;
01008         menuColSize = 0;
01009         
01010         char data[24];
01011         sprintf(data, "Max pickups: %d  ", numPickups);
01012         struct menuItem temp2 = {12, 60, 3, 7, data, 0, 0, NULL, NULL};
01013         menuItems.push_back(temp2);
01014         
01015         strcpy(data, "Pre-show pickups: ");
01016         strcat(data, (showPickups ? "ON " : "OFF"));
01017         struct menuItem temp3 = {12, 84, 3, 10, data, 0, 0, NULL, NULL};
01018         menuItems.push_back(temp3);
01019         
01020         strcpy(data, "Die while dancing: ");
01021         strcat(data, (dieWhileDancing ? "ON " : "OFF"));
01022         struct menuItem tempA = {12, 108, 3, 13, data, 0, 0, NULL, NULL};
01023         menuItems.push_back(tempA);
01024         
01025         //instructions
01026         makeInstructions(5, 96);
01027         makeInstructions(6, 160);
01028 }
01029 
01031 void menuBottom::statsMenu()
01032 {
01033         clearMenus();
01034         navFunction = &menuBottom::statsNav;
01035         renderFunction = &menuBottom::statsRender;
01036         actionFunction = &menuBottom::statsAction;
01037         menuColSize = 7;                //first column = players, 2nd = pages
01038         
01039         //players
01040         struct menuItem temp1 = {8, 52, 2, 6, "All", 0, 0, NULL, NULL};
01041         menuItems.push_back(temp1);
01042         struct menuItem temp2 = {8, 68, 2, 8, "P1", 0, 0, NULL, NULL};
01043         menuItems.push_back(temp2);
01044         struct menuItem temp3 = {8, 84, 2, 10, "P2", 0, 0, NULL, NULL};
01045         menuItems.push_back(temp3);
01046         struct menuItem temp4 = {8, 100, 2, 12, "P3", 0, 0, NULL, NULL};
01047         menuItems.push_back(temp4);
01048         struct menuItem temp5 = {8, 116, 2, 14, "P4", 0, 0, NULL, NULL};
01049         menuItems.push_back(temp5);
01050         struct menuItem temp6 = {8, 132, 2, 16, "P5", 0, 0, NULL, NULL};
01051         menuItems.push_back(temp6);
01052         struct menuItem temp7 = {8, 148, 2, 18, "P6", 0, 0, NULL, NULL};
01053         menuItems.push_back(temp7);
01054         
01055         //pages
01056         for (u8 i=0; i<4; ++i)
01057         {
01058                 spriteObject *icon = new spriteObject(this);
01059                 icon->setPallete(cursorSprite.palleteID);
01060                 icon->giveSprite(cursorSprite.spriteData, OBJ_SIZE_16X16, 8, 8);
01061                 icon->setFrame(0);
01062                 u16 x=0;                        //x pos
01063                 u16 ix=0;                       //icon x pos
01064                 string text;            //text for menuItems
01065                 switch (i)
01066                 {
01067                         case 0:
01068                                 x=4; ix=60; text="General";
01069                         break;
01070                         case 1:
01071                                 x=13; ix=120; text="Time";
01072                         break;
01073                         case 2:
01074                                 x=19; ix=172; text="Kills";
01075                         break;
01076                         case 3:
01077                                 x=26; ix=232; text="Deaths";
01078                         break;
01079                 }
01080                 struct menuItem temp = {0, 0, x, 0, text, ix, 4, icon, NULL};
01081                 menuItems.push_back(temp);
01082         }
01083         
01084         autoMenuClickRegions();
01085         
01086         //instructions
01087         makeInstructions(7, 96);
01088         makeInstructions(6, 160);
01089         
01090         //draw first screen
01091         settingsPlayer = 1;     //now it's different, so screen gets drawn.
01092         drawStatsFor(0, 0);
01093 }
01094 
01098 void menuBottom::autoMenuClickRegions()
01099 {
01100         for (u8 i=0; i<menuItems.size(); ++i)
01101         {
01102                 menuItems[i].x1 = menuItems[i].textx*8;
01103                 menuItems[i].x2 = menuItems[i].x1 + (menuItems[i].text.length())*8;
01104                 menuItems[i].y1 = menuItems[i].texty*8;
01105                 menuItems[i].y2 = menuItems[i].y1+8;
01106         }
01107 }
01108 
01116 s8 menuBottom::touchingWhichItem(u16 x, u16 y)
01117 {
01118         for (u8 i=0; i<menuItems.size(); ++i)
01119         {
01120                 if (menuItems[i].x1 != 0 && menuItems[i].x2 != 0
01121                         && menuItems[i].y1 != 0 && menuItems[i].y2 != 0
01122                         && x > menuItems[i].x1 && x < menuItems[i].x2 
01123                         && y > menuItems[i].y1 && y < menuItems[i].y2)
01124                 {
01125                         return i;
01126                 }
01127         }
01128         return -1;
01129 }
01130 
01131 //================================================================================
01132 
01139 bool menuBottom::isSRAMSaved()
01140 {
01141         #ifdef __WITHSAVING
01142                 char testStr[6];
01143                 PA_LoadData(_SRAMIDOFFSET, testStr, 6);
01144                 return PA_CompareText(testStr, const_cast<char*>(_SRAMID));
01145         #else
01146         return true;
01147         #endif
01148 }
01149 
01156 void menuBottom::loadSRAM(bool firstLoad)
01157 {
01158         #ifdef __WITHSAVING
01159         if (isSRAMSaved())
01160         {
01161                 pickupMask = PA_Load32bit(_PICKUPOFFSET);
01162                 roundNum = PA_Load8bit(_ROUNDSOFFSET);
01163                 gameTop->pointsToWin = roundNum;
01164                 char pNames[49];
01165                 PA_LoadString(_NAMESOFFSET, pNames);
01166                 playerNames = pNames;
01167                 player1id = PA_Load8bit(_PLAYER1IDOFFSET);
01168                 player2id = PA_Load8bit(_PLAYER2IDOFFSET);
01169                 PA_LoadData(_PLAYERSPRSOFFSET, &playerSprs, _NUMSAVESLOTS);
01170                 PA_LoadData(_PLAYERPALSOFFSET, &playerPals, _NUMSAVESLOTS);
01171                 u8 settings = PA_Load8bit(_SETTINGSOFFSET);
01172                 dieWhileDancing = settings & 32;
01173                 showPickups = settings & 64;
01174                 numPickups = settings & 31;
01175                 PA_LoadData(_STATSOFFSET, &statistics, _STATSLEN);
01176         } else if (firstLoad) {                                                         //load defaults for first load only!
01177                 sramLoadDefaults();
01178                 sramSavePrevVars();
01179         } else {
01180                 sramLoadPrevVars();
01181         }   
01182         #else
01183         if (firstLoad) {
01184                 sramLoadDefaults();
01185                 sramSavePrevVars();
01186         } else {
01187                 sramLoadPrevVars();
01188         }
01189         #endif
01190 }
01191 
01198 void menuBottom::saveSRAM(bool dontCheck, u8 menuNumber)
01199 {
01200         #ifdef __WITHSAVING
01201         if (isSRAMSaved() || dontCheck)
01202         {
01203                 PA_SaveString(_SRAMIDOFFSET, const_cast<char*>(_SRAMID));       //SRAM identifier
01204                 PA_Save8bit(_ROUNDSOFFSET, roundNum);
01205                 PA_Save32bit(_PICKUPOFFSET, pickupMask);
01206                 PA_SaveString(_NAMESOFFSET, const_cast<char*>(playerNames.c_str()));
01207                 PA_Save8bit(_PLAYER1IDOFFSET, player1id);
01208                 PA_Save8bit(_PLAYER2IDOFFSET, player2id);
01209                 PA_SaveData(_PLAYERSPRSOFFSET, playerSprs, _NUMSAVESLOTS);
01210                 PA_SaveData(_PLAYERPALSOFFSET, playerPals, _NUMSAVESLOTS);
01211                 u8 settings = numPickups + (dieWhileDancing*32) + (showPickups*64);
01212                 PA_Save8bit(_SETTINGSOFFSET, settings);
01213                 PA_SaveData(_STATSOFFSET, statistics, _STATSLEN);
01214                 sramSavePrevVars();
01215                 mainMenu(menuNumber);
01216         } else {
01217                 saveWarningMenu();
01218         }
01219         #else
01220                 sramSavePrevVars();
01221         #endif
01222 }
01223 
01228 void menuBottom::sramSavePrevVars()
01229 {
01230         prevRoundNum = roundNum;
01231         prevPickupMask = pickupMask;
01232         prevPlayerNames = playerNames;
01233         prevPlayer1id = player1id;
01234         prevPlayer2id = player2id;
01235         prevDieWhileDancing = dieWhileDancing;
01236         prevShowPickups = showPickups;
01237         prevNumPickups = numPickups;
01238         
01239         for (u8 i=0; i<_NUMSAVESLOTS; ++i) {
01240                 prevPlayerSprs[i] = playerSprs[i];
01241                 prevPlayerPals[i] = playerPals[i];
01242         }
01243 }
01244 
01249 void menuBottom::sramLoadPrevVars()
01250 {
01251         roundNum = prevRoundNum;
01252         gameTop->pointsToWin = roundNum;
01253         pickupMask = prevPickupMask;
01254         playerNames = prevPlayerNames;
01255         player1id = prevPlayer1id;
01256         player2id = prevPlayer2id;
01257         dieWhileDancing = prevDieWhileDancing;
01258         showPickups = prevShowPickups;
01259         numPickups = prevNumPickups;
01260         
01261         for (u8 i=0; i<_NUMSAVESLOTS; ++i) {
01262                 playerSprs[i] = prevPlayerSprs[i];
01263                 playerPals[i] = prevPlayerPals[i];
01264         }
01265 }
01266 
01270 void menuBottom::sramLoadDefaults()
01271 {
01272         roundNum = 3;
01273         gameTop->pointsToWin = roundNum;
01274         pickupMask = _ALLPICKUPS;
01275         playerNames = "Percy   Howard  Mowbray CliffordStanley Beaufort";
01276         player1id = 1;
01277         player2id = 2;
01278         dieWhileDancing = false;
01279         showPickups = true;
01280         numPickups = 3;
01281         
01282         playerSprs[0] = 1; playerPals[0] = 1;
01283         playerSprs[1] = 1; playerPals[1] = 3;
01284         playerSprs[2] = 2; playerPals[2] = 2;
01285         playerSprs[3] = 2; playerPals[3] = 2;
01286         playerSprs[4] = 3; playerPals[4] = 4;
01287         playerSprs[5] = 3; playerPals[5] = 4;
01288         
01289         for (u16 i=0; i<_STATSLEN; ++i)
01290                 statistics[i] = 0;
01291 }
01292 
01293 //=========================================================================
01294 
01301 void menuBottom::pickupToggle(u8 i)
01302 {
01303         u32 pickupNum = 1<<i;
01304         
01305         if (pickupSelected(i))
01306                 pickupMask &= ~pickupNum;
01307         else
01308                 pickupMask |= pickupNum;
01309 }
01310 
01319 void menuBottom::alterPlayerName(u8 playerID, u8 letterID, s8 modBy)
01320 {
01321         playerNames[(playerID-1)*8 + letterID] += modBy;
01322         
01323         //now take us away from silly characters that nobody likes
01324         if (playerNames[(playerID-1)*8 + letterID] == 31)
01325                 playerNames[(playerID-1)*8 + letterID] = 122;
01326         else if (playerNames[(playerID-1)*8 + letterID] == 123)
01327                 playerNames[(playerID-1)*8 + letterID] = 32;
01328         else if (playerNames[(playerID-1)*8 + letterID] >= 91 && playerNames[(playerID-1)*8 + letterID] <= 96)
01329         {
01330                 if (modBy > 0)
01331                         playerNames[(playerID-1)*8 + letterID] = 97;
01332                 else
01333                         playerNames[(playerID-1)*8 + letterID] = 90;
01334         }
01335         else if (playerNames[(playerID-1)*8 + letterID] == 38)
01336         {
01337                 if (modBy > 0)
01338                         playerNames[(playerID-1)*8 + letterID] = 39;
01339                 else
01340                         playerNames[(playerID-1)*8 + letterID] = 37;
01341         }
01342         
01343         #ifdef __MDDEBUG
01344         PA_OutputText(screen, 5, 0, "%d ", playerNames[(playerID-1)*8 + letterID]);
01345         #endif
01346 }
01347 
01353 void menuBottom::playerColorCycle(u8 i)
01354 {
01355         ++playerPals[i];
01356         if (playerPals[i] == 5)
01357                 playerPals[i] = 1;
01358         updatePlayerIcon(i);
01359 }
01360 
01366 void menuBottom::playerGFXCycle(u8 i)
01367 {
01368         ++playerSprs[i];
01369         if (playerSprs[i] == 4)
01370                 playerSprs[i] = 1;
01371         updatePlayerIcon(i);
01372 }
01373 
01379 void menuBottom::updatePlayerIcon(u8 i)
01380 {
01381         u8 tempx = menuItems[selectedItem].obj->getx();
01382         u8 tempy = menuItems[selectedItem].obj->gety();
01383         menuItems[selectedItem].obj->destroy();
01384         //overwrite, create another
01385         menuItems[selectedItem].obj = new spriteObject(this);
01386         menuItems[selectedItem].obj->setPallete(getPlayerPalleteID(playerPals[i]));
01387         menuItems[selectedItem].obj->giveSprite(getPlayerSpriteData(playerSprs[i]), OBJ_SIZE_32X32, 16, 16, 0, tempx, tempy);
01388         //if (selectedItem > 2)
01389                 //menuItems[selectedItem].obj->setFlipped(true);
01390 }
01391 
01398 void menuBottom::selectPlayer(u8 i, u8 playerNum)
01399 {
01400         if (player1id == i+1)
01401                 player1id = player2id;
01402         else if (player2id == i+1)
01403                 player2id = player1id;          //selecting same - SWAP it.
01404         
01405         if (playerNum == 1)
01406                 player1id = i+1;
01407         else
01408                 player2id = i+1;
01409 }
01410 
01418 void menuBottom::loadPlayerGFX(u8 dataNum, u8 playerNum)
01419 {
01420         const unsigned char *sprite = getPlayerSpriteData(playerSprs[dataNum-1]);
01421         const unsigned short *pal = getPlayerPalleteData(playerPals[dataNum-1]);
01422                 
01423         if (playerNum == 1)
01424                 gameTop->loadPlayer1SpriteSet(pal, sprite);
01425         else
01426                 gameTop->loadPlayer2SpriteSet(pal, sprite);
01427 }
01428 
01435 const unsigned char *menuBottom::getPlayerSpriteData(u8 idNum)
01436 {
01437         switch(idNum)
01438         {
01439                 case 2: return playerSprite2;
01440                 case 3: return playerSprite3;
01441                 default: return playerSprite1;
01442         }
01443 }
01444 
01451 const unsigned short *menuBottom::getPlayerPalleteData(u8 idNum)
01452 {
01453         switch(idNum)
01454         {
01455                 case 2: return playerPallete2;
01456                 case 3: return playerPallete3;
01457                 case 4: return playerPallete4;
01458                 default: return playerPallete1;
01459         }
01460 }
01461 
01468 u8 menuBottom::getPlayerPalleteID(u8 idNum)
01469 {
01470         switch(idNum)
01471         {
01472                 case 2: return playerPal2;
01473                 case 3: return playerPal3;
01474                 case 4: return playerPal4;
01475                 default: return playerPal1;
01476         }
01477 }
01478 
01479 //=====================================================================================
01480 //                                                      STATISTICS ACCESSORS / MUTATORS
01481 //=====================================================================================
01482 
01490 void menuBottom::writeStatValueAt(u16 offset, u16 value)
01491 {
01492         u8 part1 = value>>8;
01493         u8 part2 = value&255;
01494         
01495         statistics[offset] = part1;
01496         statistics[offset+1] = part2;
01497         saveStats();
01498 }
01499 
01507 u16 menuBottom::readStatValueAt(u16 offset) const
01508 {
01509         //what the shitting balls. Somehow, typecasting individually doesn't cut it!?
01510         u16 good1 = statistics[offset]<<8;
01511         u16 good2 = statistics[offset+1];
01512         u16 good = good1 + good2;
01513         
01514         return good;
01515 }
01516 
01521 void menuBottom::saveStats()
01522 {
01523         if (isSRAMSaved())
01524                 PA_SaveData(_STATSOFFSET, statistics, _STATSLEN);
01525 }
01526 
01534 void menuBottom::scoreKill(u8 player, u8 weaponID)
01535 {
01536         player--;       //1 indexed :p
01537         u16 location = GLOBALSLOTSIZE+(PLAYERSLOTSIZE*player)+(weaponID*2);
01538         writeStatValueAt(location, readStatValueAt(location)+1);
01539 }
01540 
01548 void menuBottom::scoreDeath(u8 player, u8 weaponID)
01549 {
01550         player--;       //1 indexed :p
01551         u16 location = GLOBALSLOTSIZE+(PLAYERSLOTSIZE*player)+(WEAPONBLOCKSIZE*2)+(weaponID*2);
01552         writeStatValueAt(location, readStatValueAt(location)+1);
01553         
01554         //score global kill as well
01555         location = weaponID*2;
01556         writeStatValueAt(location, readStatValueAt(location)+1);
01557 }
01558 
01566 void menuBottom::scoreTime(u8 player, u8 weaponID, u16 timeSecs)
01567 {
01568         player--;       //1 indexed :p
01569         u16 location = GLOBALSLOTSIZE+(PLAYERSLOTSIZE*player)+WEAPONBLOCKSIZE+(weaponID*2);
01570         writeStatValueAt(location, readStatValueAt(location)+timeSecs);
01571         
01572         //score global time as well
01573         location = WEAPONBLOCKSIZE+weaponID*2;
01574         writeStatValueAt(location, readStatValueAt(location)+timeSecs);
01575 }
01576 
01584 void menuBottom::scoreRound(u8 winner, u8 loser, bool tied)
01585 {
01586         winner--;
01587         loser--;        //1 indexed :p
01588         
01589         u16 winlocation = GLOBALSLOTSIZE+(PLAYERSLOTSIZE*winner)+(WEAPONBLOCKSIZE*3);
01590         u16 loselocation = GLOBALSLOTSIZE+(PLAYERSLOTSIZE*loser)+(WEAPONBLOCKSIZE*3)+2;
01591         if (tied)
01592         {
01593                 winlocation += 4;
01594                 loselocation += 2;
01595         }
01596         
01597         writeStatValueAt(winlocation, readStatValueAt(winlocation)+1);
01598         writeStatValueAt(loselocation, readStatValueAt(loselocation)+1);
01599                 
01600         //score global round as well
01601         u16 location = (WEAPONBLOCKSIZE*2);
01602         writeStatValueAt(location, readStatValueAt(location)+1);
01603 }
01604 
01610 void menuBottom::erasePlayer(u8 player)
01611 {
01612         player--;
01613         u16 startPos = GLOBALSLOTSIZE+(PLAYERSLOTSIZE*player);
01614         for (u16 i=0; i < (WEAPONBLOCKSIZE*3)+6; ++i)
01615         {
01616                 statistics[startPos+i] = 0;
01617                 //writeStatValueAt(startPos+i, 0);      //seems liable to run outside the range
01618         }
01619 }
01620 
01629 u16 menuBottom::getKillsForPlayer(s8 player, s8 weaponID) const
01630 {
01631         u16 location;
01632         if (player == -1)
01633                 location = 0;
01634         else {
01635                 player--;
01636                 location = GLOBALSLOTSIZE+(PLAYERSLOTSIZE*player);
01637         }
01638         
01639         if (weaponID != -1)
01640                 return readStatValueAt(location+weaponID*2);
01641         
01642         u16 total = 0;
01643         for (u8 i=0; i < WEAPONBLOCKSIZE; i+=2)
01644         {
01645                 total += readStatValueAt(location+i);
01646         }
01647         return total;
01648 }
01649 
01658 u16 menuBottom::getDeathsForPlayer(s8 player, s8 weaponID) const
01659 {
01660         u16 location;
01661         if (player == -1)       //cant get global deaths stat
01662                 return 0;
01663         else {
01664                 player--;
01665                 location = GLOBALSLOTSIZE+(PLAYERSLOTSIZE*player)+(WEAPONBLOCKSIZE*2);
01666         }
01667         
01668         if (weaponID != -1)
01669                 return readStatValueAt(location+weaponID*2);
01670         
01671         u16 total = 0;
01672         for (u8 i=0; i < WEAPONBLOCKSIZE; i+=2)
01673         {
01674                 total += readStatValueAt(location+i);
01675         }
01676         return total;
01677 }
01678 
01687 u16 menuBottom::getTimeForPlayer(s8 player, s8 weaponID) const
01688 {
01689         u16 location;
01690         if (player == -1)
01691                 location = WEAPONBLOCKSIZE;
01692         else {
01693                 player--;
01694                 location = GLOBALSLOTSIZE+(PLAYERSLOTSIZE*player)+WEAPONBLOCKSIZE;
01695         }
01696         
01697         if (weaponID != -1)
01698                 return readStatValueAt(location+weaponID*2);
01699         
01700         u16 total = 0;
01701         for (u8 i=0; i < WEAPONBLOCKSIZE; i+=2)
01702         {
01703                 total += readStatValueAt(location+i);
01704         }
01705         return total;
01706 }
01707 
01714 u16 menuBottom::getWins(s8 player) const
01715 {
01716         u16 location;
01717         if (player == -1)
01718                 location = WEAPONBLOCKSIZE*2;
01719         else {
01720                 player--;
01721                 location = GLOBALSLOTSIZE+(PLAYERSLOTSIZE*player)+(WEAPONBLOCKSIZE*3);
01722         }
01723         return readStatValueAt(location);
01724 }
01725 
01732 u16 menuBottom::getLosses(s8 player) const
01733 {
01734         u16 location;
01735         if (player == -1)
01736                 return 0;       //cant get global losses stat
01737         else {
01738                 player--;
01739                 location = GLOBALSLOTSIZE+(PLAYERSLOTSIZE*player)+(WEAPONBLOCKSIZE*3)+2;
01740         }
01741         return readStatValueAt(location);
01742 }
01743 
01750 u16 menuBottom::getTies(s8 player) const
01751 {
01752         u16 location;
01753         if (player == -1)
01754                 return 0;       //cant get global ties stat
01755         else {
01756                 player--;
01757                 location = GLOBALSLOTSIZE+(PLAYERSLOTSIZE*player)+(WEAPONBLOCKSIZE*3)+4;
01758         }
01759         return readStatValueAt(location);
01760 }
01761 
01762 
01773 void menuBottom::drawStatsFor(u8 player, u8 page)
01774 {
01775         if (settingsPlayer == player && settingsPage == page)
01776                 return;
01777         settingsPlayer = player;
01778         settingsPage = page;
01779         
01780         //clear text
01781         resetText();
01782         
01783         //draw this player's name
01784         if (player != 0)
01785                 PA_OutputText(screen, 4, 2, "Player: %s", macros::getPlayerName(player, playerNames, false).c_str());
01786         
01787         u8 playerSlot = (player==0 ? -1 : player);
01788                 
01789         char buf[21];   //buffer for all text output
01790         u16 (menuBottom::*statFunction)(s8, s8) const = NULL;
01791         
01792         switch (page)                   //general stats - different format
01793         {
01794                 case 0:
01795                         sprintf(buf, "Total playtime:   %5d", getTimeForPlayer(playerSlot, -1)/(player==0 ? 2 : 1));
01796                                 //playtime for global value will be half of what is recorded,
01797                                 //since recording happens for both players simultaneously
01798                         PA_OutputText(screen, 8,  5, buf);
01799                         sprintf(buf, "Rounds played:    %5d", (player==0 ? getWins(playerSlot) : getWins(playerSlot)+getLosses(playerSlot)+getTies(playerSlot)));
01800                         PA_OutputText(screen, 8,  7, buf);
01801                         sprintf(buf, "Total kills:      %5d", getKillsForPlayer(playerSlot, -1));
01802                         PA_OutputText(screen, 8,  9, buf);
01803                         if (player != 0)
01804                         {
01805                                 sprintf(buf, "Total deaths:     %5d", getDeathsForPlayer(playerSlot, -1));
01806                                 PA_OutputText(screen, 8, 11, buf);
01807                                 sprintf(buf, "Number of wins:   %5d", getWins(playerSlot));
01808                                 PA_OutputText(screen, 8, 13, buf);
01809                                 sprintf(buf, "Number of losses: %5d", getLosses(playerSlot));
01810                                 PA_OutputText(screen, 8, 15, buf);
01811                                 sprintf(buf, "Number of ties:   %5d", getTies(playerSlot));
01812                                 PA_OutputText(screen, 8, 17, buf);
01813                         }
01814                 break;
01815                 case 1:                         //all other pages are segregated by weapon
01816                         PA_OutputText(screen, 7,  5, "Skull   N/A");
01817                         sprintf(buf, "1000V %5d", getTimeForPlayer(playerSlot, 1));
01818                         PA_OutputText(screen, 7,  7, buf);
01819                         sprintf(buf, "Invis %5d", getTimeForPlayer(playerSlot, 2));
01820                         PA_OutputText(screen, 7,  9, buf);
01821                         sprintf(buf, " Mine %5d", getTimeForPlayer(playerSlot, 3));
01822                         PA_OutputText(screen, 7, 11, buf);
01823                         sprintf(buf, "  Gun %5d", getTimeForPlayer(playerSlot, 4));
01824                         PA_OutputText(screen, 7, 13, buf);
01825                         PA_OutputText(screen, 7, 15, "  TNT   N/A");
01826                         sprintf(buf, "Boots %5d", getTimeForPlayer(playerSlot, 6));
01827                         PA_OutputText(screen, 7, 17, buf);
01828                         sprintf(buf, " Gren %5d", getTimeForPlayer(playerSlot, 7));
01829                         PA_OutputText(screen, 7, 19, buf);
01830                         sprintf(buf, " Puck %5d", getTimeForPlayer(playerSlot, 8));
01831                         PA_OutputText(screen, 7, 21, buf);
01832                         sprintf(buf, "   None %5d", getTimeForPlayer(playerSlot, 18));
01833                         PA_OutputText(screen, 19, 3, buf);
01834                         sprintf(buf, "Paracht %5d", getTimeForPlayer(playerSlot, 9));
01835                         PA_OutputText(screen, 19,  5, buf);
01836                         sprintf(buf, "   Hook %5d", getTimeForPlayer(playerSlot, 10));
01837                         PA_OutputText(screen, 19,  7, buf);
01838                         sprintf(buf, "   Warp %5d", getTimeForPlayer(playerSlot, 11));
01839                         PA_OutputText(screen, 19,  9, buf);
01840                         sprintf(buf, " Magnet %5d", getTimeForPlayer(playerSlot, 12));
01841                         PA_OutputText(screen, 19, 11, buf);
01842                         sprintf(buf, "    Net %5d", getTimeForPlayer(playerSlot, 13));
01843                         PA_OutputText(screen, 19, 13, buf);
01844                         sprintf(buf, " Shield %5d", getTimeForPlayer(playerSlot, 14));
01845                         PA_OutputText(screen, 19, 15, buf);
01846                         sprintf(buf, "  Dunce %5d", getTimeForPlayer(playerSlot, 15));
01847                         PA_OutputText(screen, 19, 17, buf);
01848                         sprintf(buf, " Weasel %5d", getTimeForPlayer(playerSlot, 16));
01849                         PA_OutputText(screen, 19, 19, buf);
01850                         sprintf(buf, "Boomrng %5d", getTimeForPlayer(playerSlot, 17));
01851                         PA_OutputText(screen, 19, 21, buf);
01852                 break;
01853                 
01854                 case 2: case 3:
01855                         if (page == 2)
01856                                 statFunction = &menuBottom::getKillsForPlayer;
01857                         else
01858                                 statFunction = &menuBottom::getDeathsForPlayer;
01859                         
01860                         sprintf(buf, "Skull %5d", (this->*statFunction)(playerSlot, 0));
01861                         PA_OutputText(screen, 7,  5, buf);
01862                         sprintf(buf, "1000V %5d", (this->*statFunction)(playerSlot, 1));
01863                         PA_OutputText(screen, 7,  7, buf);
01864                         sprintf(buf, "Invis %5d", (this->*statFunction)(playerSlot, 2));
01865                         PA_OutputText(screen, 7,  9, buf);
01866                         sprintf(buf, " Mine %5d", (this->*statFunction)(playerSlot, 3));
01867                         PA_OutputText(screen, 7, 11, buf);
01868                         sprintf(buf, "  Gun %5d", (this->*statFunction)(playerSlot, 4));
01869                         PA_OutputText(screen, 7, 13, buf);
01870                         sprintf(buf, "  TNT %5d", (this->*statFunction)(playerSlot, 5));
01871                         PA_OutputText(screen, 7, 15, buf);
01872                         PA_OutputText(screen, 7, 17, "Boots   N/A");
01873                         sprintf(buf, " Gren %5d", (this->*statFunction)(playerSlot, 7));
01874                         PA_OutputText(screen, 7, 19, buf);
01875                         sprintf(buf, " Puck %5d", (this->*statFunction)(playerSlot, 8));
01876                         PA_OutputText(screen, 7, 21, buf);
01877                         sprintf(buf, (page == 3 ? "   FIDs %5d" : " Tackle %5d"), (this->*statFunction)(playerSlot, 18));
01878                         PA_OutputText(screen, 19,  3, buf);
01879                         PA_OutputText(screen, 19,  5, "Paracht   N/A");
01880                         PA_OutputText(screen, 19,  7, "   Hook   N/A");
01881                         sprintf(buf, "   Warp %5d", (this->*statFunction)(playerSlot, 11));
01882                         PA_OutputText(screen, 19,  9, buf);
01883                         sprintf(buf, " Magnet %5d", (this->*statFunction)(playerSlot, 12));
01884                         PA_OutputText(screen, 19, 11, buf);
01885                         sprintf(buf, "    Net %5d", (this->*statFunction)(playerSlot, 13));
01886                         PA_OutputText(screen, 19, 13, buf);
01887                         sprintf(buf, " Shield %5d", (this->*statFunction)(playerSlot, 14));
01888                         PA_OutputText(screen, 19, 15, buf);
01889                         PA_OutputText(screen, 19, 17, "  Dunce   N/A");
01890                         sprintf(buf, " Weasel %5d", (this->*statFunction)(playerSlot, 16));
01891                         PA_OutputText(screen, 19, 19, buf);
01892                         sprintf(buf, "Boomrng %5d", (this->*statFunction)(playerSlot, 17));
01893                         PA_OutputText(screen, 19, 21, buf);
01894                 break;
01895         }
01896 }

Generated on Tue Mar 13 23:27:53 2007 for MDuel DS by  doxygen 1.5.1-p1