mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-27 09:35:39 -05:00
First pass at adding 'web-dev' level type
This commit is contained in:
parent
c0a70cb2ab
commit
349ab24da7
13 changed files with 62 additions and 25 deletions
|
@ -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
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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') ? []
|
||||
|
|
|
@ -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: ->
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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')}"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue