mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-12-24 14:32:24 -05:00
d77625bc77
* Tweak API doc behavior and styling * Instead of moving to the left during active dialogues, just move to the top * Allow pointer events * Adjust close button * Re-enable pinning API docs for game-dev and web-dev levels * Make sidebar in PlayGameDevLevelView stretch, better layout columns * Set up content of PlayGameDevLevelView sidebar to scroll * Add rest of PlayGameDevLevelView sidebar content, rework what loading looks like * Finish PlayGameDevLevelView * Add share area below * Cover the brown background, paint it gray * Tweak PlayGameDevLevelView * Have progress bar show everything * Fix Surface resize handling * Fix PlayGameDevLevelView resizing incorrectly when playing * Add GameDevVictoryModal to PlayGameDevLevelView * Don't show missing-doctype annotation in Ace * Hook up GameDevVictoryModal copy button * Fix onChangeAnnotation runtime error * Fix onLevelLoaded runtime error * Have CourseVictoryModal link to /courses when course is done * Trim, update CourseDetailsView * Remove last vestiges of teacherMode * Remove giant navigation buttons at top * Quick switch to flat style * Add analytics for game-dev * Update Analytics events for gamedev * Prefix event names with context * Send to Mixpanel * Include more properties * Mostly set up indefinite play and autocast for game-dev levels * Set up cast buttons and shortcut for game-dev * Add rudimentary instructions when students play game-dev levels * Couple tweaks * fix a bit of code that expects frames to always stick around * have PlayGameDevLevelView render a couple frames on load * API Docs use 'game' instead of 'hero' * Move tags to head without combining * Add HTML comment-start string Fixes missing entry point arrows * Fix some whitespace
149 lines
5.1 KiB
CoffeeScript
149 lines
5.1 KiB
CoffeeScript
CocoView = require 'views/core/CocoView'
|
|
template = require 'templates/play/level/goals'
|
|
{me} = require 'core/auth'
|
|
utils = require 'core/utils'
|
|
|
|
stateIconMap =
|
|
success: 'glyphicon-ok'
|
|
failure: 'glyphicon-remove'
|
|
|
|
module.exports = class LevelGoalsView extends CocoView
|
|
id: 'goals-view'
|
|
template: template
|
|
className: 'secret expanded'
|
|
playbackEnded: false
|
|
|
|
subscriptions:
|
|
'goal-manager:new-goal-states': 'onNewGoalStates'
|
|
'tome:cast-spells': 'onTomeCast'
|
|
'level:set-letterbox': 'onSetLetterbox'
|
|
'level:set-playing': 'onSetPlaying'
|
|
'surface:playback-restarted': 'onSurfacePlaybackRestarted'
|
|
'surface:playback-ended': 'onSurfacePlaybackEnded'
|
|
|
|
events:
|
|
'mouseenter': ->
|
|
@mouseEntered = true
|
|
@updatePlacement()
|
|
|
|
'mouseleave': ->
|
|
@mouseEntered = false
|
|
@updatePlacement()
|
|
|
|
constructor: (options) ->
|
|
super options
|
|
@level = options.level
|
|
|
|
onNewGoalStates: (e) ->
|
|
firstRun = not @previousGoalStatus?
|
|
@previousGoalStatus ?= {}
|
|
@$el.find('.goal-status').addClass 'secret'
|
|
classToShow = null
|
|
classToShow = 'success' if e.overallStatus is 'success'
|
|
classToShow = 'failure' if e.overallStatus is 'failure'
|
|
classToShow ?= 'timed-out' if e.timedOut
|
|
classToShow ?= 'incomplete'
|
|
@$el.find('.goal-status.'+classToShow).removeClass 'secret'
|
|
list = $('#primary-goals-list', @$el)
|
|
list.empty()
|
|
goals = []
|
|
for goal in e.goals
|
|
state = e.goalStates[goal.id]
|
|
continue if goal.optional and @level.isType('course') and state.status isnt 'success'
|
|
if goal.hiddenGoal
|
|
continue if goal.optional and state.status isnt 'success'
|
|
continue if not goal.optional and state.status isnt 'failure'
|
|
continue if goal.team and me.team isnt goal.team
|
|
text = utils.i18n goal, 'name'
|
|
if state.killed
|
|
dead = _.filter(_.values(state.killed)).length
|
|
targeted = _.values(state.killed).length
|
|
if targeted > 1
|
|
# Does this make sense?
|
|
if goal.isPositive
|
|
completed = dead
|
|
else
|
|
completed = targeted - dead
|
|
text = text + " (#{completed}/#{targeted})"
|
|
# This should really get refactored, along with GoalManager, so that goals have a standard
|
|
# representation of how many are done, how many are needed, what that means, etc.
|
|
li = $('<li></li>').addClass("status-#{state.status}").text(text)
|
|
iconClass = stateIconMap[state.status]
|
|
li.prepend($('<i></i>').addClass("glyphicon #{iconClass or ''}")) # If empty, insert a .glyphicon to take up space
|
|
list.append(li)
|
|
goals.push goal
|
|
if not firstRun and state.status is 'success' and @previousGoalStatus[goal.id] isnt 'success'
|
|
@soundToPlayWhenPlaybackEnded = 'goal-success'
|
|
else if not firstRun and state.status isnt 'success' and @previousGoalStatus[goal.id] is 'success'
|
|
@soundToPlayWhenPlaybackEnded = 'goal-incomplete-again'
|
|
else
|
|
@soundToPlayWhenPlaybackEnded = null
|
|
@previousGoalStatus[goal.id] = state.status
|
|
if goals.length > 0 and @$el.hasClass 'secret'
|
|
@$el.removeClass('secret')
|
|
@lastSizeTweenTime = new Date()
|
|
@updatePlacement()
|
|
|
|
onTomeCast: (e) ->
|
|
return if e.preload
|
|
@$el.find('.goal-status').addClass('secret')
|
|
@$el.find('.goal-status.running').removeClass('secret')
|
|
|
|
onSetPlaying: (e) ->
|
|
return unless e.playing
|
|
# Automatically hide it while we replay
|
|
@mouseEntered = false
|
|
@expanded = true
|
|
@updatePlacement()
|
|
|
|
onSurfacePlaybackRestarted: ->
|
|
@playbackEnded = false
|
|
@$el.removeClass 'brighter'
|
|
@lastSizeTweenTime = new Date()
|
|
@updatePlacement()
|
|
|
|
onSurfacePlaybackEnded: ->
|
|
return if @level.isType('game-dev')
|
|
@playbackEnded = true
|
|
@updateHeight()
|
|
@$el.addClass 'brighter'
|
|
@lastSizeTweenTime = new Date()
|
|
@updatePlacement()
|
|
if @soundToPlayWhenPlaybackEnded
|
|
@playSound @soundToPlayWhenPlaybackEnded
|
|
|
|
updateHeight: ->
|
|
return if @$el.hasClass('brighter') or @$el.hasClass('secret')
|
|
return if (new Date() - @lastSizeTweenTime) < 500 # Don't measure this while still animating, might get the wrong value. Should match sass transition time.
|
|
@normalHeight = @$el.outerHeight()
|
|
|
|
updatePlacement: ->
|
|
# Expand it if it's at the end. Mousing over reverses this.
|
|
expand = @playbackEnded isnt @mouseEntered
|
|
return if expand is @expanded
|
|
@updateHeight()
|
|
sound = if expand then 'goals-expand' else 'goals-collapse'
|
|
if expand
|
|
top = -5
|
|
else
|
|
height = @normalHeight
|
|
height = @$el.outerHeight() if not height or @playbackEnded
|
|
top = 41 - height
|
|
@$el.css 'top', top
|
|
if @soundTimeout
|
|
# Don't play the sound we were going to play after all; the transition has reversed.
|
|
clearTimeout @soundTimeout
|
|
@soundTimeout = null
|
|
else if @expanded?
|
|
# Play it when the transition ends, not when it begins.
|
|
@soundTimeout = _.delay @playToggleSound, 500, sound
|
|
@expanded = expand
|
|
|
|
playToggleSound: (sound) =>
|
|
return if @destroyed
|
|
@playSound sound unless @options.level.isType('game-dev')
|
|
@soundTimeout = null
|
|
|
|
onSetLetterbox: (e) ->
|
|
@$el.toggle not e.on
|
|
@updatePlacement()
|