mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-25 08:38:09 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
bf0013ea0a
12 changed files with 103 additions and 135 deletions
|
@ -4,22 +4,4 @@ module.exports = [
|
|||
noteChain: []
|
||||
id: "Introduction"
|
||||
}
|
||||
{
|
||||
channel: "world:won"
|
||||
noteChain: []
|
||||
id: "Victory Playback"
|
||||
scriptPrereqs: ["Introduction"]
|
||||
}
|
||||
{
|
||||
channel: "level:set-playing"
|
||||
noteChain: []
|
||||
scriptPrereqs: ["Victory Playback"]
|
||||
id: "Victory Playback Started"
|
||||
}
|
||||
{
|
||||
channel: "surface:frame-changed"
|
||||
noteChain: []
|
||||
scriptPrereqs: ["Victory Playback Started"]
|
||||
id: "Show Victory"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -256,7 +256,7 @@ module.exports = ScriptManager = class ScriptManager extends CocoClass
|
|||
@publishNote(note)
|
||||
|
||||
publishNote: (note) ->
|
||||
Backbone.Mediator.publish 'playback:real-time-playback-ended', {}
|
||||
Backbone.Mediator.publish 'playback:real-time-playback-ended', {} unless @session.get('heroConfig') # Only old levels need this, to stop interfering with old victory coolcams.
|
||||
Backbone.Mediator.publish note.channel, note.event ? {}
|
||||
|
||||
# ENDING NOTES
|
||||
|
|
|
@ -408,9 +408,10 @@
|
|||
tome_minion_spells: "Your Minions' Spells"
|
||||
tome_read_only_spells: "Read-Only Spells"
|
||||
tome_other_units: "Other Units"
|
||||
tome_cast_button_castable: "Cast Spell"
|
||||
tome_cast_button_casting: "Casting"
|
||||
tome_cast_button_cast: "Spell Cast"
|
||||
tome_cast_button_run: "Run"
|
||||
tome_cast_button_running: "Running"
|
||||
tome_cast_button_ran: "Ran"
|
||||
tome_submit_button: "Submit"
|
||||
tome_select_spell: "Select a Spell"
|
||||
tome_select_a_thang: "Select Someone for "
|
||||
tome_available_spells: "Available Spells"
|
||||
|
|
|
@ -4,86 +4,55 @@
|
|||
+keyframes(castablePulse)
|
||||
from
|
||||
@include box-shadow(0px 0px 8px #333)
|
||||
50%
|
||||
@include box-shadow(0px 0px 35px skyblue)
|
||||
to
|
||||
@include box-shadow(0px 0px 8px #333)
|
||||
|
||||
+keyframes(castablePulseButton)
|
||||
from
|
||||
color: white
|
||||
50%
|
||||
@include box-shadow(0px 0px 35px skyblue)
|
||||
color: skyblue
|
||||
to
|
||||
@include box-shadow(0px 0px 8px #333)
|
||||
color: white
|
||||
|
||||
+keyframes(winnablePulse)
|
||||
from
|
||||
@include box-shadow(0px 0px 8px #333)
|
||||
color: white
|
||||
50%
|
||||
@include box-shadow(0px 0px 35px #87FFCE)
|
||||
color: #87FFFF
|
||||
to
|
||||
@include box-shadow(0px 0px 8px #333)
|
||||
color: white
|
||||
|
||||
#cast-button-view
|
||||
display: none
|
||||
position: absolute
|
||||
width: 35%
|
||||
|
||||
.cast-button-group
|
||||
z-index: 2
|
||||
z-index: 2
|
||||
width: 100%
|
||||
border-radius: 6px
|
||||
|
||||
.btn
|
||||
padding: 3px 10px
|
||||
height: 40px
|
||||
|
||||
.submit-button
|
||||
margin-left: 20px
|
||||
|
||||
.cast-button
|
||||
margin-left: 10px
|
||||
@include opacity(0.77)
|
||||
width: 100%
|
||||
border-radius: 6px
|
||||
|
||||
.button-progress-overlay
|
||||
position: absolute
|
||||
left: -1px
|
||||
top: -1px
|
||||
bottom: -1px
|
||||
border-radius: 6px
|
||||
z-index: 10
|
||||
pointer-events: none
|
||||
// This transition time should roughly match the world progress update interval
|
||||
@include transition(width .2s linear)
|
||||
@include transition(box-shadow .2s linear)
|
||||
|
||||
&.casting .button-progress-overlay
|
||||
background-color: green
|
||||
@include opacity(0.5)
|
||||
@include box-shadow(0px 0px 15px green)
|
||||
|
||||
|
||||
&:hover, &.castable
|
||||
@include opacity(1)
|
||||
|
||||
&:not(.winnable) .cast-button.castable
|
||||
font-weight: bold
|
||||
-webkit-animation-name: castablePulse
|
||||
-webkit-animation-duration: 3s
|
||||
-webkit-animation-iteration-count: infinite
|
||||
|
||||
&.castable
|
||||
-webkit-animation-name: castablePulse
|
||||
-webkit-animation-duration: 3s
|
||||
-webkit-animation-iteration-count: infinite
|
||||
|
||||
.cast-button
|
||||
font-weight: bold
|
||||
-webkit-animation-name: castablePulseButton
|
||||
-webkit-animation-duration: 3s
|
||||
-webkit-animation-iteration-count: infinite
|
||||
&:not(.castable):not(:hover)
|
||||
.cast-options-button
|
||||
// Mimic the disabled visuals
|
||||
@include opacity(0.65)
|
||||
background-image: none
|
||||
@include box-shadow(none)
|
||||
|
||||
.btn
|
||||
padding: 3px 10px
|
||||
height: 40px
|
||||
|
||||
.cast-button
|
||||
width: 80%
|
||||
width: -webkit-calc(100% - 40px)
|
||||
width: calc(100% - 40px)
|
||||
border-top-left-radius: 6px
|
||||
border-bottom-left-radius: 6px
|
||||
|
||||
@media screen and (max-width: 1440px)
|
||||
font-size: 16px
|
||||
@media screen and (max-width: 1280px)
|
||||
font-size: 14px
|
||||
@media screen and (max-width: 1024px)
|
||||
font-size: 12px
|
||||
|
||||
.cast-real-time-button
|
||||
width: 20%
|
||||
width: -webkit-calc(40px)
|
||||
width: calc(40px)
|
||||
&.winnable .submit-button
|
||||
font-weight: bold
|
||||
-webkit-animation-name: winnablePulse
|
||||
-webkit-animation-duration: 3s
|
||||
-webkit-animation-iteration-count: infinite
|
||||
|
|
|
@ -16,9 +16,8 @@ block modal-footer-content
|
|||
else if level.get('type') === 'ladder'
|
||||
a.btn.btn-primary(href="/play/ladder/#{level.get('slug')}#my-matches", data-dismiss="modal", data-i18n="play_level.victory_go_ladder") Return to Ladder
|
||||
else if hasNextLevel
|
||||
button.btn.btn-primary.next-level-button(data-dismiss="modal", data-i18n="play_level.victory_play_next_level") Play Next Level
|
||||
else
|
||||
a.btn.btn-primary(href="/", data-dismiss="modal", data-i18n="play_level.victory_go_home") Go Home
|
||||
button.btn.btn-success.next-level-button(data-dismiss="modal", data-i18n="play_level.victory_play_next_level") Play Next Level
|
||||
a.btn.btn-primary(href="/play-hero", data-dismiss="modal", data-i18n="play_level.victory_go_home") Go Home
|
||||
if me.get('anonymous')
|
||||
p.sign-up-poke
|
||||
button.btn.btn-success.sign-up-button.btn-large(data-toggle="coco-modal", data-target="modal/SignupModal", data-i18n="play_level.victory_sign_up") Sign Up to Save Progress
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
div.btn-group.btn-group-lg.cast-button-group
|
||||
.button-progress-overlay
|
||||
button.btn.btn-inverse.banner.cast-button(title=castVerbose, data-i18n="play_level.tome_cast_button_cast") Spell Cast
|
||||
button.btn.btn-inverse.banner.cast-real-time-button(title=castRealTimeVerbose)
|
||||
i.glyphicon.glyphicon-play
|
||||
button.btn.btn-lg.btn-inverse.banner.cast-button(title=castVerbose, data-i18n="play_level.tome_run_button_ran") Ran
|
||||
|
||||
button.btn.btn-lg.btn-success.banner.submit-button(title=castRealTimeVerbose) Submit
|
||||
|
|
|
@ -7,19 +7,19 @@ TEXTDIFF_OPTIONS =
|
|||
newTextName: "New"
|
||||
contextSize: 5
|
||||
viewType: 1
|
||||
|
||||
|
||||
module.exports = class DeltaView extends CocoView
|
||||
|
||||
|
||||
###
|
||||
Takes a CocoModel instance (model) and displays changes since the
|
||||
Takes a CocoModel instance (model) and displays changes since the
|
||||
last save (attributes vs _revertAttributes).
|
||||
|
||||
|
||||
* If headModel is included, will look for and display conflicts with the changes in model.
|
||||
* If comparisonModel is included, will show deltas between model and comparisonModel instead
|
||||
of changes within model itself.
|
||||
|
||||
|
||||
###
|
||||
|
||||
|
||||
@deltaCounter: 0
|
||||
className: 'delta-view'
|
||||
template: template
|
||||
|
@ -28,26 +28,26 @@ module.exports = class DeltaView extends CocoView
|
|||
super(options)
|
||||
@expandedDeltas = []
|
||||
@skipPaths = options.skipPaths
|
||||
|
||||
|
||||
for modelName in ['model', 'headModel', 'comparisonModel']
|
||||
@[modelName] = options[modelName]
|
||||
continue unless @[modelName] and options.loadModels
|
||||
if not @[modelName].isLoaded
|
||||
@[modelName] = @supermodel.loadModel(@[modelName], 'document').model
|
||||
|
||||
|
||||
@buildDeltas() if @supermodel.finished()
|
||||
|
||||
|
||||
onLoaded: ->
|
||||
@buildDeltas()
|
||||
super()
|
||||
|
||||
|
||||
buildDeltas: ->
|
||||
if @comparisonModel
|
||||
@expandedDeltas = @model.getExpandedDeltaWith(@comparisonModel)
|
||||
else
|
||||
@expandedDeltas = @model.getExpandedDelta()
|
||||
[@expandedDeltas, @skippedDeltas] = @filterDeltas(@expandedDeltas)
|
||||
|
||||
|
||||
if @headModel
|
||||
@headDeltas = @headModel.getExpandedDelta()
|
||||
@headDeltas = @filterDeltas(@headDeltas)[0]
|
||||
|
@ -74,33 +74,34 @@ module.exports = class DeltaView extends CocoView
|
|||
c.counter = DeltaView.deltaCounter
|
||||
DeltaView.deltaCounter += @expandedDeltas.length
|
||||
c
|
||||
|
||||
|
||||
afterRender: ->
|
||||
deltas = @$el.find('.details')
|
||||
for delta, i in deltas
|
||||
deltaEl = $(delta)
|
||||
deltaData = @expandedDeltas[i]
|
||||
@expandDetails(deltaEl, deltaData)
|
||||
|
||||
|
||||
conflictDeltas = @$el.find('.conflict-details')
|
||||
conflicts = (delta.conflict for delta in @expandedDeltas when delta.conflict)
|
||||
for delta, i in conflictDeltas
|
||||
deltaEl = $(delta)
|
||||
deltaData = conflicts[i]
|
||||
@expandDetails(deltaEl, deltaData)
|
||||
|
||||
|
||||
expandDetails: (deltaEl, deltaData) ->
|
||||
treemaOptions = { schema: deltaData.schema or {}, readOnly: true }
|
||||
|
||||
|
||||
if _.isObject(deltaData.left) and leftEl = deltaEl.find('.old-value')
|
||||
options = _.defaults {data: deltaData.left}, treemaOptions
|
||||
TreemaNode.make(leftEl, options).build()
|
||||
|
||||
|
||||
if _.isObject(deltaData.right) and rightEl = deltaEl.find('.new-value')
|
||||
options = _.defaults {data: deltaData.right}, treemaOptions
|
||||
TreemaNode.make(rightEl, options).build()
|
||||
|
||||
|
||||
if deltaData.action is 'text-diff'
|
||||
return console.error "Couldn't show diff for left: #{deltaData.left}, right: #{deltaData.right} of delta:", deltaData unless deltaData.left? and deltaData.right?
|
||||
left = difflib.stringAsLines deltaData.left
|
||||
right = difflib.stringAsLines deltaData.right
|
||||
sm = new difflib.SequenceMatcher(left, right)
|
||||
|
|
|
@ -587,7 +587,7 @@ hero = [
|
|||
difficulty: 1
|
||||
id: 'kithgard-gates'
|
||||
image: '/file/db/level/526fd3043c637ece50001bb2/the_herd_icon.png'
|
||||
description: 'Board up Kithguard and escape into the forest.'
|
||||
description: 'Escape the Kithgard dungeons and don\'t let the guardians get you.'
|
||||
x: 47.38
|
||||
y: 70.55
|
||||
}
|
||||
|
|
|
@ -53,8 +53,10 @@ module.exports = class ControlBarView extends CocoView
|
|||
c.multiplayerEnabled = @session.get('multiplayer')
|
||||
c.ladderGame = @level.get('type') is 'ladder'
|
||||
c.spectateGame = @spectateGame
|
||||
if @level.get('type') in ['ladder', 'ladder-tutorial']
|
||||
if @level.get('type', true) in ['ladder', 'ladder-tutorial']
|
||||
c.homeLink = '/play/ladder/' + @level.get('slug').replace /\-tutorial$/, ''
|
||||
else if @level.get('type', true) is 'hero'
|
||||
c.homeLink = '/play-hero'
|
||||
else
|
||||
c.homeLink = '/'
|
||||
c.editorLink = "/editor/level/#{@level.get('slug')}"
|
||||
|
|
|
@ -146,7 +146,11 @@ module.exports = class LevelHUDView extends CocoView
|
|||
createProperties: ->
|
||||
props = @$el.find('.thang-props')
|
||||
props.find(':not(.thang-name)').remove()
|
||||
props.find('.thang-name').text(if @thang.type then "#{@thang.id} - #{@thang.type}" else @thang.id)
|
||||
if @thang.id is 'Hero Placeholder'
|
||||
name = {knight: 'Tharin', captain: 'Anya'}[@thang.type] ? 'Hero'
|
||||
else
|
||||
name = if @thang.type then "#{@thang.id} - #{@thang.type}" else @thang.id
|
||||
props.find('.thang-name').text name
|
||||
propNames = _.without @thang.hudProperties ? [], 'action'
|
||||
nColumns = Math.ceil propNames.length / 5
|
||||
columns = ($('<div class="thang-props-column"></div>').appendTo(props) for i in [0 ... nColumns])
|
||||
|
|
|
@ -430,7 +430,7 @@ module.exports = class PlayLevelView extends RootView
|
|||
onDonePressed: -> @showVictory()
|
||||
|
||||
onShowVictory: (e) ->
|
||||
$('#level-done-button').show()
|
||||
$('#level-done-button').show() unless @level.get('type', true) is 'hero'
|
||||
@showVictory() if e.showModal
|
||||
setTimeout(@preloadNextLevel, 3000)
|
||||
return if @victorySeen
|
||||
|
@ -584,8 +584,12 @@ module.exports = class PlayLevelView extends RootView
|
|||
@world.scripts = scripts
|
||||
thangTypes = @supermodel.getModels(ThangType)
|
||||
startFrame = @lastWorldFramesLoaded ? 0
|
||||
if @world.frames.length is @world.totalFrames # Finished loading
|
||||
finishedLoading = @world.frames.length is @world.totalFrames
|
||||
if finishedLoading
|
||||
@lastWorldFramesLoaded = 0
|
||||
if @waitingForSubmissionComplete
|
||||
@onSubmissionComplete()
|
||||
@waitingForSubmissionComplete = false
|
||||
else
|
||||
@lastWorldFramesLoaded = @world.frames.length
|
||||
for [spriteName, message] in @world.thangDialogueSounds startFrame
|
||||
|
@ -605,15 +609,23 @@ module.exports = class PlayLevelView extends RootView
|
|||
onRealTimePlaybackEnded: (e) ->
|
||||
@$el.removeClass 'real-time'
|
||||
@onWindowResize()
|
||||
if @world.frames.length is @world.totalFrames
|
||||
_.delay @onSubmissionComplete, 750 # Wait for transition to end.
|
||||
else
|
||||
@waitingForSubmissionComplete = true
|
||||
@onRealTimeMultiplayerPlaybackEnded()
|
||||
|
||||
onSubmissionComplete: =>
|
||||
return if @destroyed
|
||||
@showVictory() if @goalManager.checkOverallStatus() is 'success'
|
||||
|
||||
destroy: ->
|
||||
@levelLoader?.destroy()
|
||||
@surface?.destroy()
|
||||
@god?.destroy()
|
||||
@goalManager?.destroy()
|
||||
@scriptManager?.destroy()
|
||||
@ambientSound.stop()
|
||||
@ambientSound?.stop()
|
||||
$(window).off 'resize', @onWindowResize
|
||||
delete window.world # not sure where this is set, but this is one way to clean it up
|
||||
clearInterval(@pointerInterval)
|
||||
|
|
|
@ -8,15 +8,15 @@ module.exports = class CastButtonView extends CocoView
|
|||
|
||||
events:
|
||||
'click .cast-button': 'onCastButtonClick'
|
||||
'click .cast-real-time-button': 'onCastRealTimeButtonClick'
|
||||
'click .submit-button': 'onCastRealTimeButtonClick'
|
||||
|
||||
subscriptions:
|
||||
'tome:spell-changed': 'onSpellChanged'
|
||||
'tome:cast-spells': 'onCastSpells'
|
||||
'god:world-load-progress-changed': 'onWorldLoadProgressChanged'
|
||||
'god:new-world-created': 'onNewWorld'
|
||||
'real-time-multiplayer:joined-game': 'onJoinedRealTimeMultiplayerGame'
|
||||
'real-time-multiplayer:left-game': 'onLeftRealTimeMultiplayerGame'
|
||||
'goal-manager:new-goal-states': 'onNewGoalStates'
|
||||
|
||||
constructor: (options) ->
|
||||
super options
|
||||
|
@ -37,11 +37,11 @@ module.exports = class CastButtonView extends CocoView
|
|||
afterRender: ->
|
||||
super()
|
||||
@castButton = $('.cast-button', @$el)
|
||||
@castButtonGroup = $('.cast-button-group', @$el)
|
||||
@castOptions = $('.autocast-delays', @$el)
|
||||
#delay = me.get('autocastDelay') # No more autocast
|
||||
delay = 90019001
|
||||
@setAutocastDelay delay
|
||||
@$el.find('.submit-button').hide() if @options.levelID is 'dungeons-of-kithgard'
|
||||
|
||||
attachTo: (spellView) ->
|
||||
@$el.detach().prependTo(spellView.toolbarView.$el).show()
|
||||
|
@ -71,12 +71,6 @@ module.exports = class CastButtonView extends CocoView
|
|||
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'cast', volume: 0.5
|
||||
@hasStartedCastingOnce = true
|
||||
@updateCastButton()
|
||||
@onWorldLoadProgressChanged progress: 0
|
||||
|
||||
onWorldLoadProgressChanged: (e) ->
|
||||
return # trying out showing progress on the canvas instead
|
||||
overlay = @castButtonGroup.find '.button-progress-overlay'
|
||||
overlay.css 'width', e.progress * @castButton.outerWidth() + 1
|
||||
|
||||
onNewWorld: (e) ->
|
||||
@casting = false
|
||||
|
@ -85,6 +79,12 @@ module.exports = class CastButtonView extends CocoView
|
|||
@hasCastOnce = true
|
||||
@updateCastButton()
|
||||
|
||||
onNewGoalStates: (e) ->
|
||||
@winnable = e.overallStatus is 'success'
|
||||
@$el.toggleClass 'winnable', @winnable
|
||||
if @winnable
|
||||
@$el.find('.submit-button').show() # In case we hid it, like on the first level.
|
||||
|
||||
updateCastButton: ->
|
||||
return if _.some @spells, (spell) => not spell.loaded
|
||||
|
||||
|
@ -92,13 +92,13 @@ module.exports = class CastButtonView extends CocoView
|
|||
spell.hasChangedSignificantly spell.getSource(), null, callback
|
||||
, (castable) =>
|
||||
Backbone.Mediator.publish 'tome:spell-has-changed-significantly-calculation', hasChangedSignificantly: castable
|
||||
@castButtonGroup.toggleClass('castable', castable).toggleClass('casting', @casting)
|
||||
@castButton.toggleClass('castable', castable).toggleClass('casting', @casting)
|
||||
if @casting
|
||||
s = $.i18n.t('play_level.tome_cast_button_casting', defaultValue: 'Casting')
|
||||
s = $.i18n.t('play_level.tome_cast_button_running')
|
||||
else if castable
|
||||
s = $.i18n.t('play_level.tome_cast_button_castable', defaultValue: 'Cast Spell') + ' ' + @castShortcut
|
||||
s = $.i18n.t('play_level.tome_cast_button_run') + ' ' + @castShortcut
|
||||
else
|
||||
s = $.i18n.t('play_level.tome_cast_button_cast', defaultValue: 'Spell Cast')
|
||||
s = $.i18n.t('play_level.tome_cast_button_ran')
|
||||
@castButton.text s
|
||||
@castButton.prop 'disabled', not castable
|
||||
|
||||
|
|
Loading…
Reference in a new issue