diff --git a/app/lib/AudioPlayer.coffee b/app/lib/AudioPlayer.coffee index 7208bd20e..3a32d3759 100644 --- a/app/lib/AudioPlayer.coffee +++ b/app/lib/AudioPlayer.coffee @@ -108,7 +108,7 @@ class AudioPlayer extends CocoClass # TODO: load Interface sounds somehow, somewhere, somewhen preloadSoundReference: (sound) -> - name = @nameForSoundReference sound + return unless name = @nameForSoundReference sound filename = '/file/' + name @preloadSound filename, name filename diff --git a/app/lib/LevelLoader.coffee b/app/lib/LevelLoader.coffee index e832a9495..d588238fb 100644 --- a/app/lib/LevelLoader.coffee +++ b/app/lib/LevelLoader.coffee @@ -97,12 +97,21 @@ module.exports = class LevelLoader extends CocoClass heroConfig ?= {inventory: {}, thangType: '529ffbf1cf1818f2be000001'} # If we got here not from PlayLevelModal (like level editor preview), assign Tharin as the hero. session.set 'heroConfig', heroConfig unless _.isEqual heroConfig, session.get('heroConfig') url = "/db/thang.type/#{heroConfig.thangType}/version" - @worldNecessities.push @maybeLoadURL(url, ThangType, 'thang') + if heroResource = @maybeLoadURL(url, ThangType, 'thang') + @worldNecessities.push heroResource + else + heroThangType = @supermodel.getModel url + @loadDefaultComponentsForThangType heroThangType + @loadThangsRequiredByThangType heroThangType for itemThangType in _.values(heroConfig.inventory) url = "/db/thang.type/#{itemThangType}/version?project=name,components,original" - @worldNecessities.push @maybeLoadURL(url, ThangType, 'thang') - + if itemResource = @maybeLoadURL(url, ThangType, 'thang') + @worldNecessities.push itemResource + else + itemThangType = @supermodel.getModel url + @loadDefaultComponentsForThangType itemThangType + @loadThangsRequiredByThangType itemThangType # Grabbing the rest of the required data for the level diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee index f76caa2e4..798a8f38b 100644 --- a/app/lib/surface/CocoSprite.coffee +++ b/app/lib/surface/CocoSprite.coffee @@ -90,7 +90,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass setUpSprite: -> for trigger, sounds of @thangType.get('soundTriggers') or {} when trigger isnt 'say' - AudioPlayer.preloadSoundReference sound for sound in sounds + AudioPlayer.preloadSoundReference sound for sound in sounds when sound if @thangType.get('raster') @stillLoading = false @actions = {} diff --git a/app/lib/world/world.coffee b/app/lib/world/world.coffee index 299296b3d..0cc3469de 100644 --- a/app/lib/world/world.coffee +++ b/app/lib/world/world.coffee @@ -68,6 +68,7 @@ module.exports = class World setThang: (thang) -> for old, i in @thangs + console.error 'world trying to set', thang, 'over', old unless old? and thang? if old.id is thang.id @thangs[i] = thang @thangMap[thang.id] = thang diff --git a/app/styles/game-menu/inventory-view.sass b/app/styles/game-menu/inventory-view.sass index 5d139338d..70615c5ea 100644 --- a/app/styles/game-menu/inventory-view.sass +++ b/app/styles/game-menu/inventory-view.sass @@ -122,25 +122,6 @@ $stashWidth: $totalWidth - $equippedWidth - $stashMargin margin-bottom: $heroContainerBottomMargin / 2 - 1 border-top: 1px solid #aaa - .panel - text-align: center - width: 31.3% - margin: 5px 2% 5px 0 - float: left - cursor: pointer - - .panel-heading - padding: 5px - - .panel-info .panel-body - background-color: #e0f0f5 - - .panel-body - height: 50px - padding: 5px - overflow: scroll - font-size: 12px - #available-equipment width: $stashWidth position: absolute @@ -163,6 +144,11 @@ $stashWidth: $totalWidth - $equippedWidth - $stashMargin background-color: #e0f0f5 &.equipped display: none + &.restricted + @include opacity(0.5) + + .item-info:after + content: ' (locked)' .item-view cursor: pointer diff --git a/app/templates/play/level/modal/victory.jade b/app/templates/play/level/modal/victory.jade index 08a753b81..0620c91e8 100644 --- a/app/templates/play/level/modal/victory.jade +++ b/app/templates/play/level/modal/victory.jade @@ -17,7 +17,10 @@ block modal-footer-content a.btn.btn-primary(href="/play/ladder/#{level.get('slug')}#my-matches", data-dismiss="modal", data-i18n="play_level.victory_go_ladder") Return to Ladder else if hasNextLevel button.btn.btn-success.next-level-button(data-dismiss="modal", data-i18n="play_level.victory_play_next_level") Play Next Level - a.btn.btn-primary(href="/play-hero", data-dismiss="modal", data-i18n="play_level.victory_go_home") Go Home + else if level.get('type', true) === 'hero' + a.btn.btn-success(href="/play-hero", data-dismiss="modal", data-i18n="play_level.victory_play_next_level") Play Next Level + else + a.btn.btn-primary(href="/", data-dismiss="modal", data-i18n="play_level.victory_go_home") Go Home if me.get('anonymous') p.sign-up-poke button.btn.btn-success.sign-up-button.btn-large(data-toggle="coco-modal", data-target="modal/SignupModal", data-i18n="play_level.victory_sign_up") Sign Up to Save Progress diff --git a/app/views/game-menu/GameMenuModal.coffee b/app/views/game-menu/GameMenuModal.coffee index 514f1e486..6d64d44e8 100644 --- a/app/views/game-menu/GameMenuModal.coffee +++ b/app/views/game-menu/GameMenuModal.coffee @@ -23,6 +23,7 @@ module.exports = class GameMenuModal extends ModalView @options.showDevBits = me.isAdmin() or /https?:\/\/localhost/.test(window.location.href) @options.showInventory = @options.level.get('type', true) is 'hero' @options.levelID = @options.level.get('slug') + @options.startingSessionHeroConfig = $.extend {}, true, (@options.session.get('heroConfig') ? {}) getRenderData: (context={}) -> context = super(context) @@ -51,7 +52,7 @@ module.exports = class GameMenuModal extends ModalView Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'game-menu-close', volume: 1 updateConfig: -> - sessionHeroConfig = $.extend {}, true, (@options.session.get('heroConfig') ? {}) + sessionHeroConfig = @options.startingSessionHeroConfig lastHeroConfig = me.get('heroConfig') ? {} thangType = @subviews.choose_hero_view.selectedHero?.get 'original' inventory = @subviews.inventory_view.getCurrentEquipmentConfig() diff --git a/app/views/game-menu/InventoryView.coffee b/app/views/game-menu/InventoryView.coffee index ea35d572d..4482a51af 100644 --- a/app/views/game-menu/InventoryView.coffee +++ b/app/views/game-menu/InventoryView.coffee @@ -39,7 +39,6 @@ module.exports = class InventoryView extends CocoView super() onLoaded: -> - @items.models = _.filter(@items.models, (item) => item.get('original') in @allowedItems) if @allowedItems item.notInLevel = true for item in @items.models super() @@ -51,6 +50,8 @@ module.exports = class InventoryView extends CocoView for item in @items.models item.classes = item.getAllowedSlots() item.classes.push 'equipped' if item.get('original') in context.equipped + item.classes.push 'restricted' if @allowedItems and not (item.get('original') in @allowedItems) + @items.models.sort (a, b) -> ('restricted' in a.classes) - ('restricted' in b.classes) context.slots = @slots context.equipment = _.clone @equipment @@ -82,6 +83,7 @@ module.exports = class InventoryView extends CocoView itemView.render() $(availableItemEl).append(itemView.$el) @registerSubView(itemView) + continue if $(availableItemEl).hasClass 'restricted' dragHelper = itemView.$el.find('img').clone().addClass('draggable-item') do (dragHelper, itemView) => itemView.$el.draggable @@ -134,13 +136,17 @@ module.exports = class InventoryView extends CocoView onAvailableItemClick: (e) -> itemContainer = $(e.target).closest('.list-group-item') + return if itemContainer.hasClass 'restricted' wasActive = itemContainer.hasClass 'active' @unselectAllAvailableEquipment() @selectAvailableItem(itemContainer) unless wasActive @onSelectionChanged() onAvailableItemDoubleClick: (e) -> - @selectAvailableItem $(e.target).closest('.list-group-item') if e + if e + itemContainer = $(e.target).closest('.list-group-item') + return if itemContainer.hasClass 'restricted' + @selectAvailableItem itemContainer @onSelectionChanged() slot = @getSelectedSlot() slot = @$el.find('.item-slot:not(.disabled):first') if not slot.length @@ -316,7 +322,13 @@ module.exports = class InventoryView extends CocoView necessaryGear = gearByLevel[@options.levelID] for slot, item of necessaryGear ? {} @equipment[slot] ?= gear[item] - @allowedItems = _.union(_.values(gear), _.values(@equipment)) if necessaryGear # If it's one of these levels, don't show the extra items. + + # Restrict available items to those that would be available by this item. + @allowedItems = [] + for level, items of gearByLevel + for slot, item of items + @allowedItems.push gear[item] unless gear[item] in @allowedItems + break if level is @options.levelID onHeroSelectionUpdated: (e) -> @selectedHero = e.hero diff --git a/app/views/play/level/LevelHUDView.coffee b/app/views/play/level/LevelHUDView.coffee index aac9d209a..1c37ac3df 100644 --- a/app/views/play/level/LevelHUDView.coffee +++ b/app/views/play/level/LevelHUDView.coffee @@ -199,7 +199,12 @@ module.exports = class LevelHUDView extends CocoView group.append('' + sk + '') group.append($('')) @lastResponses = null - @bubble.append($("

#{@speaker ? 'Captain Anya'}

")) + if @speaker is 'Hero Placeholder' + # Doesn't work if it fires from a script; we don't really know who we are then. + name = {knight: 'Tharin', captain: 'Anya'}[@speakerSprite?.thang?.id] ? 'Hero' + else + name = @speaker + @bubble.append($("

#{name}

")) @animator = new DialogueAnimator(message, @bubble) @messageInterval = setInterval(@addMoreMessage, 1000 / 30) # 30 FPS diff --git a/app/views/play/level/PlayLevelView.coffee b/app/views/play/level/PlayLevelView.coffee index 891cc4862..8bce360df 100644 --- a/app/views/play/level/PlayLevelView.coffee +++ b/app/views/play/level/PlayLevelView.coffee @@ -369,16 +369,19 @@ module.exports = class PlayLevelView extends RootView return if @alreadyLoadedState @alreadyLoadedState = true state = @originalSessionState - if state.frame and @level.get('type', true) isnt 'ladder' # https://github.com/codecombat/codecombat/issues/714 - Backbone.Mediator.publish 'level:set-time', time: 0, frameOffset: state.frame if @level.get('type', true) is 'hero' Backbone.Mediator.publish 'tome:select-primary-sprite', {} @surface.focusOnHero() - else if state.selected - # TODO: Should also restore selected spell here by saving spellName - Backbone.Mediator.publish 'level:select-sprite', thangID: state.selected, spellName: null - if state.playing? - Backbone.Mediator.publish 'level:set-playing', playing: state.playing + Backbone.Mediator.publish 'level:set-time', time: 0 + Backbone.Mediator.publish 'level:set-playing', playing: true + else + if state.frame and @level.get('type', true) isnt 'ladder' # https://github.com/codecombat/codecombat/issues/714 + Backbone.Mediator.publish 'level:set-time', time: 0, frameOffset: state.frame + if state.selected + # TODO: Should also restore selected spell here by saving spellName + Backbone.Mediator.publish 'level:select-sprite', thangID: state.selected, spellName: null + if state.playing? + Backbone.Mediator.publish 'level:set-playing', playing: state.playing # callbacks diff --git a/app/views/play/level/modal/VictoryModal.coffee b/app/views/play/level/modal/VictoryModal.coffee index 083963193..e985b9e70 100644 --- a/app/views/play/level/modal/VictoryModal.coffee +++ b/app/views/play/level/modal/VictoryModal.coffee @@ -34,6 +34,9 @@ module.exports = class VictoryModal extends ModalView @session = options.session @saveReviewEventually = _.debounce(@saveReviewEventually, 2000) @loadExistingFeedback() + if @level.get('type', true) is 'hero' + @closeButton = false + @closesOnClickOutside = false super options loadExistingFeedback: ->