Merge branch 'master' into production
This commit is contained in:
commit
29cbf16dd7
17 changed files with 232 additions and 135 deletions
app
server
test/server/functional
23
app/lib/CampaignOptions.coffee
Normal file
23
app/lib/CampaignOptions.coffee
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
CampaignList = require('views/play/WorldMapView').campaigns
|
||||||
|
|
||||||
|
# TODO: Is this file structured correctly?
|
||||||
|
|
||||||
|
# Per-campaign options, with default fallback set
|
||||||
|
options =
|
||||||
|
'default':
|
||||||
|
autocompleteFontSizePx: 16
|
||||||
|
'dungeon':
|
||||||
|
autocompleteFontSizePx: 20
|
||||||
|
|
||||||
|
module.exports = CampaignOptions =
|
||||||
|
getCampaignForSlug: (slug) ->
|
||||||
|
return unless slug
|
||||||
|
for campaign in CampaignList
|
||||||
|
for level in campaign.levels
|
||||||
|
return campaign.id if level.id is slug
|
||||||
|
|
||||||
|
getOption: (levelSlug, option) ->
|
||||||
|
return unless levelSlug and option
|
||||||
|
return unless campaign = CampaignOptions.getCampaignForSlug levelSlug
|
||||||
|
return options[campaign]?[option] if options[campaign]?[option]?
|
||||||
|
return options.default[option] if options.default[option]?
|
|
@ -204,6 +204,14 @@ module.exports = LevelOptions =
|
||||||
hidesCodeToolbar: true
|
hidesCodeToolbar: true
|
||||||
requiredGear: {feet: 'leather-boots', 'right-hand': 'crude-builders-hammer'}
|
requiredGear: {feet: 'leather-boots', 'right-hand': 'crude-builders-hammer'}
|
||||||
restrictedGear: {feet: 'simple-boots', 'right-hand': 'simple-sword'}
|
restrictedGear: {feet: 'simple-boots', 'right-hand': 'simple-sword'}
|
||||||
|
'endangered-burl':
|
||||||
|
requiredGear: {feet: 'leather-boots', 'right-hand': 'simple-sword', eyes: 'crude-glasses'}
|
||||||
|
hidesCodeToolbar: true
|
||||||
|
restrictedGear: {feet: 'simple-boots', 'right-hand': 'crude-builders-hammer'}
|
||||||
|
'village-guard':
|
||||||
|
requiredGear: {feet: 'leather-boots', 'right-hand': 'simple-sword', eyes: 'crude-glasses'}
|
||||||
|
hidesCodeToolbar: true
|
||||||
|
restrictedGear: {feet: 'simple-boots', 'right-hand': 'crude-builders-hammer'}
|
||||||
'thornbush-farm':
|
'thornbush-farm':
|
||||||
requiredGear: {feet: 'leather-boots', 'right-hand': 'crude-builders-hammer', eyes: 'crude-glasses'}
|
requiredGear: {feet: 'leather-boots', 'right-hand': 'crude-builders-hammer', eyes: 'crude-glasses'}
|
||||||
hidesCodeToolbar: true
|
hidesCodeToolbar: true
|
||||||
|
@ -235,12 +243,12 @@ module.exports = LevelOptions =
|
||||||
restrictedGear: {}
|
restrictedGear: {}
|
||||||
'drop-the-flag':
|
'drop-the-flag':
|
||||||
requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', 'right-hand': 'crude-builders-hammer'}
|
requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', 'right-hand': 'crude-builders-hammer'}
|
||||||
restrictedGear: {'right-hand': 'longsword'}
|
restrictedGear: {'right-hand': 'long-sword'}
|
||||||
'deadly-pursuit':
|
'deadly-pursuit':
|
||||||
requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', 'right-hand': 'crude-builders-hammer'}
|
requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', 'right-hand': 'crude-builders-hammer'}
|
||||||
restrictedGear: {'right-hand': 'longsword'}
|
restrictedGear: {'right-hand': 'long-sword'}
|
||||||
'rich-forager':
|
'rich-forager':
|
||||||
requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', torso: 'leather-tunic', 'right-hand': 'longsword', 'left-hand': 'bronze-shield'}
|
requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', torso: 'leather-tunic', 'right-hand': 'long-sword', 'left-hand': 'bronze-shield'}
|
||||||
restrictedGear: {'right-hand': 'crude-builders-hammer'}
|
restrictedGear: {'right-hand': 'crude-builders-hammer'}
|
||||||
'multiplayer-treasure-grove':
|
'multiplayer-treasure-grove':
|
||||||
requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', torso: 'leather-tunic'}
|
requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', torso: 'leather-tunic'}
|
||||||
|
|
|
@ -283,8 +283,9 @@ module.exports = class Camera extends CocoClass
|
||||||
target = @boundTarget @target, @zoom
|
target = @boundTarget @target, @zoom
|
||||||
return if not force and _.isEqual target, @currentTarget
|
return if not force and _.isEqual target, @currentTarget
|
||||||
@currentTarget = target
|
@currentTarget = target
|
||||||
@updateViewports target
|
viewportDifference = @updateViewports target
|
||||||
Backbone.Mediator.publish 'camera:zoom-updated', camera: @, zoom: @zoom, surfaceViewport: @surfaceViewport
|
if viewportDifference > 0.1 # Roughly 0.1 pixel difference in what we can see
|
||||||
|
Backbone.Mediator.publish 'camera:zoom-updated', camera: @, zoom: @zoom, surfaceViewport: @surfaceViewport
|
||||||
|
|
||||||
boundTarget: (pos, zoom) ->
|
boundTarget: (pos, zoom) ->
|
||||||
# Given an {x, y} in Surface coordinates, return one that will keep our viewport on the Surface.
|
# Given an {x, y} in Surface coordinates, return one that will keep our viewport on the Surface.
|
||||||
|
@ -303,6 +304,11 @@ module.exports = class Camera extends CocoClass
|
||||||
sv = width: @canvasWidth / @zoom, height: @canvasHeight / @zoom, cx: target.x, cy: target.y
|
sv = width: @canvasWidth / @zoom, height: @canvasHeight / @zoom, cx: target.x, cy: target.y
|
||||||
sv.x = sv.cx - sv.width / 2
|
sv.x = sv.cx - sv.width / 2
|
||||||
sv.y = sv.cy - sv.height / 2
|
sv.y = sv.cy - sv.height / 2
|
||||||
|
if @surfaceViewport
|
||||||
|
# Calculate how different this viewport is. (If it's basically not different, we can avoid visualizing the update.)
|
||||||
|
viewportDifference = Math.abs(@surfaceViewport.x - sv.x) + 1.01 * Math.abs(@surfaceViewport.y - sv.y) + 1.02 * Math.abs(@surfaceViewport.width - sv.width)
|
||||||
|
else
|
||||||
|
viewportDifference = 9001
|
||||||
@surfaceViewport = sv
|
@surfaceViewport = sv
|
||||||
|
|
||||||
wv = @surfaceToWorld sv # get x and y
|
wv = @surfaceToWorld sv # get x and y
|
||||||
|
@ -312,6 +318,8 @@ module.exports = class Camera extends CocoClass
|
||||||
wv.cy = wv.y + wv.height / 2
|
wv.cy = wv.y + wv.height / 2
|
||||||
@worldViewport = wv
|
@worldViewport = wv
|
||||||
|
|
||||||
|
viewportDifference
|
||||||
|
|
||||||
lock: ->
|
lock: ->
|
||||||
@target = @currentTarget
|
@target = @currentTarget
|
||||||
@locked = true
|
@locked = true
|
||||||
|
|
|
@ -16,6 +16,7 @@ module.exports = class CoordinateDisplay extends createjs.Container
|
||||||
console.error @toString(), 'needs a camera.' unless @camera
|
console.error @toString(), 'needs a camera.' unless @camera
|
||||||
console.error @toString(), 'needs a layer.' unless @layer
|
console.error @toString(), 'needs a layer.' unless @layer
|
||||||
@build()
|
@build()
|
||||||
|
@performShow = @show
|
||||||
@show = _.debounce @show, 125
|
@show = _.debounce @show, 125
|
||||||
Backbone.Mediator.subscribe(channel, @[func], @) for channel, func of @subscriptions
|
Backbone.Mediator.subscribe(channel, @[func], @) for channel, func of @subscriptions
|
||||||
|
|
||||||
|
@ -46,6 +47,7 @@ module.exports = class CoordinateDisplay extends createjs.Container
|
||||||
wop.y = Math.round(wop.y)
|
wop.y = Math.round(wop.y)
|
||||||
return if wop.x is @lastPos?.x and wop.y is @lastPos?.y
|
return if wop.x is @lastPos?.x and wop.y is @lastPos?.y
|
||||||
@lastPos = wop
|
@lastPos = wop
|
||||||
|
@lastScreenPos = x: e.x, y: e.y
|
||||||
@hide()
|
@hide()
|
||||||
@show() # debounced
|
@show() # debounced
|
||||||
|
|
||||||
|
@ -58,8 +60,11 @@ module.exports = class CoordinateDisplay extends createjs.Container
|
||||||
Backbone.Mediator.publish 'surface:coordinate-selected', wop
|
Backbone.Mediator.publish 'surface:coordinate-selected', wop
|
||||||
|
|
||||||
onZoomUpdated: (e) ->
|
onZoomUpdated: (e) ->
|
||||||
@hide()
|
return unless @lastPos
|
||||||
@show()
|
wop = @camera.screenToWorld @lastScreenPos
|
||||||
|
@lastPos.x = Math.round wop.x
|
||||||
|
@lastPos.y = Math.round wop.y
|
||||||
|
@performShow() if @label.parent
|
||||||
|
|
||||||
onFlagColorSelected: (e) ->
|
onFlagColorSelected: (e) ->
|
||||||
@placingFlag = Boolean e.color
|
@placingFlag = Boolean e.color
|
||||||
|
|
|
@ -224,8 +224,8 @@ module.exports = class LankBoss extends CocoClass
|
||||||
item = @world.getThangByID itemID
|
item = @world.getThangByID itemID
|
||||||
unless item.equipped
|
unless item.equipped
|
||||||
console.log thang.id, 'equipping', item, 'in', thang.slot, 'Surface-side, but it cannot equip?' unless item.equip
|
console.log thang.id, 'equipping', item, 'in', thang.slot, 'Surface-side, but it cannot equip?' unless item.equip
|
||||||
item.equip()
|
item.equip?()
|
||||||
itemsJustEquipped.push item
|
itemsJustEquipped.push item if item.equip
|
||||||
return itemsJustEquipped
|
return itemsJustEquipped
|
||||||
|
|
||||||
cacheObstacles: (updatedObstacles=null) ->
|
cacheObstacles: (updatedObstacles=null) ->
|
||||||
|
|
|
@ -12,7 +12,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
for_developers: "适合开发者" # Not currently shown on home page.
|
for_developers: "适合开发者" # Not currently shown on home page.
|
||||||
|
|
||||||
nav:
|
nav:
|
||||||
play: "开始游戏" # The top nav bar entry where players choose which levels to play
|
play: "关卡选择" # The top nav bar entry where players choose which levels to play
|
||||||
community: "社区"
|
community: "社区"
|
||||||
editor: "编辑器"
|
editor: "编辑器"
|
||||||
blog: "博客"
|
blog: "博客"
|
||||||
|
@ -98,7 +98,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
authenticate_gplus: "使用 G+ 授权"#Authenticate G+"
|
authenticate_gplus: "使用 G+ 授权"#Authenticate G+"
|
||||||
load_profile: "载入 G+ 档案" # Load G+ Profile"
|
load_profile: "载入 G+ 档案" # Load G+ Profile"
|
||||||
load_email: "载入 G+ 电子邮件" #Load G+ Email"
|
load_email: "载入 G+ 电子邮件" #Load G+ Email"
|
||||||
finishing: "完成" #Finishing"
|
finishing: "完成..." #Finishing"
|
||||||
|
|
||||||
signup:
|
signup:
|
||||||
create_account_title: "创建一个账户来保存进度"
|
create_account_title: "创建一个账户来保存进度"
|
||||||
|
@ -243,13 +243,13 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
tome_select_a_thang: "选择人物来 "
|
tome_select_a_thang: "选择人物来 "
|
||||||
tome_available_spells: "可用的法术"
|
tome_available_spells: "可用的法术"
|
||||||
tome_your_skills: "你的技能"
|
tome_your_skills: "你的技能"
|
||||||
# tome_current_method: "Current Method"
|
tome_current_method: "当前方法"
|
||||||
hud_continue_short: "继续"
|
hud_continue_short: "继续"
|
||||||
code_saved: "代码已保存"
|
code_saved: "代码已保存"
|
||||||
skip_tutorial: "跳过(esc)"
|
skip_tutorial: "跳过(esc)"
|
||||||
keyboard_shortcuts: "快捷键"
|
keyboard_shortcuts: "快捷键"
|
||||||
loading_ready: "载入完成!"
|
loading_ready: "载入完成!"
|
||||||
loading_start: "关卡开始"
|
loading_start: "开战"
|
||||||
problem_alert_title: "修正你的代码"
|
problem_alert_title: "修正你的代码"
|
||||||
time_current: "现在:"
|
time_current: "现在:"
|
||||||
time_total: "最大:"
|
time_total: "最大:"
|
||||||
|
@ -270,7 +270,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
tip_baby_coders: "在未来,就算小孩都能成为大法师."
|
tip_baby_coders: "在未来,就算小孩都能成为大法师."
|
||||||
tip_morale_improves: "在士气提升之前会一直进行读取."
|
tip_morale_improves: "在士气提升之前会一直进行读取."
|
||||||
tip_all_species: "我们相信学习编程的机会对任何种族都是平等的。"
|
tip_all_species: "我们相信学习编程的机会对任何种族都是平等的。"
|
||||||
# tip_reticulating: "Reticulating spines."
|
tip_reticulating: "网格状锯齿。(指 Maxis 开发的许多游戏,如《模拟城市》、《孢子》中,加载进程中跑动时出现的卡顿现象)"
|
||||||
tip_harry: "巫师, "
|
tip_harry: "巫师, "
|
||||||
tip_great_responsibility: "更高的编程技巧也意味着更大的调试责任。"
|
tip_great_responsibility: "更高的编程技巧也意味着更大的调试责任。"
|
||||||
tip_munchkin: "如果你不吃掉你的蔬菜, 一个小矮人将在你睡着之后来找你。"
|
tip_munchkin: "如果你不吃掉你的蔬菜, 一个小矮人将在你睡着之后来找你。"
|
||||||
|
@ -315,7 +315,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
equip: "装备"
|
equip: "装备"
|
||||||
unequip: "取消装备"
|
unequip: "取消装备"
|
||||||
|
|
||||||
# buy_gems:
|
buy_gems:
|
||||||
few_gems: "几个宝石"
|
few_gems: "几个宝石"
|
||||||
pile_gems: "一堆宝石"
|
pile_gems: "一堆宝石"
|
||||||
chest_gems: "一箱宝石"
|
chest_gems: "一箱宝石"
|
||||||
|
@ -324,7 +324,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
choose_hero: "请选择您的英雄"
|
choose_hero: "请选择您的英雄"
|
||||||
programming_language: "编程语言"
|
programming_language: "编程语言"
|
||||||
programming_language_description: "您希望使用那门编程语言?"
|
programming_language_description: "您希望使用那门编程语言?"
|
||||||
# default: "默认"
|
default: "默认"
|
||||||
experimental: "实验性的"
|
experimental: "实验性的"
|
||||||
python_blurb: "简单而强大, Python是一个伟大的通用编程语言。"
|
python_blurb: "简单而强大, Python是一个伟大的通用编程语言。"
|
||||||
javascript_blurb: "为web开发而生的语言。"
|
javascript_blurb: "为web开发而生的语言。"
|
||||||
|
@ -350,23 +350,23 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
granularity_change_history: "历史记录"
|
granularity_change_history: "历史记录"
|
||||||
|
|
||||||
options:
|
options:
|
||||||
# general_options: "General Options" # Check out the Options tab in the Game Menu while playing a level
|
general_options: "一般设置" # Check out the Options tab in the Game Menu while playing a level
|
||||||
volume_label: "音量"
|
volume_label: "音量"
|
||||||
music_label: "音乐"
|
music_label: "音乐"
|
||||||
music_description: "开/关背景音乐"
|
music_description: "开/关背景音乐"
|
||||||
autorun_label: "自动运行"
|
autorun_label: "自动运行"
|
||||||
# autorun_description: "Control automatic code execution."
|
autorun_description: "控制是否自动运行代码"
|
||||||
editor_config: "编辑器配置"
|
editor_config: "编辑器配置"
|
||||||
editor_config_title: "编辑器配置"
|
editor_config_title: "编辑器配置"
|
||||||
editor_config_level_language_label: "这个等级的语言"
|
editor_config_level_language_label: "本关卡编程语言"
|
||||||
# editor_config_level_language_description: "Define the programming language for this particular level."
|
editor_config_level_language_description: "针对本关设定使用的编程语言。"
|
||||||
editor_config_default_language_label: "默认编程语言"
|
editor_config_default_language_label: "默认编程语言"
|
||||||
editor_config_default_language_description: "在开始新游戏前确认你要在这个等级的游戏中使用的编程语言。"
|
editor_config_default_language_description: "在开始新游戏前确认你要在这个等级的游戏中使用的编程语言。"
|
||||||
editor_config_keybindings_label: "按键设置s"
|
editor_config_keybindings_label: "快捷键绑定"
|
||||||
editor_config_keybindings_default: "默认 (Ace)"
|
editor_config_keybindings_default: "默认 (Ace)"
|
||||||
editor_config_keybindings_description: "在命令编辑器中增加已知的快捷键。"
|
editor_config_keybindings_description: "在命令编辑器中增加已知的快捷键。"
|
||||||
# editor_config_livecompletion_label: "Live Autocompletion"
|
editor_config_livecompletion_label: "实时代码补全"
|
||||||
# editor_config_livecompletion_description: "Displays autocomplete suggestions while typing."
|
editor_config_livecompletion_description: "当输入代码时显示代码自动补全建议。"
|
||||||
editor_config_invisibles_label: "显示空白字符"
|
editor_config_invisibles_label: "显示空白字符"
|
||||||
editor_config_invisibles_description: "显示空格或TAB键等空白字符。"
|
editor_config_invisibles_description: "显示空格或TAB键等空白字符。"
|
||||||
editor_config_indentguides_label: "显示缩进提示"
|
editor_config_indentguides_label: "显示缩进提示"
|
||||||
|
@ -376,8 +376,8 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
|
|
||||||
about:
|
about:
|
||||||
why_codecombat: "为什么选择 CodeCombat?"
|
why_codecombat: "为什么选择 CodeCombat?"
|
||||||
why_paragraph_1: "你想学编程?你不用上课。你需要的是写好多代码,并且享受这个过程。"
|
why_paragraph_1: "如果你想学习如何编程,你根本不需要上课。你需要的是写好多代码,并且享受这个过程。"
|
||||||
why_paragraph_2_prefix: "这才是编程的要义。编程必须要好玩。不是"
|
why_paragraph_2_prefix: "这才是编程的要义。编程应该是有趣的过程。不该是"
|
||||||
why_paragraph_2_italic: "哇又一个奖章诶"
|
why_paragraph_2_italic: "哇又一个奖章诶"
|
||||||
why_paragraph_2_center: "那种“好玩”,而是"
|
why_paragraph_2_center: "那种“好玩”,而是"
|
||||||
why_paragraph_2_italic_caps: "老妈,我得先把这关打完!"
|
why_paragraph_2_italic_caps: "老妈,我得先把这关打完!"
|
||||||
|
@ -388,16 +388,16 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
press_paragraph_1_link: "成套宣传包"
|
press_paragraph_1_link: "成套宣传包"
|
||||||
press_paragraph_1_suffix: "里的所有材料. 所有商标和图像的使用都不必事先联系我们。"
|
press_paragraph_1_suffix: "里的所有材料. 所有商标和图像的使用都不必事先联系我们。"
|
||||||
team: "团队"
|
team: "团队"
|
||||||
# george_title: "CEO"
|
george_title: "CEO"
|
||||||
# george_blurb: "Businesser"
|
george_blurb: "商人"
|
||||||
# scott_title: "Programmer"
|
scott_title: "程序员"
|
||||||
# scott_blurb: "Reasonable One"
|
scott_blurb: "理性至上"
|
||||||
# nick_title: "Programmer"
|
nick_title: "程序员"
|
||||||
# nick_blurb: "Motivation Guru"
|
nick_blurb: "充满动力的大牛"
|
||||||
# michael_title: "Programmer"
|
michael_title: "程序员"
|
||||||
# michael_blurb: "Sys Admin"
|
michael_blurb: "系统管理员"
|
||||||
# matt_title: "Programmer"
|
matt_title: "程序员"
|
||||||
# matt_blurb: "Bicyclist"
|
matt_blurb: "自行车爱好者"
|
||||||
|
|
||||||
versions:
|
versions:
|
||||||
save_version_title: "保存新版本"
|
save_version_title: "保存新版本"
|
||||||
|
@ -461,22 +461,22 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
wizard_color: "巫师 衣服 颜色"
|
wizard_color: "巫师 衣服 颜色"
|
||||||
|
|
||||||
keyboard_shortcuts:
|
keyboard_shortcuts:
|
||||||
keyboard_shortcuts: "热键"
|
keyboard_shortcuts: "快捷键"
|
||||||
space: "空格"
|
space: "空格"
|
||||||
enter: "回车"
|
enter: "回车"
|
||||||
escape: "Esc"
|
escape: "Esc"
|
||||||
shift: "Shift"
|
shift: "Shift"
|
||||||
run_code: "运行当前代码"
|
run_code: "运行当前代码"
|
||||||
run_real_time: "实时运行"
|
run_real_time: "实时运行"
|
||||||
# continue_script: "Continue past current script."
|
continue_script: "继续运行当前脚本。"
|
||||||
# skip_scripts: "Skip past all skippable scripts."
|
skip_scripts: "跳过所有能跳过的脚本。"
|
||||||
toggle_playback: "继续/暂停按钮"
|
toggle_playback: "继续/暂停按钮"
|
||||||
# scrub_playback: "Scrub back and forward through time."
|
scrub_playback: "向前/向后移动一段时间"
|
||||||
# single_scrub_playback: "Scrub back and forward through time by a single frame."
|
single_scrub_playback: "向前/向后移动一帧"
|
||||||
# scrub_execution: "Scrub through current spell execution."
|
scrub_execution: "向前/向后移动一句语句"
|
||||||
# toggle_debug: "Toggle debug display."
|
toggle_debug: "显示/关闭调试信息"
|
||||||
# toggle_grid: "Toggle grid overlay."
|
toggle_grid: "显示/关闭网格提示"
|
||||||
# toggle_pathfinding: "Toggle pathfinding overlay."
|
toggle_pathfinding: "显示/关闭路径寻找提示"
|
||||||
beautify: "利用标准编码格式美化你的代码。"
|
beautify: "利用标准编码格式美化你的代码。"
|
||||||
maximize_editor: "最大化/最小化代码编辑器"
|
maximize_editor: "最大化/最小化代码编辑器"
|
||||||
move_wizard: "在关卡中移动你的巫师角色。"
|
move_wizard: "在关卡中移动你的巫师角色。"
|
||||||
|
@ -486,7 +486,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
introduction: "看看下面这些你可以参与的项目,如果有你喜欢的就加入进来吧。 我们期待着与您一起工作。"
|
introduction: "看看下面这些你可以参与的项目,如果有你喜欢的就加入进来吧。 我们期待着与您一起工作。"
|
||||||
level_editor_prefix: "使用"
|
level_editor_prefix: "使用"
|
||||||
level_editor_suffix: "来创建和编辑关卡。你可以通过这个工具来给你的同学,朋友,兄弟姐妹们设计谜题,或者用于教学或比赛。如果你觉得直接开始建立一个关卡可能非常困难,那么可以先从一个现成(但尚未完成)的关卡开始做起。"
|
level_editor_suffix: "来创建和编辑关卡。你可以通过这个工具来给你的同学,朋友,兄弟姐妹们设计谜题,或者用于教学或比赛。如果你觉得直接开始建立一个关卡可能非常困难,那么可以先从一个现成(但尚未完成)的关卡开始做起。"
|
||||||
thang_editor_prefix: "我们管游戏中的单位叫 '实体'。 利用"
|
thang_editor_prefix: "我们管游戏中的单位叫 '物品'。 利用"
|
||||||
thang_editor_suffix: "来改良 CodeCombat 中的原材料。让游戏中的东西可以被捡起来扔出去,改变游戏动画的指向,调整一些东西的生命值,或上传您自制的素材。"
|
thang_editor_suffix: "来改良 CodeCombat 中的原材料。让游戏中的东西可以被捡起来扔出去,改变游戏动画的指向,调整一些东西的生命值,或上传您自制的素材。"
|
||||||
article_editor_prefix: "你在游戏中发现了错误了吗?想要自己设计一些指令吗?来看看我们的"
|
article_editor_prefix: "你在游戏中发现了错误了吗?想要自己设计一些指令吗?来看看我们的"
|
||||||
article_editor_suffix: "来帮助玩家从游戏中学到更多的知识。"
|
article_editor_suffix: "来帮助玩家从游戏中学到更多的知识。"
|
||||||
|
@ -516,7 +516,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
editor:
|
editor:
|
||||||
main_title: "CodeCombat 编辑器"
|
main_title: "CodeCombat 编辑器"
|
||||||
article_title: "指令编辑器"
|
article_title: "指令编辑器"
|
||||||
thang_title: "实体编辑器"
|
thang_title: "物品编辑器"
|
||||||
level_title: "关卡编辑器"
|
level_title: "关卡编辑器"
|
||||||
achievement_title: "目标编辑器"
|
achievement_title: "目标编辑器"
|
||||||
back: "后退"
|
back: "后退"
|
||||||
|
@ -527,7 +527,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
grassy: "草地"
|
grassy: "草地"
|
||||||
fork_title: "派生新版本"
|
fork_title: "派生新版本"
|
||||||
fork_creating: "正在执行派生..."
|
fork_creating: "正在执行派生..."
|
||||||
# generate_terrain: "Generate Terrain"
|
generate_terrain: "Generate Terrain"
|
||||||
more: "更多"
|
more: "更多"
|
||||||
wiki: "维基"
|
wiki: "维基"
|
||||||
live_chat: "在线聊天"
|
live_chat: "在线聊天"
|
||||||
|
@ -537,14 +537,14 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
level_tab_settings: "设定"
|
level_tab_settings: "设定"
|
||||||
level_tab_components: "组件"
|
level_tab_components: "组件"
|
||||||
level_tab_systems: "系统"
|
level_tab_systems: "系统"
|
||||||
# level_tab_docs: "Documentation"
|
level_tab_docs: "文档"
|
||||||
level_tab_thangs_title: "目前所有物体"
|
level_tab_thangs_title: "目前所有物体"
|
||||||
level_tab_thangs_all: "所有"
|
level_tab_thangs_all: "所有"
|
||||||
level_tab_thangs_conditions: "启动条件"
|
level_tab_thangs_conditions: "启动条件"
|
||||||
level_tab_thangs_add: "增加物体"
|
level_tab_thangs_add: "增加物体"
|
||||||
delete: "删除"
|
delete: "删除"
|
||||||
duplicate: "复制"
|
duplicate: "复制"
|
||||||
# rotate: "Rotate"
|
rotate: "旋转"
|
||||||
level_settings_title: "设置"
|
level_settings_title: "设置"
|
||||||
level_component_tab_title: "目前所有组件"
|
level_component_tab_title: "目前所有组件"
|
||||||
level_component_btn_new: "创建新的组件"
|
level_component_btn_new: "创建新的组件"
|
||||||
|
@ -564,7 +564,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
new_thang_title: "创建一个新物品类型"
|
new_thang_title: "创建一个新物品类型"
|
||||||
new_level_title: "创建一个新关卡"
|
new_level_title: "创建一个新关卡"
|
||||||
new_article_title_login: "登录以创建新指令"
|
new_article_title_login: "登录以创建新指令"
|
||||||
new_thang_title_login: "登录以创建新实体"
|
new_thang_title_login: "登录以创建新物品"
|
||||||
new_level_title_login: "登录以创建新关卡"
|
new_level_title_login: "登录以创建新关卡"
|
||||||
new_achievement_title: "创建新目标"
|
new_achievement_title: "创建新目标"
|
||||||
new_achievement_title_login: "登录以创建新目标"
|
new_achievement_title_login: "登录以创建新目标"
|
||||||
|
@ -577,7 +577,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
# achievement_query_misc: "Key achievement off of miscellanea"
|
# achievement_query_misc: "Key achievement off of miscellanea"
|
||||||
# achievement_query_goals: "Key achievement off of level goals"
|
# achievement_query_goals: "Key achievement off of level goals"
|
||||||
level_completion: "关卡完成"
|
level_completion: "关卡完成"
|
||||||
# pop_i18n: "Populate I18N"
|
pop_i18n: "填写 I18N"
|
||||||
|
|
||||||
article:
|
article:
|
||||||
edit_btn_preview: "预览"
|
edit_btn_preview: "预览"
|
||||||
|
@ -611,12 +611,12 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
archmage_subscribe_desc: "通过电子邮件获得新的编码机会和公告。"
|
archmage_subscribe_desc: "通过电子邮件获得新的编码机会和公告。"
|
||||||
artisan_summary_pref: "想要设计 CodeCombat 的关卡吗?人们玩的比我们做的快多了!现在我们的关卡编辑器还很基本,所以做起关卡来会有点麻烦,还会有bug。只要你有制作关卡的灵感,不管是简单的for循环还是"
|
artisan_summary_pref: "想要设计 CodeCombat 的关卡吗?人们玩的比我们做的快多了!现在我们的关卡编辑器还很基本,所以做起关卡来会有点麻烦,还会有bug。只要你有制作关卡的灵感,不管是简单的for循环还是"
|
||||||
artisan_summary_suf: "这种东西,这个职业都很适合你。"
|
artisan_summary_suf: "这种东西,这个职业都很适合你。"
|
||||||
# artisan_introduction_pref: "We must construct additional levels! People be clamoring for more content, and we can only build so many ourselves. Right now your workstation is level one; our level editor is barely usable even by its creators, so be wary. If you have visions of campaigns spanning for-loops to"
|
artisan_introduction_pref: "我们必须设计更多的关卡! 大家为了更多的游戏内容在高声呐喊,但是我们靠自己只能创建这些。现在你的电脑就是一关!我们的关卡编辑器刚刚完成了基本功能,所以创造关卡的时候请小心使用。只要你有制作关卡的灵感,不管是简单的for循环还是"
|
||||||
# artisan_introduction_suf: ", then this class might be for you."
|
artisan_introduction_suf: "这种东西,这个职业都很适合你。"
|
||||||
# artisan_attribute_1: "Any experience in building content like this would be nice, such as using Blizzard's level editors. But not required!"
|
artisan_attribute_1: "任何类似的创建内容经验都有加分,无论是暴雪的关卡编辑器,但这不是必须的条件。"
|
||||||
# artisan_attribute_2: "A hankering to do a whole lot of testing and iteration. To make good levels, you need to take it to others and watch them play it, and be prepared to find a lot of things to fix."
|
artisan_attribute_2: "渴望完成全部的测试和迭代。要做一个优秀的关卡,你需要把它给别的玩家观察他们怎么玩,然后时刻准备着找到很多细节去打磨。"
|
||||||
# artisan_attribute_3: "For the time being, endurance en par with an Adventurer. Our Level Editor is super preliminary and frustrating to use. You have been warned!"
|
artisan_attribute_3: "探险家般的忍耐力。我们的关卡编辑器非常的初级,还会有很多不好用的地方。唔,我已经提前告诉你了~"
|
||||||
# artisan_join_desc: "Use the Level Editor in these steps, give or take:"
|
artisan_join_desc: "如下步骤使用关卡编辑器:"
|
||||||
artisan_join_step1: "阅读文档."
|
artisan_join_step1: "阅读文档."
|
||||||
artisan_join_step2: "创建一个新关卡 以及探索已经存在的关卡."
|
artisan_join_step2: "创建一个新关卡 以及探索已经存在的关卡."
|
||||||
artisan_join_step3: "来我们的 HipChat 聊天室寻求帮助."
|
artisan_join_step3: "来我们的 HipChat 聊天室寻求帮助."
|
||||||
|
@ -649,7 +649,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
diplomat_attribute_1: "既会说流利的英语,也熟悉自己的语言。编程是一件很复杂的事情,而要翻译复杂的概念,你必须对两种语言都在行!"
|
diplomat_attribute_1: "既会说流利的英语,也熟悉自己的语言。编程是一件很复杂的事情,而要翻译复杂的概念,你必须对两种语言都在行!"
|
||||||
diplomat_i18n_page_prefix: "你可以在我们的"
|
diplomat_i18n_page_prefix: "你可以在我们的"
|
||||||
diplomat_i18n_page: "翻译页面"
|
diplomat_i18n_page: "翻译页面"
|
||||||
diplomat_i18n_page_suffix: "开始翻译游戏,或者在GibHub我们的页面上进行。"
|
diplomat_i18n_page_suffix: "开始翻译游戏,或者在 GitHub 我们的页面上进行。"
|
||||||
diplomat_join_pref_github: "在"
|
diplomat_join_pref_github: "在"
|
||||||
diplomat_github_url: " GitHub "
|
diplomat_github_url: " GitHub "
|
||||||
diplomat_join_suf_github: "找到你的语言文件 (中文的是: codecombat/app/locale/zh-HNAS.coffee),在线编辑它,然后提交一个合并请求。同时,选中下面这个复选框来关注最新的国际化开发!"
|
diplomat_join_suf_github: "找到你的语言文件 (中文的是: codecombat/app/locale/zh-HNAS.coffee),在线编辑它,然后提交一个合并请求。同时,选中下面这个复选框来关注最新的国际化开发!"
|
||||||
|
@ -675,13 +675,13 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
please_login: "请在对奕之前先登录."
|
please_login: "请在对奕之前先登录."
|
||||||
my_matches: "我的对手"
|
my_matches: "我的对手"
|
||||||
simulate: "模拟"
|
simulate: "模拟"
|
||||||
# simulation_explanation: "By simulating games you can get your game ranked faster!"
|
simulation_explanation: "通过模拟游戏,你可以让你的游戏更快的得到评分。"
|
||||||
simulate_games: "模拟游戏!"
|
simulate_games: "模拟游戏!"
|
||||||
# simulate_all: "RESET AND SIMULATE GAMES"
|
simulate_all: "重置并模拟游戏!"
|
||||||
# games_simulated_by: "Games simulated by you:"
|
games_simulated_by: "你模拟玩过的游戏:"
|
||||||
# games_simulated_for: "Games simulated for you:"
|
games_simulated_for: "待你模拟玩的游戏:"
|
||||||
# games_simulated: "Games simulated"
|
games_simulated: "游戏已模拟"
|
||||||
# games_played: "Games played"
|
games_played: "已玩过"
|
||||||
# ratio: "Ratio"
|
# ratio: "Ratio"
|
||||||
leaderboard: "排行榜"
|
leaderboard: "排行榜"
|
||||||
battle_as: "我要加入这一方 "
|
battle_as: "我要加入这一方 "
|
||||||
|
@ -692,13 +692,13 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
rank_no_code: "没有新代码可供评分"
|
rank_no_code: "没有新代码可供评分"
|
||||||
rank_my_game: "为我的游戏评分!"
|
rank_my_game: "为我的游戏评分!"
|
||||||
rank_submitting: "正在提交..."
|
rank_submitting: "正在提交..."
|
||||||
# rank_submitted: "Submitted for Ranking"
|
rank_submitted: "提交评分"
|
||||||
rank_failed: "评分失败"
|
rank_failed: "评分失败"
|
||||||
rank_being_ranked: "已评价"
|
rank_being_ranked: "已评价"
|
||||||
rank_last_submitted: "已提交"
|
rank_last_submitted: "已提交"
|
||||||
# help_simulate: "Help simulate games?"
|
help_simulate: "模拟游戏需要帮助?"
|
||||||
# code_being_simulated: "Your new code is being simulated by other players for ranking. This will refresh as new matches come in."
|
code_being_simulated: "你的新代码正在被其他玩家模拟评分。这个将会刷新,作为一个新游戏开始。"
|
||||||
# no_ranked_matches_pre: "No ranked matches for the "
|
# no_ranked_matches_pre: "No ranked matches for the "
|
||||||
# no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
|
# no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
|
||||||
choose_opponent: "选择一个对手"
|
choose_opponent: "选择一个对手"
|
||||||
select_your_language: "选择你使用的语言!"
|
select_your_language: "选择你使用的语言!"
|
||||||
|
@ -714,13 +714,13 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
social_connect_blurb: "连接然后与朋友对战!"
|
social_connect_blurb: "连接然后与朋友对战!"
|
||||||
invite_friends_to_battle: "邀请你的朋友参加战斗!"
|
invite_friends_to_battle: "邀请你的朋友参加战斗!"
|
||||||
fight: "战斗!"
|
fight: "战斗!"
|
||||||
# watch_victory: "Watch your victory"
|
watch_victory: "观看你的胜利"
|
||||||
# defeat_the: "Defeat the"
|
defeat_the: "击败了"
|
||||||
# tournament_ends: "Tournament ends"
|
# tournament_ends: "Tournament ends"
|
||||||
# tournament_ended: "Tournament ended"
|
# tournament_ended: "Tournament ended"
|
||||||
# tournament_rules: "Tournament Rules"
|
tournament_rules: "锦标赛规则"
|
||||||
# tournament_blurb: "Write code, collect gold, build armies, crush foes, win prizes, and upgrade your career in our $40,000 Greed tournament! Check out the details"
|
# tournament_blurb: "Write code, collect gold, build armies, crush foes, win prizes, and upgrade your career in our $40,000 Greed tournament! Check out the details"
|
||||||
# tournament_blurb_criss_cross: "Win bids, construct paths, outwit opponents, grab gems, and upgrade your career in our Criss-Cross tournament! Check out the details"
|
tournament_blurb_criss_cross: "赢得竞拍,建造道路,智胜对手,夺取宝石,在纵横交错锦标赛中完成生涯晋级! 现在就查看详情!"
|
||||||
# tournament_blurb_blog: "on our blog"
|
# tournament_blurb_blog: "on our blog"
|
||||||
rules: "规则"
|
rules: "规则"
|
||||||
winners: "胜利者"
|
winners: "胜利者"
|
||||||
|
@ -745,16 +745,16 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
amount_achieved: "数量"
|
amount_achieved: "数量"
|
||||||
achievement: "成就"
|
achievement: "成就"
|
||||||
category_contributor: "贡献"
|
category_contributor: "贡献"
|
||||||
# category_miscellaneous: "Miscellaneous"
|
category_miscellaneous: "其他"
|
||||||
category_levels: "等级"
|
category_levels: "等级"
|
||||||
# category_undefined: "Uncategorized"
|
category_undefined: "未分类"
|
||||||
# current_xp_prefix: ""
|
current_xp_prefix: "当前总共"
|
||||||
# current_xp_postfix: " in total"
|
current_xp_postfix: "经验"
|
||||||
# new_xp_prefix: ""
|
new_xp_prefix: "获得"
|
||||||
new_xp_postfix: "获取"
|
new_xp_postfix: "经验"
|
||||||
# left_xp_prefix: ""
|
left_xp_prefix: "还需要"
|
||||||
# left_xp_infix: " until level "
|
left_xp_infix: "经验"
|
||||||
# left_xp_postfix: ""
|
left_xp_postfix: "到下一等级"
|
||||||
|
|
||||||
account:
|
account:
|
||||||
recently_played: "最近玩过的关卡"
|
recently_played: "最近玩过的关卡"
|
||||||
|
@ -787,25 +787,25 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
user_schema: "用户模式"
|
user_schema: "用户模式"
|
||||||
user_profile: "用户信息"
|
user_profile: "用户信息"
|
||||||
patches: "补丁"
|
patches: "补丁"
|
||||||
# patched_model: "Source Document"
|
patched_model: "源文档"
|
||||||
# model: "Model"
|
model: "型号"
|
||||||
# system: "System"
|
system: "系统"
|
||||||
# systems: "Systems"
|
systems: "系统"
|
||||||
# component: "Component"
|
component: "组件"
|
||||||
# components: "Components"
|
components: "组件"
|
||||||
# thang: "Thang"
|
thang: "物品"
|
||||||
# thangs: "Thangs"
|
thangs: "物品"
|
||||||
# level_session: "Your Session"
|
# level_session: "Your Session"
|
||||||
# opponent_session: "Opponent Session"
|
# opponent_session: "Opponent Session"
|
||||||
# article: "Article"
|
article: "文章"
|
||||||
user_names: "用户名"
|
user_names: "用户名"
|
||||||
# thang_names: "Thang Names"
|
thang_names: "物品名称"
|
||||||
files: "文件"
|
files: "文件"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
# source_document: "Source Document"
|
# source_document: "Source Document"
|
||||||
# document: "Document"
|
document: "文档"
|
||||||
# sprite_sheet: "Sprite Sheet"
|
sprite_sheet: "SpriteSheet"
|
||||||
# employers: "Employers"
|
employers: "Employers"
|
||||||
# candidates: "Candidates"
|
# candidates: "Candidates"
|
||||||
# candidate_sessions: "Candidate Sessions"
|
# candidate_sessions: "Candidate Sessions"
|
||||||
# user_remark: "User Remark"
|
# user_remark: "User Remark"
|
||||||
|
@ -944,23 +944,23 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
done_editing: "完成编辑"
|
done_editing: "完成编辑"
|
||||||
profile_for_prefix: "关于他的基本资料:"
|
profile_for_prefix: "关于他的基本资料:"
|
||||||
profile_for_suffix: ""
|
profile_for_suffix: ""
|
||||||
# featured: "Featured"
|
featured: "被推荐"
|
||||||
# not_featured: "Not Featured"
|
not_featured: "未入选"
|
||||||
looking_for: "寻找"
|
looking_for: "寻找"
|
||||||
last_updated: "最后一次更新:"
|
last_updated: "最后一次更新:"
|
||||||
contact: "联系"
|
contact: "联系"
|
||||||
active: "正期待面试offer"
|
active: "正期待面试offer"
|
||||||
inactive: "并不期待面试offer"
|
inactive: "并不期待面试offer"
|
||||||
# complete: "complete"
|
complete: "完成"
|
||||||
# next: "Next"
|
next: "下一步"
|
||||||
# next_city: "city?"
|
next_city: "城市?"
|
||||||
# next_country: "pick your country."
|
next_country: "选择你的城市。"
|
||||||
# next_name: "name?"
|
next_name: "姓名?"
|
||||||
# next_short_description: "write a short description."
|
next_short_description: "写一个简短的描述"
|
||||||
# next_long_description: "describe your desired position."
|
next_long_description: "描述你渴望的职位。"
|
||||||
# next_skills: "list at least five skills."
|
next_skills: "列出至少五个技能。"
|
||||||
# next_work: "chronicle your work history."
|
next_work: "你的过往工作经验"
|
||||||
# next_education: "recount your educational ordeals."
|
next_education: "教育经历"
|
||||||
# next_projects: "show off up to three projects you've worked on."
|
# next_projects: "show off up to three projects you've worked on."
|
||||||
# next_links: "add any personal or social links."
|
# next_links: "add any personal or social links."
|
||||||
# next_photo: "add an optional professional photo."
|
# next_photo: "add an optional professional photo."
|
||||||
|
|
|
@ -50,6 +50,7 @@ visa = c.shortString
|
||||||
|
|
||||||
_.extend UserSchema.properties,
|
_.extend UserSchema.properties,
|
||||||
email: c.shortString({title: 'Email', format: 'email'})
|
email: c.shortString({title: 'Email', format: 'email'})
|
||||||
|
iosIdentifierForVendor: c.shortString({format: 'hidden'})
|
||||||
firstName: c.shortString({title: 'First Name'})
|
firstName: c.shortString({title: 'First Name'})
|
||||||
lastName: c.shortString({title: 'Last Name'})
|
lastName: c.shortString({title: 'Last Name'})
|
||||||
gender: {type: 'string', 'enum': ['male', 'female']}
|
gender: {type: 'string', 'enum': ['male', 'female']}
|
||||||
|
|
|
@ -218,7 +218,7 @@ $level-resize-transition-time: 0.5s
|
||||||
#stop-real-time-playback-button
|
#stop-real-time-playback-button
|
||||||
display: none
|
display: none
|
||||||
position: absolute
|
position: absolute
|
||||||
bottom: 40px
|
bottom: 70px
|
||||||
right: 15px
|
right: 15px
|
||||||
font-size: 30px
|
font-size: 30px
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
left: 40px
|
left: 40px
|
||||||
width: 160px
|
width: 160px
|
||||||
text-align: center
|
text-align: center
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
a.levels-link
|
a.levels-link
|
||||||
margin: 0
|
margin: 0
|
||||||
|
@ -38,8 +39,11 @@
|
||||||
color: $control-yellow
|
color: $control-yellow
|
||||||
text-shadow: 1px 1px 0px rgb(143, 123, 62)
|
text-shadow: 1px 1px 0px rgb(143, 123, 62)
|
||||||
|
|
||||||
&:hover .glyphicon
|
&:hover
|
||||||
color: $control-yellow-highlight
|
a.levels-link
|
||||||
|
text-decoration: underline
|
||||||
|
.glyphicon
|
||||||
|
color: $control-yellow-highlight
|
||||||
|
|
||||||
.left-cap, .right-cap, .center-chain, .right-chain, .wood-background
|
.left-cap, .right-cap, .center-chain, .right-chain, .wood-background
|
||||||
position: absolute
|
position: absolute
|
||||||
|
|
|
@ -612,10 +612,32 @@ forest = [
|
||||||
original: '5446cb40ce01c23e05ecf027'
|
original: '5446cb40ce01c23e05ecf027'
|
||||||
description: 'Stay alive and navigate through the forest.'
|
description: 'Stay alive and navigate through the forest.'
|
||||||
nextLevels:
|
nextLevels:
|
||||||
continue: 'thornbush-farm'
|
continue: 'endangered-burl'
|
||||||
x: 39.03
|
x: 39.03
|
||||||
y: 54.97
|
y: 54.97
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
name: 'Endangered Burl'
|
||||||
|
type: 'hero'
|
||||||
|
id: 'endangered-burl'
|
||||||
|
original: ''
|
||||||
|
description: 'Hunt ogres in the woods, but watch out for lumbering beasts.'
|
||||||
|
nextLevels:
|
||||||
|
continue: 'village-guard'
|
||||||
|
x: 41.09
|
||||||
|
y: 43.75
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name: 'Village Guard'
|
||||||
|
type: 'hero'
|
||||||
|
id: 'village-guard'
|
||||||
|
original: '546e91b8a4b7840000ee92dc'
|
||||||
|
description: 'Defend a village from marauding munchkin mayhem.'
|
||||||
|
nextLevels:
|
||||||
|
continue: 'thornbush-farm'
|
||||||
|
x: 48.09
|
||||||
|
y: 42.75
|
||||||
|
}
|
||||||
{
|
{
|
||||||
name: 'Thornbush Farm'
|
name: 'Thornbush Farm'
|
||||||
type: 'hero'
|
type: 'hero'
|
||||||
|
|
|
@ -7,6 +7,7 @@ RealTimeModel = require 'models/RealTimeModel'
|
||||||
RealTimeCollection = require 'collections/RealTimeCollection'
|
RealTimeCollection = require 'collections/RealTimeCollection'
|
||||||
LevelSetupManager = require 'lib/LevelSetupManager'
|
LevelSetupManager = require 'lib/LevelSetupManager'
|
||||||
GameMenuModal = require 'views/game-menu/GameMenuModal'
|
GameMenuModal = require 'views/game-menu/GameMenuModal'
|
||||||
|
CampaignOptions = require 'lib/CampaignOptions'
|
||||||
|
|
||||||
module.exports = class ControlBarView extends CocoView
|
module.exports = class ControlBarView extends CocoView
|
||||||
id: 'control-bar-view'
|
id: 'control-bar-view'
|
||||||
|
@ -22,6 +23,7 @@ module.exports = class ControlBarView extends CocoView
|
||||||
'click #next-game-button': -> Backbone.Mediator.publish 'level:next-game-pressed', {}
|
'click #next-game-button': -> Backbone.Mediator.publish 'level:next-game-pressed', {}
|
||||||
'click #game-menu-button': 'showGameMenuModal'
|
'click #game-menu-button': 'showGameMenuModal'
|
||||||
'click': -> Backbone.Mediator.publish 'tome:focus-editor', {}
|
'click': -> Backbone.Mediator.publish 'tome:focus-editor', {}
|
||||||
|
'click .levels-link-area': 'onClickHome'
|
||||||
'click .home a': 'onClickHome'
|
'click .home a': 'onClickHome'
|
||||||
'click .multiplayer-area': 'onClickMultiplayer'
|
'click .multiplayer-area': 'onClickMultiplayer'
|
||||||
|
|
||||||
|
@ -66,7 +68,7 @@ module.exports = class ControlBarView extends CocoView
|
||||||
else if @level.get('type', true) in ['hero', 'hero-coop']
|
else if @level.get('type', true) in ['hero', 'hero-coop']
|
||||||
@homeLink = c.homeLink = '/play'
|
@homeLink = c.homeLink = '/play'
|
||||||
@homeViewClass = require 'views/play/WorldMapView'
|
@homeViewClass = require 'views/play/WorldMapView'
|
||||||
campaign = @getCampaignForSlug @level.get 'slug'
|
campaign = CampaignOptions.getCampaignForSlug @level.get 'slug'
|
||||||
if campaign isnt 'dungeon'
|
if campaign isnt 'dungeon'
|
||||||
@homeLink += '/' + campaign
|
@homeLink += '/' + campaign
|
||||||
@homeViewArgs.push campaign
|
@homeViewArgs.push campaign
|
||||||
|
@ -101,11 +103,6 @@ module.exports = class ControlBarView extends CocoView
|
||||||
@controlsEnabled = enabled
|
@controlsEnabled = enabled
|
||||||
@$el.toggleClass 'controls-disabled', not enabled
|
@$el.toggleClass 'controls-disabled', not enabled
|
||||||
|
|
||||||
getCampaignForSlug: (slug) ->
|
|
||||||
for campaign in require('views/play/WorldMapView').campaigns
|
|
||||||
for level in campaign.levels
|
|
||||||
return campaign.id if level.id is slug
|
|
||||||
|
|
||||||
onIPadMemoryWarning: (e) ->
|
onIPadMemoryWarning: (e) ->
|
||||||
@hasReceivedMemoryWarning = true
|
@hasReceivedMemoryWarning = true
|
||||||
|
|
||||||
|
@ -142,7 +139,7 @@ class MultiplayerStatusManager
|
||||||
# @playersCollection?.off 'add', @onPlayerAdded
|
# @playersCollection?.off 'add', @onPlayerAdded
|
||||||
# player.off 'change', @onPlayerChanged for id, player of @players
|
# player.off 'change', @onPlayerChanged for id, player of @players
|
||||||
|
|
||||||
onMultiplayerPlayerStatus: (e) =>
|
onMultiplayerPlayerStatus: (e) =>
|
||||||
@status = e.status
|
@status = e.status
|
||||||
@statusChangedCallback()
|
@statusChangedCallback()
|
||||||
|
|
||||||
|
@ -151,10 +148,10 @@ class MultiplayerStatusManager
|
||||||
# @players[player.id] = new RealTimeModel('multiplayer_players/' + @levelID + '/' + player.id)
|
# @players[player.id] = new RealTimeModel('multiplayer_players/' + @levelID + '/' + player.id)
|
||||||
# @players[player.id].on 'change', @onPlayerChanged
|
# @players[player.id].on 'change', @onPlayerChanged
|
||||||
# @countPlayers player
|
# @countPlayers player
|
||||||
#
|
#
|
||||||
# onPlayerChanged: (player) =>
|
# onPlayerChanged: (player) =>
|
||||||
# @countPlayers player
|
# @countPlayers player
|
||||||
#
|
#
|
||||||
# countPlayers: (changedPlayer) =>
|
# countPlayers: (changedPlayer) =>
|
||||||
# # TODO: save this stale hearbeat threshold setting somewhere
|
# # TODO: save this stale hearbeat threshold setting somewhere
|
||||||
# staleHeartbeat = new Date()
|
# staleHeartbeat = new Date()
|
||||||
|
|
|
@ -8,6 +8,7 @@ utils = require 'lib/utils'
|
||||||
ThangType = require 'models/ThangType'
|
ThangType = require 'models/ThangType'
|
||||||
LadderSubmissionView = require 'views/play/common/LadderSubmissionView'
|
LadderSubmissionView = require 'views/play/common/LadderSubmissionView'
|
||||||
AudioPlayer = require 'lib/AudioPlayer'
|
AudioPlayer = require 'lib/AudioPlayer'
|
||||||
|
CampaignOptions = require 'lib/CampaignOptions'
|
||||||
|
|
||||||
module.exports = class HeroVictoryModal extends ModalView
|
module.exports = class HeroVictoryModal extends ModalView
|
||||||
id: 'hero-victory-modal'
|
id: 'hero-victory-modal'
|
||||||
|
@ -265,16 +266,11 @@ module.exports = class HeroVictoryModal extends ModalView
|
||||||
for level in campaign.levels
|
for level in campaign.levels
|
||||||
return level if level.id is slug
|
return level if level.id is slug
|
||||||
|
|
||||||
getCampaignForSlug: (slug) ->
|
|
||||||
for campaign in require('views/play/WorldMapView').campaigns
|
|
||||||
for level in campaign.levels
|
|
||||||
return campaign.id if level.id is slug
|
|
||||||
|
|
||||||
getNextLevelCampaign: ->
|
getNextLevelCampaign: ->
|
||||||
# Wouldn't handle skipping/more practice across campaign boundaries, but we don't do that.
|
# Wouldn't handle skipping/more practice across campaign boundaries, but we don't do that.
|
||||||
campaign = @getCampaignForSlug @level.get 'slug'
|
campaign = CampaignOptions.getCampaignForSlug @level.get 'slug'
|
||||||
if nextLevelSlug = @getNextLevel 'continue'
|
if nextLevelSlug = @getNextLevel 'continue'
|
||||||
campaign = @getCampaignForSlug nextLevelSlug
|
campaign = CampaignOptions.getCampaignForSlug nextLevelSlug
|
||||||
campaign or 'dungeon'
|
campaign or 'dungeon'
|
||||||
|
|
||||||
getNextLevelLink: (type) ->
|
getNextLevelLink: (type) ->
|
||||||
|
|
|
@ -9,6 +9,7 @@ SpellDebugView = require './SpellDebugView'
|
||||||
SpellToolbarView = require './SpellToolbarView'
|
SpellToolbarView = require './SpellToolbarView'
|
||||||
LevelComponent = require 'models/LevelComponent'
|
LevelComponent = require 'models/LevelComponent'
|
||||||
UserCodeProblem = require 'models/UserCodeProblem'
|
UserCodeProblem = require 'models/UserCodeProblem'
|
||||||
|
CampaignOptions = require 'lib/CampaignOptions'
|
||||||
LevelOptions = require 'lib/LevelOptions'
|
LevelOptions = require 'lib/LevelOptions'
|
||||||
|
|
||||||
module.exports = class SpellView extends CocoView
|
module.exports = class SpellView extends CocoView
|
||||||
|
@ -216,6 +217,7 @@ module.exports = class SpellView extends CocoView
|
||||||
# TODO: Turn on more autocompletion based on level sophistication
|
# TODO: Turn on more autocompletion based on level sophistication
|
||||||
# TODO: E.g. using the language default snippets yields a bunch of crazy non-beginner suggestions
|
# TODO: E.g. using the language default snippets yields a bunch of crazy non-beginner suggestions
|
||||||
# TODO: Options logic shouldn't exist both here and in updateAutocomplete()
|
# TODO: Options logic shouldn't exist both here and in updateAutocomplete()
|
||||||
|
popupFontSizePx = CampaignOptions.getOption(@options.level.get('slug'), 'autocompleteFontSizePx') ? 16
|
||||||
@zatanna = new Zatanna @ace,
|
@zatanna = new Zatanna @ace,
|
||||||
basic: false
|
basic: false
|
||||||
liveCompletion: false
|
liveCompletion: false
|
||||||
|
@ -226,7 +228,7 @@ module.exports = class SpellView extends CocoView
|
||||||
text: @autocomplete
|
text: @autocomplete
|
||||||
autoLineEndings:
|
autoLineEndings:
|
||||||
javascript: ';'
|
javascript: ';'
|
||||||
popupFontSizePx: 16
|
popupFontSizePx: popupFontSizePx
|
||||||
popupWidthPx: 380
|
popupWidthPx: 380
|
||||||
|
|
||||||
updateAutocomplete: (@autocomplete) ->
|
updateAutocomplete: (@autocomplete) ->
|
||||||
|
@ -253,7 +255,7 @@ module.exports = class SpellView extends CocoView
|
||||||
if doc?.snippets?[e.language]
|
if doc?.snippets?[e.language]
|
||||||
entry =
|
entry =
|
||||||
content: doc.snippets[e.language].code
|
content: doc.snippets[e.language].code
|
||||||
meta: 'press enter'
|
meta: 'press tab'
|
||||||
name: doc.name
|
name: doc.name
|
||||||
tabTrigger: doc.snippets[e.language].tab
|
tabTrigger: doc.snippets[e.language].tab
|
||||||
if doc.name is 'findNearestEnemy'
|
if doc.name is 'findNearestEnemy'
|
||||||
|
|
|
@ -10,7 +10,7 @@ hipchat = require '../hipchat'
|
||||||
deltasLib = require '../../app/lib/deltas'
|
deltasLib = require '../../app/lib/deltas'
|
||||||
|
|
||||||
PROJECT = {original: 1, name: 1, version: 1, description: 1, slug: 1, kind: 1, created: 1, permissions: 1}
|
PROJECT = {original: 1, name: 1, version: 1, description: 1, slug: 1, kind: 1, created: 1, permissions: 1}
|
||||||
FETCH_LIMIT = 500
|
FETCH_LIMIT = 1000 # So many ThangTypes
|
||||||
|
|
||||||
module.exports = class Handler
|
module.exports = class Handler
|
||||||
# subclasses should override these properties
|
# subclasses should override these properties
|
||||||
|
|
|
@ -15,7 +15,14 @@ module.exports.setup = (app) ->
|
||||||
|
|
||||||
authentication.use(new LocalStrategy(
|
authentication.use(new LocalStrategy(
|
||||||
(username, password, done) ->
|
(username, password, done) ->
|
||||||
User.findOne({emailLower: username.toLowerCase()}).exec((err, user) ->
|
|
||||||
|
# kind of a hacky way to make it possible for iPads to 'log in' with their unique device id
|
||||||
|
if username.length is 36 and '@' not in username # must be an identifier for vendor
|
||||||
|
q = { iosIdentifierForVendor: username }
|
||||||
|
else
|
||||||
|
q = { emailLower: username.toLowerCase() }
|
||||||
|
|
||||||
|
User.findOne(q).exec((err, user) ->
|
||||||
return done(err) if err
|
return done(err) if err
|
||||||
return done(null, false, {message: 'not found', property: 'email'}) if not user
|
return done(null, false, {message: 'not found', property: 'email'}) if not user
|
||||||
passwordReset = (user.get('passwordReset') or '').toLowerCase()
|
passwordReset = (user.get('passwordReset') or '').toLowerCase()
|
||||||
|
|
|
@ -96,7 +96,7 @@ UserSchema.statics.updateMailChimp = (doc, callback) ->
|
||||||
params.email = if existingProps then {leid: existingProps.leid} else {email: doc.get('email')}
|
params.email = if existingProps then {leid: existingProps.leid} else {email: doc.get('email')}
|
||||||
params.merge_vars = {groupings: [{id: mail.MAILCHIMP_GROUP_ID, groups: newGroups}]}
|
params.merge_vars = {groupings: [{id: mail.MAILCHIMP_GROUP_ID, groups: newGroups}]}
|
||||||
params.update_existing = true
|
params.update_existing = true
|
||||||
params.double_optin = false
|
params.double_optin = true
|
||||||
|
|
||||||
onSuccess = (data) ->
|
onSuccess = (data) ->
|
||||||
doc.set('mailChimp', data)
|
doc.set('mailChimp', data)
|
||||||
|
@ -200,7 +200,7 @@ UserSchema.statics.editableProperties = [
|
||||||
'firstName', 'lastName', 'gender', 'facebookID', 'gplusID', 'emails',
|
'firstName', 'lastName', 'gender', 'facebookID', 'gplusID', 'emails',
|
||||||
'testGroupNumber', 'music', 'hourOfCode', 'hourOfCodeComplete', 'preferredLanguage',
|
'testGroupNumber', 'music', 'hourOfCode', 'hourOfCodeComplete', 'preferredLanguage',
|
||||||
'wizard', 'aceConfig', 'autocastDelay', 'lastLevel', 'jobProfile', 'savedEmployerFilterAlerts',
|
'wizard', 'aceConfig', 'autocastDelay', 'lastLevel', 'jobProfile', 'savedEmployerFilterAlerts',
|
||||||
'heroConfig'
|
'heroConfig', 'iosIdentifierForVendor'
|
||||||
]
|
]
|
||||||
|
|
||||||
UserSchema.plugin plugins.NamedPlugin
|
UserSchema.plugin plugins.NamedPlugin
|
||||||
|
|
|
@ -15,7 +15,31 @@ describe '/auth/whoami', ->
|
||||||
|
|
||||||
describe '/auth/login', ->
|
describe '/auth/login', ->
|
||||||
|
|
||||||
it 'clears Users first', (done) ->
|
it 'clears Users', (done) ->
|
||||||
|
clearModels [User], (err) ->
|
||||||
|
throw err if err
|
||||||
|
request.get getURL('/auth/whoami'), ->
|
||||||
|
throw err if err
|
||||||
|
done()
|
||||||
|
|
||||||
|
it 'allows logging in by iosIdentifierForVendor', (done) ->
|
||||||
|
req = request.post(getURL('/db/user'),
|
||||||
|
(error, response) ->
|
||||||
|
expect(response).toBeDefined()
|
||||||
|
expect(response.statusCode).toBe(200)
|
||||||
|
req = request.post(urlLogin, (error, response) ->
|
||||||
|
expect(response.statusCode).toBe(200)
|
||||||
|
done()
|
||||||
|
)
|
||||||
|
form = req.form()
|
||||||
|
form.append('username', '012345678901234567890123456789012345')
|
||||||
|
form.append('password', '12345')
|
||||||
|
)
|
||||||
|
form = req.form()
|
||||||
|
form.append('iosIdentifierForVendor', '012345678901234567890123456789012345')
|
||||||
|
form.append('password', '12345')
|
||||||
|
|
||||||
|
it 'clears Users', (done) ->
|
||||||
clearModels [User], (err) ->
|
clearModels [User], (err) ->
|
||||||
throw err if err
|
throw err if err
|
||||||
request.get getURL('/auth/whoami'), ->
|
request.get getURL('/auth/whoami'), ->
|
||||||
|
@ -84,7 +108,7 @@ describe '/auth/reset', ->
|
||||||
form = req.form()
|
form = req.form()
|
||||||
form.append('username', 'scott@gmail.com')
|
form.append('username', 'scott@gmail.com')
|
||||||
|
|
||||||
it 'can\'t reset an unknow user', (done) ->
|
it 'can\'t reset an unknown user', (done) ->
|
||||||
req = request.post(urlReset, (error, response) ->
|
req = request.post(urlReset, (error, response) ->
|
||||||
expect(response).toBeDefined()
|
expect(response).toBeDefined()
|
||||||
expect(response.statusCode).toBe(404)
|
expect(response.statusCode).toBe(404)
|
||||||
|
|
Reference in a new issue