// Hyperbolic Rogue -- achievements // Copyright (C) 2011-2016 Zeno Rogue, see 'hyper.cpp' for details #define NUMLEADER 78 #define SCORE_UNKNOWN (-1) #define NO_SCORE_YET (-2) bool offlineMode = false; int syncstate = 0; int currentscore[NUMLEADER]; const char* leadernames[NUMLEADER] = { "Score", "Diamonds", "Gold", "Spice", "Rubies", "Elixirs", "Shards100", "Totems", "Daisies", "Statues", "Feathers", "Sapphires", "Hyperstones", "Time to Win-71", "Turns to Win-71", "Time to 10 Hyperstones-103", "Turns to 10 Hyperstones-103", "Orbs of Yendor", "Fern Flowers", "Royal Jellies", "Powerstones", "Silver", "Wine", "Emeralds", "Grimoires", "Holy Grails", "Red Gems", "Pirate Treasures", "Shmup Score", "Shmup Time to Win", "Shmup Knife to Win", "Bomberbird Eggs", // 31 "Ambers", // 32 "Pearls", // 33 "Hypersian Rugs", // 34 "Garnets", // 35 "Princess Challenge", // 36 "Ivory Figurines", // 37 "Elemental Gems", // 38 "Onyxes", // 39 "Yendor Challenge", // 40 "Pure Tactics Mode", // 41 "Mutant Saplings", // 42 "Fulgurites", // 43 "Shmup Score 2p", // 44 "Coop Shmup Time to Win", // 45 "Black Lotuses", // 46 "Mutant Fruits", // 47 "White Dove Feathers", // 48 "Pure Tactics Mode (shmup)", // 49 "Pure Tactics Mode (2p)", // 50 "Corals", // 51 "Thornless Roses", // 52 "Chaos Mode", // 53 "Tortoise points", // 54 "Dragon Scales", // 55 "Apples", // 56 "Heptagonal Mode", // 57 "Sunken Treasures", // 58 "Ancient Jewelry", // 59 "Golden Eggs", // 60 "Multiplayer Score", // 61 "Statistics", // 62 "Halloween", // 63 "Amethysts", // 64 "Slime Molds", // 65 "Dodecahedra", // 66 "Green Grass", // 67 "Spinel", // 68 "Orb Strategy Score", // 69 "Real time to Win-OS", // 70 "Turns to Win-OS", // 71 "Ancient Weapons", // 72 "Forgotten Relics", // 73 "Lava Lilies", // 74 "Turquoises", // 75 "Chrysoberyls", // 76 "Tasty Jellies" // 77 }; #define LB_STATISTICS 62 #define LB_HALLOWEEN 63 bool haveLeaderboard(int id); void upload_score(int id, int v); string achievementMessage[3]; int achievementTimer; vector achievementsReceived; bool wrongMode(char flags) { if(cheater) return true; if(flags == 'x') return false; if(nonchamfered != (flags == '7')) return true; if(euclid != (flags == 'e')) return true; if(flags == 'E' && S7 < 5) return false; if(sphere != (flags == 'E')) return true; if((quotient == 1) != (flags == 'q')) return true; if((quotient == 2) != (flags == 'Q')) return true; if(shmup::on != (flags == 's')) return true; if(randomPatternsMode) return true; if(yendor::on) return true; if(peace::on) return true; if(tactic::on) return true; #if CAP_TOUR if(tour::on) return true; #endif if(chaosmode != (flags == 'C')) return true; if((numplayers() > 1) != (flags == 'm')) return true; return false; } void achievement_log(const char* s, char flags) { #ifdef PRINT_ACHIEVEMENTS printf("achievement = %s [%d]\n", s, wrongMode(flags)); #endif if(wrongMode(flags)) return; for(int i=0; i= 5) achievement_gain("GOLEM2"); if(s == "GOLEM" && current >= 10) achievement_gain("GOLEM3"); if(s == "STAB" && current >= 1) achievement_gain("STABBER1"); if(s == "STAB" && current >= 2) achievement_gain("STABBER2"); if(s == "SLASH" && current >= 2) achievement_gain("SLASH2"); if(s == "STAB" && current >= 4) achievement_gain("STABBER3"); if(s == "MIRRORKILL" && current-prev >= 1) achievement_gain("MIRRORKILL1"); if(s == "MIRRORKILL" && current-prev >= 2) achievement_gain("MIRRORKILL2"); if(s == "MIRRORKILL" && current-prev >= 3) achievement_gain("MIRRORKILL3"); if(s == "FLASH" && current-prev >= 1) achievement_gain("FLASH1"); if(s == "FLASH" && current-prev >= 5) achievement_gain("FLASH2"); if(s == "FLASH" && current-prev >= 10) achievement_gain("FLASH3"); if(s == "LIGHTNING" && current-prev >= 1) achievement_gain("LIGHTNING1"); if(s == "LIGHTNING" && current-prev >= 5) achievement_gain("LIGHTNING2"); if(s == "LIGHTNING" && current-prev >= 10) achievement_gain("LIGHTNING3"); if(s == "MIRAGE" && current >= 35) achievement_gain("MIRAGE", 'e'); if(s == "ORB" && current >= 10) achievement_gain("ORB3"); if(s == "BUG" && current >= 1000) achievement_gain("BUG3"); if(s == "ELEC" && current >= 10) achievement_gain("ELEC3"); } int specific_improved = 0; int specific_what = 0; void improve_score(int i, eItem what) { if(offlineMode) return; #ifdef HAVE_ACHIEVEMENTS if(haveLeaderboard(i)) updateHi(what, currentscore[i]); if(items[what] && haveLeaderboard(i)) { if(items[what] > currentscore[i] && currentscore[i] != SCORE_UNKNOWN) { specific_improved++; specific_what = what; } upload_score(i, items[what]); } #endif } void achievement_score(int cat, int number) { if(offlineMode) return; #ifdef HAVE_ACHIEVEMENTS if(cheater) return; if(euclid) return; if(sphere && cat != LB_HALLOWEEN) return; if(quotient) return; if(elliptic && cat != LB_HALLOWEEN) return; if(nonchamfered) return; if(randomPatternsMode) return; if(shmup::on && cat != LB_PURE_TACTICS_SHMUP && cat != LB_PURE_TACTICS_COOP) return; if(yendor::on && cat != LB_YENDOR_CHALLENGE) return; if(tactic::on && cat != LB_PURE_TACTICS && cat != LB_PURE_TACTICS_SHMUP && cat != LB_PURE_TACTICS_COOP) return; upload_score(cat, number); #endif } void improveItemScores() { for(int i=1; i<=12; i++) improve_score(i, eItem(i)); improve_score(17, itOrbYendor); improve_score(18, itFernFlower); improve_score(19, itRoyalJelly); improve_score(20, itPower); improve_score(21, itSilver); improve_score(22, itWine); improve_score(23, itEmerald); improve_score(24, itGrimoire); improve_score(25, itHolyGrail); improve_score(26, itRedGem); improve_score(27, itPirate); improve_score(31, itBombEgg); improve_score(32, itCoast); improve_score(33, itWhirlpool); improve_score(34, itPalace); improve_score(35, itFjord); improve_score(37, itIvory); improve_score(38, itElemental); improve_score(39, itZebra); improve_score(42, itMutant); improve_score(43, itFulgurite); if(!isHaunted(cwt.c->land)) improve_score(46, itLotus); improve_score(47, itMutant2); improve_score(48, itWindstone); improve_score(51, itCoral); improve_score(52, itRose); improve_score(54, itBabyTortoise); improve_score(55, itDragon); improve_score(56, itApple); improve_score(58, itKraken); improve_score(59, itBarrow); improve_score(60, itTrollEgg); improve_score(64, itAmethyst); improve_score(65, itSlime); improve_score(66, itDodeca); improve_score(67, itGreenGrass); improve_score(68, itBull); improve_score(72, itTerra); improve_score(73, itBlizzard); improve_score(74, itLavaLily); improve_score(75, itHunting); improve_score(76, itRuins); improve_score(77, itSwitch); } void achievement_final(bool really_final) { if(offlineMode) return; #ifdef HAVE_ACHIEVEMENTS upload_score(LB_STATISTICS, time(NULL)); if(cheater) return; #if CAP_TOUR if(tour::on) return; #endif if(randomPatternsMode) return; if(peace::on) return; if(yendor::on) return; if(tactic::on) { tactic::record(); tactic::unrecord(); tactic::uploadScore(); return; } if(sphere && specialland == laHalloween) { if(shmup::on || chaosmode || nonchamfered || numplayers() > 1 || tactic::on || randomPatternsMode) return; achievement_score(LB_HALLOWEEN, items[itTreat]); } if(euclid) return; if(sphere) return; if(elliptic) return; // no leaderboards for two special modes at once int specials = 0; if(shmup::on) specials++; if(chaosmode) specials++; if(nonchamfered) specials++; if(inv::on) specials++; if(specials > 1) return; if(numplayers() > 1 && chaosmode) return; if(numplayers() > 1 && nonchamfered) return; if(numplayers() > 1 && inv::on) return; int total_improved = 0; specific_improved = 0; specific_what = 0; if(!shmup::on && !chaosmode && !nonchamfered && numplayers() == 1 && !inv::on) improveItemScores(); int sid = nonchamfered ? 57 : chaosmode ? 53 : shmup::on ? (numplayers() > 1 ? 44 : 28) : inv::on ? 69 : (numplayers() > 1 ? 61 : 0); int tg = gold(); if(tg && haveLeaderboard(sid)) { if(tg > currentscore[sid] && currentscore[sid] != SCORE_UNKNOWN) { if(currentscore[sid] < 0) total_improved += 2; total_improved++; // currentscore[sid] = tg; } upload_score(sid, tg); } if(total_improved >= 2) { #if !ISANDROID addMessage(XLAT("Your total treasure has been recorded in the " LEADERFULL ".")); addMessage(XLAT("Congratulations!")); #endif } else if(total_improved && specific_improved >= 2) addMessage(XLAT("You have improved your total high score and %1 specific high scores!", its(specific_improved))); else if(total_improved && specific_improved) addMessage(XLAT("You have improved your total and '%1' high score!", iinf[specific_what].name)); else if(total_improved) { #if !ISANDROID addMessage(XLAT("You have improved your total high score on " LEADER ". Congratulations!")); #endif } else if(specific_improved >= 2) addMessage(XLAT("You have improved %1 of your specific high scores!", its(specific_improved))); else if(specific_improved) { #if !ISANDROID addMessage(XLAT("You have improved your '%1' high score on " LEADER "!", iinf[specific_what].name)); #endif } #endif } bool hadtotalvictory; void check_total_victory() { if(!inv::on) return; if(hadtotalvictory) return; if(!items[itOrbYendor]) return; if(!items[itHolyGrail]) return; if(items[itHyperstone] < 50) return; if(!princess::reviveAt) return; hadtotalvictory = true; achievement_gain("TOTALVICTORY"); } void achievement_victory(bool hyper) { DEBB(DF_STEAM, (debugfile,"achievement_victory\n")) if(offlineMode) return; #ifdef HAVE_ACHIEVEMENTS if(cheater) return; if(euclid) return; if(sphere) return; if(quotient) return; if(nonchamfered) return; if(randomPatternsMode) return; if(hyper && shmup::on) return; if(yendor::on) return; if(peace::on) return; if(tactic::on) return; if(chaosmode) return; DEBB(DF_STEAM, (debugfile,"after checks\n")) int t = getgametime(); if(hyper && shmup::on) return; if(hyper && inv::on) return; int ih1 = hyper ? 15 : inv::on ? 70 : shmup::on ? (numplayers() > 1 ? 45 : 29) : 13; int ih2 = hyper ? 16 : inv::on ? 71 : shmup::on ? 30 : 14; int improved = 0; if(currentscore[ih1] == NO_SCORE_YET || currentscore[ih2] == NO_SCORE_YET) improved += 4; if(currentscore[ih1] < 0 || currentscore[ih1] > t) { improved++; // currentscore[ih1] = t; } if(currentscore[ih2] < 0 || currentscore[ih2] > turncount) { improved+=2; // currentscore[ih2] = turncount; } if(hyper) addMessage(XLAT("You have collected 10 treasures of each type.")); if(improved) { if(improved >= 4) { if(!hyper) addMessage(XLAT("This is your first victory!")); #if !ISANDROID addMessage(XLAT("This has been recorded in the " LEADERFULL ".")); #endif addMessage(XLAT("The faster you get here, the better you are!")); } else if(improved >= 3) { if(shmup::on) addMessage(XLAT("You have improved both your real time and knife count. Congratulations!")); else addMessage(XLAT("You have improved both your real time and turn count. Congratulations!")); } else if(improved == 1) addMessage(XLAT("You have used less real time than ever before. Congratulations!")); else if(improved == 2) { if(shmup::on) addMessage(XLAT("You have used less knives than ever before. Congratulations!")); else addMessage(XLAT("You have used less turns than ever before. Congratulations!")); } } DEBB(DF_STEAM, (debugfile, "uploading scores\n")) upload_score(ih1, t); upload_score(ih2, turncount); #endif } void achievement_pump(); #ifndef HAVE_ACHIEVEMENTS void achievement_pump() {} #endif void achievement_display() { #ifdef HAVE_ACHIEVEMENTS if(achievementTimer) { int col = (ticks - achievementTimer); if(col > 5000) { achievementTimer = 0; return; } if(col > 2500) col = 5000 - col; col /= 10; col *= 0x10101; displayfr(vid.xres/2, vid.yres/4, 2, vid.fsize * 2, achievementMessage[0], col & 0xFFFF00, 8); int w = 2 * vid.fsize; #if ISMOBILE==0 while(w>3 && textwidth(w, achievementMessage[1]) > vid.xres) w--; #endif displayfr(vid.xres/2, vid.yres/4 + vid.fsize*2, 2, w, achievementMessage[1], col, 8); w = vid.fsize; #if ISMOBILE==0 while(w>3 && textwidth(w, achievementMessage[2]) > vid.xres) w--; #endif displayfr(vid.xres/2, vid.yres/4 + vid.fsize*4, 2, w, achievementMessage[2], col, 8); } #endif } bool isAscending(int i) { return i == 13 || i == 14 || i == 15 || i == 16 || i == 29 || i == 30 || i == 45; };