Started getting hero-ladder level type working.

This commit is contained in:
Nick Winter 2014-10-18 14:51:43 -07:00
parent 91db158c5e
commit 56a80e3615
23 changed files with 81 additions and 59 deletions

View file

@ -91,9 +91,9 @@ module.exports = class LevelLoader extends CocoClass
loadDependenciesForSession: (session) -> loadDependenciesForSession: (session) ->
if session is @session if session is @session
Backbone.Mediator.publish 'level:session-loaded', level: @level, session: @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 = 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. heroConfig ?= {inventory: {}, thangType: '529ffbf1cf1818f2be000001'} # If all else fails, assign Tharin as the hero.
session.set 'heroConfig', heroConfig unless _.isEqual heroConfig, session.get('heroConfig') session.set 'heroConfig', heroConfig unless _.isEqual heroConfig, session.get('heroConfig')
url = "/db/thang.type/#{heroConfig.thangType}/version" url = "/db/thang.type/#{heroConfig.thangType}/version"
@ -334,7 +334,7 @@ module.exports = class LevelLoader extends CocoClass
@initialized = true @initialized = true
@world = new World() @world = new World()
@world.levelSessionIDs = if @opponentSessionID then [@sessionID, @opponentSessionID] else [@sessionID] @world.levelSessionIDs = if @opponentSessionID then [@sessionID, @opponentSessionID] else [@sessionID]
serializedLevel = @level.serialize(@supermodel, @session) serializedLevel = @level.serialize(@supermodel, @session, @opponentSession)
@world.loadFromLevel serializedLevel, false @world.loadFromLevel serializedLevel, false
console.log 'World has been initialized from level loader.' console.log 'World has been initialized from level loader.'

View file

@ -193,7 +193,7 @@ module.exports = class Simulator extends CocoClass
@levelLoader = null @levelLoader = null
setupGod: -> 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.setLevelSessionIDs (session.sessionID for session in @task.getSessions())
@god.setWorldClassMap @world.classMap @god.setWorldClassMap @world.classMap
@god.setGoalManager new GoalManager(@world, @level.get 'goals') @god.setGoalManager new GoalManager(@world, @level.get 'goals')

View file

@ -540,7 +540,9 @@ module.exports = Surface = class Surface extends CocoClass
#- Camera focus on hero #- Camera focus on hero
focusOnHero: -> focusOnHero: ->
@heroLank = @lankBoss.lankFor 'Hero Placeholder' @heroLank = @lankBoss.lankFor 'Hero Placeholder'
if me.team is 'ogres'
# TODO: do this for real
@heroLank = @lankBoss.lankFor 'Hero Placeholder 1'
#- Real-time playback #- Real-time playback

View file

@ -8,8 +8,8 @@ module.exports = class Level extends CocoModel
@schema: require 'schemas/models/level' @schema: require 'schemas/models/level'
urlRoot: '/db/level' urlRoot: '/db/level'
serialize: (supermodel, session, cached=false) -> serialize: (supermodel, session, otherSession, cached=false) ->
o = @denormalize supermodel, session # hot spot to optimize o = @denormalize supermodel, session, otherSession # hot spot to optimize
# Figure out Components # Figure out Components
o.levelComponents = if cached then @getCachedLevelComponents(supermodel) else $.extend true, [], (lc.attributes for lc in supermodel.getModels LevelComponent) 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.push(@cachedLevelComponents[levelComponent.id])
newLevelComponents newLevelComponents
denormalize: (supermodel, session) -> denormalize: (supermodel, session, otherSession) ->
o = $.extend true, {}, @attributes o = $.extend true, {}, @attributes
if o.thangs and @get('type', true) is 'hero' if o.thangs and @get('type', true) in ['hero', 'hero-ladder', 'hero-coop']
# TOOD: figure out if/when/how we are doing this for non-Hero levels that aren't expecting denormalization.
for levelThang in o.thangs for levelThang in o.thangs
@denormalizeThang(levelThang, supermodel, session) @denormalizeThang(levelThang, supermodel, session, otherSession)
o o
denormalizeThang: (levelThang, supermodel, session) -> denormalizeThang: (levelThang, supermodel, session, otherSession) ->
levelThang.components ?= [] 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. # Empty out placeholder Components and store their values if we're the hero placeholder.
if isHero 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: 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: 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: 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. # 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. # 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 console.error parentType, thang.id or thang.name, 'does not have dependent Component', dependent, 'from', lc.name
visit c2 if c2 visit c2 if c2
if lc.name is 'Collides' if lc.name is 'Collides'
allied = _.find levelComponents, {name: 'Allied'} if allied = _.find levelComponents, {name: 'Allied'}
if allied allied = _.find(thang.components, {original: allied.original})
collides = _.find(thang.components, {original: allied.original}) visit allied if allied
visit collides if collides 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 #console.log thang.id, 'sorted comps adding', lc.name
sorted.push c sorted.push c
for comp in thang.components for comp in thang.components

View file

@ -244,7 +244,7 @@ _.extend LevelSchema.properties,
icon: {type: 'string', format: 'image-file', title: 'Icon'} icon: {type: 'string', format: 'image-file', title: 'Icon'}
banner: {type: 'string', format: 'image-file', title: 'Banner'} 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 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 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']) showsGuide: c.shortString(title: 'Shows Guide', description: 'If the guide is shown at the beginning of the level.', 'enum': ['first-time', 'always'])

View file

@ -52,7 +52,7 @@ module.exports = class ThangComponentConfigView extends CocoView
schema.default ?= {} schema.default ?= {}
_.merge schema.default, @additionalDefaults if @additionalDefaults _.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 = [] schema.required = []
treemaOptions = treemaOptions =
supermodel: @supermodel supermodel: @supermodel

View file

@ -46,7 +46,7 @@ module.exports = class LevelThangEditView extends CocoView
level: @level level: @level
world: @world 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 @thangComponentEditView = new ThangComponentsEditView options
@listenTo @thangComponentEditView, 'components-changed', @onComponentsChanged @listenTo @thangComponentEditView, 'components-changed', @onComponentsChanged

View file

@ -520,7 +520,7 @@ module.exports = class ThangsTabView extends CocoView
@level.set 'thangs', thangs @level.set 'thangs', thangs
return if @editThangView return if @editThangView
serializedLevel = @level.serialize @supermodel, null, true serializedLevel = @level.serialize @supermodel, null, null, true
try try
@world.loadFromLevel serializedLevel, false @world.loadFromLevel serializedLevel, false
catch error catch error
@ -552,14 +552,14 @@ module.exports = class ThangsTabView extends CocoView
if batchInsert if batchInsert
if thangType.get('name') is 'Hero Placeholder' if thangType.get('name') is 'Hero Placeholder'
thangID = '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 else
thangID = "Random #{thangType.get('name')} #{@thangsBatch.length}" thangID = "Random #{thangType.get('name')} #{@thangsBatch.length}"
else else
thangID = Thang.nextID(thangType.get('name'), @world) until thangID and not @getThangByID(thangID) thangID = Thang.nextID(thangType.get('name'), @world) until thangID and not @getThangByID(thangID)
if @cloneSourceThang if @cloneSourceThang
components = _.cloneDeep @getThangByID(@cloneSourceThang.id).components 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 components = [] # Load them all from default ThangType Components
else else
components = _.cloneDeep thangType.get('components') ? [] components = _.cloneDeep thangType.get('components') ? []

View file

@ -21,7 +21,7 @@ module.exports = class GameMenuModal extends ModalView
constructor: (options) -> constructor: (options) ->
super options super options
@options.showDevBits = me.isAdmin() or /https?:\/\/localhost/.test(window.location.href) @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.levelID = @options.level.get('slug')
@options.startingSessionHeroConfig = $.extend {}, true, (@options.session.get('heroConfig') ? {}) @options.startingSessionHeroConfig = $.extend {}, true, (@options.session.get('heroConfig') ? {})

View file

@ -40,7 +40,7 @@ module.exports = class MultiplayerView extends CocoView
c.team = @session.get 'team' c.team = @session.get 'team'
c.levelSlug = @level?.get 'slug' c.levelSlug = @level?.get 'slug'
# For now, ladderGame will disallow multiplayer, because session code combining doesn't play nice yet. # 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.ladderGame = true
c.readyToRank = @session?.readyToRank() c.readyToRank = @session?.readyToRank()
@ -68,7 +68,7 @@ module.exports = class MultiplayerView extends CocoView
updateLinkSection: -> updateLinkSection: ->
multiplayer = @$el.find('#multiplayer').prop('checked') multiplayer = @$el.find('#multiplayer').prop('checked')
la = @$el.find('#link-area') 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 true
onHidden: -> onHidden: ->

View file

@ -68,7 +68,7 @@ module.exports = class SpectateLevelView extends RootView
@load() @load()
setLevel: (@level, @supermodel) -> setLevel: (@level, @supermodel) ->
serializedLevel = @level.serialize @supermodel, @session serializedLevel = @level.serialize @supermodel, @session, @otherSession
@god?.setLevel serializedLevel @god?.setLevel serializedLevel
if @world if @world
@world.loadFromLevel serializedLevel, false @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 #at this point, all requisite data is loaded, and sessions are not denormalized
team = @world.teamForPlayer(0) team = @world.teamForPlayer(0)
@loadOpponentTeam(team) @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.setLevelSessionIDs if @otherSession then [@session.id, @otherSession.id] else [@session.id]
@god.setWorldClassMap @world.classMap @god.setWorldClassMap @world.classMap
@setTeam team @setTeam team
@ -119,7 +119,7 @@ module.exports = class SpectateLevelView extends RootView
@register() @register()
@controlBar.setBus(@bus) @controlBar.setBus(@bus)
@surface.showLevel() @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' if me.id isnt @session.get 'creator'
@surface.createOpponentWizard @surface.createOpponentWizard
id: @session.get('creator') id: @session.get('creator')

View file

@ -718,6 +718,17 @@ hero = [
x: 95.31 x: 95.31
y: 88.26 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: '' # name: ''
# type: 'hero' # type: 'hero'

View file

@ -1,7 +1,7 @@
{hslToHex} = require 'lib/utils' {hslToHex} = require 'lib/utils'
module.exports.teamDataFromLevel = (level) -> 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) teamNames = (teamName for teamName, teamConfig of alliedSystem.config.teams when teamConfig.playable)
teamConfigs = alliedSystem.config.teams teamConfigs = alliedSystem.config.teams

View file

@ -51,15 +51,15 @@ module.exports = class ControlBarView extends CocoView
super c super c
c.worldName = @worldName c.worldName = @worldName
c.multiplayerEnabled = @session.get('multiplayer') c.multiplayerEnabled = @session.get('multiplayer')
c.ladderGame = @level.get('type') is 'ladder' c.ladderGame = @level.get('type') in ['ladder', 'hero-ladder']
c.spectateGame = @spectateGame c.spectateGame = @spectateGame
@homeViewArgs = [{supermodel: @supermodel}] @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$/, '' levelID = @level.get('slug').replace /\-tutorial$/, ''
@homeLink = c.homeLink = '/play/ladder/' + levelID @homeLink = c.homeLink = '/play/ladder/' + levelID
@homeViewClass = require 'views/play/ladder/LadderView' @homeViewClass = require 'views/play/ladder/LadderView'
@homeViewArgs.push levelID @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' @homeLink = c.homeLink = '/play'
@homeViewClass = require 'views/play/WorldMapView' @homeViewClass = require 'views/play/WorldMapView'
else else

View file

@ -85,7 +85,7 @@ module.exports = class LevelHUDView extends CocoView
clearTimeout @hintNextSelectionTimeout clearTimeout @hintNextSelectionTimeout
@$el.find('.no-selection-message').hide() @$el.find('.no-selection-message').hide()
if not @thang 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) @hintNextSelectionTimeout = _.delay((=> @$el.find('.no-selection-message').slideDown('slow')), 10000)
return return
@createAvatar thangType, @thang @createAvatar thangType, @thang

View file

@ -167,7 +167,7 @@ module.exports = class LevelPlaybackView extends CocoView
@togglePlaybackControls false @togglePlaybackControls false
Backbone.Mediator.publish 'playback:real-time-playback-started', {} 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 '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) -> onRealTimeMultiplayerCast: (e) ->
@realTime = true @realTime = true

View file

@ -118,7 +118,7 @@ module.exports = class PlayLevelView extends RootView
@supermodel.collections = givenSupermodel.collections @supermodel.collections = givenSupermodel.collections
@supermodel.shouldSaveBackups = givenSupermodel.shouldSaveBackups @supermodel.shouldSaveBackups = givenSupermodel.shouldSaveBackups
serializedLevel = @level.serialize @supermodel, @session serializedLevel = @level.serialize @supermodel, @session, @otherSession
@god?.setLevel serializedLevel @god?.setLevel serializedLevel
if @world if @world
@world.loadFromLevel serializedLevel, false @world.loadFromLevel serializedLevel, false
@ -215,8 +215,8 @@ module.exports = class PlayLevelView extends RootView
@session = @levelLoader.session @session = @levelLoader.session
@world = @levelLoader.world @world = @levelLoader.world
@level = @levelLoader.level @level = @levelLoader.level
@$el.addClass 'hero' if @level.get('type', true) is 'hero' @$el.addClass 'hero' if @level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop']
@$el.addClass 'flags' if @level.get('slug') is 'sky-span' # TODO: figure out when the player has flags. @$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 @otherSession = @levelLoader.opponentSession
@worldLoadFakeResources = [] # first element (0) is 1%, last (100) is 100% @worldLoadFakeResources = [] # first element (0) is 1%, last (100) is 100%
for percent in [1 .. 100] for percent in [1 .. 100]
@ -251,7 +251,7 @@ module.exports = class PlayLevelView extends RootView
@session.set 'multiplayer', false @session.set 'multiplayer', false
setupGod: -> 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.setLevelSessionIDs if @otherSession then [@session.id, @otherSession.id] else [@session.id]
@god.setWorldClassMap @world.classMap @god.setWorldClassMap @world.classMap
@ -268,9 +268,9 @@ module.exports = class PlayLevelView extends RootView
insertSubviews: -> insertSubviews: ->
@insertSubView @tome = new TomeView levelID: @levelID, session: @session, otherSession: @otherSession, thangs: @world.thangs, supermodel: @supermodel, level: @level @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 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 GoldView {}
@insertSubView new HUDView {level: @level} @insertSubView new HUDView {level: @level}
@insertSubView new ChatView levelID: @levelID, sessionID: @session.id, session: @session @insertSubView new ChatView levelID: @levelID, sessionID: @session.id, session: @session
@ -297,11 +297,11 @@ module.exports = class PlayLevelView extends RootView
onLevelLoaded: (e) -> onLevelLoaded: (e) ->
# Just the level has been loaded by the level loader # 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) -> onSessionLoaded: (e) ->
# Just the level and session have been loaded by the level loader # 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 @openModalView new GameMenuModal level: e.level, session: e.session
onLoaded: -> onLoaded: ->
@ -331,7 +331,7 @@ module.exports = class PlayLevelView extends RootView
initSurface: -> initSurface: ->
webGLSurface = $('canvas#webgl-surface', @$el) webGLSurface = $('canvas#webgl-surface', @$el)
normalSurface = $('canvas#normal-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() worldBounds = @world.getBounds()
bounds = [{x: worldBounds.left, y: worldBounds.top}, {x: worldBounds.right, y: worldBounds.bottom}] bounds = [{x: worldBounds.left, y: worldBounds.top}, {x: worldBounds.right, y: worldBounds.bottom}]
@surface.camera.setBounds(bounds) @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 if window.currentModal and not window.currentModal.destroyed and window.currentModal.constructor isnt VictoryModal
return Backbone.Mediator.subscribeOnce 'modal:closed', @onLevelStarted, @ return Backbone.Mediator.subscribeOnce 'modal:closed', @onLevelStarted, @
@surface.showLevel() @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 # 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') @surface.createOpponentWizard id: @otherSession.get('creator'), name: @otherSession.get('creatorName'), team: @otherSession.get('team'), levelSlug: @level.get('slug'), codeLanguage: @otherSession.get('submittedCodeLanguage')
if @isEditorPreview if @isEditorPreview
@ -377,7 +377,7 @@ module.exports = class PlayLevelView extends RootView
return if @alreadyLoadedState return if @alreadyLoadedState
@alreadyLoadedState = true @alreadyLoadedState = true
state = @originalSessionState 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 'level:suppress-selection-sounds', suppress: true
Backbone.Mediator.publish 'tome:select-primary-sprite', {} Backbone.Mediator.publish 'tome:select-primary-sprite', {}
Backbone.Mediator.publish 'level:suppress-selection-sounds', suppress: false Backbone.Mediator.publish 'level:suppress-selection-sounds', suppress: false
@ -443,7 +443,7 @@ module.exports = class PlayLevelView extends RootView
onDonePressed: -> @showVictory() onDonePressed: -> @showVictory()
onShowVictory: (e) -> 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 @showVictory() if e.showModal
setTimeout(@preloadNextLevel, 3000) setTimeout(@preloadNextLevel, 3000)
return if @victorySeen return if @victorySeen
@ -455,7 +455,8 @@ module.exports = class PlayLevelView extends RootView
showVictory: -> showVictory: ->
options = {level: @level, supermodel: @supermodel, session: @session} 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) victoryModal = new ModalClass(options)
@openModalView(victoryModal) @openModalView(victoryModal)
if me.get('anonymous') if me.get('anonymous')

View file

@ -36,9 +36,6 @@ module.exports = class VictoryModal extends ModalView
@session = options.session @session = options.session
@saveReviewEventually = _.debounce(@saveReviewEventually, 2000) @saveReviewEventually = _.debounce(@saveReviewEventually, 2000)
@loadExistingFeedback() @loadExistingFeedback()
if @level.get('type', true) is 'hero'
@closeButton = false
@closesOnClickOutside = false
super options super options
loadExistingFeedback: -> loadExistingFeedback: ->
@ -82,7 +79,7 @@ module.exports = class VictoryModal extends ModalView
c.hasNextLevel = _.isObject(@level.get('nextLevel')) c.hasNextLevel = _.isObject(@level.get('nextLevel'))
c.levelName = utils.i18n @level.attributes, 'name' c.levelName = utils.i18n @level.attributes, 'name'
c.level = @level c.level = @level
if c.level.get('type') is 'ladder' if c.level.get('type') in ['ladder', 'hero-ladder']
c.readyToRank = @session.readyToRank() c.readyToRank = @session.readyToRank()
if me.get 'hourOfCode' if me.get 'hourOfCode'
# Show the Hour of Code "I'm Done" tracking pixel after they played for 30 minutes # Show the Hour of Code "I'm Done" tracking pixel after they played for 30 minutes

View file

@ -133,7 +133,7 @@ module.exports = class Spell
writable = @permissions.readwrite.length > 0 writable = @permissions.readwrite.length > 0
skipProtectAPI = @skipProtectAPI or not writable skipProtectAPI = @skipProtectAPI or not writable
problemContext = @createProblemContext thang 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 aether = new Aether aetherOptions
if @worker if @worker
workerMessage = workerMessage =

View file

@ -121,7 +121,7 @@ module.exports = class SpellPaletteView extends CocoView
else else
propStorage = propStorage =
'this': ['apiProperties', 'apiMethods'] '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 @organizePalette propStorage, allDocs, excludedDocs
else else
@organizePaletteHero propStorage, allDocs, excludedDocs @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') if tabbify and _.find @entries, ((entry) -> entry.doc.owner isnt 'this')
@entryGroups = _.groupBy @entries, groupForEntry @entryGroups = _.groupBy @entries, groupForEntry
else 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 defaultGroup = $.i18n.t i18nKey
@entryGroups = {} @entryGroups = {}
@entryGroups[defaultGroup] = @entries @entryGroups[defaultGroup] = @entries
@ -218,7 +218,7 @@ module.exports = class SpellPaletteView extends CocoView
return true if doc.owner is owner return true if doc.owner is owner
return (owner is 'this' or owner is 'more') and (not doc.owner? or doc.owner is 'this') return (owner is 'this' or owner is 'more') and (not doc.owner? or doc.owner is 'this')
if not doc and not excludedDocs['__' + prop] 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 doc ?= prop
if doc if doc
@entries.push @addEntry(doc, shortenize, false, owner is 'snippets', item, propIndex > 0) @entries.push @addEntry(doc, shortenize, false, owner is 'snippets', item, propIndex > 0)

View file

@ -186,7 +186,7 @@ module.exports = class TomeView extends CocoView
@thangList?.$el.show() @thangList?.$el.show()
onSpriteSelected: (e) -> 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 thang = e.thang
spellName = e.spellName spellName = e.spellName
@spellList?.$el.hide() @spellList?.$el.hide()

View file

@ -67,7 +67,7 @@ LevelHandler = class LevelHandler extends Handler
sessionQuery.team = req.query.team sessionQuery.team = req.query.team
# TODO: generalize this for levels based on their teams # 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' sessionQuery.team = 'humans'
Session.findOne(sessionQuery).exec (err, doc) => Session.findOne(sessionQuery).exec (err, doc) =>

View file

@ -279,7 +279,7 @@ fetchAndVerifyLevelType = (levelID, cb) ->
.lean() .lean()
query.exec (err, levelWithType) -> query.exec (err, levelWithType) ->
if err? then return cb err 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 cb null
fetchSessionObjectToSubmit = (sessionID, callback) -> fetchSessionObjectToSubmit = (sessionID, callback) ->