diff --git a/data/trophies/trophies.json b/data/trophies/trophies.json index f0f04e2..70e7107 100644 --- a/data/trophies/trophies.json +++ b/data/trophies/trophies.json @@ -12,49 +12,49 @@ "value" : "TROPHY_BRONZE" }, { - "id" : "CAMPAIGN_10", + "id" : "_CAMPAIGN_10", "title" : "1st Lieutenant", "description" : "Complete 10%% of all missions", "value" : "TROPHY_BRONZE" }, { - "id" : "CAMPAIGN_20", + "id" : "_CAMPAIGN_20", "title" : "Lieutenant Commander", "description" : "Complete 20%% of all missions", "value" : "TROPHY_BRONZE" }, { - "id" : "CAMPAIGN_40", + "id" : "_CAMPAIGN_40", "title" : "Commander", "description" : "Complete 40%% of all missions", "value" : "TROPHY_BRONZE" }, { - "id" : "CAMPAIGN_50", + "id" : "_CAMPAIGN_50", "title" : "Captain", "description" : "Complete 50%% of all missions", "value" : "TROPHY_SILVER" }, { - "id" : "CAMPAIGN_60", + "id" : "_CAMPAIGN_60", "title" : "Commodore", "description" : "Complete 60%% of all missions", "value" : "TROPHY_SILVER" }, { - "id" : "CAMPAIGN_80", + "id" : "_CAMPAIGN_80", "title" : "Rear Admiral", "description" : "Complete 80%% of all missions", "value" : "TROPHY_SILVER" }, { - "id" : "CAMPAIGN_90", + "id" : "_CAMPAIGN_90", "title" : "Admiral", "description" : "Complete 90%% of all missions", "value" : "TROPHY_GOLD" }, { - "id" : "CAMPAIGN_100", + "id" : "_CAMPAIGN_100", "title" : "Fleet Admiral", "description" : "Complete all campaign missions", "value" : "TROPHY_GOLD" @@ -94,8 +94,8 @@ "hidden" : 1 }, { - "id" : "CAMPAIGN_MACE", - "title" : "Going out with a bang.", + "id" : "_CAMPAIGN_MACE", + "title" : "Going out with a bang", "description" : "Complete all missions at Mace", "value" : "TROPHY_SILVER", "hidden" : 1 @@ -145,19 +145,19 @@ "value" : "TROPHY_SILVER" }, { - "id" : "CHALLENGE_25", + "id" : "_CHALLENGE_25", "title" : "", "description" : "Complete 25%% of all challenges", "value" : "TROPHY_BRONZE" }, { - "id" : "CHALLENGE_50", + "id" : "_CHALLENGE_50", "title" : "", "description" : "Complete 50%% of all challenges", "value" : "TROPHY_SILVER" }, { - "id" : "CHALLENGE_100", + "id" : "_CHALLENGE_100", "title" : "", "description" : "Complete 100%% of all challenges", "value" : "TROPHY_GOLD" @@ -221,7 +221,7 @@ }, { "id" : "ATAF_DESTROYED", - "title" : "Almost indestructable. Almost.", + "title" : "Almost indestructable. Almost", "description" : "Be destroyed while piloting an ATAF", "value" : "TROPHY_BRONZE", "hidden" : 1 diff --git a/data/widgets/title.json b/data/widgets/title.json index 9329241..0fb2002 100644 --- a/data/widgets/title.json +++ b/data/widgets/title.json @@ -5,7 +5,7 @@ "type" : "WT_BUTTON", "text" : "Campaign", "x" : -1, - "y" : 225, + "y" : 200, "w" : 200, "h": 34 }, @@ -15,7 +15,17 @@ "type" : "WT_BUTTON", "text" : "Challenges", "x" : -1, - "y" : 325, + "y" : 290, + "w" : 200, + "h": 34 + }, + { + "name" : "trophies", + "group" : "title", + "type" : "WT_BUTTON", + "text" : "Trophies", + "x" : -1, + "y" : 380, "w" : 200, "h": 34 }, @@ -25,7 +35,7 @@ "type" : "WT_BUTTON", "text" : "Stats", "x" : -1, - "y" : 425, + "y" : 470, "w" : 200, "h": 34 }, @@ -35,7 +45,7 @@ "type" : "WT_BUTTON", "text" : "Options", "x" : -1, - "y" : 525, + "y" : 560, "w" : 200, "h": 34 }, @@ -45,7 +55,7 @@ "type" : "WT_BUTTON", "text" : "Quit", "x" : -1, - "y" : 625, + "y" : 650, "w" : 200, "h": 34 } diff --git a/data/widgets/trophies.json b/data/widgets/trophies.json new file mode 100644 index 0000000..7011b99 --- /dev/null +++ b/data/widgets/trophies.json @@ -0,0 +1,32 @@ +[ + { + "name" : "ok", + "group" : "trophies", + "type" : "WT_BUTTON", + "text" : "OK", + "x" : -1, + "y" : 665, + "w" : 150, + "h": 34 + }, + { + "name" : "prev", + "group" : "trophies", + "type" : "WT_IMG_BUTTON", + "x" : 540, + "y" : 110, + "w" : 150, + "h": 34, + "texture" : "gfx/widgets/optionsLeft.png" + }, + { + "name" : "next", + "group" : "trophies", + "type" : "WT_IMG_BUTTON", + "x" : 720, + "y" : 110, + "w" : 150, + "h": 34, + "texture" : "gfx/widgets/optionsRight.png" + } +] diff --git a/gfx/trophies/alertSphere.png b/gfx/trophies/alertSphere.png new file mode 100644 index 0000000..ebcdbd7 Binary files /dev/null and b/gfx/trophies/alertSphere.png differ diff --git a/gfx/trophies/bronze.png b/gfx/trophies/bronze.png index 1935847..f477d39 100644 Binary files a/gfx/trophies/bronze.png and b/gfx/trophies/bronze.png differ diff --git a/gfx/trophies/gold.png b/gfx/trophies/gold.png index cb3d2c8..76c4430 100644 Binary files a/gfx/trophies/gold.png and b/gfx/trophies/gold.png differ diff --git a/gfx/trophies/platinum.png b/gfx/trophies/platinum.png index af3a96b..b90f557 100644 Binary files a/gfx/trophies/platinum.png and b/gfx/trophies/platinum.png differ diff --git a/gfx/trophies/silver.png b/gfx/trophies/silver.png index e61cd36..6d4ae0e 100644 Binary files a/gfx/trophies/silver.png and b/gfx/trophies/silver.png differ diff --git a/gfx/trophies/sparkle.png b/gfx/trophies/sparkle.png new file mode 100644 index 0000000..0f46185 Binary files /dev/null and b/gfx/trophies/sparkle.png differ diff --git a/gfx/trophies/unearned.png b/gfx/trophies/unearned.png new file mode 100644 index 0000000..661ecf4 Binary files /dev/null and b/gfx/trophies/unearned.png differ diff --git a/src/challenges/challengeHome.c b/src/challenges/challengeHome.c index 595bf1a..1864f76 100644 --- a/src/challenges/challengeHome.c +++ b/src/challenges/challengeHome.c @@ -160,7 +160,7 @@ static void logic(void) break; } - doTrophies(); + doTrophyAlerts(); doWidgets(); } diff --git a/src/challenges/challengeHome.h b/src/challenges/challengeHome.h index 94e752a..8ab59ef 100644 --- a/src/challenges/challengeHome.h +++ b/src/challenges/challengeHome.h @@ -60,7 +60,7 @@ extern void playMusic(char *filename); extern char *timeToString(long millis, int showHours); extern char *getChallengeDescription(Challenge *c); extern void clearInput(void); -extern void doTrophies(void); +extern void doTrophyAlerts(void); extern void drawTrophyAlert(void); extern void awardStatsTrophies(void); extern void awardChallengeTrophies(void); diff --git a/src/defs.h b/src/defs.h index aa0004e..2d2616a 100644 --- a/src/defs.h +++ b/src/defs.h @@ -367,5 +367,6 @@ enum TROPHY_SILVER, TROPHY_GOLD, TROPHY_PLATINUM, + TROPHY_UNEARNED, TROPHY_MAX }; diff --git a/src/galaxy/galacticMap.c b/src/galaxy/galacticMap.c index b0a57cc..5513a44 100644 --- a/src/galaxy/galacticMap.c +++ b/src/galaxy/galacticMap.c @@ -176,7 +176,7 @@ static void logic(void) doWidgets(); - doTrophies(); + doTrophyAlerts(); } static void doStarSystems(void) diff --git a/src/galaxy/galacticMap.h b/src/galaxy/galacticMap.h index ca97173..aff7d83 100644 --- a/src/galaxy/galacticMap.h +++ b/src/galaxy/galacticMap.h @@ -60,7 +60,7 @@ extern StarSystem *getStarSystem(char *name); extern void showOKDialog(void (*callback)(void), const char *format, ...); extern char *getTranslatedString(char *string); extern void clearInput(void); -extern void doTrophies(void); +extern void doTrophyAlerts(void); extern void drawTrophyAlert(void); extern void awardCampaignTrophies(void); extern void awardStatsTrophies(void); diff --git a/src/game/title.c b/src/game/title.c index 2cc2a11..234db68 100644 --- a/src/game/title.c +++ b/src/game/title.c @@ -28,8 +28,9 @@ static void doFighters(void); static void drawFighters(void); static void campaign(void); static void challenges(void); +static void trophies(void); static void stats(void); -static void statsOK(void); +static void ok(void); static void options(void); static void quit(void); static void returnFromOptions(void); @@ -78,11 +79,13 @@ void initTitle(void) getWidget("campaign", "title")->action = campaign; getWidget("challenges", "title")->action = challenges; + getWidget("trophies", "title")->action = trophies; getWidget("stats", "title")->action = stats; getWidget("options", "title")->action = options; getWidget("quit", "title")->action = quit; - getWidget("ok", "stats")->action = statsOK; + getWidget("ok", "stats")->action = ok; + getWidget("ok", "trophies")->action = ok; show = SHOW_TITLE; @@ -128,6 +131,8 @@ static void logic(void) doEffects(); + doTrophies(); + doWidgets(); } @@ -190,6 +195,10 @@ static void draw(void) case SHOW_OPTIONS: drawOptions(); break; + + case SHOW_TROPHIES: + drawTrophies(); + break; } } @@ -226,6 +235,15 @@ static void challenges(void) initChallengeHome(); } +static void trophies(void) +{ + selectWidget("ok", "trophies"); + + show = SHOW_TROPHIES; + + initTrophyDisplay(); +} + static void options(void) { selectWidget("ok", "options"); @@ -244,7 +262,7 @@ static void stats(void) initStatsDisplay(); } -static void statsOK(void) +static void ok(void) { selectWidget("stats", "title"); diff --git a/src/game/title.h b/src/game/title.h index 818165e..1c7eb47 100644 --- a/src/game/title.h +++ b/src/game/title.h @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define SHOW_TITLE 0 #define SHOW_STATS 1 #define SHOW_OPTIONS 2 +#define SHOW_TROPHIES 3 #define NUM_FIGHTERS 12 @@ -56,6 +57,9 @@ extern void selectWidget(const char *name, const char *group); extern void drawStats(void); extern void updateAllMissions(void); extern void clearInput(void); +extern void initTrophyDisplay(void); +extern void drawTrophies(void); +extern void doTrophies(void); extern App app; extern Battle battle; diff --git a/src/game/trophies.c b/src/game/trophies.c index bd51af3..b5b5ebc 100644 --- a/src/game/trophies.c +++ b/src/game/trophies.c @@ -20,15 +20,29 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "trophies.h" +static void prevPage(void); +static void nextPage(void); static void loadTrophyData(char *filename); static void resetAlert(void); static void awardCraftTrophy(void); +static void setSparkleColor(Trophy *t); +static void nextAlert(void); static Trophy *alertTrophy; static SDL_Texture *trophyIcons[TROPHY_MAX]; +static SDL_Texture *sparkle; +static SDL_Texture *alertSphere; static SDL_Rect alertRect; static float alertDX; static int alertTimer; +static int page; +static int awarded; +static int total; +static int boxWidth; +static float sparkleAngle; +static float maxPages; +static Widget *prev; +static Widget *next; void initTrophies(void) { @@ -38,10 +52,155 @@ void initTrophies(void) trophyIcons[TROPHY_SILVER] = getTexture("gfx/trophies/silver.png"); trophyIcons[TROPHY_GOLD] = getTexture("gfx/trophies/gold.png"); trophyIcons[TROPHY_PLATINUM] = getTexture("gfx/trophies/platinum.png"); + trophyIcons[TROPHY_UNEARNED] = getTexture("gfx/trophies/unearned.png"); + sparkle = getTexture("gfx/trophies/sparkle.png"); + alertSphere = getTexture("gfx/trophies/alertSphere.png"); + + alertRect.h = 90; + alertRect.y = 10; resetAlert(); } +void initTrophyDisplay(void) +{ + int w, h; + Trophy *t; + + boxWidth = total = awarded = 0; + + for (t = game.trophyHead.next ; t != NULL ; t = t->next) + { + total++; + + if (t->awarded) + { + awarded++; + + STRNCPY(t->awardDateStr, timeToDate(t->awardDate), MAX_NAME_LENGTH); + } + + textSize(t->description, 18, &w, &h); + + boxWidth = MAX(boxWidth, w); + } + + boxWidth += 125; + + page = 0; + + maxPages = total; + maxPages /= TROPHIES_PER_PAGE; + maxPages = ceil(maxPages); + + prev = getWidget("prev", "trophies"); + prev->action = prevPage; + prev->visible = 0; + + next = getWidget("next", "trophies"); + next->action = nextPage; + + sparkleAngle = 0; +} + +static void nextPage(void) +{ + page = MIN(page + 1, maxPages - 1); + + next->visible = page < maxPages - 1; + prev->visible = 1; +} + +static void prevPage(void) +{ + page = MAX(0, page - 1); + + next->visible = 1; + prev->visible = page > 0; +} + +void doTrophies(void) +{ + sparkleAngle += 0.25; + if (sparkleAngle >= 360) + { + sparkleAngle = 0; + } +} + +void drawTrophies(void) +{ + Trophy *t; + SDL_Rect r; + int start, i, x, y; + + SDL_SetRenderDrawBlendMode(app.renderer, SDL_BLENDMODE_BLEND); + SDL_SetRenderDrawColor(app.renderer, 0, 0, 0, 128); + SDL_RenderFillRect(app.renderer, NULL); + SDL_SetRenderDrawBlendMode(app.renderer, SDL_BLENDMODE_NONE); + + r.w = boxWidth; + r.h = 650; + r.x = (SCREEN_WIDTH / 2) - r.w / 2; + r.y = (SCREEN_HEIGHT / 2) - r.h / 2; + + SDL_SetRenderDrawColor(app.renderer, 0, 0, 0, 0); + SDL_RenderFillRect(app.renderer, &r); + SDL_SetRenderDrawColor(app.renderer, 200, 200, 200, 255); + SDL_RenderDrawRect(app.renderer, &r); + + drawText(SCREEN_WIDTH / 2, 40, 28, TA_CENTER, colors.white, _("Trophies")); + drawText(SCREEN_WIDTH / 2, 83, 16, TA_CENTER, colors.lightGrey, _("Awarded : %d / %d"), awarded, total); + drawText(SCREEN_WIDTH / 2, 110, 16, TA_CENTER, colors.lightGrey, _("Page : %d / %d"), page + 1, (int)maxPages); + + SDL_SetRenderDrawColor(app.renderer, 128, 128, 128, 255); + SDL_RenderDrawLine(app.renderer, r.x, 150, r.x + r.w, 150); + + x = r.x + 15; + y = 180; + start = page * TROPHIES_PER_PAGE; + i = 0; + + for (t = game.trophyHead.next ; t != NULL ; t = t->next) + { + if (i >= start && i < start + TROPHIES_PER_PAGE) + { + if (t->awarded) + { + setSparkleColor(t); + blitRotated(sparkle, x + 32, y + 32, sparkleAngle); + blitRotated(sparkle, x + 32, y + 32, -sparkleAngle); + + blitScaled(trophyIcons[t->value], x, y, 64, 64); + drawText(x + 85, y - 10, 20, TA_LEFT, colors.white, t->title); + drawText(x + 85, y + 20, 18, TA_LEFT, colors.lightGrey, t->description); + drawText(x + 85, y + 48, 18, TA_LEFT, colors.yellow, t->awardDateStr); + } + else + { + blitScaled(trophyIcons[TROPHY_UNEARNED], x, y, 64, 64); + + if (!t->hidden) + { + drawText(x + 85, y - 10, 20, TA_LEFT, colors.white, t->title); + drawText(x + 85, y + 20, 18, TA_LEFT, colors.lightGrey, t->description); + drawText(x + 85, y + 48, 18, TA_LEFT, colors.lightGrey, "-"); + } + else + { + drawText(x + 85, y + 20, 20, TA_LEFT, colors.darkGrey, _("[Hidden]")); + } + } + + y += 120; + } + + i++; + } + + drawWidgets("trophies"); +} + void awardTrophy(char *id) { Trophy *t; @@ -57,53 +216,72 @@ void awardTrophy(char *id) } } -void doTrophies(void) +void doTrophyAlerts(void) { + if (!alertTrophy) + { + nextAlert(); + } + else if (alertTrophy) + { + alertRect.x += alertDX; + + if (alertRect.x > -150) + { + alertDX *= 0.9; + + alertTimer--; + } + + if (alertTimer <= 0) + { + alertTrophy->notify = 0; + resetAlert(); + } + + /* do the sparkle rotation */ + doTrophies(); + } +} + +static void nextAlert(void) +{ + int h; Trophy *t; for (t = game.trophyHead.next ; t != NULL ; t = t->next) { if (t->notify) { - if (alertTrophy != t) + if (!alertTrophy || t->awardDate < alertTrophy->awardDate) { alertTrophy = t; - playSound(SND_TROPHY); } - - alertRect.x += alertDX; - - if (alertRect.x > -150) - { - alertDX *= 0.9; - - alertTimer--; - } - - if (alertTimer <= 0) - { - t->notify = 0; - resetAlert(); - } - - return; } } + + if (alertTrophy) + { + playSound(SND_TROPHY); + + textSize(t->title, 30, &alertRect.w, &h); + alertRect.w += 125; + alertRect.w = MAX(alertRect.w, 500); + alertRect.x = -alertRect.w; + } } static void resetAlert(void) { - alertRect.w = 500; - alertRect.h = 90; - alertRect.x = -alertRect.w; - alertRect.y = 10; - alertDX = 12; alertTimer = FPS * 3; + alertTrophy = NULL; } void drawTrophyAlert(void) { + int x, y; + if (alertTrophy) { SDL_SetRenderDrawColor(app.renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); @@ -114,15 +292,19 @@ void drawTrophyAlert(void) drawText(alertRect.x + 15, alertRect.y + 5, 30, TA_LEFT, colors.white, alertTrophy->title); drawText(alertRect.x + 15, alertRect.y + 45, 20, TA_LEFT, colors.white, alertTrophy->shortDescription); + + setSparkleColor(alertTrophy); + + x = alertRect.x + alertRect.w - 72; + y = alertRect.y + 20; - blitScaled(trophyIcons[alertTrophy->value], alertRect.x + alertRect.w - 64, alertRect.y + 16, 48, 48); + blit(alertSphere, x + 24, y + 24, 1); + blitRotated(sparkle, x + 24, y + 24, sparkleAngle); + blitRotated(sparkle, x + 24, y + 24, -sparkleAngle); + blitScaled(trophyIcons[alertTrophy->value], x, y, 48, 48); } } -void drawTrophies(void) -{ -} - Trophy *getTrophy(char *id) { Trophy *t; @@ -272,3 +454,25 @@ static void awardCraftTrophy(void) awardTrophy(trophyId); } + +static void setSparkleColor(Trophy *t) +{ + switch (t->value) + { + case TROPHY_BRONZE: + SDL_SetTextureColorMod(sparkle, 255, 128, 0); + break; + + case TROPHY_SILVER: + SDL_SetTextureColorMod(sparkle, 192, 192, 192); + break; + + case TROPHY_GOLD: + SDL_SetTextureColorMod(sparkle, 255, 255, 0); + break; + + case TROPHY_PLATINUM: + SDL_SetTextureColorMod(sparkle, 0, 128, 255); + break; + } +} diff --git a/src/game/trophies.h b/src/game/trophies.h index 319a92f..77d00ba 100644 --- a/src/game/trophies.h +++ b/src/game/trophies.h @@ -18,7 +18,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define SHORT_DESCRIPTION_LENGTH 40 +#define SHORT_DESCRIPTION_LENGTH 40 +#define TROPHIES_PER_PAGE 4 #include "../common.h" #include "../json/cJSON.h" @@ -30,10 +31,16 @@ extern char *readFile(char *filename); extern int getJSONValue(cJSON *node, char *name, int defValue); extern int getPercent(float current, float total); extern void drawText(int x, int y, int size, int align, SDL_Color c, const char *format, ...); +extern void blit(SDL_Texture *texture, int x, int y, int centered); +extern void blitRotated(SDL_Texture *texture, int x, int y, float angle); extern void blitScaled(SDL_Texture *t, int x, int y, int w, int h); extern char *getTranslatedString(char *string); extern SDL_Texture *getTexture(char *filename); extern void playSound(int id); +extern Widget *getWidget(const char *name, const char *group); +extern void drawWidgets(char *groupName); +extern char *timeToDate(long millis); +extern void textSize(char *text, int size, int *w, int *h); extern App app; extern Colors colors; diff --git a/src/structs.h b/src/structs.h index 04099fa..25558e0 100644 --- a/src/structs.h +++ b/src/structs.h @@ -371,6 +371,7 @@ struct Trophy { char title[MAX_DESCRIPTION_LENGTH]; char description[MAX_DESCRIPTION_LENGTH]; char shortDescription[MAX_DESCRIPTION_LENGTH]; + char awardDateStr[MAX_NAME_LENGTH]; int value; int hidden; int stat; diff --git a/src/system/util.c b/src/system/util.c index 2d9f409..b9314da 100644 --- a/src/system/util.c +++ b/src/system/util.c @@ -128,6 +128,19 @@ char *timeToString(long millis, int showHours) return TIME; } +char *timeToDate(long millis) +{ + static char DATE[MAX_NAME_LENGTH]; + + struct tm *timeinfo; + + timeinfo = localtime(&millis); + + strftime(DATE, MAX_NAME_LENGTH, "%d %b %Y, %H:%M", timeinfo); + + return DATE; +} + char *getJSONValueStr(cJSON *node, char *name, char *defValue) { cJSON *child; diff --git a/src/system/util.h b/src/system/util.h index 667646c..1f43fb9 100644 --- a/src/system/util.h +++ b/src/system/util.h @@ -20,3 +20,4 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "../common.h" #include "../json/cJSON.h" +#include "time.h"