Merge branch 'master' into production

This commit is contained in:
Nick Winter 2014-09-04 20:10:45 -07:00
commit c85c39fd92
17 changed files with 100 additions and 136 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -334,7 +334,7 @@ module.exports = class SpriteBoss extends CocoClass
onFlagUpdated: (e) ->
return unless e.active
pendingFlag = new FlagSprite @thangTypeFor('Flag'), @createSpriteOptions(thangID: 'Pending Flag ' + Math.random(), color: e.color, team: me.team, isCursor: false, pos: e.pos)
pendingFlag = new FlagSprite @thangTypeFor('Flag'), @createSpriteOptions(thangID: 'Pending Flag ' + Math.random(), color: e.color, team: e.team, isCursor: false, pos: e.pos)
@addSprite pendingFlag, pendingFlag.thang.id, @spriteLayers['Floating']
@pendingFlags.push pendingFlag

View file

@ -657,12 +657,16 @@
why_paragraph_4: "If you're going to get addicted to some game, get addicted to this one and become one of the wizards of the tech age."
why_ending: "And hey, it's free. "
why_ending_url: "Start wizarding now!"
george_description: "CEO, business guy, web designer, game designer, and champion of beginning programmers everywhere."
scott_description: "Programmer extraordinaire, software architect, kitchen wizard, and master of finances. Scott is the reasonable one."
nick_description: "Programming wizard, eccentric motivation mage, and upside-down experimenter. Nick can do anything and chooses to build CodeCombat."
jeremy_description: "Customer support mage, usability tester, and community organizer; you've probably already spoken with Jeremy."
michael_description: "Programmer, sys-admin, and undergrad technical wunderkind, Michael is the person keeping our servers online."
matt_description: "Bicyclist, Software Engineer, reader of heroic fantasy, connoisseur of peanut butter, sipper of coffee."
george_title: "CEO"
george_description: "Businesser"
scott_title: "Programmer"
scott_description: "Reasonable One"
nick_title: "Programmer"
nick_description: "Motivation Guru"
michael_title: "Programmer"
michael_description: "Sys Admin"
matt_title: "Programmer"
matt_description: "Bicyclist"
legal:
page_title: "Legal"

View file

@ -2,8 +2,7 @@ c = require './../schemas'
# TODO add these: http://docs.mongodb.org/manual/reference/operator/query/
MongoQueryOperatorSchema =
title: 'MongoDB Query operator'
id: 'mongoQueryOperator'
title: 'Query Operator'
type: 'object'
properties:
'$gt': type: 'number'
@ -13,26 +12,23 @@ MongoQueryOperatorSchema =
'$lte': type: 'number'
'$ne': type: ['number', 'string']
'$nin': type: 'array'
additionalProperties: true # TODO set to false when the schema's done
'$exists': type: 'boolean'
additionalProperties: false
MongoFindQuerySchema =
title: 'MongoDB Query'
id: 'mongoFindQuery'
title: 'Query'
type: 'object'
patternProperties:
#'^[-a-zA-Z0-9_]*$':
'^[-a-zA-Z0-9\.]*$':
oneOf: [
#{$ref: '#/definitions/' + MongoQueryOperatorSchema.id},
'^[-a-zA-Z0-9.]*$':
anyOf: [
{$ref: '#/definitions/mongoQueryOperator'},
{type: 'string'}
{type: 'object'}
{type: 'boolean'}
]
additionalProperties: true # TODO make Treema accept new pattern matched keys
additionalProperties: false
definitions: {}
MongoFindQuerySchema.definitions[MongoQueryOperatorSchema.id] = MongoQueryOperatorSchema
AchievementSchema = c.object()
c.extendNamedProperties AchievementSchema
c.extendBasicProperties AchievementSchema, 'achievement'
@ -48,7 +44,7 @@ AchievementSchema.default =
_.extend AchievementSchema.properties,
query:
#type:'object'
$ref: '#/definitions/' + MongoFindQuerySchema.id
$ref: '#/definitions/mongoFindQuery'
worth: c.float
collection: {type: 'string'}
description: c.shortString()
@ -93,6 +89,7 @@ _.extend AchievementSchema, # Let's have these on the bottom
additionalProperties: false
AchievementSchema.definitions = {}
AchievementSchema.definitions[MongoFindQuerySchema.id] = MongoFindQuerySchema
AchievementSchema.definitions['mongoQueryOperator'] = MongoQueryOperatorSchema
AchievementSchema.definitions['mongoFindQuery'] = MongoFindQuerySchema
module.exports = AchievementSchema

View file

@ -148,10 +148,7 @@ _.extend LevelComponentSchema.properties,
type: 'boolean'
title: 'Official'
description: 'Whether this is an official CodeCombat Component.'
searchStrings: {
type: 'array'
items: { type: 'string' }
}
searchStrings: {type: 'string'}
c.extendBasicProperties LevelComponentSchema, 'level.component'
c.extendSearchableProperties LevelComponentSchema

View file

@ -11,4 +11,4 @@ module.exports =
'real-time-multiplayer:new-opponent-code': c.object {title: 'Multiplayer new opponent code', required: ['code', 'codeLanguage']},
code: {type: 'object'}
codeLanguage: {type: 'string'}
team: {type: 'string'}

View file

@ -180,5 +180,5 @@ module.exports = # /app/lib/surface
'surface:remove-selected-flag': c.object {}
'surface:remove-flag': c.object {required: 'color'},
'surface:remove-flag': c.object {required: ['color']},
color: {type: 'string'}

View file

@ -18,6 +18,13 @@
&:hover
background-color: rgba(200, 244, 255, 0.2)
float: left
width: 100px
height: 100px
margin-top: 22px
width: 80px
height: 80px
margin: 0px 10px 22px 0px
.team_name
margin-top: 0
.team_bio
width: 150px
float: left

View file

@ -121,7 +121,7 @@
background-position-x: -4 * $iconSize
&.prop-label-icon-attackDamage
background-position-x: -5 * $iconSize
&.prop-label-icon-attackRange
&.prop-label-icon-attackRange, &.prop-label-icon-attackNearbyEnemyRange
background-position-x: -6 * $iconSize
&.prop-label-icon-maxSpeed
background-position-x: -7 * $iconSize

View file

@ -2,48 +2,17 @@ extends /templates/base
block content
img(src="/images/pages/about/coco_comic.jpg")
.row
.col-sm-6
h2(data-i18n="about.who_is_codecombat")
| Who is CodeCombat?
p
a(href="http://georgesaines.com/") George
span ,
a(href="http://scotterickson.info/") Scott
span ,
span(data-i18n="general.and") and
span
a(href="http://www.nickwinter.net") Nick
span
span(data-i18n="about.who_description_prefix")
| together started CodeCombat in 2013. We also created
a(href="http://www.skritter.com/") Skritter
span
span(data-i18n="about.who_description_suffix")
| in 2008, growing it to the #1 web and iOS application
| for learning to write Chinese and Japanese characters.
p(data-i18n="about.who_description_ending")
| Now it's time to teach people to write code.
h2(data-i18n="about.why_codecombat")
| Why CodeCombat?
p(data-i18n="about.why_paragraph_1")
| When making Skritter, George didn't know how to program and was constantly
| frustrated by his inability to implement his ideas. Afterwards,
| he tried learning, but the lessons were too slow. His housemate,
| wanting to reskill and stop teaching, tried Codecademy, but "got bored."
| Each week another friend started Codecademy, then dropped off.
| We realized it was the same problem we'd solved with Skritter:
| people learning a skill via slow, intensive lessons when what they need is fast,
| extensive practice. We know how to fix that.
p(data-i18n="about.why_paragraph_2")
| Need to learn to code? You don't need lessons.
| If you want to learn to program, you don't need lessons.
| You need to write a lot of code and have a great time doing it.
p
@ -69,11 +38,13 @@ block content
| If you're going to get addicted to some game,
| get addicted to this one and become one of the wizards of the tech age.
p.lead
span(data-i18n="about.why_ending")
| And hey, it's free.
a(href="/", data-i18n="about.why_ending_url")
| Start wizarding now!
h2
| Bloggers/Press
p
| Want to write about us? Feel free to download and use all of the resources included in our
a(href="https://s3.amazonaws.com/CodeCombatMisc/press_packet.zip") press packet.
| All logos and images may be used without contacting us directly.
ul.col-sm-6.team-column
@ -82,86 +53,73 @@ block content
li.row
a(href="http://georgesaines.com")
h2 Team
img(src="/images/pages/about/george_small.png").img-thumbnail
.col-sm-8
.team_bio
h3
h4.team_name
a(href="http://georgesaines.com") George Saines
p(data-i18n="about.george_title")
| CEO
p(data-i18n="about.george_description")
| CEO, business guy, web designer, game designer,
| and champion of beginning programmers everywhere.
li.row
| Businesser
a(href="http://scotterickson.info")
img(src="/images/pages/about/scott_small.png").img-thumbnail
.col-sm-8
.team_bio
h3
h4.team_name
a(href="http://scotterickson.info") Scott Erickson
p(data-i18n="about.scott_title")
| Programmer
p(data-i18n="about.scott_description")
| Programmer extraordinaire, software architect,
| kitchen wizard, and master of finances.
| Scott is the reasonable one.
| Reasonable one
li.row
a(href="http://www.nickwinter.net")
img(src="/images/pages/about/nick_small.png").img-thumbnail
.col-sm-8
.team_bio
h3
h4.team_name
a(href="http://www.nickwinter.net") Nick Winter
p(data-i18n="about.nick_title")
| Programmer
p(data-i18n="about.nick_description")
| Programming wizard, eccentric motivation mage,
| and upside-down experimenter.
| Nick can do anything and chooses to build CodeCombat.
li.row
| Motivation Guru
a(href="http://michaelschmatz.com")
img(src="/images/pages/about/michael_small.png").img-thumbnail
.col-sm-8
.team_bio
h3
h4.team_name
a(href="http://michaelschmatz.com/") Michael Schmatz
p(data-i18n="about.michael_title")
| Programmer
p(data-i18n="about.michael_description")
| Programmer, sys-admin, and undergrad technical wunderkind,
| Michael is the person keeping our servers online.
| Sys Admin
li.row
img(src="/images/pages/about/jeremy_small.png").img-thumbnail
img(src="/images/pages/about/placeholder.png").img-thumbnail
.col-sm-8
.team_bio
h3 Jeremy Arns
p(data-i18n="about.jeremy_description")
| Customer support mage, usability tester,
| and community organizer; you've probably
| already spoken with Jeremy.
li.row
img(src="/images/pages/contribute/archmage.png").img-thumbnail
.col-sm-8
h3
h4.team_name
a(href="http://www.mattlott.com/") Matt Lott
p(data-i18n="about.matt_title")
| Programmer
p(data-i18n="about.matt_description")
| Bicyclist, Software Engineer, reader of heroic fantasy, connoisseur
| of peanut butter, sipper of coffee.
| Bicyclist

View file

@ -28,22 +28,13 @@ module.exports = class NewAchievementModal extends NewModelModal
createQuery: ->
checked = @$el.find('[name=queryOptions]:checked')
checkedValues = ($(check).val() for check in checked)
subQueries = []
query = {}
for id in checkedValues
switch id
when 'misc-level-completion'
subQueries.push state: complete: true
else # It's a goal
q = state: goalStates: {}
q.state.goalStates[id] = {}
q.state.goalStates[id].status = 'success'
subQueries.push q
unless subQueries.length
query = {}
else if subQueries.length is 1
query = subQueries[0]
query['state.complete'] = true
else
query = $or: subQueries
query["state.goalStates.#{id}.status"] = 'success'
query['level.original'] = @level.get 'original'
query

View file

@ -3,6 +3,8 @@ template = require 'templates/play/level/level-flags-view'
{me} = require 'lib/auth'
RealTimeCollection = require 'collections/RealTimeCollection'
multiplayerFlagDelay = 0.5 # Long, static second delay for now; should be more than enough.
module.exports = class LevelFlagsView extends CocoView
id: 'level-flags-view'
template: template
@ -54,7 +56,9 @@ module.exports = class LevelFlagsView extends CocoView
onStageMouseDown: (e) ->
return unless @flagColor and @realTime
pos = x: e.worldPos.x, y: e.worldPos.y
flag = player: me.id, team: me.team, color: @flagColor, pos: pos, time: @world.dt * @world.frames.length, active: true
delay = if @realTimeFlags then multiplayerFlagDelay else 0
now = @world.dt * @world.frames.length
flag = player: me.id, team: me.team, color: @flagColor, pos: pos, time: now + delay, active: true
@flags[@flagColor] = flag
@flagHistory.push flag
@realTimeFlags?.create flag
@ -67,7 +71,9 @@ module.exports = class LevelFlagsView extends CocoView
onRemoveFlag: (e) ->
delete @flags[e.color]
flag = player: me.id, team: me.team, color: e.color, time: @world.dt * @world.frames.length, active: false
delay = if @realTimeFlags then multiplayerFlagDelay else 0
now = @world.dt * @world.frames.length
flag = player: me.id, team: me.team, color: e.color, time: now + delay, active: false
@flagHistory.push flag
Backbone.Mediator.publish 'level:flag-updated', flag
#console.log e.color, 'deleted at time', flag.time
@ -79,6 +85,7 @@ module.exports = class LevelFlagsView extends CocoView
onJoinedMultiplayerGame: (e) ->
@realTimeFlags = new RealTimeCollection('multiplayer_level_sessions/' + e.session.id + '/flagHistory')
@realTimeFlags.on 'add', @onRealTimeMultiplayerFlagAdded
@realTimeFlags.on 'remove', @onRealTimeMultiplayerFlagRemoved
onLeftMultiplayerGame: (e) ->
if @realTimeFlags
@ -98,3 +105,5 @@ module.exports = class LevelFlagsView extends CocoView
active: e.get('active')
@flagHistory.push flag
Backbone.Mediator.publish 'level:flag-updated', flag
onRealTimeMultiplayerFlagRemoved: (e) =>

View file

@ -265,7 +265,7 @@ module.exports = class LevelHUDView extends CocoView
return null # included in the bar
context =
prop: prop
hasIcon: prop in ['health', 'pos', 'target', 'collectedThangIDs', 'gold', 'bountyGold', 'visualRange', 'attackDamage', 'attackRange', 'maxSpeed']
hasIcon: prop in ['health', 'pos', 'target', 'collectedThangIDs', 'gold', 'bountyGold', 'visualRange', 'attackDamage', 'attackRange', 'maxSpeed', 'attackNearbyEnemyRange']
hasBar: prop in ['health']
$(prop_template(context))

View file

@ -619,6 +619,7 @@ module.exports = class PlayLevelView extends RootView
myPlayer.set 'code', @session.get('code')
myPlayer.set 'codeLanguage', @session.get('codeLanguage')
myPlayer.set 'state', 'submitted'
myPlayer.set 'team', me.team
else
console.error 'Did not find my player in onRealTimeMultiplayerCast'
if opponentPlayer
@ -636,7 +637,7 @@ module.exports = class PlayLevelView extends RootView
onOpponentSubmitted: (opponentPlayer, myPlayer) =>
# Save opponent's code
Backbone.Mediator.publish 'real-time-multiplayer:new-opponent-code', {codeLanguage: opponentPlayer.get('codeLanguage'), code: opponentPlayer.get('code')}
Backbone.Mediator.publish 'real-time-multiplayer:new-opponent-code', {codeLanguage: opponentPlayer.get('codeLanguage'), code: opponentPlayer.get('code'), team: opponentPlayer.get('team')}
# I'm ready to rumble
myPlayer.set 'state', 'ready'
if opponentPlayer.get('state') is 'ready'

View file

@ -164,11 +164,11 @@ module.exports = class Spell
false
onNewOpponentCode: (e) =>
return unless @spellKey
return unless @spellKey and @canWrite e.team
if e.codeLanguage and e.code
spellkeyComponents = @spellKey.split '/'
if e.code[spellkeyComponents[0]]?[spellkeyComponents[1]]
@source = e.code[spellkeyComponents[0]][spellkeyComponents[1]]
[thangSlug, methodSlug] = @spellKey.split '/'
if opponentCode = e.code[thangSlug]?[methodSlug]
@source = opponentCode
@updateLanguageAether e.codeLanguage
else
console.error 'Spell onNewOpponentCode did not receive code', e