From 56a80e3615ef720f2d9c639b3c83a58361c981d3 Mon Sep 17 00:00:00 2001 From: Nick Winter Date: Sat, 18 Oct 2014 14:51:43 -0700 Subject: [PATCH] Started getting hero-ladder level type working. --- app/lib/LevelLoader.coffee | 6 ++-- app/lib/simulator/Simulator.coffee | 2 +- app/lib/surface/Surface.coffee | 4 ++- app/models/Level.coffee | 35 ++++++++++++------- app/schemas/models/level.coffee | 2 +- .../component/ThangComponentConfigView.coffee | 2 +- .../level/thangs/LevelThangEditView.coffee | 2 +- .../editor/level/thangs/ThangsTabView.coffee | 6 ++-- app/views/game-menu/GameMenuModal.coffee | 2 +- app/views/game-menu/MultiplayerView.coffee | 4 +-- app/views/play/SpectateView.coffee | 6 ++-- app/views/play/WorldMapView.coffee | 11 ++++++ app/views/play/ladder/utils.coffee | 2 +- app/views/play/level/ControlBarView.coffee | 6 ++-- app/views/play/level/LevelHUDView.coffee | 2 +- app/views/play/level/LevelPlaybackView.coffee | 2 +- app/views/play/level/PlayLevelView.coffee | 27 +++++++------- .../play/level/modal/VictoryModal.coffee | 5 +-- app/views/play/level/tome/Spell.coffee | 2 +- .../play/level/tome/SpellPaletteView.coffee | 6 ++-- app/views/play/level/tome/TomeView.coffee | 2 +- server/levels/level_handler.coffee | 2 +- server/queues/scoring.coffee | 2 +- 23 files changed, 81 insertions(+), 59 deletions(-) diff --git a/app/lib/LevelLoader.coffee b/app/lib/LevelLoader.coffee index 3bd7c64b3..8f69b2229 100644 --- a/app/lib/LevelLoader.coffee +++ b/app/lib/LevelLoader.coffee @@ -91,9 +91,9 @@ module.exports = class LevelLoader extends CocoClass loadDependenciesForSession: (session) -> if session is @session Backbone.Mediator.publish 'level:session-loaded', level: @level, session: @session - return unless @level.get('type', true) is 'hero' + return unless @level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] heroConfig = session.get('heroConfig') - heroConfig ?= me.get('heroConfig') + heroConfig ?= me.get('heroConfig') if session is @session heroConfig ?= {inventory: {}, thangType: '529ffbf1cf1818f2be000001'} # If all else fails, assign Tharin as the hero. session.set 'heroConfig', heroConfig unless _.isEqual heroConfig, session.get('heroConfig') url = "/db/thang.type/#{heroConfig.thangType}/version" @@ -334,7 +334,7 @@ module.exports = class LevelLoader extends CocoClass @initialized = true @world = new World() @world.levelSessionIDs = if @opponentSessionID then [@sessionID, @opponentSessionID] else [@sessionID] - serializedLevel = @level.serialize(@supermodel, @session) + serializedLevel = @level.serialize(@supermodel, @session, @opponentSession) @world.loadFromLevel serializedLevel, false console.log 'World has been initialized from level loader.' diff --git a/app/lib/simulator/Simulator.coffee b/app/lib/simulator/Simulator.coffee index 01cff2057..eef6edae0 100644 --- a/app/lib/simulator/Simulator.coffee +++ b/app/lib/simulator/Simulator.coffee @@ -193,7 +193,7 @@ module.exports = class Simulator extends CocoClass @levelLoader = null setupGod: -> - @god.setLevel @level.serialize @supermodel + @god.setLevel @level.serialize @supermodel, @task.getSessions()[0], @task.getSessions()[1] @god.setLevelSessionIDs (session.sessionID for session in @task.getSessions()) @god.setWorldClassMap @world.classMap @god.setGoalManager new GoalManager(@world, @level.get 'goals') diff --git a/app/lib/surface/Surface.coffee b/app/lib/surface/Surface.coffee index bb2f26f86..727cab71a 100644 --- a/app/lib/surface/Surface.coffee +++ b/app/lib/surface/Surface.coffee @@ -540,7 +540,9 @@ module.exports = Surface = class Surface extends CocoClass #- Camera focus on hero focusOnHero: -> @heroLank = @lankBoss.lankFor 'Hero Placeholder' - + if me.team is 'ogres' + # TODO: do this for real + @heroLank = @lankBoss.lankFor 'Hero Placeholder 1' #- Real-time playback diff --git a/app/models/Level.coffee b/app/models/Level.coffee index 1851bfbe1..1a89588cd 100644 --- a/app/models/Level.coffee +++ b/app/models/Level.coffee @@ -8,8 +8,8 @@ module.exports = class Level extends CocoModel @schema: require 'schemas/models/level' urlRoot: '/db/level' - serialize: (supermodel, session, cached=false) -> - o = @denormalize supermodel, session # hot spot to optimize + serialize: (supermodel, session, otherSession, cached=false) -> + o = @denormalize supermodel, session, otherSession # hot spot to optimize # Figure out Components o.levelComponents = if cached then @getCachedLevelComponents(supermodel) else $.extend true, [], (lc.attributes for lc in supermodel.getModels LevelComponent) @@ -44,17 +44,24 @@ module.exports = class Level extends CocoModel newLevelComponents.push(@cachedLevelComponents[levelComponent.id]) newLevelComponents - denormalize: (supermodel, session) -> + denormalize: (supermodel, session, otherSession) -> o = $.extend true, {}, @attributes - if o.thangs and @get('type', true) is 'hero' - # TOOD: figure out if/when/how we are doing this for non-Hero levels that aren't expecting denormalization. + if o.thangs and @get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] for levelThang in o.thangs - @denormalizeThang(levelThang, supermodel, session) + @denormalizeThang(levelThang, supermodel, session, otherSession) o - denormalizeThang: (levelThang, supermodel, session) -> + denormalizeThang: (levelThang, supermodel, session, otherSession) -> levelThang.components ?= [] - isHero = levelThang.id is 'Hero Placeholder' + isHero = /Hero Placeholder/.test levelThang.id + if isHero and otherSession + # If it's a hero and there's another session, find the right session for it. + # If there is no other session (playing against default code, or on single player), clone all placeholders. + # TODO: actually look at the teams on these things to determine which session should go with which placeholder. + if levelThang.id is 'Hero Placeholder 1' and session.get('team') is 'humans' + session = otherSession + else if levelThang.id is 'Hero Placeholder' and session.get('team') is 'ogres' + session = otherSession # Empty out placeholder Components and store their values if we're the hero placeholder. if isHero @@ -129,6 +136,7 @@ module.exports = class Level extends CocoModel # Example: Programmable must come last, since it has to override any Component-provided methods that any other Component might have created. Can't enumerate all soft dependencies. # Example: Plans needs to come after everything except Programmable, since other Components that add plannable methods need to have done so by the time Plans is attached. # Example: Collides doesn't depend on Allied, but if both exist, Collides must come after Allied. Soft dependency example. Can't just figure out a proper priority to take care of it. + # Example: Moves doesn't depend on Acts, but if both exist, Moves must come after Acts. Another soft dependency example. # Decision? Just special case the sort logic in here until we have more examples than these two and decide how best to handle most of the cases then, since we don't really know the whole of the problem yet. # TODO: anything that depends on Programmable will break right now. @@ -158,10 +166,13 @@ module.exports = class Level extends CocoModel console.error parentType, thang.id or thang.name, 'does not have dependent Component', dependent, 'from', lc.name visit c2 if c2 if lc.name is 'Collides' - allied = _.find levelComponents, {name: 'Allied'} - if allied - collides = _.find(thang.components, {original: allied.original}) - visit collides if collides + if allied = _.find levelComponents, {name: 'Allied'} + allied = _.find(thang.components, {original: allied.original}) + visit allied if allied + if lc.name is 'Moves' + if acts = _.find levelComponents, {name: 'Acts'} + acts = _.find(thang.components, {original: acts.original}) + visit acts if acts #console.log thang.id, 'sorted comps adding', lc.name sorted.push c for comp in thang.components diff --git a/app/schemas/models/level.coffee b/app/schemas/models/level.coffee index 318265cfb..be5b83621 100644 --- a/app/schemas/models/level.coffee +++ b/app/schemas/models/level.coffee @@ -244,7 +244,7 @@ _.extend LevelSchema.properties, icon: {type: 'string', format: 'image-file', title: 'Icon'} banner: {type: 'string', format: 'image-file', title: 'Banner'} goals: c.array {title: 'Goals', description: 'An array of goals which are visible to the player and can trigger scripts.'}, GoalSchema - type: c.shortString(title: 'Type', description: 'What kind of level this is.', 'enum': ['campaign', 'ladder', 'ladder-tutorial', 'hero']) + type: c.shortString(title: 'Type', description: 'What kind of level this is.', 'enum': ['campaign', 'ladder', 'ladder-tutorial', 'hero', 'hero-ladder', 'hero-coop']) terrain: c.terrainString showsGuide: c.shortString(title: 'Shows Guide', description: 'If the guide is shown at the beginning of the level.', 'enum': ['first-time', 'always']) diff --git a/app/views/editor/component/ThangComponentConfigView.coffee b/app/views/editor/component/ThangComponentConfigView.coffee index 343a75017..b89f96db3 100644 --- a/app/views/editor/component/ThangComponentConfigView.coffee +++ b/app/views/editor/component/ThangComponentConfigView.coffee @@ -52,7 +52,7 @@ module.exports = class ThangComponentConfigView extends CocoView schema.default ?= {} _.merge schema.default, @additionalDefaults if @additionalDefaults - if @level?.get('type', true) is 'hero' + if @level?.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] schema.required = [] treemaOptions = supermodel: @supermodel diff --git a/app/views/editor/level/thangs/LevelThangEditView.coffee b/app/views/editor/level/thangs/LevelThangEditView.coffee index d5debf33b..b909acb25 100644 --- a/app/views/editor/level/thangs/LevelThangEditView.coffee +++ b/app/views/editor/level/thangs/LevelThangEditView.coffee @@ -46,7 +46,7 @@ module.exports = class LevelThangEditView extends CocoView level: @level world: @world - if @level.get('type', true) is 'hero' then options.thangType = thangType + if @level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] then options.thangType = thangType @thangComponentEditView = new ThangComponentsEditView options @listenTo @thangComponentEditView, 'components-changed', @onComponentsChanged diff --git a/app/views/editor/level/thangs/ThangsTabView.coffee b/app/views/editor/level/thangs/ThangsTabView.coffee index 292c02d2f..6d2f39c6f 100644 --- a/app/views/editor/level/thangs/ThangsTabView.coffee +++ b/app/views/editor/level/thangs/ThangsTabView.coffee @@ -520,7 +520,7 @@ module.exports = class ThangsTabView extends CocoView @level.set 'thangs', thangs return if @editThangView - serializedLevel = @level.serialize @supermodel, null, true + serializedLevel = @level.serialize @supermodel, null, null, true try @world.loadFromLevel serializedLevel, false catch error @@ -552,14 +552,14 @@ module.exports = class ThangsTabView extends CocoView if batchInsert if thangType.get('name') is 'Hero Placeholder' thangID = 'Hero Placeholder' - return if @level.get('type', true) isnt 'hero' or @getThangByID(thangID) + return if not (@level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop']) or @getThangByID(thangID) else thangID = "Random #{thangType.get('name')} #{@thangsBatch.length}" else thangID = Thang.nextID(thangType.get('name'), @world) until thangID and not @getThangByID(thangID) if @cloneSourceThang components = _.cloneDeep @getThangByID(@cloneSourceThang.id).components - else if @level.get('type', true) is 'hero' + else if @level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] components = [] # Load them all from default ThangType Components else components = _.cloneDeep thangType.get('components') ? [] diff --git a/app/views/game-menu/GameMenuModal.coffee b/app/views/game-menu/GameMenuModal.coffee index 1b4d63092..04df7322e 100644 --- a/app/views/game-menu/GameMenuModal.coffee +++ b/app/views/game-menu/GameMenuModal.coffee @@ -21,7 +21,7 @@ module.exports = class GameMenuModal extends ModalView constructor: (options) -> super options @options.showDevBits = me.isAdmin() or /https?:\/\/localhost/.test(window.location.href) - @options.showInventory = @options.level.get('type', true) is 'hero' + @options.showInventory = @options.level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] @options.levelID = @options.level.get('slug') @options.startingSessionHeroConfig = $.extend {}, true, (@options.session.get('heroConfig') ? {}) diff --git a/app/views/game-menu/MultiplayerView.coffee b/app/views/game-menu/MultiplayerView.coffee index 9d95345bd..e1a3b56b4 100644 --- a/app/views/game-menu/MultiplayerView.coffee +++ b/app/views/game-menu/MultiplayerView.coffee @@ -40,7 +40,7 @@ module.exports = class MultiplayerView extends CocoView c.team = @session.get 'team' c.levelSlug = @level?.get 'slug' # For now, ladderGame will disallow multiplayer, because session code combining doesn't play nice yet. - if @level?.get('type') is 'ladder' + if @level?.get('type') in ['ladder', 'hero-ladder'] c.ladderGame = true c.readyToRank = @session?.readyToRank() @@ -68,7 +68,7 @@ module.exports = class MultiplayerView extends CocoView updateLinkSection: -> multiplayer = @$el.find('#multiplayer').prop('checked') la = @$el.find('#link-area') - la.toggle if @level?.get('type') is 'ladder' then false else Boolean(multiplayer) + la.toggle if @level?.get('type') in ['ladder', 'hero-ladder'] then false else Boolean(multiplayer) true onHidden: -> diff --git a/app/views/play/SpectateView.coffee b/app/views/play/SpectateView.coffee index 9c6cc5dc9..095ee4be9 100644 --- a/app/views/play/SpectateView.coffee +++ b/app/views/play/SpectateView.coffee @@ -68,7 +68,7 @@ module.exports = class SpectateLevelView extends RootView @load() setLevel: (@level, @supermodel) -> - serializedLevel = @level.serialize @supermodel, @session + serializedLevel = @level.serialize @supermodel, @session, @otherSession @god?.setLevel serializedLevel if @world @world.loadFromLevel serializedLevel, false @@ -105,7 +105,7 @@ module.exports = class SpectateLevelView extends RootView #at this point, all requisite data is loaded, and sessions are not denormalized team = @world.teamForPlayer(0) @loadOpponentTeam(team) - @god.setLevel @level.serialize @supermodel, @session + @god.setLevel @level.serialize @supermodel, @session, @otherSession @god.setLevelSessionIDs if @otherSession then [@session.id, @otherSession.id] else [@session.id] @god.setWorldClassMap @world.classMap @setTeam team @@ -119,7 +119,7 @@ module.exports = class SpectateLevelView extends RootView @register() @controlBar.setBus(@bus) @surface.showLevel() - if @level.get('type', true) isnt 'hero' + if not (@level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop']) if me.id isnt @session.get 'creator' @surface.createOpponentWizard id: @session.get('creator') diff --git a/app/views/play/WorldMapView.coffee b/app/views/play/WorldMapView.coffee index 80a83eadc..2968c9884 100644 --- a/app/views/play/WorldMapView.coffee +++ b/app/views/play/WorldMapView.coffee @@ -718,6 +718,17 @@ hero = [ x: 95.31 y: 88.26 } + { + name: 'Dueling Grounds' + type: 'hero-ladder' + difficulty: 1 + id: 'dueling-grounds' + original: '5442ba0e1e835500007eb1c7' + description: 'Battle head-to-head against another hero in this basic beginner combat arena.' + disabled: not me.isAdmin() + x: 17.54 + y: 78.39 + } #{ # name: '' # type: 'hero' diff --git a/app/views/play/ladder/utils.coffee b/app/views/play/ladder/utils.coffee index ffa340ac3..182777b37 100644 --- a/app/views/play/ladder/utils.coffee +++ b/app/views/play/ladder/utils.coffee @@ -1,7 +1,7 @@ {hslToHex} = require 'lib/utils' module.exports.teamDataFromLevel = (level) -> - alliedSystem = _.find level.get('systems'), (value) -> value.config?.teams? + alliedSystem = _.find level.get('systems', true), (value) -> value.config?.teams? teamNames = (teamName for teamName, teamConfig of alliedSystem.config.teams when teamConfig.playable) teamConfigs = alliedSystem.config.teams diff --git a/app/views/play/level/ControlBarView.coffee b/app/views/play/level/ControlBarView.coffee index f5a779e94..722dec599 100644 --- a/app/views/play/level/ControlBarView.coffee +++ b/app/views/play/level/ControlBarView.coffee @@ -51,15 +51,15 @@ module.exports = class ControlBarView extends CocoView super c c.worldName = @worldName c.multiplayerEnabled = @session.get('multiplayer') - c.ladderGame = @level.get('type') is 'ladder' + c.ladderGame = @level.get('type') in ['ladder', 'hero-ladder'] c.spectateGame = @spectateGame @homeViewArgs = [{supermodel: @supermodel}] - if @level.get('type', true) in ['ladder', 'ladder-tutorial'] + if @level.get('type', true) in ['ladder', 'ladder-tutorial', 'hero-ladder'] levelID = @level.get('slug').replace /\-tutorial$/, '' @homeLink = c.homeLink = '/play/ladder/' + levelID @homeViewClass = require 'views/play/ladder/LadderView' @homeViewArgs.push levelID - else if @level.get('type', true) is 'hero' + else if @level.get('type', true) in ['hero', 'hero-coop'] @homeLink = c.homeLink = '/play' @homeViewClass = require 'views/play/WorldMapView' else diff --git a/app/views/play/level/LevelHUDView.coffee b/app/views/play/level/LevelHUDView.coffee index f315920a1..87691450e 100644 --- a/app/views/play/level/LevelHUDView.coffee +++ b/app/views/play/level/LevelHUDView.coffee @@ -85,7 +85,7 @@ module.exports = class LevelHUDView extends CocoView clearTimeout @hintNextSelectionTimeout @$el.find('.no-selection-message').hide() if not @thang - unless @options.level.get('type', true) is 'hero' + unless @options.level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] @hintNextSelectionTimeout = _.delay((=> @$el.find('.no-selection-message').slideDown('slow')), 10000) return @createAvatar thangType, @thang diff --git a/app/views/play/level/LevelPlaybackView.coffee b/app/views/play/level/LevelPlaybackView.coffee index b01b7081c..ed4a4b822 100644 --- a/app/views/play/level/LevelPlaybackView.coffee +++ b/app/views/play/level/LevelPlaybackView.coffee @@ -167,7 +167,7 @@ module.exports = class LevelPlaybackView extends CocoView @togglePlaybackControls false Backbone.Mediator.publish 'playback:real-time-playback-started', {} Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'real-time-playback-start', volume: 1 - Backbone.Mediator.publish 'level:set-letterbox', on: true + Backbone.Mediator.publish 'level:set-letterbox', on: true if @options.level.get('type', true) is ['hero'] # not with flags...? onRealTimeMultiplayerCast: (e) -> @realTime = true diff --git a/app/views/play/level/PlayLevelView.coffee b/app/views/play/level/PlayLevelView.coffee index 27b54efbb..f966fe230 100644 --- a/app/views/play/level/PlayLevelView.coffee +++ b/app/views/play/level/PlayLevelView.coffee @@ -118,7 +118,7 @@ module.exports = class PlayLevelView extends RootView @supermodel.collections = givenSupermodel.collections @supermodel.shouldSaveBackups = givenSupermodel.shouldSaveBackups - serializedLevel = @level.serialize @supermodel, @session + serializedLevel = @level.serialize @supermodel, @session, @otherSession @god?.setLevel serializedLevel if @world @world.loadFromLevel serializedLevel, false @@ -215,8 +215,8 @@ module.exports = class PlayLevelView extends RootView @session = @levelLoader.session @world = @levelLoader.world @level = @levelLoader.level - @$el.addClass 'hero' if @level.get('type', true) is 'hero' - @$el.addClass 'flags' if @level.get('slug') is 'sky-span' # TODO: figure out when the player has flags. + @$el.addClass 'hero' if @level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] + @$el.addClass 'flags' if @level.get('slug') is 'sky-span' or (@level.get('type', true) in ['hero-ladder', 'hero-coop']) # TODO: figure out when the player has flags. @otherSession = @levelLoader.opponentSession @worldLoadFakeResources = [] # first element (0) is 1%, last (100) is 100% for percent in [1 .. 100] @@ -251,7 +251,7 @@ module.exports = class PlayLevelView extends RootView @session.set 'multiplayer', false setupGod: -> - @god.setLevel @level.serialize @supermodel, @session + @god.setLevel @level.serialize @supermodel, @session, @otherSession @god.setLevelSessionIDs if @otherSession then [@session.id, @otherSession.id] else [@session.id] @god.setWorldClassMap @world.classMap @@ -268,9 +268,9 @@ module.exports = class PlayLevelView extends RootView insertSubviews: -> @insertSubView @tome = new TomeView levelID: @levelID, session: @session, otherSession: @otherSession, thangs: @world.thangs, supermodel: @supermodel, level: @level - @insertSubView new LevelPlaybackView session: @session, levelID: @levelID + @insertSubView new LevelPlaybackView session: @session, levelID: @levelID, level: @level @insertSubView new GoalsView {} - @insertSubView new LevelFlagsView world: @world if @levelID is 'sky-span' # TODO: figure out when flags are available + @insertSubView new LevelFlagsView world: @world if @levelID is 'sky-span' or @level.get('type', true) in ['hero-ladder', 'hero-coop'] # TODO: figure out when flags are available @insertSubView new GoldView {} @insertSubView new HUDView {level: @level} @insertSubView new ChatView levelID: @levelID, sessionID: @session.id, session: @session @@ -297,11 +297,11 @@ module.exports = class PlayLevelView extends RootView onLevelLoaded: (e) -> # Just the level has been loaded by the level loader - @showWizardSettingsModal() if not me.get('name') and not @isIPadApp() and e.level.get('type', true) isnt 'hero' + @showWizardSettingsModal() if not me.get('name') and not @isIPadApp() and not (e.level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop']) onSessionLoaded: (e) -> # Just the level and session have been loaded by the level loader - if e.level.get('type', true) is 'hero' and not _.size e.session.get('heroConfig')?.inventory ? {} + if e.level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] and not _.size e.session.get('heroConfig')?.inventory ? {} @openModalView new GameMenuModal level: e.level, session: e.session onLoaded: -> @@ -331,7 +331,7 @@ module.exports = class PlayLevelView extends RootView initSurface: -> webGLSurface = $('canvas#webgl-surface', @$el) normalSurface = $('canvas#normal-surface', @$el) - @surface = new Surface(@world, normalSurface, webGLSurface, thangTypes: @supermodel.getModels(ThangType), playJingle: not @isEditorPreview, wizards: @level.get('type', true) isnt 'hero') + @surface = new Surface(@world, normalSurface, webGLSurface, thangTypes: @supermodel.getModels(ThangType), playJingle: not @isEditorPreview, wizards: not (@level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'])) worldBounds = @world.getBounds() bounds = [{x: worldBounds.left, y: worldBounds.top}, {x: worldBounds.right, y: worldBounds.bottom}] @surface.camera.setBounds(bounds) @@ -346,7 +346,7 @@ module.exports = class PlayLevelView extends RootView if window.currentModal and not window.currentModal.destroyed and window.currentModal.constructor isnt VictoryModal return Backbone.Mediator.subscribeOnce 'modal:closed', @onLevelStarted, @ @surface.showLevel() - if @otherSession and @level.get('type', true) isnt 'hero' + if @otherSession and not (@level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop']) # TODO: colorize name and cloud by team, colorize wizard by user's color config @surface.createOpponentWizard id: @otherSession.get('creator'), name: @otherSession.get('creatorName'), team: @otherSession.get('team'), levelSlug: @level.get('slug'), codeLanguage: @otherSession.get('submittedCodeLanguage') if @isEditorPreview @@ -377,7 +377,7 @@ module.exports = class PlayLevelView extends RootView return if @alreadyLoadedState @alreadyLoadedState = true state = @originalSessionState - if @level.get('type', true) is 'hero' + if @level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] Backbone.Mediator.publish 'level:suppress-selection-sounds', suppress: true Backbone.Mediator.publish 'tome:select-primary-sprite', {} Backbone.Mediator.publish 'level:suppress-selection-sounds', suppress: false @@ -443,7 +443,7 @@ module.exports = class PlayLevelView extends RootView onDonePressed: -> @showVictory() onShowVictory: (e) -> - $('#level-done-button').show() unless @level.get('type', true) is 'hero' + $('#level-done-button').show() unless @level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] @showVictory() if e.showModal setTimeout(@preloadNextLevel, 3000) return if @victorySeen @@ -455,7 +455,8 @@ module.exports = class PlayLevelView extends RootView showVictory: -> options = {level: @level, supermodel: @supermodel, session: @session} - ModalClass = if @level.get('type', true) is 'hero' then HeroVictoryModal else VictoryModal + ModalClass = if @level.get('type', true) in ['hero', 'hero-coop'] then HeroVictoryModal else VictoryModal + # TODO: made HeroVictoryModal able to support hero-ladder and then switch over for that level type, too victoryModal = new ModalClass(options) @openModalView(victoryModal) if me.get('anonymous') diff --git a/app/views/play/level/modal/VictoryModal.coffee b/app/views/play/level/modal/VictoryModal.coffee index d2afe6a1c..4fa83402c 100644 --- a/app/views/play/level/modal/VictoryModal.coffee +++ b/app/views/play/level/modal/VictoryModal.coffee @@ -36,9 +36,6 @@ 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: -> @@ -82,7 +79,7 @@ module.exports = class VictoryModal extends ModalView c.hasNextLevel = _.isObject(@level.get('nextLevel')) c.levelName = utils.i18n @level.attributes, 'name' c.level = @level - if c.level.get('type') is 'ladder' + if c.level.get('type') in ['ladder', 'hero-ladder'] c.readyToRank = @session.readyToRank() if me.get 'hourOfCode' # Show the Hour of Code "I'm Done" tracking pixel after they played for 30 minutes diff --git a/app/views/play/level/tome/Spell.coffee b/app/views/play/level/tome/Spell.coffee index 1abf57c29..aba1c56b1 100644 --- a/app/views/play/level/tome/Spell.coffee +++ b/app/views/play/level/tome/Spell.coffee @@ -133,7 +133,7 @@ module.exports = class Spell writable = @permissions.readwrite.length > 0 skipProtectAPI = @skipProtectAPI or not writable problemContext = @createProblemContext thang - aetherOptions = createAetherOptions functionName: @name, codeLanguage: @language, functionParameters: @parameters, skipProtectAPI: skipProtectAPI, includeFlow: @levelType is 'hero', problemContext: problemContext + aetherOptions = createAetherOptions functionName: @name, codeLanguage: @language, functionParameters: @parameters, skipProtectAPI: skipProtectAPI, includeFlow: @levelType in ['hero', 'hero-ladder', 'hero-coop'], problemContext: problemContext aether = new Aether aetherOptions if @worker workerMessage = diff --git a/app/views/play/level/tome/SpellPaletteView.coffee b/app/views/play/level/tome/SpellPaletteView.coffee index 98eaacaea..e94734028 100644 --- a/app/views/play/level/tome/SpellPaletteView.coffee +++ b/app/views/play/level/tome/SpellPaletteView.coffee @@ -121,7 +121,7 @@ module.exports = class SpellPaletteView extends CocoView else propStorage = 'this': ['apiProperties', 'apiMethods'] - if @options.level.get('type', true) isnt 'hero' or not @options.programmable + if not (@options.level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop']) or not @options.programmable @organizePalette propStorage, allDocs, excludedDocs else @organizePaletteHero propStorage, allDocs, excludedDocs @@ -162,7 +162,7 @@ module.exports = class SpellPaletteView extends CocoView if tabbify and _.find @entries, ((entry) -> entry.doc.owner isnt 'this') @entryGroups = _.groupBy @entries, groupForEntry else - i18nKey = if @options.level.get('type', true) is 'hero' then 'play_level.tome_your_skills' else 'play_level.tome_available_spells' + i18nKey = if @options.level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] then 'play_level.tome_your_skills' else 'play_level.tome_available_spells' defaultGroup = $.i18n.t i18nKey @entryGroups = {} @entryGroups[defaultGroup] = @entries @@ -218,7 +218,7 @@ module.exports = class SpellPaletteView extends CocoView return true if doc.owner is owner return (owner is 'this' or owner is 'more') and (not doc.owner? or doc.owner is 'this') if not doc and not excludedDocs['__' + prop] - console.log 'could not find doc for', prop, 'from', allDocs['__' + prop], 'for', owner, 'of', propGroups, 'with item', item + console.log 'could not find doc for', prop, 'from', allDocs['__' + prop], 'for', owner, 'of', propsByItem, 'with item', item doc ?= prop if doc @entries.push @addEntry(doc, shortenize, false, owner is 'snippets', item, propIndex > 0) diff --git a/app/views/play/level/tome/TomeView.coffee b/app/views/play/level/tome/TomeView.coffee index 9d6e961fa..528ebfa77 100644 --- a/app/views/play/level/tome/TomeView.coffee +++ b/app/views/play/level/tome/TomeView.coffee @@ -186,7 +186,7 @@ module.exports = class TomeView extends CocoView @thangList?.$el.show() onSpriteSelected: (e) -> - return if @spellView and @options.level.get('type', true) is 'hero' # Never deselect the hero in the Tome. + return if @spellView and @options.level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] # Never deselect the hero in the Tome. thang = e.thang spellName = e.spellName @spellList?.$el.hide() diff --git a/server/levels/level_handler.coffee b/server/levels/level_handler.coffee index 908a6b1dd..b14a71968 100644 --- a/server/levels/level_handler.coffee +++ b/server/levels/level_handler.coffee @@ -67,7 +67,7 @@ LevelHandler = class LevelHandler extends Handler sessionQuery.team = req.query.team # TODO: generalize this for levels based on their teams - else if level.get('type') is 'ladder' + else if level.get('type') in ['ladder', 'hero-ladder'] sessionQuery.team = 'humans' Session.findOne(sessionQuery).exec (err, doc) => diff --git a/server/queues/scoring.coffee b/server/queues/scoring.coffee index d6aa6f3cb..13b3259e8 100644 --- a/server/queues/scoring.coffee +++ b/server/queues/scoring.coffee @@ -279,7 +279,7 @@ fetchAndVerifyLevelType = (levelID, cb) -> .lean() query.exec (err, levelWithType) -> if err? then return cb err - if not levelWithType.type or levelWithType.type isnt 'ladder' then return cb 'Level isn\'t of type "ladder"' + if not levelWithType.type or not (levelWithType.type in ['ladder', 'hero-ladder']) then return cb 'Level isn\'t of type "ladder"' cb null fetchSessionObjectToSubmit = (sessionID, callback) ->