diff --git a/app/assets/images/pages/play/level/modal/reward_plate_wide.png b/app/assets/images/pages/play/level/modal/reward_plate_wide.png new file mode 100644 index 000000000..466c0af7f Binary files /dev/null and b/app/assets/images/pages/play/level/modal/reward_plate_wide.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 7ebfad857..11f8ad8f1 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 new file mode 100644 index 000000000..0c87583bf Binary files /dev/null and b/app/assets/images/pages/play/level/modal/victory_modal_blue_banner.png differ diff --git a/app/lib/LevelOptions.coffee b/app/lib/LevelOptions.coffee index 8279e7e1f..4470c4ebe 100644 --- a/app/lib/LevelOptions.coffee +++ b/app/lib/LevelOptions.coffee @@ -170,29 +170,29 @@ module.exports = LevelOptions = hidesSay: true hidesCodeToolbar: true hidesRealTimePlayback: true - requiredGear: {feet: 'simple-boots', 'right-hand': 'builders-hammer', torso: 'leather-tunic'} + requiredGear: {feet: 'simple-boots', 'right-hand': 'crude-builders-hammer', torso: 'leather-tunic'} restrictedGear: {'right-hand': 'simple-sword'} 'defense-of-plainswood': hidesRealTimePlayback: true hidesCodeToolbar: true - requiredGear: {feet: 'simple-boots', 'right-hand': 'builders-hammer'} + requiredGear: {feet: 'simple-boots', 'right-hand': 'crude-builders-hammer'} restrictedGear: {'right-hand': 'simple-sword'} 'winding-trail': hidesRealTimePlayback: true hidesCodeToolbar: true - requiredGear: {feet: 'leather-boots', 'right-hand': 'builders-hammer'} + requiredGear: {feet: 'leather-boots', 'right-hand': 'crude-builders-hammer'} restrictedGear: {feet: 'simple-boots', 'right-hand': 'simple-sword'} 'thornbush-farm': - requiredGear: {feet: 'leather-boots', 'right-hand': 'builders-hammer', eyes: 'crude-glasses'} + requiredGear: {feet: 'leather-boots', 'right-hand': 'crude-builders-hammer', eyes: 'crude-glasses'} hidesCodeToolbar: true restrictedGear: {feet: 'simple-boots', 'right-hand': 'simple-sword'} 'back-to-back': hidesCodeToolbar: true requiredGear: {feet: 'leather-boots', torso: 'leather-tunic', waist: 'leather-belt', 'programming-book': 'programmaticon-i', eyes: 'crude-glasses', 'right-hand': 'simple-sword', 'left-hand': 'wooden-shield'} - restrictedGear: {feet: 'simple-boots', 'right-hand': 'builders-hammer'} + restrictedGear: {feet: 'simple-boots', 'right-hand': 'crude-builders-hammer'} 'ogre-encampment': requiredGear: {torso: 'leather-tunic', waist: 'leather-belt', 'programming-book': 'programmaticon-i', eyes: 'crude-glasses', 'right-hand': 'simple-sword', 'left-hand': 'wooden-shield'} - restrictedGear: {feet: 'simple-boots', 'right-hand': 'builders-hammer'} + restrictedGear: {feet: 'simple-boots', 'right-hand': 'crude-builders-hammer'} 'woodland-cleaver': requiredGear: {torso: 'leather-tunic', waist: 'leather-belt', 'programming-book': 'programmaticon-i', eyes: 'crude-glasses', 'right-hand': 'long-sword', 'left-hand': 'wooden-shield', wrists: 'sundial-wristwatch', feet: 'leather-boots'} restrictedGear: {feet: 'simple-boots', 'right-hand': 'simple-sword'} @@ -212,14 +212,14 @@ module.exports = LevelOptions = requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses'} restrictedGear: {} 'drop-the-flag': - requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', 'right-hand': 'builders-hammer'} + requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', 'right-hand': 'crude-builders-hammer'} restrictedGear: {'right-hand': 'longsword'} 'deadly-pursuit': - requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', 'right-hand': 'builders-hammer'} + requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', 'right-hand': 'crude-builders-hammer'} restrictedGear: {'right-hand': 'longsword'} 'rich-forager': requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', torso: 'leather-tunic', 'right-hand': 'longsword', 'left-hand': 'bronze-shield'} - restrictedGear: {'right-hand': 'builders-hammer'} + restrictedGear: {'right-hand': 'crude-builders-hammer'} 'multiplayer-treasure-grove': requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', torso: 'leather-tunic'} restrictedGear: {} diff --git a/app/lib/surface/Surface.coffee b/app/lib/surface/Surface.coffee index 580029687..20c76ad36 100644 --- a/app/lib/surface/Surface.coffee +++ b/app/lib/surface/Surface.coffee @@ -558,7 +558,7 @@ module.exports = Surface = class Surface extends CocoClass @playing = false # Will start when countdown is done. if @heroLank @previousCameraZoom = @camera.zoom - @camera.zoomTo @heroLank.sprite, 2, 3000 + #@camera.zoomTo @heroLank.sprite, 2, 3000 # This makes flag placement hard, now that we're only rarely using this as a coolcam. onRealTimePlaybackEnded: (e) -> return unless @realTime diff --git a/app/styles/play/level/modal/hero-victory-modal.sass b/app/styles/play/level/modal/hero-victory-modal.sass index 17cdedfe9..4e4c8b523 100644 --- a/app/styles/play/level/modal/hero-victory-modal.sass +++ b/app/styles/play/level/modal/hero-victory-modal.sass @@ -12,15 +12,25 @@ .background-wrapper //background: url("/images/pages/play/level/modal/victory_modal_background.png") width: 550px + background-color: transparent + border: 0px solid transparent border-width: 25px border-image: url("/images/pages/play/level/modal/victory_modal_background.png") 25 fill round - border-radius: 10px + border-radius: 12px + + #victory-banner + position: absolute + left: -30px + z-index: 0 #victory-header + position: absolute + left: 135px display: block - margin: 15px auto 0 + 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) @@ -92,6 +102,15 @@ z-index: 1 @include transition(0.25s ease) + &.hero, &.item + background: url("/images/pages/play/level/modal/reward_plate_wide.png") + width: 120px + height: 83px + margin-top: 1px + + .reward-image-container + left: 33px + &.animating @include scale(1.5) z-index: 2 @@ -216,10 +235,15 @@ html.no-borderimage #hero-victory-modal .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 diff --git a/app/templates/play/level/modal/hero-victory-modal.jade b/app/templates/play/level/modal/hero-victory-modal.jade index 58a420693..6a7559e8b 100644 --- a/app/templates/play/level/modal/hero-victory-modal.jade +++ b/app/templates/play/level/modal/hero-victory-modal.jade @@ -1,5 +1,6 @@ extends /templates/modal/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 block modal-body-content diff --git a/app/views/game-menu/InventoryModal.coffee b/app/views/game-menu/InventoryModal.coffee index 69865e442..b5e3491bc 100644 --- a/app/views/game-menu/InventoryModal.coffee +++ b/app/views/game-menu/InventoryModal.coffee @@ -67,7 +67,7 @@ module.exports = class InventoryModal extends ModalView @itemGroups.availableItems = new Backbone.Collection() @itemGroups.restrictedItems = new Backbone.Collection() @itemGroups.lockedItems = new Backbone.Collection() - itemGroup.comparator = 'gems' for itemGroup in _.values @itemGroups + itemGroup.comparator = ((m) -> m.get('gems') ? m.get('tier')) for itemGroup in _.values @itemGroups equipped = _.values(@equipment) @sortItem(item, equipped) for item in @items.models @@ -89,6 +89,7 @@ module.exports = class InventoryModal extends ModalView @itemGroups.lockedItems.add(item) item.classes.push 'locked' item.classes.push 'silhouette' if item.isSilhouettedItem() + item.classes.push 'hidden' unless item.get('gems') else if item.get('slug') in _.values(LevelOptions[@options.levelID]?.restrictedGear ? {}) @itemGroups.restrictedItems.add(item) item.classes.push 'restricted' @@ -375,8 +376,8 @@ module.exports = class InventoryModal extends ModalView #continue if item is 'leather-tunic' and inWorldMap and @options.levelID is 'the-raised-sword' # Don't tell them they need it until they need it in the level # ... when we make it so that you can buy it equipped = equipment[slot] continue if equipped and not ( - (item is 'builders-hammer' and equipped in [gear['simple-sword'], gear['long-sword'], gear['sharpened-sword'], gear['roughedge']]) or - (item in ['simple-sword', 'long-sword', 'roughedge', 'sharpened-sword'] and equipped is gear['builders-hammer']) or + (item is 'crude-builders-hammer' and equipped in [gear['simple-sword'], gear['long-sword'], gear['sharpened-sword'], gear['roughedge']]) or + (item in ['simple-sword', 'long-sword', 'roughedge', 'sharpened-sword'] and equipped is gear['crude-builders-hammer']) or (item is 'leather-boots' and equipped is gear['simple-boots']) or (item is 'simple-boots' and equipped is gear['leather-boots']) ) @@ -463,7 +464,7 @@ gear = 'leather-belt': '5437002a7beba4a82024a97d' 'programmaticon-i': '53e4108204c00d4607a89f78' 'crude-glasses': '53e238df53457600003e3f0b' - 'builders-hammer': '53f4e6e3d822c23505b74f42' + 'crude-builders-hammer': '53f4e6e3d822c23505b74f42' 'long-sword': '544d7d1f8494308424f564a3' 'sundial-wristwatch': '53e2396a53457600003e3f0f' 'bronze-shield': '544c310ae0017993fce214bf' diff --git a/app/views/play/level/modal/HeroVictoryModal.coffee b/app/views/play/level/modal/HeroVictoryModal.coffee index 85d5991f1..6e16c442e 100644 --- a/app/views/play/level/modal/HeroVictoryModal.coffee +++ b/app/views/play/level/modal/HeroVictoryModal.coffee @@ -116,8 +116,8 @@ module.exports = class HeroVictoryModal extends ModalView c.readyToRank = @level.get('type', true) is 'hero-ladder' and @session.readyToRank() c.level = @level @continueLevelLink = @getNextLevelLink 'continue' - @morePracticeLevelLink = me.isAdmin() and @getNextLevelLink 'more_practice' - @skipAheadLevelLink = me.isAdmin() and @getNextLevelLink 'skip_ahead' + @morePracticeLevelLink = @getNextLevelLink 'more_practice' + @skipAheadLevelLink = @getNextLevelLink 'skip_ahead' c.continueButtons = [ {key: 'skip_ahead', link: @skipAheadLevelLink, 'choice-explicit': 'skip', 'choice-implicit': 'too_easy'} {key: 'continue', link: @continueLevelLink, 'choice-explicit': 'next_level', 'choice-implicit': 'just_right'} diff --git a/app/views/play/level/tome/TomeView.coffee b/app/views/play/level/tome/TomeView.coffee index fff2529b4..6845e18b9 100644 --- a/app/views/play/level/tome/TomeView.coffee +++ b/app/views/play/level/tome/TomeView.coffee @@ -161,7 +161,7 @@ module.exports = class TomeView extends CocoView sessionState = @options.session.get('state') ? {} if realTime sessionState.submissionCount = (sessionState.submissionCount ? 0) + 1 - sessionState.flagHistory = _.filter sessionState.flagHistory ? [], (event) => event.team isnt @options.session.get('team') + sessionState.flagHistory = _.filter sessionState.flagHistory ? [], (event) => event.team isnt (@options.session.get('team') ? 'humans') @options.session.set 'state', sessionState Backbone.Mediator.publish 'tome:cast-spells', spells: @spells, preload: preload, realTime: realTime, submissionCount: sessionState.submissionCount ? 0, flagHistory: sessionState.flagHistory ? [] diff --git a/app/views/play/modal/PlayItemsModal.coffee b/app/views/play/modal/PlayItemsModal.coffee index 88805a346..6ccbd123c 100644 --- a/app/views/play/modal/PlayItemsModal.coffee +++ b/app/views/play/modal/PlayItemsModal.coffee @@ -83,7 +83,7 @@ module.exports = class PlayItemsModal extends ModalView category = slotToCategory[model.getAllowedSlots()[0]] or 'misc' @itemCategoryCollections[category] ?= new Backbone.Collection() collection = @itemCategoryCollections[category] - collection.comparator = 'gems' + collection.comparator = (m) -> m.get('gems') ? m.get('tier') collection.add(model) model.name = utils.i18n model.attributes, 'name' model.affordable = cost <= gemsOwned diff --git a/server/achievements/earned_achievement_handler.coffee b/server/achievements/earned_achievement_handler.coffee index 4c7cc979f..e39e1dd4c 100644 --- a/server/achievements/earned_achievement_handler.coffee +++ b/server/achievements/earned_achievement_handler.coffee @@ -23,12 +23,12 @@ class EarnedAchievementHandler extends Handler ids = req.query.achievementIDs if (not ids) or (ids.length is 0) return @sendBadInputError(res, 'For a get-by-achievement-ids request, need to provide ids.') - + ids = ids.split(',') for id in ids if not Handler.isID(id) return @sendBadInputError(res, "Not a MongoDB ObjectId: #{id}") - + query.achievement = {$in: ids} EarnedAchievement.find query, (err, earnedAchievements) -> return @sendDatabaseError(res, err) if err @@ -121,6 +121,7 @@ class EarnedAchievementHandler extends Handler return doneWithAchievement new Error "Model with collection '#{achievement.get 'collection'}' doesn't exist." unless model? finalQuery = _.clone achievement.get 'query' + return doneWithAchievement() if _.isEmpty finalQuery finalQuery.$or = [{}, {}] # Allow both ObjectIDs or hex string IDs finalQuery.$or[0][achievement.userField] = userID finalQuery.$or[1][achievement.userField] = mongoose.Types.ObjectId userID diff --git a/server/plugins/achievements.coffee b/server/plugins/achievements.coffee index b252981e4..c29d25374 100644 --- a/server/plugins/achievements.coffee +++ b/server/plugins/achievements.coffee @@ -36,6 +36,7 @@ AchievablePlugin = (schema, options) -> for achievement in loadedAchievements[category] do (achievement) -> query = achievement.get('query') + return log.warn("Empty achievement query for #{achievement.get('name')}.") if _.isEmpty query isRepeatable = achievement.get('proportionalTo')? alreadyAchieved = if isNew then false else LocalMongo.matchesQuery originalDocObj, query newlyAchieved = LocalMongo.matchesQuery(docObj, query)