diff --git a/app/assets/images/common/button-background-success-active-border.png b/app/assets/images/common/button-background-success-active-border.png new file mode 100644 index 000000000..b64df9e49 Binary files /dev/null and b/app/assets/images/common/button-background-success-active-border.png differ diff --git a/app/assets/images/common/button-background-success-active.png b/app/assets/images/common/button-background-success-active.png new file mode 100644 index 000000000..bb6850e8b Binary files /dev/null and b/app/assets/images/common/button-background-success-active.png differ diff --git a/app/assets/images/common/button-background-success-inactive-border.png b/app/assets/images/common/button-background-success-inactive-border.png new file mode 100644 index 000000000..cf1dfc217 Binary files /dev/null and b/app/assets/images/common/button-background-success-inactive-border.png differ diff --git a/app/assets/images/common/button-background-success-inactive.png b/app/assets/images/common/button-background-success-inactive.png new file mode 100644 index 000000000..0e02036c2 Binary files /dev/null and b/app/assets/images/common/button-background-success-inactive.png differ diff --git a/app/assets/images/common/button-background-success-pressed-border.png b/app/assets/images/common/button-background-success-pressed-border.png new file mode 100644 index 000000000..c12979058 Binary files /dev/null and b/app/assets/images/common/button-background-success-pressed-border.png differ diff --git a/app/assets/images/common/button-background-success-pressed.png b/app/assets/images/common/button-background-success-pressed.png new file mode 100644 index 000000000..41c23a01f Binary files /dev/null and b/app/assets/images/common/button-background-success-pressed.png differ diff --git a/app/assets/images/pages/play/level/modal/achievement_plate.png b/app/assets/images/pages/play/level/modal/achievement_plate.png deleted file mode 100644 index 1ab5a60b3..000000000 Binary files a/app/assets/images/pages/play/level/modal/achievement_plate.png and /dev/null differ diff --git a/app/assets/images/pages/play/level/modal/victory_hero.png b/app/assets/images/pages/play/level/modal/victory_hero.png new file mode 100644 index 000000000..068af4688 Binary files /dev/null and b/app/assets/images/pages/play/level/modal/victory_hero.png differ diff --git a/app/assets/images/pages/play/level/modal/victory_modal_background.png b/app/assets/images/pages/play/level/modal/victory_modal_background.png index 11f8ad8f1..7ed30bcb4 100644 Binary files a/app/assets/images/pages/play/level/modal/victory_modal_background.png and b/app/assets/images/pages/play/level/modal/victory_modal_background.png differ diff --git a/app/assets/images/pages/play/level/modal/victory_modal_blue_banner.png b/app/assets/images/pages/play/level/modal/victory_modal_blue_banner.png deleted file mode 100644 index 0c87583bf..000000000 Binary files a/app/assets/images/pages/play/level/modal/victory_modal_blue_banner.png and /dev/null differ diff --git a/app/assets/images/pages/play/level/modal/victory_modal_border_background.png b/app/assets/images/pages/play/level/modal/victory_modal_border_background.png new file mode 100644 index 000000000..00657032c Binary files /dev/null and b/app/assets/images/pages/play/level/modal/victory_modal_border_background.png differ diff --git a/app/assets/images/pages/play/level/modal/victory_modal_shelf.png b/app/assets/images/pages/play/level/modal/victory_modal_shelf.png new file mode 100644 index 000000000..bd8586443 Binary files /dev/null and b/app/assets/images/pages/play/level/modal/victory_modal_shelf.png differ diff --git a/app/assets/images/pages/play/level/modal/victory_word.png b/app/assets/images/pages/play/level/modal/victory_word.png index 60563a588..0ead423a1 100644 Binary files a/app/assets/images/pages/play/level/modal/victory_word.png and b/app/assets/images/pages/play/level/modal/victory_word.png differ diff --git a/app/assets/images/pages/play/level/modal/xp_gems_parchment.png b/app/assets/images/pages/play/level/modal/xp_gems_parchment.png new file mode 100644 index 000000000..917db106f Binary files /dev/null and b/app/assets/images/pages/play/level/modal/xp_gems_parchment.png differ diff --git a/app/locale/en.coffee b/app/locale/en.coffee index e88f1503a..aac19b3e9 100644 --- a/app/locale/en.coffee +++ b/app/locale/en.coffee @@ -222,6 +222,7 @@ reload_title: "Reload All Code?" reload_really: "Are you sure you want to reload this level back to the beginning?" reload_confirm: "Reload All" + victory: "Victory" victory_title_prefix: "" victory_title_suffix: " Complete" victory_sign_up: "Sign Up to Save Progress" @@ -234,6 +235,8 @@ victory_review: "Tell us more!" # Only in old-style levels. victory_hour_of_code_done: "Are You Done?" victory_hour_of_code_done_yes: "Yes, I'm finished with my Hour of Codeā¢!" + victory_experience_gained: "XP Gained" + victory_gems_gained: "Gems Gained" guide_title: "Guide" tome_minion_spells: "Your Minions' Spells" # Only in old-style levels. tome_read_only_spells: "Read-Only Spells" # Only in old-style levels. diff --git a/app/styles/common/common.sass b/app/styles/common/common.sass index b54695b29..0cb17cf71 100644 --- a/app/styles/common/common.sass +++ b/app/styles/common/common.sass @@ -253,13 +253,19 @@ kbd border-image-source: url(/images/common/button-background-primary-active-border.png) &.btn-success border-image-source: url(/images/common/button-background-success-active-border.png) + color: darken(white, 5%) &.btn-warning border-image-source: url(/images/common/button-background-warning-active-border.png) + color: darken(white, 5%) &.btn-danger border-image-source: url(/images/common/button-background-danger-active-border.png) &:hover color: lighten(rgb(248, 197, 146), 5%) + &.btn-success + color: white + &.btn-warning + color: white &:active &.btn-lg diff --git a/app/styles/play/level/modal/hero-victory-modal.sass b/app/styles/play/level/modal/hero-victory-modal.sass index 468bef75e..6344b42cb 100644 --- a/app/styles/play/level/modal/hero-victory-modal.sass +++ b/app/styles/play/level/modal/hero-victory-modal.sass @@ -2,55 +2,89 @@ @import "app/styles/bootstrap/variables" #hero-victory-modal + $hero-yellow-text: rgb(252, 201, 53) + //- Top-level modal container .modal-dialog - margin-top: 15px + margin-top: 0 padding-top: 0 + width: 750px + + .modal-content + position: relative + margin-top: -251px + + &.full-achievements + @media only screen and (max-height: 720px) + .modal-dialog + margin-top: -76px + #victory-header + background: transparent + @media only screen and (max-height: 640px) + .modal-dialog + margin-top: -130px + #victory-header + display: none //- Header .background-wrapper //background: url("/images/pages/play/level/modal/victory_modal_background.png") - width: 550px - background-color: transparent + width: 750px + background: transparent border: 0px solid transparent - border-width: 25px - border-image: url("/images/pages/play/level/modal/victory_modal_background.png") 25 fill round + border-image: url("/images/pages/play/level/modal/victory_modal_border_background.png") 250 0 100 0 fill round + border-width: 250px 0 100px 0 border-radius: 12px - #victory-banner - position: absolute - left: -30px - z-index: 0 - - #victory-header - position: absolute - left: 135px - display: block - margin: 10px auto 0 - // http://easings.net/#easeOutBack plus tweaked a bit: http://cubic-bezier.com/#.18,.68,.75,2 - @include transition(0.5s cubic-bezier(0.18, 0.68, 0.75, 2)) - z-index: 1 - - &.out - @include scale(0) - .modal-header - height: 85px border: none + position: absolute + left: 188px + width: 378px + height: 134px + margin: 0 + padding: 0 + + #victory-header + position: relative + // http://easings.net/#easeOutBack plus tweaked a bit: http://cubic-bezier.com/#.18,.68,.75,2 + @include transition(0.5s cubic-bezier(0.18, 0.68, 0.75, 2)) + z-index: 1 + width: 100% + height: 100% + text-align: center + background: transparent url(/images/pages/play/level/modal/victory_hero.png/) no-repeat + background-position: center -88px + &.out + @include scale(0) + + #victory-title + display: inline-block + margin-top: 74px + + h1 + text-transform: uppercase + text-align: center + color: $hero-yellow-text + font-size: 80px + margin: 0 + padding: 0 + text-shadow: black 8px 8px 0, black -8px -8px 0, black 8px -8px 0, black -8px 8px 0, black 8px 0px 0, black 0px -8px 0, black -8px 0px 0, black 0px 8px 0 //- Achievement panels .modal-body padding: 0 20px min-height: 30px + margin-top: 160px .achievement-panel - background: url("/images/pages/play/level/modal/achievement_plate.png") - width: 451px - height: 144px - margin: 5px auto + background: transparent url("/images/pages/play/level/modal/victory_modal_shelf.png") no-repeat center 73px + width: 824px + height: 127px + margin: 0px -37px 0px -57px position: relative @include transition-duration(1s) @@ -71,12 +105,16 @@ .achievement-description @include opacity(0.75) + z-index: 1 position: absolute text-align: center left: 95px right: 98px - top: 10px - color: white + top: 86px + color: $hero-yellow-text + font-weight: bold + text-transform: uppercase + font-family: 'Open Sans Condensed' white-space: nowrap overflow: hidden text-overflow: ellipsis @@ -85,8 +123,7 @@ position: absolute left: 25px right: 23px - top: 41px - bottom: 18px + top: 0 @include flexbox() @include flex-justify-center() @@ -102,7 +139,7 @@ z-index: 1 @include transition(0.25s ease) - &.hero, &.item + &.hero, &.item, &.xp, &.gems background: url("/images/pages/play/level/modal/reward_plate_wide.png") width: 120px height: 83px @@ -185,28 +222,112 @@ .gems .pulse @include animation(rewardPulse 0.25s infinite) - //- Footer - - .modal-footer - padding-bottom: 0 - - p.sign-up-poke - color: white - .sign-up-button - float: right - margin: 2px 10px + //- Footer - totals #totals - color: white + width: 709px + height: 96px + background: transparent url(/images/pages/play/level/modal/xp_gems_parchment.png) + position: relative + text-align: left + + .total-wrapper + position: absolute + top: 18px + + &#xp-wrapper + left: 117px + width: 300px + + &#gem-wrapper + left: 529px + + .total-label + width: 90px + + .total-count + float: left + font-size: 45px + font-weight: bold + color: rgb(40, 33, 22) + margin-right: 12px + + .total-label + float: left + color: rgb(103, 92, 76) + text-transform: uppercase + font-weight: bold + font-family: 'Open Sans Condensed' + font-size: 18px + margin-top: 13px + line-height: 18px + + .xp-bar-outer + background-color: rgb(40, 33, 22) + border: 4px solid rgb(40, 33, 22) + border-radius: 8px + width: 150px + height: 16px + margin-top: 3px + position: relative + float: left + + .xp-bar-already-achieved + background-color: rgb(166, 213, 88) + //background-color: white + border-radius: 8px + height: 100% + position: absolute + z-index: 1 + + .xp-bar-total + background-color: rgb(253, 171, 45) + border: 1px solid rgb(239, 177, 73) + border-radius: 8px + height: 100% + position: absolute + + + //- Footer - other stuff + + .modal-footer + // Negative bottom margin counteracts most of the extra the border image height. + margin: 0 0 -80px 0 + padding: 0 20px + text-align: center + + .sign-up-poke + width: 430px + + .sign-up-blurb + width: 175px + font-family: 'Open Sans Condensed' + font-weight: bold + text-transform: uppercase + font-size: 18px + line-height: 18px + text-align: left + float: left + margin: 5px 0 0 5px + color: rgb(160, 150, 126) + + .sign-up-button + width: 250px + height: 60px + line-height: 30px + margin: 0 + float: left + .next-level-buttons float: right - .next-level-button - display: block - margin: 8px 10px - width: 150px + .next-level-button, .return-to-ladder-button + width: 258px + height: 60px + line-height: 30px + margin: 0 10px .ladder-submission-view display: inline-block @@ -223,7 +344,11 @@ .hour-of-code-done clear: both - padding-top: 10px + margin: 5px auto 0 auto + padding: 10px + background-color: rgba(22, 34, 30, 0.5) + border-radius: 8px + display: inline-block strong color: white @@ -241,23 +366,25 @@ html.no-borderimage #hero-victory-modal + .modal-dialog + margin-top: 251px .background-wrapper border: 0 background: url("/images/pages/play/level/modal/victory_modal_background.png") - height: 650px - #victory-header - margin-top: 40px - left: 160px - #victory-banner - left: 0px - top: 40px - .modal-header - height: 110px - .modal-content - height: 650px - padding-bottom: 0 - .modal-footer - bottom: 20px + height: 713px + + &.full-achievements + @media only screen and (max-height: 720px) + .modal-dialog + margin-top: 175px + #victory-header + background: transparent + @media only screen and (max-height: 640px) + .modal-dialog + margin-top: 121px + #victory-header + display: none + body.ipad #hero-victory-modal diff --git a/app/templates/play/level/modal/hero-victory-modal.jade b/app/templates/play/level/modal/hero-victory-modal.jade index 0537a7aee..986d5ecb4 100644 --- a/app/templates/play/level/modal/hero-victory-modal.jade +++ b/app/templates/play/level/modal/hero-victory-modal.jade @@ -1,7 +1,11 @@ extends /templates/core/modal-base block modal-header-content - img(src="/images/pages/play/level/modal/victory_modal_blue_banner.png")#victory-banner - img(src="/images/pages/play/level/modal/victory_word.png")#victory-header.out + #victory-header.out + #victory-title + if me.get('preferredLanguage').split('-')[0] == 'en' + img(src="/images/pages/play/level/modal/victory_word.png", draggable="false") + else + h1(data-i18n="play_level.victory") Victory block modal-body-content @@ -43,33 +47,41 @@ block modal-body-content .reward-text= animate ? 'New Item' : item.get('name') block modal-footer-content + #totals + .total-wrapper#xp-wrapper + .total-count#xp-total 0 + .total-label + span.spr(data-i18n="play_level.victory_experience_gained") XP Gained + | - + span.spl.spr(data-i18n="general.player_level") Level + span.level= me.level() + .xp-bar-outer + .xp-bar-already-achieved + .xp-bar-total + .total-wrapper#gem-wrapper + .total-count#gem-total 0 + .total-label(data-i18n="play_level.victory_gems_gained") Gems Gained + if me.get('anonymous') - p.sign-up-poke.hide - button.btn.btn-success.sign-up-button.btn-large(data-toggle="coco-modal", data-target="core/AuthModal", data-i18n="play_level.victory_sign_up") Sign Up to Save Progress - span(data-i18n="play_level.victory_sign_up_poke") Want to save your code? Create a free account! + .sign-up-poke.hide + .sign-up-blurb(data-i18n="play_level.victory_sign_up_poke") Want to save your code? Create a free account! + button.btn.btn-illustrated.btn-warning.sign-up-button.btn-lg(data-toggle="coco-modal", data-target="core/AuthModal", data-i18n="play_level.victory_sign_up") Sign Up to Save Progress - div#totals.pull-left - span.spr Experience Gained: - span#xp-total +0 - br - span.spr Gems Gained: - span#gem-total +0 - - button.btn.btn-warning.hide#saving-progress-label(disabled, data-i18n="play_level.victory_saving_progress") Saving Progress + button.btn.btn-illustrated.btn-lg.btn-warning.hide#saving-progress-label(disabled, data-i18n="play_level.victory_saving_progress") Saving Progress .next-level-buttons if readyToRank .ladder-submission-view else if level.get('type') === 'hero-ladder' - button.btn.btn-primary.return-to-ladder-button(data-href="/play/ladder/#{level.get('slug')}#my-matches", data-dismiss="modal", data-i18n="play_level.victory_return_to_ladder") Return to Ladder + button.btn.btn-illustrated.btn-primary.btn-lg.return-to-ladder-button(data-href="/play/ladder/#{level.get('slug')}#my-matches", data-dismiss="modal", data-i18n="play_level.victory_return_to_ladder") Return to Ladder else - button.btn.btn-success.world-map-button.next-level-button.hide#continue-button(data-i18n="play_level.victory_play_continue") Continue + button.btn.btn-illustrated.btn-success.btn-lg.world-map-button.next-level-button.hide#continue-button(data-i18n="play_level.victory_play_continue") Continue if showHourOfCodeDoneButton .hour-of-code-done - hr a.image-link(href="http://code.org/api/hour/finish") img(src="/images/level/csedweek-logo-final-small.jpg", alt="CS Ed Week Hour of Code", title="I'm finished with my Hour of Code", width=80) strong(data-i18n="play_level.victory_hour_of_code_done") Are You Done? a.text-link(href="http://code.org/api/hour/finish") span(data-i18n="play_level.victory_hour_of_code_done_yes") Yes, I'm finished with my Hour of Code! + .clearfix \ No newline at end of file diff --git a/app/views/play/level/modal/HeroVictoryModal.coffee b/app/views/play/level/modal/HeroVictoryModal.coffee index 7f4ac26a3..d316a96ea 100644 --- a/app/views/play/level/modal/HeroVictoryModal.coffee +++ b/app/views/play/level/modal/HeroVictoryModal.coffee @@ -9,6 +9,8 @@ ThangType = require 'models/ThangType' LadderSubmissionView = require 'views/play/common/LadderSubmissionView' AudioPlayer = require 'lib/AudioPlayer' CampaignOptions = require 'lib/CampaignOptions' +User = require 'models/User' +utils = require 'core/utils' module.exports = class HeroVictoryModal extends ModalView id: 'hero-victory-modal' @@ -36,6 +38,8 @@ module.exports = class HeroVictoryModal extends ModalView @listenToOnce @achievements, 'sync', @onAchievementsLoaded @readyToContinue = false @waitingToContinueSince = new Date() + @previousXP = me.get 'points', true + @previousLevel = me.level() Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'victory' destroy: -> @@ -47,6 +51,7 @@ module.exports = class HeroVictoryModal extends ModalView super() onAchievementsLoaded: -> + @$el.toggleClass 'full-achievements', @achievements.models.length is 3 thangTypeOriginals = [] achievementIDs = [] for achievement in @achievements.models @@ -133,6 +138,7 @@ module.exports = class HeroVictoryModal extends ModalView return unless @supermodel.finished() @playSelectionSound hero, true for original, hero of @thangTypes # Preload them @updateSavingProgressStatus() + @updateXPBars 0 @$el.find('#victory-header').delay(250).queue(-> $(@).removeClass('out').dequeue() Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'victory-title-appear' # TODO: actually add this @@ -196,7 +202,8 @@ module.exports = class HeroVictoryModal extends ModalView totalXP = @totalXPAnimated + newXP if totalXP isnt @lastTotalXP panel.textEl.text('+' + newXP) - @XPEl.text('+' + totalXP) + @XPEl.text(totalXP) + @updateXPBars(totalXP) xpTrigger = 'xp-' + (totalXP % 6) # 6 xp sounds Backbone.Mediator.publish 'audio-player:play-sound', trigger: xpTrigger, volume: 0.5 + ratio / 2 @lastTotalXP = totalXP @@ -205,7 +212,7 @@ module.exports = class HeroVictoryModal extends ModalView totalGems = @totalGemsAnimated + newGems if totalGems isnt @lastTotalGems panel.textEl.text('+' + newGems) - @gemEl.text('+' + totalGems) + @gemEl.text(totalGems) gemTrigger = 'gem-' + (parseInt(panel.number * ratio) % 4) # 4 gem sounds Backbone.Mediator.publish 'audio-player:play-sound', trigger: gemTrigger, volume: 0.5 + ratio / 2 @lastTotalGems = totalGems @@ -237,6 +244,32 @@ module.exports = class HeroVictoryModal extends ModalView --t -0.5 * (t * (t - 2) - 1) + updateXPBars: (achievedXP) -> + previousXP = @previousXP + previousLevel = @previousLevel + + currentXP = previousXP + achievedXP + currentLevel = User.levelFromExp currentXP + currentLevelXP = User.expForLevel currentLevel + + nextLevel = currentLevel + 1 + nextLevelXP = User.expForLevel nextLevel + + leveledUp = currentLevel > previousLevel + totalXPNeeded = nextLevelXP - currentLevelXP + alreadyAchievedPercentage = 100 * (previousXP - currentLevelXP) / totalXPNeeded + alreadyAchievedPercentage = 0 if alreadyAchievedPercentage < 0 # In case of level up + if leveledUp + newlyAchievedPercentage = 100 * (currentXP - currentLevelXP) / totalXPNeeded + else + newlyAchievedPercentage = 100 * achievedXP / totalXPNeeded + + xpEl = $('#xp-wrapper') + xpBarJustEarned = xpEl.find('.xp-bar-already-achieved').css('width', alreadyAchievedPercentage + '%') + xpBarTotal = xpEl.find('.xp-bar-total').css('width', (alreadyAchievedPercentage + newlyAchievedPercentage) + '%') + levelLabel = xpEl.find('.level') + utils.replaceText levelLabel, currentLevel + endSequentialAnimations: -> clearInterval @sequentialAnimationInterval @animationComplete = true diff --git a/app/views/play/menu/InventoryModal.coffee b/app/views/play/menu/InventoryModal.coffee index a6ba6e20a..f83edf1a4 100644 --- a/app/views/play/menu/InventoryModal.coffee +++ b/app/views/play/menu/InventoryModal.coffee @@ -446,7 +446,7 @@ module.exports = class InventoryModal extends ModalView patchSession = patchMe = false patchSession ||= not _.isEqual inventory, sessionHeroConfig.inventory sessionHeroConfig.inventory = inventory - if hero = @selectedHero.get('original') + if hero = @selectedHero?.get('original') patchSession ||= not _.isEqual hero, sessionHeroConfig.thangType sessionHeroConfig.thangType = hero patchMe ||= not _.isEqual inventory, lastHeroConfig.inventory @@ -527,8 +527,8 @@ module.exports = class InventoryModal extends ModalView onClickedSomewhere: (e) -> return if @destroyed @$el.find('.unlock-button').popover 'destroy' - - + + #- Dynamic portrait loading onScrollUnequipped: ->