mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-27 09:35:39 -05:00
Stub WebSurface showing for web-dev levels
This commit is contained in:
parent
c5c831c211
commit
16b10612b6
16 changed files with 102 additions and 40 deletions
|
@ -19,6 +19,7 @@ var languagesImported = {};
|
|||
|
||||
var ensureLanguageImported = function(language) {
|
||||
if (languagesImported[language]) return;
|
||||
if (language === 'html') return;
|
||||
importScripts("/javascripts/app/vendor/aether-" + language + ".js");
|
||||
languagesImported[language] = true;
|
||||
};
|
||||
|
|
|
@ -80,7 +80,7 @@ var myImportScripts = importScripts;
|
|||
var languagesImported = {};
|
||||
var ensureLanguageImported = function(language) {
|
||||
if (languagesImported[language]) return;
|
||||
if (language === 'javascript') return; // Only has JSHint, but we don't need to lint here.
|
||||
if (language === 'javascript' || language === 'html') return; // Only has JSHint, but we don't need to lint here.
|
||||
myImportScripts("/javascripts/app/vendor/aether-" + language + ".js");
|
||||
languagesImported[language] = true;
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@ CocoModel = require 'models/CocoModel'
|
|||
CocoCollection = require 'collections/CocoCollection'
|
||||
{me} = require('core/auth')
|
||||
locale = require 'locale/locale'
|
||||
utils = require 'core/utils'
|
||||
|
||||
initializeFilePicker = ->
|
||||
require('core/services/filepicker')() unless window.application.isIPadApp
|
||||
|
@ -234,21 +235,14 @@ class ImageFileTreema extends TreemaNode.nodeMap.string
|
|||
@refreshDisplay()
|
||||
|
||||
|
||||
codeLanguages =
|
||||
javascript: 'ace/mode/javascript'
|
||||
coffeescript: 'ace/mode/coffee'
|
||||
python: 'ace/mode/python'
|
||||
lua: 'ace/mode/lua'
|
||||
java: 'ace/mode/java'
|
||||
|
||||
class CodeLanguagesObjectTreema extends TreemaNode.nodeMap.object
|
||||
childPropertiesAvailable: ->
|
||||
(key for key in _.keys(codeLanguages) when not @data[key]? and not (key is 'javascript' and @workingSchema.skipJavaScript))
|
||||
(key for key in _.keys(utils.aceEditModes) when not @data[key]? and not (key is 'javascript' and @workingSchema.skipJavaScript))
|
||||
|
||||
class CodeLanguageTreema extends TreemaNode.nodeMap.string
|
||||
buildValueForEditing: (valEl, data) ->
|
||||
super(valEl, data)
|
||||
valEl.find('input').autocomplete(source: _.keys(codeLanguages), minLength: 0, delay: 0, autoFocus: true)
|
||||
valEl.find('input').autocomplete(source: _.keys(utils.aceEditModes), minLength: 0, delay: 0, autoFocus: true)
|
||||
valEl
|
||||
|
||||
class CodeTreema extends TreemaNode.nodeMap.ace
|
||||
|
@ -256,8 +250,8 @@ class CodeTreema extends TreemaNode.nodeMap.ace
|
|||
super(arguments...)
|
||||
@workingSchema.aceTabSize = 4
|
||||
# TODO: Find a less hacky solution for this
|
||||
@workingSchema.aceMode = mode if mode = codeLanguages[@keyForParent]
|
||||
@workingSchema.aceMode = mode if mode = codeLanguages[@parent?.data?.language]
|
||||
@workingSchema.aceMode = mode if mode = utils.aceEditModes[@keyForParent]
|
||||
@workingSchema.aceMode = mode if mode = utils.aceEditModes[@parent?.data?.language]
|
||||
|
||||
class CoffeeTreema extends CodeTreema
|
||||
constructor: ->
|
||||
|
|
|
@ -259,7 +259,7 @@ startsWithVowel = (s) -> s[0] in 'aeiouAEIOU'
|
|||
module.exports.filterMarkdownCodeLanguages = (text, language) ->
|
||||
return '' unless text
|
||||
currentLanguage = language or me.get('aceConfig')?.language or 'python'
|
||||
excludedLanguages = _.without ['javascript', 'python', 'coffeescript', 'clojure', 'lua', 'java', 'io'], currentLanguage
|
||||
excludedLanguages = _.without ['javascript', 'python', 'coffeescript', 'clojure', 'lua', 'java', 'io', 'html'], currentLanguage
|
||||
# Exclude language-specific code blocks like ```python (... code ...)``` for each non-target language.
|
||||
codeBlockExclusionRegex = new RegExp "```(#{excludedLanguages.join('|')})\n[^`]+```\n?", 'gm'
|
||||
# Exclude language-specific images like ![python - image description](image url) for each non-target language.
|
||||
|
@ -290,12 +290,12 @@ module.exports.filterMarkdownCodeLanguages = (text, language) ->
|
|||
return text
|
||||
|
||||
module.exports.aceEditModes = aceEditModes =
|
||||
'javascript': 'ace/mode/javascript'
|
||||
'coffeescript': 'ace/mode/coffee'
|
||||
'python': 'ace/mode/python'
|
||||
'java': 'ace/mode/java'
|
||||
'lua': 'ace/mode/lua'
|
||||
'java': 'ace/mode/java'
|
||||
javascript: 'ace/mode/javascript'
|
||||
coffeescript: 'ace/mode/coffee'
|
||||
python: 'ace/mode/python'
|
||||
lua: 'ace/mode/lua'
|
||||
java: 'ace/mode/java'
|
||||
html: 'ace/mode/html'
|
||||
|
||||
module.exports.initializeACE = (el, codeLanguage) ->
|
||||
contents = $(el).text().trim()
|
||||
|
|
|
@ -74,6 +74,8 @@ module.exports = class LevelLoader extends CocoClass
|
|||
onLevelLoaded: ->
|
||||
if not @sessionless and @level.isType('hero', 'hero-ladder', 'hero-coop', 'course')
|
||||
@sessionDependenciesRegistered = {}
|
||||
if @level.isType('web-dev')
|
||||
@headless = true
|
||||
if (@courseID and not @level.isType('course', 'course-ladder')) or window.serverConfig.picoCTF
|
||||
# Because we now use original hero levels for both hero and course levels, we fake being a course level in this context.
|
||||
originalGet = @level.get
|
||||
|
@ -481,6 +483,7 @@ module.exports = class LevelLoader extends CocoClass
|
|||
initWorld: ->
|
||||
return if @initialized
|
||||
@initialized = true
|
||||
return if @level.isType('web-dev')
|
||||
@world = new World()
|
||||
@world.levelSessionIDs = if @opponentSessionID then [@sessionID, @opponentSessionID] else [@sessionID]
|
||||
@world.submissionCount = @session?.get('state')?.submissionCount ? 0
|
||||
|
|
|
@ -61,7 +61,7 @@ _.extend CampaignSchema.properties, {
|
|||
i18n: { type: 'object', format: 'hidden' }
|
||||
requiresSubscription: { type: 'boolean' }
|
||||
replayable: { type: 'boolean' }
|
||||
type: {'enum': ['ladder', 'ladder-tutorial', 'hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev']}
|
||||
type: {'enum': ['ladder', 'ladder-tutorial', 'hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev', 'web-dev']}
|
||||
slug: { type: 'string', format: 'hidden' }
|
||||
original: { type: 'string', format: 'hidden' }
|
||||
adventurer: { type: 'boolean' }
|
||||
|
|
|
@ -313,7 +313,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', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev'])
|
||||
type: c.shortString(title: 'Type', description: 'What kind of level this is.', 'enum': ['campaign', 'ladder', 'ladder-tutorial', 'hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev', 'web-dev'])
|
||||
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'])
|
||||
requiresSubscription: {title: 'Requires Subscription', description: 'Whether this level is available to subscribers only.', type: 'boolean'}
|
||||
|
|
|
@ -272,6 +272,26 @@ $level-resize-transition-time: 0.5s
|
|||
right: 45%
|
||||
z-index: 1000000
|
||||
|
||||
&.web-dev
|
||||
position: absolute
|
||||
top: 0
|
||||
bottom: 0
|
||||
left: 0
|
||||
right: 0
|
||||
|
||||
#playback-view, #thang-hud, #level-dialogue-view, #play-footer, #level-footer-background, #level-footer-shadow
|
||||
display: none
|
||||
|
||||
.game-container, .level-content, #game-area, #canvas-wrapper
|
||||
height: 100%
|
||||
|
||||
#canvas-wrapper canvas
|
||||
display: none
|
||||
|
||||
#web-surface
|
||||
width: 100%
|
||||
height: 100%
|
||||
|
||||
html.fullscreen-editor
|
||||
#level-view
|
||||
#fullscreen-editor-background-screen
|
||||
|
|
|
@ -24,6 +24,8 @@ if view.showAds()
|
|||
#canvas-wrapper
|
||||
canvas(width=924, height=589)#webgl-surface
|
||||
canvas(width=924, height=589)#normal-surface
|
||||
|
||||
#web-surface
|
||||
#ascii-surface
|
||||
#canvas-left-gradient.gradient
|
||||
#canvas-top-gradient.gradient
|
||||
|
|
|
@ -169,7 +169,7 @@ module.exports = class LevelLoadingView extends CocoView
|
|||
@playSound 'loading-view-unveil', 0.5
|
||||
@$el.find('.left-wing').css left: '-100%', backgroundPosition: 'right -400px top 0'
|
||||
@$el.find('.right-wing').css right: '-100%', backgroundPosition: 'left -400px top 0'
|
||||
$('#level-footer-background').detach().appendTo('#page-container').slideDown(duration)
|
||||
$('#level-footer-background').detach().appendTo('#page-container').slideDown(duration) unless @level.isType('web-dev')
|
||||
|
||||
unveilIntro: =>
|
||||
return if @destroyed or not @intro or @unveiled
|
||||
|
|
|
@ -132,7 +132,7 @@ module.exports = class PlayLevelView extends RootView
|
|||
|
||||
load: ->
|
||||
@loadStartTime = new Date()
|
||||
@god = new God({@gameUIState})
|
||||
@god = new God({@gameUIState}) # TODO: don't make one of these in web-dev mode
|
||||
levelLoaderOptions = supermodel: @supermodel, levelID: @levelID, sessionID: @sessionID, opponentSessionID: @opponentSessionID, team: @getQueryVariable('team'), observing: @observing, courseID: @courseID
|
||||
if me.isSessionless()
|
||||
levelLoaderOptions.fakeSessionConfig = {}
|
||||
|
@ -196,9 +196,12 @@ module.exports = class PlayLevelView extends RootView
|
|||
|
||||
grabLevelLoaderData: ->
|
||||
@session = @levelLoader.session
|
||||
@world = @levelLoader.world
|
||||
@level = @levelLoader.level
|
||||
@$el.addClass 'hero' if @level.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev', 'web-dev') # TODO: figure out what this does and comment it
|
||||
if @level.isType('web-dev')
|
||||
@$el.addClass 'web-dev' # Hide some of the elements we won't be using
|
||||
return
|
||||
@world = @levelLoader.world
|
||||
@$el.addClass 'hero' if @level.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev') # TODO: figure out what this does and comment it
|
||||
@$el.addClass 'flags' if _.any(@world.thangs, (t) -> (t.programmableProperties and 'findFlags' in t.programmableProperties) or t.inventory?.flag) or @level.get('slug') is 'sky-span'
|
||||
# TODO: Update terminology to always be opponentSession or otherSession
|
||||
# TODO: E.g. if it's always opponent right now, then variable names should be opponentSession until we have coop play
|
||||
|
@ -234,6 +237,7 @@ module.exports = class PlayLevelView extends RootView
|
|||
@session.set('code', myCode)
|
||||
|
||||
setupGod: ->
|
||||
return if @level.isType('web-dev')
|
||||
@god.setLevel @level.serialize {@supermodel, @session, @otherSession, headless: false, sessionless: false}
|
||||
@god.setLevelSessionIDs if @otherSession then [@session.id, @otherSession.id] else [@session.id]
|
||||
@god.setWorldClassMap @world.classMap
|
||||
|
@ -252,12 +256,12 @@ module.exports = class PlayLevelView extends RootView
|
|||
|
||||
insertSubviews: ->
|
||||
@hintsState = new HintsState({ hidden: true }, { @session, @level })
|
||||
@insertSubView @tome = new TomeView { @levelID, @session, @otherSession, thangs: @world.thangs, @supermodel, @level, @observing, @courseID, @courseInstanceID, @god, @hintsState }
|
||||
@insertSubView new LevelPlaybackView session: @session, level: @level
|
||||
@insertSubView @tome = new TomeView { @levelID, @session, @otherSession, thangs: @world?.thangs ? [], @supermodel, @level, @observing, @courseID, @courseInstanceID, @god, @hintsState }
|
||||
@insertSubView new LevelPlaybackView session: @session, level: @level unless @level.isType('web-dev')
|
||||
@insertSubView new GoalsView {level: @level}
|
||||
@insertSubView new LevelFlagsView levelID: @levelID, world: @world if @$el.hasClass 'flags'
|
||||
@insertSubView new GoldView {} unless @level.get('slug') in ['wakka-maul']
|
||||
@insertSubView new HUDView {level: @level}
|
||||
@insertSubView new GoldView {} unless @level.get('slug') in ['wakka-maul'] unless @level.isType('web-dev')
|
||||
@insertSubView new HUDView {level: @level} unless @level.isType('web-dev')
|
||||
@insertSubView new LevelDialogueView {level: @level, sessionID: @session.id}
|
||||
@insertSubView new ChatView levelID: @levelID, sessionID: @session.id, session: @session
|
||||
@insertSubView new ProblemAlertView session: @session, level: @level, supermodel: @supermodel
|
||||
|
@ -272,6 +276,7 @@ module.exports = class PlayLevelView extends RootView
|
|||
Backbone.Mediator.publish 'level:set-volume', volume: volume
|
||||
|
||||
initScriptManager: ->
|
||||
return if @level.isType('web-dev')
|
||||
@scriptManager = new ScriptManager({scripts: @world.scripts or [], view: @, session: @session, levelID: @level.get('slug')})
|
||||
@scriptManager.loadFromSession()
|
||||
|
||||
|
@ -318,7 +323,10 @@ module.exports = class PlayLevelView extends RootView
|
|||
@saveRecentMatch() if @otherSession
|
||||
@levelLoader.destroy()
|
||||
@levelLoader = null
|
||||
@initSurface()
|
||||
if @level.isType('web-dev')
|
||||
@initWebSurface()
|
||||
else
|
||||
@initSurface()
|
||||
|
||||
saveRecentMatch: ->
|
||||
allRecentlyPlayedMatches = storage.load('recently-played-matches') ? {}
|
||||
|
@ -355,12 +363,13 @@ module.exports = class PlayLevelView extends RootView
|
|||
# Once Surface is Loaded ####################################################
|
||||
|
||||
onLevelStarted: ->
|
||||
return unless @surface?
|
||||
return unless @surface? or @webSurface?
|
||||
@loadingView.showReady()
|
||||
@trackLevelLoadEnd()
|
||||
if window.currentModal and not window.currentModal.destroyed and window.currentModal.constructor isnt VictoryModal
|
||||
return Backbone.Mediator.subscribeOnce 'modal:closed', @onLevelStarted, @
|
||||
@surface.showLevel()
|
||||
@surface?.showLevel()
|
||||
@webSurface?.showLevel()
|
||||
Backbone.Mediator.publish 'level:set-time', time: 0
|
||||
if (@isEditorPreview or @observing) and not @getQueryVariable('intro')
|
||||
@loadingView.startUnveiling()
|
||||
|
@ -406,7 +415,7 @@ module.exports = class PlayLevelView extends RootView
|
|||
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
|
||||
@surface.focusOnHero()
|
||||
@surface?.focusOnHero()
|
||||
|
||||
perhapsStartSimulating: ->
|
||||
return unless @shouldSimulate()
|
||||
|
@ -662,3 +671,11 @@ module.exports = class PlayLevelView extends RootView
|
|||
@setupManager?.destroy()
|
||||
@setupManager = new LevelSetupManager({supermodel: @supermodel, level: @level, levelID: @levelID, parent: @, session: @session, hadEverChosenHero: true})
|
||||
@setupManager.open()
|
||||
|
||||
|
||||
# web-dev levels
|
||||
initWebSurface: ->
|
||||
@webSurface = showLevel: =>
|
||||
# TODO: make a real WebSurface class
|
||||
@$('#web-surface').css('background-color', 'red')
|
||||
Backbone.Mediator.publish 'level:started', {}
|
||||
|
|
|
@ -42,6 +42,7 @@ module.exports = class DocFormatter
|
|||
@fillOutDoc()
|
||||
|
||||
fillOutDoc: ->
|
||||
# TODO: figure out how to do html docs for web-dev levels
|
||||
if _.isString @doc
|
||||
@doc = name: @doc, type: typeof @options.thang[@doc]
|
||||
if @options.isSnippet
|
||||
|
|
|
@ -65,6 +65,7 @@ module.exports = class Spell
|
|||
@worker = null
|
||||
|
||||
setLanguage: (@language) ->
|
||||
@language = 'html' if @level.isType('web-dev')
|
||||
#console.log 'setting language to', @language, 'so using original source', @languages[language] ? @languages.javascript
|
||||
@originalSource = @languages[@language] ? @languages.javascript
|
||||
@originalSource = @addPicoCTFProblem() if window.serverConfig.picoCTF
|
||||
|
@ -126,6 +127,8 @@ module.exports = class Spell
|
|||
else
|
||||
source = @getSource()
|
||||
[pure, problems] = [null, null]
|
||||
if @language is 'html'
|
||||
[pure, problems] = [source, []] # TODO: problems? Actually do something when transpiling
|
||||
for thangID, spellThang of @thangs
|
||||
unless pure
|
||||
pure = spellThang.aether.transpile source
|
||||
|
|
|
@ -55,6 +55,7 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView
|
|||
@buildDocs() unless @docsBuilt
|
||||
|
||||
buildAvatar: ->
|
||||
return unless @thang.world
|
||||
avatar = new ThangAvatarView thang: @thang, includeName: false, supermodel: @supermodel
|
||||
if @avatar
|
||||
@avatar.$el.replaceWith avatar.$el
|
||||
|
|
|
@ -226,7 +226,7 @@ module.exports = class SpellView extends CocoView
|
|||
disableSpaces = @options.level.get('disableSpaces') or false
|
||||
aceConfig = me.get('aceConfig') ? {}
|
||||
disableSpaces = false if aceConfig.keyBindings and aceConfig.keyBindings isnt 'default' # Not in vim/emacs mode
|
||||
disableSpaces = false if @spell.language in ['lua', 'java', 'coffeescript'] # Don't disable for more advanced/experimental languages
|
||||
disableSpaces = false if @spell.language in ['lua', 'java', 'coffeescript', 'html'] # Don't disable for more advanced/experimental languages
|
||||
if not disableSpaces or (_.isNumber(disableSpaces) and disableSpaces < me.level())
|
||||
return @ace.execCommand 'insertstring', ' '
|
||||
line = @aceDoc.getLine @ace.getCursorPosition().row
|
||||
|
@ -470,6 +470,7 @@ module.exports = class SpellView extends CocoView
|
|||
# TODO: Turn on more autocompletion based on level sophistication
|
||||
# TODO: E.g. using the language default snippets yields a bunch of crazy non-beginner suggestions
|
||||
# TODO: Options logic shouldn't exist both here and in updateAutocomplete()
|
||||
return if @spell.language is 'html'
|
||||
popupFontSizePx = @options.level.get('autocompleteFontSizePx') ? 16
|
||||
@zatanna = new Zatanna @ace,
|
||||
basic: false
|
||||
|
@ -864,7 +865,9 @@ module.exports = class SpellView extends CocoView
|
|||
beginningOfLine = not currentLine.substr(0, cursorPosition.column).trim().length # uncommenting code, for example
|
||||
incompleteThis = /^(s|se|sel|self|t|th|thi|this)$/.test currentLine.trim()
|
||||
#console.log "finished=#{valid and (endOfLine or beginningOfLine) and not incompleteThis}", valid, endOfLine, beginningOfLine, incompleteThis, cursorPosition, currentLine.length, aether, new Date() - 0, currentLine
|
||||
if valid and (endOfLine or beginningOfLine) and not incompleteThis
|
||||
if @options.level.isType('web-dev') and valid
|
||||
console.log 'Update it!'
|
||||
else if valid and (endOfLine or beginningOfLine) and not incompleteThis
|
||||
@preload()
|
||||
|
||||
singleLineCommentRegex: ->
|
||||
|
@ -976,8 +979,6 @@ module.exports = class SpellView extends CocoView
|
|||
@ace.insert "{x=#{e.x}, y=#{e.y}}"
|
||||
else
|
||||
@ace.insert "{x: #{e.x}, y: #{e.y}}"
|
||||
|
||||
|
||||
@highlightCurrentLine()
|
||||
|
||||
onStatementIndexUpdated: (e) ->
|
||||
|
@ -1246,7 +1247,7 @@ module.exports = class SpellView extends CocoView
|
|||
@debugView?.destroy()
|
||||
@translationView?.destroy()
|
||||
@toolbarView?.destroy()
|
||||
@zatanna.addSnippets [], @editorLang if @editorLang?
|
||||
@zatanna?.addSnippets [], @editorLang if @editorLang?
|
||||
$(window).off 'resize', @onWindowResize
|
||||
window.clearTimeout @saveSpadeTimeout
|
||||
@saveSpadeTimeout = null
|
||||
|
|
|
@ -59,6 +59,9 @@ module.exports = class TomeView extends CocoView
|
|||
super()
|
||||
@worker = @createWorker()
|
||||
programmableThangs = _.filter @options.thangs, (t) -> t.isProgrammable and t.programmableMethods
|
||||
if @options.level.isType('web-dev')
|
||||
if @fakeProgrammableThang = @createFakeProgrammableThang()
|
||||
programmableThangs = [@fakeProgrammableThang]
|
||||
@createSpells programmableThangs, programmableThangs[0]?.world # Do before spellList, thangList, and castButton
|
||||
unless @options.level.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev', 'web-dev')
|
||||
@spellList = @insertSubView new SpellListView spells: @spells, supermodel: @supermodel, level: @options.level
|
||||
|
@ -140,7 +143,7 @@ module.exports = class TomeView extends CocoView
|
|||
god: @options.god
|
||||
|
||||
for thangID, spellKeys of @thangSpells
|
||||
thang = world.getThangByID thangID
|
||||
thang = @fakeProgrammableThang ? world.getThangByID thangID
|
||||
if thang
|
||||
@spells[spellKey].addThang thang for spellKey in spellKeys
|
||||
else
|
||||
|
@ -161,6 +164,7 @@ module.exports = class TomeView extends CocoView
|
|||
@cast e?.preload, e?.realTime
|
||||
|
||||
cast: (preload=false, realTime=false) ->
|
||||
return if @options.level.isType('web-dev')
|
||||
sessionState = @options.session.get('state') ? {}
|
||||
if realTime
|
||||
sessionState.submissionCount = (sessionState.submissionCount ? 0) + 1
|
||||
|
@ -194,7 +198,7 @@ module.exports = class TomeView extends CocoView
|
|||
@castButton?.$el.hide()
|
||||
|
||||
onSpriteSelected: (e) ->
|
||||
return if @spellView and @options.level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev'] # Never deselect the hero in the Tome.
|
||||
return if @spellView and @options.level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev', 'web-dev'] # Never deselect the hero in the Tome.
|
||||
thang = e.thang
|
||||
spellName = e.spellName
|
||||
@spellList?.$el.hide()
|
||||
|
@ -204,6 +208,9 @@ module.exports = class TomeView extends CocoView
|
|||
@clearSpellView()
|
||||
@updateSpellPalette thang, spell if spell
|
||||
return
|
||||
@setSpellView spell, thang
|
||||
|
||||
setSpellView: (spell, thang) ->
|
||||
unless spell.view is @spellView
|
||||
@clearSpellView()
|
||||
@spellView = spell.view
|
||||
|
@ -246,6 +253,9 @@ module.exports = class TomeView extends CocoView
|
|||
@cast()
|
||||
|
||||
onSelectPrimarySprite: (e) ->
|
||||
if @options.level.isType('web-dev')
|
||||
@setSpellView @spells['hero-placeholder/plan'], @fakeProgrammableThang
|
||||
return
|
||||
# This is only fired by PlayLevelView for hero levels currently
|
||||
# TODO: Don't hard code these hero names
|
||||
if @options.session.get('team') is 'ogres'
|
||||
|
@ -253,6 +263,15 @@ module.exports = class TomeView extends CocoView
|
|||
else
|
||||
Backbone.Mediator.publish 'level:select-sprite', thangID: 'Hero Placeholder'
|
||||
|
||||
createFakeProgrammableThang: ->
|
||||
return null unless hero = _.find @options.level.get('thangs'), id: 'Hero Placeholder'
|
||||
return null unless programmableConfig = _.find(hero.components, (component) -> component.config?.programmableMethods).config
|
||||
thang =
|
||||
id: 'Hero Placeholder'
|
||||
isProgrammable: true
|
||||
thang = _.merge thang, programmableConfig
|
||||
thang
|
||||
|
||||
destroy: ->
|
||||
spell.destroy() for spellKey, spell of @spells
|
||||
@worker?.terminate()
|
||||
|
|
Loading…
Reference in a new issue