Merge branch 'master' into production

This commit is contained in:
Nick Winter 2014-11-26 12:57:10 -08:00
commit 318b499e3e
11 changed files with 146 additions and 74 deletions

View file

@ -39,7 +39,12 @@ module.exports = class Angel extends CocoClass
# say: debugging stuff, usually off; log: important performance indicators, keep on
say: (args...) -> #@log args...
log: (args...) -> console.info "|#{@shared.godNick}'s #{@nick}|", args...
log: ->
# console.info.apply is undefined in IE9, CofeeScript splats invocation won't work.
# http://stackoverflow.com/questions/5472938/does-ie9-support-console-log-and-is-it-a-real-function
message = "|#{@shared.godNick}'s #{@nick}|"
message += " #{arg}" for arg in arguments
console.info message
testWorker: =>
return if @destroyed
@ -238,7 +243,13 @@ module.exports = class Angel extends CocoClass
console?.profile? "World Generation #{(Math.random() * 1000).toFixed(0)}" if imitateIE9?
work.t0 = now()
work.testWorld = testWorld = new World work.userCodeMap
work.testWorld.levelSessionIDs = work.levelSessionIDs
work.testWorld.submissionCount = work.submissionCount
work.testWorld.flagHistory = work.flagHistory ? []
testWorld.loadFromLevel work.level
work.testWorld.preloading = work.preload
work.testWorld.headless = work.headless
work.testWorld.realTime = work.realTime
if @shared.goalManager
testGM = new GoalManager(testWorld)
testGM.setGoals work.goals
@ -254,7 +265,7 @@ module.exports = class Angel extends CocoClass
work.testWorld.goalManager.worldGenerationEnded() if work.testWorld.ended
serialized = testWorld.serialize()
window.BOX2D_ENABLED = false
World.deserialize serialized.serializedWorld, @shared.worldClassMap, @shared.lastSerializedWorldFrames, @finishBeholdingWorld(goalStates), serialized.startFrame, work.level, serialized.endFrame
World.deserialize serialized.serializedWorld, @shared.worldClassMap, @shared.lastSerializedWorldFrames, @finishBeholdingWorld(goalStates), serialized.startFrame, serialized.endFrame, work.level
window.BOX2D_ENABLED = true
@shared.lastSerializedWorldFrames = serialized.serializedWorld.frames

View file

@ -51,3 +51,4 @@ functionParameters =
initializeCentroids: []
update: []
getNearestEnemy: []
die: []

View file

@ -49,11 +49,15 @@
body:not(.dialogue-view-active)
.spell-palette-popover.popover
right: 45%
min-width: 350px
min-width: 500px
.spell-palette-popover.popover
// Only those popovers which are our direct children (spell documentation)
max-width: 600px
padding: 0
border-image: url(/images/level/popover_background.png) 29 39 fill stretch
border-width: 15px 20px
@include box-shadow(0 0 0 #000)
// Jiggle animation
// TODO: consolidate with problem_alert.sass jiggle
@ -98,13 +102,8 @@ body:not(.dialogue-view-active)
&:hover
@include opacity(1)
padding: 0
border-image: url(/images/level/popover_background.png) 29 39 fill stretch
border-width: 15px 20px
@include box-shadow(0 0 0 #000)
h1:not(.not-code), h2:not(.not-code), h3:not(.not-code), h4:not(.not-code), h5:not(.not-code), h6:not(.not-code)
font-family: Menlo, Monaco, Consolas, "Courier New", monospace
font-family: Monaco, Menlo, Ubuntu Mono, Consolas, "source-code-pro", monospace !important
font-variant: normal
.popover-title
@ -129,6 +128,24 @@ body:not(.dialogue-view-active)
&.right .arrow
left: -3%
.docs-ace-container
padding: 2px 4px
border-radius: 4px
&, .docs-ace
background-color: #f9f2f4
font-size: 12px
font-family: Monaco, Menlo, Ubuntu Mono, Consolas, "source-code-pro", monospace !important
.docs-ace
.ace_cursor, .ace_bracket
display: none
code
color: black
font-family: Monaco, Menlo, Ubuntu Mono, Consolas, "source-code-pro", monospace !important
font-size: 12px
html.no-borderimage
.spell-palette-popover.popover
background: transparent url(/images/level/popover_background.png)

View file

@ -62,25 +62,28 @@ if !selectedMethod
strong
span(data-i18n="skill_docs.example") Example
| :
div!= marked("```\n" + doc.example + "```")
.docs-ace-container
.docs-ace= doc.example
else if doc.type == 'function' && argumentExamples.length
p.example
strong
span(data-i18n="skill_docs.example") Example
| :
div
if language == 'javascript'
code= doc.owner + '.' + doc.name + '(' + argumentExamples.join(', ') + ');'
else if language == 'coffeescript'
code= doc.ownerName + (doc.ownerName == '@' ? '' : '.') + doc.name + ' ' + argumentExamples.join(', ')
else if language == 'python'
code= doc.ownerName + '.' + doc.name + '(' + argumentExamples.join(', ') + ')'
else if language == 'clojure'
code= '(.' + doc.name + ' ' + doc.ownerName + ' ' + argumentExamples.join(', ') + ')'
else if language == 'lua'
code= doc.ownerName + ':' + doc.name + '(' + argumentExamples.join(', ') + ')'
else if language == 'io'
code= (doc.ownerName == 'this' ? '' : doc.ownerName + ' ') + doc.name + '(' + argumentExamples.join(', ') + ')'
.docs-ace-container
.docs-ace
if language == 'javascript'
span= doc.owner + '.' + doc.name + '(' + argumentExamples.join(', ') + ');'
else if language == 'coffeescript'
span= doc.ownerName + (doc.ownerName == '@' ? '' : '.') + doc.name + ' ' + argumentExamples.join(', ')
else if language == 'python'
span= doc.ownerName + '.' + doc.name + '(' + argumentExamples.join(', ') + ')'
else if language == 'clojure'
span= '(.' + doc.name + ' ' + doc.ownerName + ' ' + argumentExamples.join(', ') + ')'
else if language == 'lua'
span= doc.ownerName + ':' + doc.name + '(' + argumentExamples.join(', ') + ')'
else if language == 'io'
span= (doc.ownerName == 'this' ? '' : doc.ownerName + ' ') + doc.name + '(' + argumentExamples.join(', ') + ')'
if (doc.type != 'function' && doc.type != 'snippet') || doc.name == 'now'
p.value

View file

@ -15,6 +15,10 @@ clusters = {
'thangs': ['Tree 1', 'Tree 2', 'Tree 3', 'Tree 4']
'margin': 0.5
}
'tree_stands': {
'thangs': ['Tree Stand 1', 'Tree Stand 2', 'Tree Stand 3', 'Tree Stand 4', 'Tree Stand 5', 'Tree Stand 6']
'margin': 3
}
'shrubs': {
'thangs': ['Shrub 1', 'Shrub 2', 'Shrub 3']
'margin': 0.5
@ -165,10 +169,10 @@ presets = {
'grassy': {
'terrainName': 'Grass'
'type':'grassy'
'borders':'trees'
'borders':'tree_stands'
'borderNoise':1
'borderSize':0
'borderThickness':3
'borderSize':2
'borderThickness':2
'floors':'grass_floor'
'decorations': {
'hero': {

View file

@ -728,7 +728,6 @@ forest = [
description: 'Join forces with a new hero: Amara Arrowhead.'
nextLevels:
continue: 'swift-dagger'
disabled: not me.isAdmin()
x: 64.37
y: 69.18
}
@ -740,7 +739,6 @@ forest = [
description: 'Deal damage from a distance with your new hero.'
nextLevels:
continue: 'shrapnel'
disabled: not me.isAdmin()
x: 66
y: 75.61
}
@ -752,7 +750,6 @@ forest = [
description: 'Explore the explosive arts.'
nextLevels:
continue: 'coinucopia'
disabled: not me.isAdmin()
x: 67
y: 81
}
@ -766,7 +763,6 @@ forest = [
description: 'Stand your ground against large ogres with a new hero: Ms. Hushbaum.'
nextLevels:
continue: 'touch-of-death'
disabled: not me.isAdmin()
x: 64.37
y: 55.18
}
@ -778,7 +774,6 @@ forest = [
description: 'Learn your first spell to siphon life from your foes.'
nextLevels:
continue: 'bonemender'
disabled: not me.isAdmin()
x: 65
y: 48
}
@ -790,7 +785,6 @@ forest = [
description: 'Cast regeneration on allied soldiers to withstand a siege.'
nextLevels:
continue: 'coinucopia'
disabled: not me.isAdmin()
x: 66
y: 40
}

View file

@ -64,37 +64,24 @@ module.exports = class HeroVictoryModal extends ModalView
thangType.project = ['original', 'rasterIcon', 'name', 'soundTriggers']
@thangTypes[thangTypeOriginal] = @supermodel.loadModel(thangType, 'thang').model
if achievementIDs.length
url = "/db/earned_achievement?view=get-by-achievement-ids&achievementIDs=#{achievementIDs.join(',')}"
earnedAchievements = new CocoCollection([], {
url: url
model: EarnedAchievement
@newEarnedAchievements = []
for achievement in @achievements.models
continue unless achievement.completed
ea = new EarnedAchievement({
collection: achievement.get('collection')
triggeredBy: @session.id
achievement: achievement.id
})
earnedAchievements.sizeShouldBe = achievementIDs.length
res = @supermodel.loadCollection(earnedAchievements, 'earned_achievements')
@earnedAchievements = res.model
@listenToOnce @earnedAchievements, 'sync', ->
@newEarnedAchievements = []
recorded = (earned.get('achievement') for earned in @earnedAchievements.length)
for achievement in @achievements.models
continue unless achievement.completed
earnedObjects = []
if achievement.id not in recorded
ea = new EarnedAchievement({
collection: achievement.get('collection')
triggeredBy: @session.id
achievement: achievement.id
})
ea.save()
@newEarnedAchievements.push ea
@listenToOnce ea, 'sync', ->
if _.all((ea.id for ea in @newEarnedAchievements))
@listenToOnce me, 'sync', ->
@readyToContinue = true
@updateSavingProgressStatus()
me.fetch() unless me.loading
else
@readyToContinue = true
ea.save()
@newEarnedAchievements.push ea
@listenToOnce ea, 'sync', ->
if _.all((ea.id for ea in @newEarnedAchievements))
@listenToOnce me, 'sync', ->
@readyToContinue = true
@updateSavingProgressStatus()
me.fetch() unless me.loading
@readyToContinue = true if not @achievements.models.length
getRenderData: ->
c = super()

View file

@ -3,6 +3,7 @@ template = require 'templates/play/level/tome/spell_palette_entry'
{me} = require 'lib/auth'
filters = require 'lib/image_filter'
DocFormatter = require './DocFormatter'
SpellView = require 'views/play/level/tome/SpellView'
module.exports = class SpellPaletteEntryView extends CocoView
tagName: 'div' # Could also try <code> instead of <div>, but would need to adjust colors
@ -28,6 +29,7 @@ module.exports = class SpellPaletteEntryView extends CocoView
@docFormatter = new DocFormatter options
@doc = @docFormatter.doc
@doc.initialHTML = @docFormatter.formatPopover()
@aceEditors = []
getRenderData: ->
c = super()
@ -52,6 +54,31 @@ module.exports = class SpellPaletteEntryView extends CocoView
Backbone.Mediator.publish 'audio-player:play-sound', trigger: "spell-palette-entry-open-#{soundIndex}", volume: 0.75
popover = @$el.data('bs.popover')
popover?.$tip?.i18n()
codeLanguage = @options.language
oldEditor.destroy() for oldEditor in @aceEditors
@aceEditors = []
aceEditors = @aceEditors
popover?.$tip?.find('.docs-ace').each ->
contents = $(@).text()
editor = ace.edit @
editor.setOptions maxLines: Infinity
editor.setReadOnly true
editor.setTheme 'ace/theme/textmate'
editor.setShowPrintMargin false
editor.setShowFoldWidgets false
editor.setHighlightActiveLine false
editor.setHighlightActiveLine false
editor.setBehavioursEnabled false
editor.renderer.setShowGutter false
editor.setValue contents
editor.clearSelection()
session = editor.getSession()
session.setUseWorker false
session.setMode SpellView.editModes[codeLanguage]
session.setWrapLimitRange null
session.setUseWrapMode true
session.setNewLineMode 'unix'
aceEditors.push editor
onMouseEnter: (e) ->
# Make sure the doc has the updated Thang so it can regenerate its prop value
@ -121,4 +148,5 @@ module.exports = class SpellPaletteEntryView extends CocoView
@togglePinned() if @popoverPinned
@$el.popover 'destroy'
@$el.off()
oldEditor.destroy() for oldEditor in @aceEditors
super()

View file

@ -20,7 +20,7 @@ module.exports = class SpellView extends CocoView
eventsSuppressed: true
writable: true
editModes:
@editModes:
'javascript': 'ace/mode/javascript'
'coffeescript': 'ace/mode/coffee'
'python': 'ace/mode/python'
@ -91,7 +91,7 @@ module.exports = class SpellView extends CocoView
@aceSession = @ace.getSession()
@aceDoc = @aceSession.getDocument()
@aceSession.setUseWorker false
@aceSession.setMode @editModes[@spell.language]
@aceSession.setMode SpellView.editModes[@spell.language]
@aceSession.setWrapLimitRange null
@aceSession.setUseWrapMode true
@aceSession.setNewLineMode 'unix'
@ -324,7 +324,7 @@ module.exports = class SpellView extends CocoView
# window.zatannaInstance = @zatanna
# window.snippetEntries = snippetEntries
lang = @editModes[e.language].substr 'ace/mode/'.length
lang = SpellView.editModes[e.language].substr 'ace/mode/'.length
@zatanna.addSnippets snippetEntries, lang
onMultiplayerChanged: ->
@ -904,8 +904,8 @@ module.exports = class SpellView extends CocoView
onChangeLanguage: (e) ->
return unless @spell.canWrite()
@aceSession.setMode @editModes[e.language]
@zatanna?.set 'language', @editModes[e.language].substr('ace/mode/')
@aceSession.setMode SpellView.editModes[e.language]
@zatanna?.set 'language', SpellView.editModes[e.language].substr('ace/mode/')
wasDefault = @getSource() is @spell.originalSource
@spell.setLanguage e.language
@reloadCode true if wasDefault

View file

@ -246,6 +246,7 @@ module.exports = class PlayHeroesModal extends ModalView
heroEntry = @$el.find(".hero-item[data-hero-id='#{@visibleHero.get('original')}']")
heroEntry.find('.hero-status-value').attr('data-i18n', 'play.available').i18n()
heroEntry.removeClass 'locked purchasable'
@selectedHero = @visibleHero
@rerenderFooter()
Backbone.Mediator.publish 'store:hero-purchased', hero: @visibleHero, heroSlug: @visibleHero.get('slug')

View file

@ -61,19 +61,45 @@ class EarnedAchievementHandler extends Handler
EarnedAchievement.findOne q, (err, earned) -> callback(err, earned)
}, (err, { achievement, trigger, earned } ) =>
return @sendDatabaseError(res, err) if err
if earned
return @sendSuccess(res, earned.toObject())
if not achievement
return @sendNotFoundError(res, 'Could not find achievement.')
if not trigger
else if not trigger
return @sendNotFoundError(res, 'Could not find trigger.')
if achievement.get('proportionalTo')
else if earned
achievementEarned = achievement.get('rewards')
actuallyEarned = earned.get('earnedRewards')
if not _.isEqual(achievementEarned, actuallyEarned)
earned.set('earnedRewards', achievementEarned)
earned.save((err) =>
return @sendDatabaseError(res, err) if err
@upsertNonNumericRewards(req.user, achievement, (err) =>
return @sendDatabaseError(res, err) if err
return @sendSuccess(res, earned.toObject())
)
)
else
@upsertNonNumericRewards(req.user, achievement, (err) =>
return @sendDatabaseError(res, err) if err
return @sendSuccess(res, earned.toObject())
)
else if achievement.get('proportionalTo')
return @sendBadInputError(res, 'Cannot currently do this to repeatable docs...')
EarnedAchievement.createForAchievement(achievement, trigger, null, (earnedAchievementDoc) =>
@sendCreated(res, earnedAchievementDoc.toObject())
)
else
EarnedAchievement.createForAchievement(achievement, trigger, null, (earnedAchievementDoc) =>
@sendCreated(res, earnedAchievementDoc.toObject())
)
)
upsertNonNumericRewards: (user, achievement, done) ->
update = {}
for rewardType, rewards of achievement.get('rewards') ? {}
continue if rewardType is 'gems'
if rewards.length
update.$addToSet ?= {}
update.$addToSet["earned.#{rewardType}"] = $each: rewards
User.update {_id: user._id}, update, {}, (err, count) ->
log.error err if err?
done?(err)
getByAchievementIDs: (req, res) ->
query = { user: req.user._id+''}