First pass at adding 'web-dev' level type

This commit is contained in:
Nick Winter 2016-07-14 09:38:45 -07:00
parent c0a70cb2ab
commit 349ab24da7
13 changed files with 62 additions and 25 deletions

View file

@ -245,6 +245,12 @@ particleKinds['level-dungeon-game-dev'] = particleKinds['level-dungeon-game-dev-
colorMiddle: hsl 0.7, 0.75, 0.5
colorEnd: hsl 0.7, 0.75, 0.3
particleKinds['level-dungeon-web-dev'] = particleKinds['level-dungeon-web-dev-premium'] = ext particleKinds['level-dungeon-hero-ladder'],
emitter:
colorStart: hsl 0.7, 0.25, 0.7
colorMiddle: hsl 0.7, 0.25, 0.5
colorEnd: hsl 0.7, 0.25, 0.3
particleKinds['level-dungeon-premium-item'] = ext particleKinds['level-dungeon-gate'],
emitter:
particleCount: 2000
@ -300,6 +306,12 @@ particleKinds['level-forest-game-dev'] = particleKinds['level-forest-game-dev-pr
colorMiddle: hsl 0.7, 0.75, 0.5
colorEnd: hsl 0.7, 0.75, 0.3
particleKinds['level-forest-web-dev'] = particleKinds['level-forest-web-dev-premium'] = ext particleKinds['level-forest-hero-ladder'],
emitter:
colorStart: hsl 0.7, 0.25, 0.7
colorMiddle: hsl 0.7, 0.25, 0.5
colorEnd: hsl 0.7, 0.25, 0.3
particleKinds['level-forest-premium-item'] = ext particleKinds['level-forest-gate'],
emitter:
particleCount: 2000
@ -355,6 +367,12 @@ particleKinds['level-desert-game-dev'] = particleKinds['level-desert-game-dev-pr
colorMiddle: hsl 0.7, 0.75, 0.5
colorEnd: hsl 0.7, 0.75, 0.3
particleKinds['level-desert-web-dev'] = particleKinds['level-desert-web-dev-premium'] = ext particleKinds['level-desert-hero-ladder'],
emitter:
colorStart: hsl 0.7, 0.25, 0.7
colorMiddle: hsl 0.7, 0.25, 0.5
colorEnd: hsl 0.7, 0.25, 0.3
particleKinds['level-mountain-premium-hero'] = ext particleKinds['level-mountain-premium'],
emitter:
particleCount: 200
@ -395,6 +413,12 @@ particleKinds['level-mountain-game-dev'] = particleKinds['level-mountain-game-de
colorMiddle: hsl 0.7, 0.75, 0.5
colorEnd: hsl 0.7, 0.75, 0.3
particleKinds['level-mountain-web-dev'] = particleKinds['level-mountain-web-dev-premium'] = ext particleKinds['level-mountain-hero-ladder'],
emitter:
colorStart: hsl 0.7, 0.25, 0.7
colorMiddle: hsl 0.7, 0.25, 0.5
colorEnd: hsl 0.7, 0.25, 0.3
particleKinds['level-glacier-premium-hero'] = ext particleKinds['level-glacier-premium'],
emitter:
particleCount: 200
@ -435,6 +459,12 @@ particleKinds['level-glacier-game-dev'] = particleKinds['level-glacier-game-dev-
colorMiddle: hsl 0.7, 0.75, 0.5
colorEnd: hsl 0.7, 0.75, 0.3
particleKinds['level-glacier-web-dev'] = particleKinds['level-glacier-web-dev-premium'] = ext particleKinds['level-glacier-hero-ladder'],
emitter:
colorStart: hsl 0.7, 0.25, 0.7
colorMiddle: hsl 0.7, 0.25, 0.5
colorEnd: hsl 0.7, 0.25, 0.3
particleKinds['level-volcano-premium-hero'] = ext particleKinds['level-volcano-premium'],
emitter:
particleCount: 200
@ -474,3 +504,9 @@ particleKinds['level-volcano-game-dev'] = particleKinds['level-volcano-game-dev-
colorStart: hsl 0.7, 0.75, 0.7
colorMiddle: hsl 0.7, 0.75, 0.5
colorEnd: hsl 0.7, 0.75, 0.3
particleKinds['level-volcano-web-dev'] = particleKinds['level-volcano-web-dev-premium'] = ext particleKinds['level-volcano-hero-ladder'],
emitter:
colorStart: hsl 0.7, 0.25, 0.7
colorMiddle: hsl 0.7, 0.25, 0.5
colorEnd: hsl 0.7, 0.25, 0.3

View file

@ -74,7 +74,7 @@ module.exports = class LevelSetupManager extends CocoClass
@session.set 'heroConfig', {"thangType":raider,"inventory":{}}
@onInventoryModalPlayClicked()
return
if @level.isType('course', 'course-ladder') or window.serverConfig.picoCTF
if @level.isType('course', 'course-ladder', 'game-dev', 'web-dev') or window.serverConfig.picoCTF
@onInventoryModalPlayClicked()
return
@heroesModal = new PlayHeroesModal({supermodel: @supermodel, session: @session, confirmButtonI18N: 'play.next', level: @level, hadEverChosenHero: @options.hadEverChosenHero})

View file

@ -59,7 +59,7 @@ module.exports = class Level extends CocoModel
denormalize: (supermodel, session, otherSession) ->
o = $.extend true, {}, @attributes
if o.thangs and @isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev')
if o.thangs and @isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev', 'web-dev')
thangTypesWithComponents = (tt for tt in supermodel.getModels(ThangType) when tt.get('components')?)
thangTypesByOriginal = _.indexBy thangTypesWithComponents, (tt) -> tt.get('original') # Optimization
for levelThang in o.thangs

View file

@ -46,7 +46,7 @@ module.exports = class ThangComponentConfigView extends CocoView
schema.default ?= {}
_.merge schema.default, @additionalDefaults if @additionalDefaults
if @level?.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev')
if @level?.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev', 'web-dev')
schema.required = []
treemaOptions =
supermodel: @supermodel

View file

@ -41,7 +41,7 @@ module.exports = class LevelThangEditView extends CocoView
level: @level
world: @world
if @level.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev') then options.thangType = thangType
if @level.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev', 'web-dev') then options.thangType = thangType
@thangComponentEditView = new ThangComponentsEditView options
@listenTo @thangComponentEditView, 'components-changed', @onComponentsChanged

View file

@ -636,14 +636,14 @@ module.exports = class ThangsTabView extends CocoView
if batchInsert
if thangType.get('name') is 'Hero Placeholder'
thangID = 'Hero Placeholder'
return if not @level.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev') or @getThangByID(thangID)
return if not @level.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev', 'web-dev') 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.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev')
else if @level.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev', 'web-dev')
components = [] # Load them all from default ThangType Components
else
components = _.cloneDeep thangType.get('components') ? []

View file

@ -51,7 +51,7 @@ module.exports = class VerifierView extends RootView
for campaign in @campaigns.models when campaign.get('type') in ['course', 'hero'] and campaign.get('slug') isnt 'picoctf'
@levelsByCampaign[campaign.get('slug')] ?= {levels: [], checked: true}
campaignInfo = @levelsByCampaign[campaign.get('slug')]
for levelID, level of campaign.get('levels') when level.type not in ['hero-ladder', 'course-ladder', 'game-dev'] # Would use isType, but it's not a Level model
for levelID, level of campaign.get('levels') when level.type not in ['hero-ladder', 'course-ladder', 'game-dev', 'web-dev'] # Would use isType, but it's not a Level model
campaignInfo.levels.push level.slug
filterCodeLanguages: ->

View file

@ -45,7 +45,7 @@ module.exports = class ControlBarView extends CocoView
@observing = options.session.get('creator') isnt me.id
@levelNumber = ''
if @level.isType('course') and @level.get('campaignIndex')?
if @level.isType('course', 'game-dev', 'web-dev') and @level.get('campaignIndex')?
@levelNumber = @level.get('campaignIndex') + 1
if @courseInstanceID
@courseInstance = new CourseInstance(_id: @courseInstanceID)
@ -137,6 +137,7 @@ module.exports = class ControlBarView extends CocoView
@homeLink += "/#{@courseInstanceID}"
@homeViewArgs.push @courseInstanceID
#else if @level.isType('game-dev') # TODO
#else if @level.isType('web-dev') # TODO
else
@homeLink = '/'
@homeViewClass = 'views/HomeView'

View file

@ -205,7 +205,7 @@ module.exports = class PlayLevelView extends RootView
@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')
@$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
@$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
@ -468,7 +468,7 @@ module.exports = class PlayLevelView extends RootView
return false if $.browser?.msie or $.browser?.msedge
return false if $.browser.linux
return false if me.level() < 8
if @level.isType('course', 'game-dev')
if @level.isType('course', 'game-dev', 'web-dev')
return false
else if @level.isType('hero') and gamesSimulated
return false if stillBuggy
@ -541,7 +541,7 @@ module.exports = class PlayLevelView extends RootView
onDonePressed: -> @showVictory()
onShowVictory: (e) ->
$('#level-done-button').show() unless @level.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev')
$('#level-done-button').show() unless @level.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev', 'web-dev')
@showVictory() if e.showModal
return if @victorySeen
@victorySeen = true
@ -559,7 +559,7 @@ module.exports = class PlayLevelView extends RootView
return if @level.hasLocalChanges() # Don't award achievements when beating level changed in level editor
@endHighlight()
options = {level: @level, supermodel: @supermodel, session: @session, hasReceivedMemoryWarning: @hasReceivedMemoryWarning, courseID: @courseID, courseInstanceID: @courseInstanceID, world: @world}
ModalClass = if @level.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev') then HeroVictoryModal else VictoryModal
ModalClass = if @level.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev', 'web-dev') then HeroVictoryModal else VictoryModal
ModalClass = CourseVictoryModal if @isCourseMode() or me.isSessionless()
ModalClass = PicoCTFVictoryModal if window.serverConfig.picoCTF
victoryModal = new ModalClass(options)

View file

@ -49,7 +49,7 @@ module.exports = class HeroVictoryModal extends ModalView
@session = options.session
@level = options.level
@thangTypes = {}
if @level.isType('hero', 'hero-ladder', 'course', 'course-ladder', 'game-dev')
if @level.isType('hero', 'hero-ladder', 'course', 'course-ladder', 'game-dev', 'web-dev')
achievements = new CocoCollection([], {
url: "/db/achievement?related=#{@session.get('level').original}"
model: Achievement
@ -63,7 +63,7 @@ module.exports = class HeroVictoryModal extends ModalView
else
@readyToContinue = true
@playSound 'victory'
if @level.isType('course')
if @level.isType('course', 'game-dev', 'web-dev')
if nextLevel = @level.get('nextLevel')
@nextLevel = new Level().setURL "/db/level/#{nextLevel.original}/version/#{nextLevel.majorVersion}"
@nextLevel = @supermodel.loadModel(@nextLevel).model
@ -73,7 +73,7 @@ module.exports = class HeroVictoryModal extends ModalView
if @level.isType('course', 'course-ladder')
@saveReviewEventually = _.debounce(@saveReviewEventually, 2000)
@loadExistingFeedback()
# TODO: support game-dev
# TODO: support 'game-dev' and 'web-dev' (not the same as 'course' since can be played outside of courses)
destroy: ->
clearInterval @sequentialAnimationInterval
@ -154,8 +154,8 @@ module.exports = class HeroVictoryModal extends ModalView
getRenderData: ->
c = super()
c.levelName = utils.i18n @level.attributes, 'name'
# TODO: support 'game-dev'
if @level.isType('hero', 'game-dev')
# TODO: support 'game-dev', 'web-dev'
if @level.isType('hero', 'game-dev', 'web-dev')
c.victoryText = utils.i18n @level.get('victory') ? {}, 'body'
earnedAchievementMap = _.indexBy(@newEarnedAchievements or [], (ea) -> ea.get('achievement'))
for achievement in (@achievements?.models or [])
@ -223,7 +223,7 @@ module.exports = class HeroVictoryModal extends ModalView
afterRender: ->
super()
@$el.toggleClass 'with-achievements', @level.isType('hero', 'hero-ladder', 'game-dev') # TODO: support game-dev
@$el.toggleClass 'with-achievements', @level.isType('hero', 'hero-ladder', 'game-dev', 'web-dev') # TODO: support game-dev, web-dev
return unless @supermodel.finished()
@playSelectionSound hero, true for original, hero of @thangTypes # Preload them
@updateSavingProgressStatus()
@ -233,7 +233,7 @@ module.exports = class HeroVictoryModal extends ModalView
@insertSubView @ladderSubmissionView, @$el.find('.ladder-submission-view')
initializeAnimations: ->
return @endSequentialAnimations() unless @level.isType('hero', 'hero-ladder', 'game-dev') # TODO: support game-dev
return @endSequentialAnimations() unless @level.isType('hero', 'hero-ladder', 'game-dev', 'web-dev') # TODO: support game-dev, web-dev
@updateXPBars 0
#playVictorySound = => @playSound 'victory-title-appear' # TODO: actually add this
@$el.find('#victory-header').delay(250).queue(->
@ -264,7 +264,7 @@ module.exports = class HeroVictoryModal extends ModalView
beginSequentialAnimations: ->
return if @destroyed
return unless @level.isType('hero', 'hero-ladder', 'game-dev') # TODO: support game-dev
return unless @level.isType('hero', 'hero-ladder', 'game-dev', 'web-dev') # TODO: support game-dev, web-dev
@sequentialAnimatedPanels = _.map(@animatedPanels.find('.reward-panel'), (panel) -> {
number: $(panel).data('number')
previousNumber: $(panel).data('previous-number')
@ -414,7 +414,7 @@ module.exports = class HeroVictoryModal extends ModalView
{'kithgard-gates': 'forest', 'kithgard-mastery': 'forest', 'siege-of-stonehold': 'desert', 'clash-of-clones': 'mountain', 'summits-gate': 'glacier'}[@level.get('slug')] or @level.get 'campaign' # Much easier to just keep this updated than to dynamically figure it out.
getNextLevelLink: (returnToCourse=false) ->
if @level.isType('course') and nextLevel = @level.get('nextLevel') and not returnToCourse
if @level.isType('course', 'game-dev', 'web-dev') and nextLevel = @level.get('nextLevel') and not returnToCourse # TODO: support game-dev and web-dev
# need to do something more complicated to load its slug
console.log 'have @nextLevel', @nextLevel, 'from nextLevel', nextLevel
link = "/play/level/#{@nextLevel.get('slug')}"

View file

@ -157,7 +157,7 @@ module.exports = class SpellPaletteView extends CocoView
else
propStorage =
'this': ['apiProperties', 'apiMethods']
if not @options.level.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev') or not @options.programmable
if not @options.level.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev', 'web-dev') or not @options.programmable
@organizePalette propStorage, allDocs, excludedDocs
else
@organizePaletteHero propStorage, allDocs, excludedDocs
@ -199,7 +199,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.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev') then 'play_level.tome_your_skills' else 'play_level.tome_available_spells'
i18nKey = if @options.level.isType('hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev', 'web-dev') then 'play_level.tome_your_skills' else 'play_level.tome_available_spells'
defaultGroup = $.i18n.t i18nKey
@entryGroups = {}
@entryGroups[defaultGroup] = @entries

View file

@ -60,7 +60,7 @@ module.exports = class TomeView extends CocoView
@worker = @createWorker()
programmableThangs = _.filter @options.thangs, (t) -> t.isProgrammable and t.programmableMethods
@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')
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
@castButton = @insertSubView new CastButtonView spells: @spells, level: @options.level, session: @options.session, god: @options.god
@teamSpellMap = @generateTeamSpellMap(@spells)

View file

@ -19,7 +19,7 @@ module.exports = class LevelGuideView extends CocoView
@levelSlug = options.level.get('slug')
@sessionID = options.session.get('_id')
@requiresSubscription = not me.isPremium()
@isCourseLevel = options.level.isType('course', 'course-ladder')
@isCourseLevel = options.level.isType('course', 'course-ladder') # TODO: figure this out for game-dev, web-dev levels
@helpVideos = if @isCourseLevel then [] else options.level.get('helpVideos') ? []
@trackedHelpVideoStart = @trackedHelpVideoFinish = false
# A/B Testing video tutorial styles