This commit is contained in:
Scott Erickson 2014-02-24 09:47:20 -08:00
commit d146febb32
41 changed files with 462 additions and 284 deletions

View file

@ -80,7 +80,7 @@ class AudioPlayer extends CocoClass
@soundsToPlayWhenLoaded[name] = volume
playSound: (name, volume=1) ->
createjs.Sound.play name, {volume: me.get('volume') * volume}
createjs.Sound.play name, {volume: (me.get('volume') ? 1) * volume}
# # TODO: load Interface sounds somehow, somewhere, somewhen

View file

@ -88,6 +88,7 @@ module.exports = class God
else
@worldWaiting = true
return
#console.log "going to run world with code", @getUserCodeMap()
angel.worker.postMessage {func: 'runWorld', args: {
worldName: @level.name
userCodeMap: @getUserCodeMap()

View file

@ -27,7 +27,7 @@ module.exports = class LevelBus extends Bus
super(arguments...)
@changedSessionProperties = {}
@saveSession = _.debounce(@saveSession, 1000, {maxWait: 5000})
init: ->
super()
@fireScriptsRef = @fireRef?.child('scripts')
@ -55,14 +55,14 @@ module.exports = class LevelBus extends Bus
@wizardRef?.child('targetPos').set(wizardSprite?.targetPos or null)
@wizardRef?.child('targetSprite').set(wizardSprite?.targetSprite?.thang.id or null)
@wizardRef?.child('wizardColor1').set(me.get('wizardColor1') or 0.0)
disconnect: ->
@wizardRef?.off()
@wizardRef = null
@fireScriptsRef?.off()
@fireScriptsRef = null
super()
removeFirebaseData: (callback) ->
return callback?() unless @myConnection
@myConnection.child('connected')
@ -78,11 +78,11 @@ module.exports = class LevelBus extends Bus
onEditingBegan: -> @wizardRef?.child('editing').set(true)
onEditingEnded: -> @wizardRef?.child('editing').set(false)
# HACK: Backbone does not work with nested documents, but we want to
# patch only those props that have changed. Look into plugins to
# give Backbone support for nested docs and update the code here.
# TODO: The LevelBus doesn't need to be in charge of updating the
# LevelSession object. Either break this off into a separate class
# or have the LevelSession object listen for all these events itself.
@ -227,7 +227,7 @@ module.exports = class LevelBus extends Bus
patch = {}
patch[prop] = @session.get(prop) for prop of @changedSessionProperties
@changedSessionProperties = {}
# since updates are coming fast and loose for session objects
# don't let what the server returns overwrite changes since the save began
tempSession = new LevelSession _id:@session.id
@ -243,4 +243,3 @@ module.exports = class LevelBus extends Bus
@changedSessionProperties.teamSpells = true
@session.set({'teamSpells': @teamSpellMap})
@saveSession()

View file

@ -22,7 +22,7 @@ module.exports = class Tracker
return unless me and olark?
olark 'api.chat.updateVisitorStatus', snippet: ["User ID: #{me.id}"]
return if me.get("anonymous")
olark 'api.visitor.updateEmailAddress', emailAddress: me.get("email")
olark 'api.visitor.updateEmailAddress', emailAddress: me.get("email") if me.get('email')
olark 'api.chat.updateVisitorNickname', snippet: me.displayName()
updatePlayState: (level, session) ->
@ -33,7 +33,6 @@ module.exports = class Tracker
"User ID: #{me.id}"
"Session ID: #{session.id}"
"Level: #{level.get('name')}"
]
olark 'api.chat.updateVisitorStatus', snippet: snippet

View file

@ -210,6 +210,17 @@ module.exports = class Simulator
functionName: methodName
protectAPI: false
includeFlow: false
#includeFlow: true
requiresThis: true
yieldConditionally: false
problems:
jshint_W040: {level: "ignore"}
jshint_W030: {level: "ignore"} # aether_NoEffect instead
aether_MissingThis: {level: 'error'}
#functionParameters: # TODOOOOO
if methodName is 'hear'
aetherOptions.functionParameters = ['speaker', 'message', 'data']
console.log "creating aether with options", aetherOptions
return new Aether aetherOptions
class SimulationTask

View file

@ -12,11 +12,13 @@ module.exports = class CoordinateDisplay extends createjs.Container
@camera = options.camera
console.error "CoordinateDisplay needs camera." unless @camera
@build()
@show = _.debounce @show, 250
@show = _.debounce @show, 125
Backbone.Mediator.subscribe(channel, @[func], @) for channel, func of @subscriptions
destroy: ->
Backbone.Mediator.unsubscribe(channel, @[func], @) for channel, func of @subscriptions
@show = null
@destroyed = true
build: ->
@mouseEnabled = @mouseChildren = false
@ -46,7 +48,7 @@ module.exports = class CoordinateDisplay extends createjs.Container
@uncache()
show: =>
return unless @mouseInBounds and @lastPos
return unless @mouseInBounds and @lastPos and not @destroyed
@label.text = "(#{@lastPos.x}, #{@lastPos.y})"
[width, height] = [@label.getMeasuredWidth(), @label.getMeasuredHeight()]
@label.regX = width / 2

View file

@ -107,6 +107,11 @@ module.exports = class SpriteBoss extends CocoClass
sprite = new IndieSprite thangType, @createSpriteOptions {thangID: indieSprite.id, pos: indieSprite.pos, sprites: @sprites, colorConfig: indieSprite.colorConfig}
@addSprite sprite, sprite.thang.id
createOpponentWizard: (opponent) ->
# TODO: colorize name and cloud by team, colorize wizard by user's color config, level-specific wizard spawn points
sprite = @createWizardSprite thangID: opponent.id, name: opponent.name
sprite.targetPos = if opponent.team is 'ogres' then {x: 52, y: 52} else {x: 28, y: 28}
createWizardSprite: (options) ->
sprite = new WizardSprite @thangTypeFor("Wizard"), @createSpriteOptions(options)
@addSprite sprite, sprite.thang.id, @spriteLayers["Floating"]

View file

@ -361,6 +361,9 @@ module.exports = Surface = class Surface extends CocoClass
createjs.Ticker.addEventListener "tick", @tick
Backbone.Mediator.publish 'level:started'
createOpponentWizard: (opponent) ->
@spriteBoss.createOpponentWizard opponent
initAudio: ->
@musicPlayer = new MusicPlayer()

View file

@ -31,6 +31,8 @@ module.exports = class WizardSprite extends IndieSprite
if @isSelf
@setNameLabel me.displayName()
@setColorHue me.get('wizardColor1')
else if options.name
@setNameLabel options.name
makeIndieThang: (thangType, thangID, pos) ->
thang = super thangType, thangID, pos

View file

@ -55,7 +55,7 @@ module.exports = class World
@thangMap[thang.id] = thang
thangDialogueSounds: ->
if @frames.length < @totalFrames then worldShouldBeOverBeforeGrabbingDialogue
if @frames.length < @totalFrames then throw new Error("World should be over before grabbing dialogue")
[sounds, seen] = [[], {}]
for frame in @frames
for thangID, state of frame.thangStateMap
@ -245,7 +245,7 @@ module.exports = class World
serialize: ->
# Code hotspot; optimize it
if @frames.length < @totalFrames then worldShouldBeOverBeforeSerialization
if @frames.length < @totalFrames then throw new Error("World Should Be Over Before Serialization")
[transferableObjects, nontransferableObjects] = [0, 0]
o = {name: @name, totalFrames: @totalFrames, maxTotalFrames: @maxTotalFrames, frameRate: @frameRate, dt: @dt, victory: @victory, userCodeMap: {}, trackedProperties: {}}
o.trackedProperties[prop] = @[prop] for prop in @trackedProperties or []

View file

@ -104,11 +104,11 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
wizard_settings:
title: "Ajustes del mago"
customize_avatar: "Personaliza tu Avatar"
# clothes: "Clothes"
clothes: "Ropa"
# trim: "Trim"
# cloud: "Cloud"
cloud: "Nube"
# spell: "Spell"
# boots: "Boots"
boots: "Botas"
# hue: "Hue"
# saturation: "Saturation"
# lightness: "Lightness"
@ -203,13 +203,13 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
# admin:
# av_title: "Admin Views"
# av_entities_sub_title: "Entities"
# av_entities_users_url: "Users"
# av_entities_active_instances_url: "Active Instances"
# av_other_sub_title: "Other"
av_entities_sub_title: "Entidades"
av_entities_users_url: "Usuarios"
av_entities_active_instances_url: "Instancias Activas"
av_other_sub_title: "Otros"
# av_other_debug_base_url: "Base (for debugging base.jade)"
# u_title: "User List"
# lg_title: "Latest Games"
u_title: "Lista de Usuarios"
lg_title: "Últimos Juegos"
editor:
main_title: "Editores de CodeCombat"
@ -376,7 +376,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
more_about_archmage: "Aprende más sobre convertirte en un poderoso Archimago"
archmage_subscribe_desc: "Recibe correos sobre nuevos anuncios y oportunidades de codificar."
# artisan_summary_pref: "Want to design levels and expand CodeCombat's arsenal? People are playing through our content at a pace faster than we can build! Right now, our level editor is barebone, so be wary. Making levels will be a little challenging and buggy. If you have visions of campaigns spanning for-loops to"
# artisan_summary_suf: "then this class is for you."
artisan_summary_suf: "entonces esta Clase es la tuya."
artisan_introduction_pref: "¡Debemos construir niveles adicionales! La gente clama por más contenido y solo podemos crear unos cuantos. Ahora mismo tu estación de trabajo es el nivel uno; nuestro editor de niveles es apenas usable por sus creadores, así que ten cuidado. Si tienes visiones de campañas que alcanzan el infinito"
artisan_introduction_suf: "entonces esta Clase es ideal para ti."
artisan_attribute_1: "Cualquier experiencia creando contenido similar estaría bien, como por ejemplo el editor de niveles de Blizzard. ¡Aunque no es necesaria!"
@ -413,9 +413,9 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
diplomat_launch_url: "lanzamiento en octubre"
diplomat_introduction_suf: "hay un interés considerable en CodeCombat en otros paises, ¡especialmente Brasil! Estamos formando un cuerpo de traductores con ganas de traducir un grupo de palabras tras otro para hacer CodeCombat tan accesible para todo el mundo como sea posible. Si quieres recibir avances de próximos contenidos y quieres poner esos niveles a disposición de los que comparten tu idioma tan pronto como sea posible, entonces esta Clase es para ti."
diplomat_attribute_1: "Fluidez con el ingles y el lenguaje al que quieras traducir. Cuando de transmitir ideas complejas se trata, ¡es importante tener grandes conocimientos de ambas!"
# diplomat_join_pref_github: "Find your language locale file "
# diplomat_github_url: "on GitHub"
# diplomat_join_suf_github: ", edit it online, and submit a pull request. Also, check this box below to keep up-to-date on new internationalization developments!"
diplomat_join_pref_github: "Encuentra el fichero local de tu idioma "
diplomat_github_url: "en GitHub"
diplomat_join_suf_github: ", edítalo online, y solicita que sea revisado. Además, marca la casilla de abajo para mantenerte informado en nuevos progresos en Internacionalización."
more_about_diplomat: "Aprende más sobre cómo convertirte en un gran Diplomático"
diplomat_subscribe_desc: "Recibe correos sobre nuevos niveles y desarrollos para traducir."
# ambassador_summary: "We are trying to build a community, and every community needs a support team when there are troubles. We have got chats, emails, and social networks so that our users can get acquainted with the game. If you want to help people get involved, have fun, and learn some programming, then this class is for you."

View file

@ -4,7 +4,7 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t
saving: "Guardando..."
sending: "Enviando..."
cancel: "Cancelar"
# save: "Save"
# save: "Guardar"
delay_1_sec: "1 segundo"
delay_3_sec: "3 segundos"
delay_5_sec: "5 segundos"
@ -31,15 +31,15 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t
about: "Sobre"
contact: "Contacto"
twitter_follow: "Seguir"
# employers: "Employers"
# employers: "Empleados"
# versions:
# save_version_title: "Save New Version"
# save_version_title: "Guardar Nueva Versión"
# new_major_version: "New Major Version"
# cla_prefix: "To save changes, first you must agree to our"
# cla_prefix: "Para poder guardar los cambios, primero debes aceptar nuestra"
# cla_url: "CLA"
# cla_suffix: "."
# cla_agree: "I AGREE"
# cla_agree: "ACEPTO"
login:
sign_up: "Crear Cuenta"
@ -48,11 +48,11 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t
recover: "recuperar cuenta"
# recover:
# recover_account_title: "Recover Account"
# send_password: "Send Recovery Password"
# recover_account_title: "Recuperar cuenta"
# send_password: "Enviar contraseña olvidada"
signup:
# create_account_title: "Create Account to Save Progress"
# create_account_title: "Crea una cuenta para guardar el progreso"
description: "Es gratis. Solo necesitas un par de cosas y estarás listo para comenzar:"
email_announcements: "Recibe noticias por email"
coppa: "más de 13 años o fuera de los Estados Unidos"
@ -102,21 +102,21 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t
subscribe_as_diplomat: "Suscribete como un Diplomático"
# wizard_settings:
# title: "Wizard Settings"
# customize_avatar: "Customize Your Avatar"
# clothes: "Clothes"
# title: "Configuración del mago"
# customize_avatar: "Personaliza tu avatar"
# clothes: "Ropa"
# trim: "Trim"
# cloud: "Cloud"
# cloud: "Nube"
# spell: "Spell"
# boots: "Boots"
# boots: "Botas"
# hue: "Hue"
# saturation: "Saturation"
# lightness: "Lightness"
# saturation: "Saturación"
# lightness: "Brillo"
account_settings:
title: "Configuración de la Cuenta"
not_logged_in: "Inicia sesión o crea una cuenta para cambiar tu configuración."
autosave: "Cambios Guardados Automáticamente"
autosave: "Los cambios se guardan Automáticamente"
me_tab: "Yo"
picture_tab: "Imagen"
wizard_tab: "Hechicero"
@ -139,7 +139,7 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t
email_toggle: "Activar todo"
error_saving: "Error al guardar"
saved: "Cambios guardados"
password_mismatch: "El password no coincide"
password_mismatch: "La contraseña no coincide"
account_profile:
edit_settings: "Editar Ajustes"
@ -233,7 +233,7 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t
# level_tab_thangs_title: "Current Thangs"
# level_tab_thangs_conditions: "Starting Conditions"
# level_tab_thangs_add: "Add Thangs"
# level_settings_title: "Settings"
# level_settings_title: "Ajustes"
# level_component_tab_title: "Current Components"
# level_component_btn_new: "Create New Component"
# level_systems_tab_title: "Current Systems"

View file

@ -1,4 +1,4 @@
module.exports = nativeDescription: "русский язык", englishDescription: "Russian", translation:
module.exports = nativeDescription: "русский", englishDescription: "Russian", translation:
common:
loading: "Загрузка..."
saving: "Сохранение..."
@ -9,18 +9,18 @@ module.exports = nativeDescription: "русский язык", englishDescriptio
delay_3_sec: "3 секунды"
delay_5_sec: "5 секунд"
manual: "Вручную"
# fork: "Fork"
fork: "Форк"
play: "Играть"
modal:
close: "Закрыть"
okay: "Хорошо"
okay: "OK"
not_found:
page_not_found: "Страница не найдена"
nav:
play: "Играть"
play: "Уровни"
editor: "Редактор"
blog: "Блог"
forum: "Форум"
@ -35,14 +35,14 @@ module.exports = nativeDescription: "русский язык", englishDescriptio
versions:
save_version_title: "Сохранить новую версию"
# new_major_version: "New Major Version"
cla_prefix: "Чтобы сохранить изменения, первым делом вы должны согласиться с нашим"
# cla_url: "CLA"
# cla_suffix: "."
new_major_version: "Новая основная версия"
cla_prefix: "Чтобы сохранить изменения, сначала вы должны согласиться с нашим"
cla_url: "лицензионным соглашением соавторов"
cla_suffix: "."
cla_agree: "Я СОГЛАСЕН"
login:
sign_up: "Создать Профиль"
sign_up: "Создать аккаунт"
log_in: "Войти"
log_out: "Выйти"
recover: "восстановить аккаунт"
@ -52,11 +52,11 @@ module.exports = nativeDescription: "русский язык", englishDescriptio
send_password: "Отправить пароль для восстановления"
signup:
# create_account_title: "Create Account to Save Progress"
description: "Это бесплатно. Нужно сделать лишь несколько шагов:"
email_announcements: "Получать оповещения по email"
coppa: "Вы старше 13 лет или живёте не в США"
coppa_why: "(Почему?)"
create_account_title: "Создать аккаунт, чтобы сохранить прогресс"
description: "Это бесплатно. Нужна лишь пара вещей и вы сможете продолжить путешествие:"
email_announcements: "Получать оповещения на email"
coppa: "Вы старше 13 лет или живёте не в США "
coppa_why: "(почему?)"
creating: "Создание аккаунта..."
sign_up: "Регистрация"
log_in: "вход с паролем"
@ -70,21 +70,21 @@ module.exports = nativeDescription: "русский язык", englishDescriptio
play:
choose_your_level: "Выберите ваш уровень"
adventurer_prefix: "Вы можете зайти на любой из этих уровней, а также обсудить уровни на "
adventurer_forum: "форуме Искателей Приключений"
adventurer_forum: "форуме Искателей приключений"
adventurer_suffix: "."
campaign_beginner: "Кампания для новичков"
campaign_beginner_description: "... в которой вы познакомитесь с магией программирования."
campaign_dev: "Случайные уровни потруднее"
campaign_dev_description: "... в которой вы изучите интерфейс и научитесь делать кое-что посложнее."
campaign_dev_description: "... в которых вы изучите интерфейс и научитесь делать кое-что посложнее."
campaign_multiplayer: "Арены для мультиплеера"
campaign_multiplayer_description: "... в которых вы соревнуетесь в программировании с другими игроками."
campaign_player_created: "Уровни игроков"
campaign_player_created_description: "... в которых вы сражаетесь с креативностью ваших друзей-<a href=\"/contribute#artisan\">Архитекторов</a>."
campaign_player_created_description: "... в которых вы сражаетесь с креативностью ваших друзей <a href=\"/contribute#artisan\">Ремесленников</a>."
level_difficulty: "Сложность: "
contact:
contact_us: "Связаться с CodeCombat"
welcome: "Мы рады вашему сообщению! Используйте эту форму, чтобы отправить нам email."
welcome: "Мы рады вашему сообщению! Используйте эту форму, чтобы отправить нам email. "
contribute_prefix: "Если вы хотите внести свой вклад в проект, зайдите на нашу "
contribute_page: "страницу сотрудничества"
contribute_suffix: "!"
@ -95,23 +95,23 @@ module.exports = nativeDescription: "русский язык", englishDescriptio
diplomat_suggestion:
title: "Помогите перевести CodeCombat!"
sub_heading: "Нам нужен ваш языковой талант."
sub_heading: "Нам нужны ваши языковые навыки."
pitch_body: "Мы создаём CodeCombat на английском, но у нас уже есть игроки со всего мира. Многие из них хотели бы играть на русском, но не знают английского, так что если вы знаете оба этих языка - зарегистрируйтесь как Дипломат и помогите перевести сайт CodeCombat и все уровни на русский язык."
missing_translations: "Пока мы не перевели всё на русский язык, вы будете видеть английский текст в тех частях игры, которые ещё не переведены на русский."
learn_more: "Узнать о том, как стать Дипломатом"
subscribe_as_diplomat: "Зарегистрироваться как Дипломат"
wizard_settings:
title: "Мастер настройки"
title: "Настройки волшебника"
customize_avatar: "Изменить свой аватар"
# clothes: "Clothes"
# trim: "Trim"
# cloud: "Cloud"
# spell: "Spell"
# boots: "Boots"
# hue: "Hue"
# saturation: "Saturation"
# lightness: "Lightness"
clothes: "Одежда"
trim: "Отделка"
cloud: "Облако"
spell: "Заклинание"
boots: "Обувь"
hue: "Оттенок"
saturation: "Насыщенность"
lightness: "Светлость"
account_settings:
title: "Настройки аккаунта"
@ -125,7 +125,7 @@ module.exports = nativeDescription: "русский язык", englishDescriptio
gravatar_select: "Выберите, какое фото с Gravatar использовать"
gravatar_add_photos: "Чтобы выбрать изображение, добавьте фото и уменьшенные изображения в ваш Gravatar-аккаунт."
gravatar_add_more_photos: "Добавьте больше фото к вашему аккаунту в Gravatar, чтобы использовать их здесь."
wizard_color: "Цвет волос персонажа"
wizard_color: "Цвет одежды волшебника"
new_password: "Новый пароль"
new_password_verify: "Подтверждение пароля"
email_subscriptions: "Email-подписки"
@ -147,10 +147,10 @@ module.exports = nativeDescription: "русский язык", englishDescriptio
# profile_for_suffix: ""
profile: "Профиль"
user_not_found: "Пользователь не найден. Пожалуйста, проверьте URL."
gravatar_not_found_mine: "Мы не можем найти профиль, связанный с:"
# gravatar_not_found_email_suffix: "."
gravatar_signup_prefix: "Зарегистрироваться на "
gravatar_signup_suffix: " чтобы настроить профиль"
gravatar_not_found_mine: "Мы не можем найти профиль, связанный с"
gravatar_not_found_email_suffix: "."
gravatar_signup_prefix: "Зарегистрируйтесь на "
gravatar_signup_suffix: ", чтобы настроить профиль."
gravatar_not_found_other: "Нет профиля, связанного с почтой данного пользователя."
gravatar_contact: "Контакты"
gravatar_websites: "Сайты"
@ -160,37 +160,37 @@ module.exports = nativeDescription: "русский язык", englishDescriptio
play_level:
level_load_error: "Уровень не может быть загружен."
done: "Готово"
grid: "Решетка"
grid: "Сетка"
customize_wizard: "Настройки волшебника"
home: "На главную"
guide: "Руководство"
multiplayer: "Мультиплеер"
restart: "Перезапустить"
goals: "Цели"
action_timeline: "Временная линия"
click_to_select: "Выберите персонажа, щелкнув на нем"
action_timeline: "График действий"
click_to_select: "Выберите персонажа, щёлкнув на нём"
reload_title: "Перезагрузить код полностью?"
reload_really: "Вы уверены, что хотите начать уровень сначала?"
reload_confirm: "Перезагрузить всё"
# victory_title_prefix: ""
victory_title_suffix: " Завершено"
victory_sign_up: "Подписаться на обновления"
victory_sign_up_poke: "Хотите получать последние новости по почте? Создайте бесплатный аккаунт, и мы будем держать вас в курсе!"
victory_title_prefix: "Уровень "
victory_title_suffix: " завершён"
victory_sign_up: "Зарегистрироваться"
victory_sign_up_poke: "Хотите сохранить ваш код? Создайте бесплатный аккаунт!"
victory_rate_the_level: "Оцените уровень:"
victory_play_next_level: "Следующий уровень"
victory_go_home: "На главную"
victory_review: "Расскажите нам больше!"
victory_hour_of_code_done: "Вы закончили?"
victory_hour_of_code_done_yes: "Да, я закончил мой Час Кода!"
multiplayer_title: "Настройки Мультиплеера"
multiplayer_link_description: "Дай эту ссылку кому-нибудь, чтоб он присоединился к тебе."
multiplayer_hint_label: "Подсказка:"
multiplayer_hint: " Кликните на ссылку, чтобы выбрать все, затем нажмите Apple-С или Ctrl-C, чтобы скопировать ссылку."
victory_hour_of_code_done_yes: "Да, я закончил мой Час Кода!"
multiplayer_title: "Настройки мультиплеера"
multiplayer_link_description: "Дайте эту ссылку кому-нибудь, чтоб он присоединился к вам."
multiplayer_hint_label: "Подсказка: "
multiplayer_hint: "кликните на ссылку, чтобы выделить её, затем нажмите ⌘-С или Ctrl-C, чтобы скопировать."
multiplayer_coming_soon: "Больше возможностей мультиплеера на подходе!"
guide_title: "Руководство"
tome_minion_spells: "Заклинания ваших миньонов"
tome_read_only_spells: "Заклинания только для чтения"
tome_other_units: "Другие персонажи"
tome_other_units: "Другие юниты"
tome_cast_button_castable: "Читать заклинание"
tome_cast_button_casting: "Заклинание читается"
tome_cast_button_cast: "Заклинание прочитано"
@ -198,7 +198,7 @@ module.exports = nativeDescription: "русский язык", englishDescriptio
tome_select_spell: "Выбрать заклинание"
tome_select_a_thang: "Выбрать кого-нибудь для "
tome_available_spells: "Доступные заклинания"
hud_continue: "Продолжить (нажмите Shift+Space)"
hud_continue: "Продолжить (нажмите Shift+Пробел)"
spell_saved: "Заклинание сохранено"
# admin:
@ -211,45 +211,45 @@ module.exports = nativeDescription: "русский язык", englishDescriptio
# u_title: "User List"
# lg_title: "Latest Games"
# editor:
# main_title: "CodeCombat Editors"
# main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!"
# article_title: "Article Editor"
# article_description: "Write articles that give players overviews of programming concepts which can be used across a variety of levels and campaigns."
# thang_title: "Thang Editor"
# thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics."
# level_title: "Level Editor"
# level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!"
# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, "
# contact_us: "contact us!"
# hipchat_prefix: "You can also find us in our"
# hipchat_url: "HipChat room."
editor:
main_title: "Редакторы CodeCombat"
main_description: "Создавайте ваши собственные уровни, кампании, юнитов и обучающий контент. Мы предоставляем все необходимые инструменты!"
article_title: "Редактор статей"
article_description: "Пишите статьи, дающие представление игрокам о концепциях программирования, которые могут быть использованы в различных уровнях и кампаниях."
thang_title: "Редактор объектов"
thang_description: "Создавайте юнитов, определяйте их логику по умолчанию, графику и звук. В настоящий момент поддерживается импорт только векторной графики Flash."
level_title: "Редактор уровней"
level_description: "Включает в себя инструменты для написания сценариев, загрузки аудио и построения собственной логики для создания всевозможных уровней. Всё, что мы используем сами!"
security_notice: "Многие основные возможности в этих редакторах в настоящее время не включены по умолчанию. Как только мы повысим безопасность этих систем, они станут общедоступными. Если вам хотелось бы использовать эти возможности раньше, "
contact_us: "свяжитесь с нами!"
hipchat_prefix: "Также вы можете найти нас в нашей"
hipchat_url: "комнате HipChat."
# level_some_options: "Some Options?"
# level_tab_thangs: "Thangs"
# level_tab_scripts: "Scripts"
# level_tab_settings: "Settings"
# level_tab_components: "Components"
# level_tab_systems: "Systems"
# level_tab_thangs_title: "Current Thangs"
# level_tab_thangs_conditions: "Starting Conditions"
# level_tab_thangs_add: "Add Thangs"
# level_settings_title: "Settings"
# level_component_tab_title: "Current Components"
# level_component_btn_new: "Create New Component"
# level_systems_tab_title: "Current Systems"
# level_systems_btn_new: "Create New System"
# level_systems_btn_add: "Add System"
# level_components_title: "Back to All Thangs"
# level_components_type: "Type"
# level_component_edit_title: "Edit Component"
# level_system_edit_title: "Edit System"
# create_system_title: "Create New System"
# new_component_title: "Create New Component"
# new_component_field_system: "System"
level_tab_thangs: "Объекты"
level_tab_scripts: "Скрипты"
level_tab_settings: "Настройки"
level_tab_components: "Компоненты"
level_tab_systems: "Системы"
level_tab_thangs_title: "Текущие объекты"
level_tab_thangs_conditions: "Начальные условия"
level_tab_thangs_add: "Добавить объект"
level_settings_title: "Настройки"
level_component_tab_title: "Текущие компоненты"
level_component_btn_new: "Создать новый компонент"
level_systems_tab_title: "Текущие системы"
level_systems_btn_new: "Создать новую систему"
level_systems_btn_add: "Добавить систему"
level_components_title: "Вернуться ко всем объектам"
level_components_type: "Тип"
level_component_edit_title: "Редактировать компонент"
level_system_edit_title: "Редактировать систему"
create_system_title: "Создать новую систему"
new_component_title: "Создать новый компонент"
new_component_field_system: "Система"
# article:
# edit_btn_preview: "Preview"
# edit_article_title: "Edit Article"
article:
edit_btn_preview: "Предпросмотр"
edit_article_title: "Редактирование статьи"
general:
and: "и"
@ -257,37 +257,37 @@ module.exports = nativeDescription: "русский язык", englishDescriptio
# body: "Body"
version: "Версия"
# commit_msg: "Commit Message"
# version_history_for: "Version History for: "
version_history_for: "История версий для: "
results: "Результаты"
description: "Описание"
or: "или"
email: "Email"
message: "Сообщение"
# about:
# who_is_codecombat: "Who is CodeCombat?"
# why_codecombat: "Why CodeCombat?"
# who_description_prefix: "together started CodeCombat in 2013. We also created "
# who_description_suffix: "in 2008, growing it to the #1 web and iOS application for learning to write Chinese and Japanese characters."
# who_description_ending: "Now it's time to teach people to write code."
# 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."
# why_paragraph_2: "Need to learn to code? You don't need lessons. You need to write a lot of code and have a great time doing it."
# why_paragraph_3_prefix: "That's what programming is about. It's gotta be fun. Not fun like"
# why_paragraph_3_italic: "yay a badge"
# why_paragraph_3_center: "but fun like"
# why_paragraph_3_italic_caps: "NO MOM I HAVE TO FINISH THE LEVEL!"
# why_paragraph_3_suffix: "That's why CodeCombat is a multiplayer game, not a gamified lesson course. We won't stop until you can't stop--but this time, that's a good thing."
# 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."
about:
who_is_codecombat: "Кто есть CodeCombat?"
why_codecombat: "Почему CodeCombat?"
who_description_prefix: "вместе начали CodeCombat in 2013. Также мы создали "
who_description_suffix: "в 2008, вывели его на первую строчку среди web и iOS приложений для обучения письму китайскими и японскими иероглифами."
who_description_ending: "Теперь пришло время научить людей написанию кода."
why_paragraph_1: "При создании Skritter, Джордж не знал, как программировать и постоянно расстраивался из-за того, что не мог реализовать свои идеи. После этого он пытался учиться, но уроки были слишком медленными. Его сосед по дому, желая переквалифицироваться и прекратить преподавать, пробовал Codecademy, но \"наскучивало.\" Каждую неделю другой друг начинал Codecademy, затем бросал. Мы поняли, что это была та же проблема, которую мы решали со Skritter: люди получают навык через медленные, интенсивные уроки, когда то, что им нужно - быстрая, обширная практика. Мы знаем, как это исправить."
why_paragraph_2: "Нужно научиться программировать? Вам не нужны уроки. Вам нужно написать много кода и прекрасно провести время, делая это."
why_paragraph_3_prefix: "Вот, о чём программирование. Это должно быть весело. Не вроде"
why_paragraph_3_italic: "вау, значок"
why_paragraph_3_center: ", а"
why_paragraph_3_italic_caps: "НЕТ, МАМ, Я ДОЛЖЕН ПРОЙТИ УРОВЕНЬ!"
why_paragraph_3_suffix: "Вот, почему CodeCombat - мультиплеерная игра, а не курс уроков в игровой форме. Мы не остановимся, пока вы не сможете остановиться--в данном случае, это хорошо."
why_paragraph_4: "Если вы собираетесь увлечься какой-нибудь игрой, увлекитесь этой и станьте одним из волшебников века информационных технологий."
why_ending: "Эй, это бесплатно. "
why_ending_url: "Начни волшебство сейчас!"
george_description: "Генеральный директор, бизнес-парень, веб-дизайнер, геймдизайнер, и чемпион начинающих программистов во всём мире."
scott_description: "Экстраординарный программист, архитектор программного обеспечения, кухонный волшебник, и мастер финансов. Скотт является разумным."
nick_description: "Маг программирования, эксцентрично мотивированный волшебник, и экспериментатор вверх ногами. Ник может делать всё и хочет построить CodeCombat."
jeremy_description: "Маг клиентской поддержки, юзабилити-тестер, и организатор сообщества; вы наверняка уже говорили с Джереми."
michael_description: "Программист, сисадмин и непризнанный технический гений, Михаэль является лицом, поддерживающим наши серверы онлайн."
# legal:
# page_title: "Legal"
legal:
page_title: "Юридическая информация"
# opensource_intro: "CodeCombat is free to play and completely open source."
# opensource_description_prefix: "Check out "
# github_url: "our GitHub"
@ -347,9 +347,9 @@ module.exports = nativeDescription: "русский язык", englishDescriptio
# nutshell_description: "Any resources we provide in the Level Editor are free to use as you like for creating Levels. But we reserve the right to restrict distribution of the Levels themselves (that are created on codecombat.com) so that they may be charged for in the future, if that's what ends up happening."
# canonical: "The English version of this document is the definitive, canonical version. If there are any discrepencies between translations, the English document takes precedence."
# contribute:
# page_title: "Contributing"
# character_classes_title: "Character Classes"
contribute:
page_title: "Сотрудничество"
character_classes_title: "Классы персонажей"
# introduction_desc_intro: "We have high hopes for CodeCombat."
# introduction_desc_pref: "We want to be where programmers of all stripes come to learn and play together, introduce others to the wonderful world of coding, and reflect the best parts of the community. We can't and don't want to do that alone; what makes projects like GitHub, Stack Overflow and Linux great are the people who use them and build on them. To that end, "
# introduction_desc_github_url: "CodeCombat is totally open source"
@ -446,8 +446,8 @@ module.exports = nativeDescription: "русский язык", englishDescriptio
archmage_title_description: "(программист)"
artisan_title: "Ремесленник"
artisan_title_description: "(строитель уровней)"
adventurer_title: "Авантюрист"
adventurer_title_description: "(Тестировщик уровней)"
adventurer_title: "Искатель приключений"
adventurer_title_description: "(тестировщик уровней)"
scribe_title: "Писарь"
scribe_title_description: "(редактор статей)"
diplomat_title: "Дипломат"

View file

@ -4,13 +4,13 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
saving: "保存中……"
sending: "发送中……"
cancel: "退出"
# save: "Save"
save: "保存"
delay_1_sec: "1 秒"
delay_3_sec: "3 秒"
delay_5_sec: "5 秒"
manual: "手动"
# fork: "Fork"
play: ""
fork: "派生"
play: "开始"
modal:
close: "关闭"
@ -33,13 +33,13 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
twitter_follow: "关注"
employers: "雇佣我们"
# versions:
# save_version_title: "Save New Version"
versions:
save_version_title: "保存新版本"
# new_major_version: "New Major Version"
# cla_prefix: "To save changes, first you must agree to our"
# cla_url: "CLA"
# cla_suffix: "."
# cla_agree: "I AGREE"
cla_agree: "我同意"
login:
sign_up: "注册"
@ -101,17 +101,17 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
learn_more: "了解更多有关成为翻译人员的说明"
subscribe_as_diplomat: "提交翻译人员申请"
# wizard_settings:
# title: "Wizard Settings"
# customize_avatar: "Customize Your Avatar"
# clothes: "Clothes"
# trim: "Trim"
# cloud: "Cloud"
# spell: "Spell"
# boots: "Boots"
# hue: "Hue"
# saturation: "Saturation"
# lightness: "Lightness"
wizard_settings:
title: "设置向导"
customize_avatar: "设置你的头像"
clothes: "衣服"
trim: "条纹"
cloud: ""
spell: "法力球"
boots: "鞋子"
hue: "色彩"
saturation: "饱和"
lightness: "亮度"
account_settings:
title: "账户设置"
@ -199,7 +199,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
tome_select_a_thang: "选择人物来 "
tome_available_spells: "可用的法术"
hud_continue: "继续(按 shift-空格)"
# spell_saved: "Spell Saved"
spell_saved: "输入已保存"
# admin:
# av_title: "Admin Views"
@ -211,45 +211,45 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
# u_title: "User List"
# lg_title: "Latest Games"
# editor:
# main_title: "CodeCombat Editors"
# main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!"
# article_title: "Article Editor"
# article_description: "Write articles that give players overviews of programming concepts which can be used across a variety of levels and campaigns."
# thang_title: "Thang Editor"
# thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics."
# level_title: "Level Editor"
# level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!"
# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, "
# contact_us: "contact us!"
# hipchat_prefix: "You can also find us in our"
# hipchat_url: "HipChat room."
editor:
main_title: "CodeCombat 编辑器"
main_description: "建立自己的关卡, 战役, 单位 和教育内容。我们提供所有你需要的工具!"
article_title: "提示编辑器"
article_description: "编写提示,让玩家可以使用编程概念,来通过各种的关卡和战役。"
thang_title: "物体编辑器"
thang_description: "创建单位并定义单位的逻辑、图形和音频。目前只支持导入Flash导出的矢量图形。"
level_title: "关卡编辑器"
level_description: "所有用来创造所有难度的关卡的工具,包括脚本、上传音频和构建自定义逻辑。"
security_notice: "编辑器的许多主要功能并不是目前默认启动的。当我们改善完这些系统的安全性的时候,他们将会变成常用的。如果你想要马上使用这些功能,"
contact_us: "联系我们!"
hipchat_prefix: "你也可以在这里找到我们"
hipchat_url: "HipChat room."
# level_some_options: "Some Options?"
# level_tab_thangs: "Thangs"
# level_tab_scripts: "Scripts"
# level_tab_settings: "Settings"
# level_tab_components: "Components"
# level_tab_systems: "Systems"
# level_tab_thangs_title: "Current Thangs"
# level_tab_thangs_conditions: "Starting Conditions"
# level_tab_thangs_add: "Add Thangs"
# level_settings_title: "Settings"
# level_component_tab_title: "Current Components"
# level_component_btn_new: "Create New Component"
# level_systems_tab_title: "Current Systems"
# level_systems_btn_new: "Create New System"
# level_systems_btn_add: "Add System"
# level_components_title: "Back to All Thangs"
# level_components_type: "Type"
# level_component_edit_title: "Edit Component"
# level_system_edit_title: "Edit System"
# create_system_title: "Create New System"
# new_component_title: "Create New Component"
# new_component_field_system: "System"
level_tab_thangs: "物体"
level_tab_scripts: "脚本"
level_tab_settings: "设定"
level_tab_components: "组件"
level_tab_systems: "系统"
level_tab_thangs_title: "目前所有物体"
level_tab_thangs_conditions: "启动条件"
level_tab_thangs_add: "增加物体"
level_settings_title: "设置"
level_component_tab_title: "目前所有组件"
level_component_btn_new: "创建新的组件"
level_systems_tab_title: "目前所有系统"
level_systems_btn_new: "创建新的系统"
level_systems_btn_add: "增加系统"
level_components_title: "返回到所以物体主页"
level_components_type: "类型"
level_component_edit_title: "编辑组件"
level_system_edit_title: "编辑系统"
create_system_title: "创建新的系统"
new_component_title: "创建新的组件"
new_component_field_system: "系统"
# article:
# edit_btn_preview: "Preview"
# edit_article_title: "Edit Article"
article:
edit_btn_preview: "预览"
edit_article_title: "编辑文章"
# general:
# and: "and"

View file

@ -131,3 +131,22 @@
top: 0
height: 100%
width: 2%
.footer
@media screen and (min-aspect-ratio: 17/10)
display: none
&:not(:hover)
@include opacity(0.6)
.hour-of-code-explanation
margin-top: 5px
color: white
font-size: 12px
&:not(:hover)
@include opacity(0.75)
a
color: white
text-decoration: underline

View file

@ -88,6 +88,13 @@
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-options-button
width: 20%
width: -webkit-calc(40px)

View file

@ -51,7 +51,7 @@
line-height: 20px
overflow: visible
&.user-code-problem
&.user-code-problem.spell-cast
@include editor-height(40px)
&.disabled

View file

@ -13,9 +13,9 @@
$childMargin: 2px
$childSize: $height - 2 * $childMargin
height: $height
width: 70%
width: -webkit-calc(100% - 170px)
width: calc(100% - 170px)
width: 80%
width: -webkit-calc(100% - 100px)
width: calc(100% - 100px)
padding: 0px 8px
background: transparent url(/images/level/code_editor_tab_background.png) no-repeat
background-size: 100% 100%
@ -25,7 +25,7 @@
background: linear-gradient(to bottom, rgba(0,0,0,0.2) 0%,rgba(0,0,0,0.2) 100%), url(/images/level/code_editor_tab_background.png)
background-size: 100% 100%
.spell-list-button, .thang-avatar-wrapper, .reload-code
.spell-list-button, .thang-avatar-wrapper, .reload-code, .beautify-code
width: $childSize
height: $childSize
margin: $childMargin
@ -38,6 +38,9 @@
float: right
display: none
.beautify-code
float: right
.btn.btn-small
background: transparent
padding: 0
@ -46,7 +49,7 @@
border-color: transparent
@include box-shadow(none)
.icon-chevron-down, .icon-repeat
.icon-chevron-down, .icon-repeat, .icon-magnet
margin-top: 7px
.thang-avatar-wrapper

View file

@ -9,16 +9,18 @@
border: 1px solid transparent
cursor: pointer
@include user-select(all)
::selection
background: transparent
&:hover
border: 1px solid #BFF
border: 1px solid #000000
&.pinned
background-color: darken(#BFF, 20%)
background-color: darken(#FFFFFF, 25%)
// Pulling these colors from the most relevant textmate-theme classes
&.function
color: #0000A2
color: #0066FF
&.object
color: rgb(6, 150, 14)
&.string

View file

@ -3,6 +3,7 @@
#tome-view
height: 100%
margin-bottom: -20px
> .popover
// Only those popovers which are our direct children (spell documentation)

View file

@ -8,7 +8,7 @@ canvas#tinting-display(width=200, height=200).img-rounded
span(data-i18n='wizard_settings.' + group.dasherized)= group.humanized
div.sliders
div.slider-cell
label(for=group.humanized+"_hue", data-i18n="wizard_settigs.hue") Hue
label(for=group.humanized+"_hue", data-i18n="wizard_settings.hue") Hue
.selector(id=group.humanized+"_hue", name=group.name+'.hue', data-key='hue')
div.slider-cell
label(for=group.humanized+"_saturation", data-i18n="wizard_settings.saturation") Saturation

View file

@ -43,7 +43,7 @@ block content
unless me.attributes.anonymous
hr
button.btn.btn-warning.btn-lg.highlight#simulate-button(style="margin-bottom:10px;") Simulate Games!
p(id="simulationStatusText", style="display:inline; margin-left:10px;")
p(id="simulation-status-text", style="display:inline; margin-left:10px;")
if simulationStatus
| #{simulationStatus}
else

View file

@ -26,4 +26,12 @@
.footer
.content
p(class='footer-link-text')
a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="nav.contact") Contact
a(title='Send CodeCombat a message', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="nav.contact") Contact
if explainHourOfCode
// Does not show up unless lang is en-US.
div.hour-of-code-explanation
| The 'Hour of Code' is a nationwide initiative by
a(href="http://csedweek.org") Computer Science Education Week
| and
a(href="http://code.org") Code.org
| to introduce millions of students to one hour of computer science and computer programming.

View file

@ -8,6 +8,9 @@ h4.title #{worldName}
button.btn.btn-xs.btn-inverse.banner#docs-button(title="Show level instructions", data-i18n="play_level.guide") Guide
button.btn.btn-xs.btn-inverse.banner#multiplayer-button(title="Multiplayer", data-i18n="play_level.multiplayer") Multiplayer
if ladderGame
button.btn.btn-xs.btn-inverse.banner#multiplayer-button(title="Leaderboard", data-i18n="play_level.leaderboard") Leaderboard
else
button.btn.btn-xs.btn-inverse.banner#multiplayer-button(title="Multiplayer", data-i18n="play_level.multiplayer") Multiplayer
button.btn.btn-xs.btn-inverse.banner#restart-button(title="Reload all custom code to reset level", data-i18n="play_level.restart") Restart

View file

@ -5,25 +5,26 @@
h3(data-i18n="play_level.multiplayer_title") Multiplayer Settings
.modal-body
.form
.form-group.checkbox
label(for="multiplayer")
input#multiplayer(name="multiplayer", type="checkbox", checked=multiplayer)
| Multiplayer
span.help-block Enable others to join your game.
hr
div#link-area
p(data-i18n="play_level.multiplayer_link_description") Give this link to anyone to have them join you.
textarea.well#multiplayer-join-link(readonly=true)= joinLink
p
strong(data-i18n="play_level.multiplayer_hint_label") Hint:
span(data-i18n="play_level.multiplayer_hint") Click the link to select all, then press ⌘-C or Ctrl-C to copy the link.
if !ladderGame
.form
.form-group.checkbox
label(for="multiplayer")
input#multiplayer(name="multiplayer", type="checkbox", checked=multiplayer)
| Multiplayer
span.help-block Enable others to join your game.
hr
p(data-i18n="play_level.multiplayer_coming_soon") More multiplayer features to come!
div#link-area
p(data-i18n="play_level.multiplayer_link_description") Give this link to anyone to have them join you.
textarea.well#multiplayer-join-link(readonly=true)= joinLink
p
strong(data-i18n="play_level.multiplayer_hint_label") Hint:
span(data-i18n="play_level.multiplayer_hint") Click the link to select all, then press ⌘-C or Ctrl-C to copy the link.
p(data-i18n="play_level.multiplayer_coming_soon") More multiplayer features to come!
if ladderGame
if me.get('anonymous')

View file

@ -7,4 +7,7 @@ code #{spell.name}(#{parameters})
.btn.btn-small.reload-code(title="Reload original code for " + spell.name)
i.icon-repeat
.btn.btn-small.beautify-code(title="Ctrl+Shift+B: Beautify code for " + spell.name)
i.icon-magnet
.clearfix

View file

@ -26,11 +26,12 @@ module.exports = class SettingsView extends View
refreshPicturePane: =>
h = $(@template(@getRenderData()))
new_pane = $('#picture-pane', h)
old_pane = $('#picture-pane')
active = old_pane.hasClass('active')
old_pane.replaceWith(new_pane)
new_pane.addClass('active') if active
newPane = $('#picture-pane', h)
oldPane = $('#picture-pane')
active = oldPane.hasClass('active')
oldPane.replaceWith(newPane)
newPane.i18n()
newPane.addClass('active') if active
afterRender: ->
super()

View file

@ -15,13 +15,9 @@ filterKeyboardEvents = (allowedEvents, func) ->
module.exports = class RootView extends CocoView
events:
"click #logout-button": "logoutAccount"
'change .language-dropdown': 'showDiplomatSuggestionModal'
'change .language-dropdown': 'onLanguageChanged'
'click .toggle-fullscreen': 'toggleFullscreen'
afterRender: ->
super()
@buildLanguages()
logoutAccount: ->
logoutUser($('#login-email').val())
@ -41,11 +37,15 @@ module.exports = class RootView extends CocoView
hash = location.hash
location.hash = ''
location.hash = hash
@buildLanguages()
# TODO: automate tabs to put in hashes and navigate to them here
buildLanguages: ->
$select = @$el.find(".language-dropdown").empty()
if $select.hasClass("fancified")
$select.parent().find('.options,.trigger').remove()
$select.unwrap().removeClass("fancified")
preferred = me.lang()
codes = _.keys(locale)
genericCodes = _.filter codes, (code) ->
@ -56,11 +56,12 @@ module.exports = class RootView extends CocoView
$("<option></option>").val(code).text(localeInfo.nativeDescription))
$select.val(preferred).fancySelect()
showDiplomatSuggestionModal: ->
onLanguageChanged: ->
newLang = $(".language-dropdown").val()
$.i18n.setLng(newLang, {})
@saveLanguage(newLang)
@render()
@buildLanguages()
unless newLang.split('-')[0] is "en"
@openModalView(application.router.getView("modal/diplomat_suggestion", "_modal"))

View file

@ -32,6 +32,7 @@ module.exports = class ControlBarView extends View
@session = options.session
@level = options.level
@playableTeams = options.playableTeams
@ladderGame = options.ladderGame
super options
setBus: (@bus) ->
@ -50,6 +51,7 @@ module.exports = class ControlBarView extends View
super context
context.worldName = @worldName
context.multiplayerEnabled = @session.get('multiplayer')
context.ladderGame = @ladderGame
context
showGuideModal: ->
@ -57,7 +59,7 @@ module.exports = class ControlBarView extends View
@openModalView(new DocsModal(options))
showMultiplayerModal: ->
@openModalView(new MultiplayerModal(session: @session, playableTeams: @playableTeams, level: @level))
@openModalView(new MultiplayerModal(session: @session, playableTeams: @playableTeams, level: @level, ladderGame: @ladderGame))
showRestartModal: ->
@openModalView(new ReloadModal())

View file

@ -17,6 +17,8 @@ module.exports = class MultiplayerModal extends View
@level = options.level
@session.on 'change:multiplayer', @updateLinkSection, @
@playableTeams = options.playableTeams
@ladderGame = options.ladderGame
console.log 'ladder game is', @ladderGame
getRenderData: ->
c = super()
@ -27,7 +29,8 @@ module.exports = class MultiplayerModal extends View
c.team = @session.get 'team'
c.levelSlug = @level?.get('slug')
c.playableTeams = @playableTeams
c.ladderGame = @level?.get('name') is 'Project DotA' and not me.get('isAnonymous')
c.ladderGame = @ladderGame
# For now, ladderGame will disallow multiplayer, because session code combining doesn't play nice yet.
c
afterRender: ->

View file

@ -17,7 +17,7 @@ module.exports = class CastButtonView extends View
@spells = options.spells
@levelID = options.levelID
isMac = navigator.platform.toUpperCase().indexOf('MAC') isnt -1
@castShortcut = ""
@castShortcut = ""
@castShortcutVerbose = "Shift+Enter"
getRenderData: (context={}) ->
@ -35,7 +35,7 @@ module.exports = class CastButtonView extends View
# TODO: use a User setting instead of localStorage
delay = localStorage.getItem 'autocastDelay'
delay ?= 5000
if @levelID is 'project-dota'
if @levelID in ['project-dota', 'brawlwood', 'ladder-tutorial']
delay = 90019001
@setAutocastDelay delay
@ -57,16 +57,17 @@ module.exports = class CastButtonView extends View
onCastSpells: (e) ->
@casting = true
Backbone.Mediator.publish 'play-sound', trigger: 'cast', volume: 0.25
Backbone.Mediator.publish 'play-sound', trigger: 'cast', volume: 0.5
@updateCastButton()
@onWorldLoadProgressChanged progress: 0
onWorldLoadProgressChanged: (e) ->
overlay = @castButtonGroup.find '.button-progress-overlay'
overlay.css 'width', e.progress * @castButtonGroup.width() + 1
overlay.css 'width', e.progress * @castButton.outerWidth() + 1
onNewWorld: (e) ->
@casting = false
Backbone.Mediator.publish 'play-sound', trigger: 'cast-end', volume: 0.5
@updateCastButton()
updateCastButton: ->

View file

@ -103,6 +103,7 @@ module.exports = class Spell
if not (me.team in @permissions.readwrite) or window.currentView?.sessionID is "52bfb88099264e565d001349" # temp fix for debugger explosion bug
#console.log "Turning off includeFlow for", @spellKey
aetherOptions.includeFlow = false
#console.log "creating aether with options", aetherOptions
aether = new Aether aetherOptions
aether

View file

@ -21,6 +21,10 @@ module.exports = class DebugView extends View
@ace = options.ace
@thang = options.thang
@variableStates = {}
@globals = {Math: Math, _: _} # ... add more as documented
for className, klass of serializedClasses
@globals[className] = klass
@onMouseMove = _.throttle @onMouseMove, 25
afterRender: ->
super()
@ -30,10 +34,11 @@ module.exports = class DebugView extends View
@update()
onMouseMove: (e) =>
return if @destroyed
pos = e.getDocumentPosition()
endOfDoc = pos.row is @ace.getSession().getDocument().getLength() - 1
it = new TokenIterator e.editor.session, pos.row, pos.column
isIdentifier = (t) -> t and (t.type is 'identifier' or t.value is 'this')
isIdentifier = (t) => t and (t.type is 'identifier' or t.value is 'this' or @globals[t.value])
while it.getCurrentTokenRow() is pos.row and not isIdentifier(token = it.getCurrentToken())
it.stepBackward()
break unless token
@ -52,7 +57,7 @@ module.exports = class DebugView extends View
token = prev
start = it.getCurrentTokenColumn()
chain.unshift token.value
if token and (token.value of @variableStates or token.value is "this")
if token and (token.value of @variableStates or token.value is "this" or @globals[token.value])
@variableChain = chain
offsetX = e.domEvent.offsetX ? e.clientX - $(e.domEvent.target).offset().left
offsetY = e.domEvent.offsetY ? e.clientY - $(e.domEvent.target).offset().top
@ -76,6 +81,10 @@ module.exports = class DebugView extends View
@$el.show().css(@pos)
else
@$el.hide()
if @variableChain?.length is 2
Backbone.Mediator.publish 'tome:spell-debug-property-hovered', property: @variableChain[1], owner: @variableChain[0]
else
Backbone.Mediator.publish 'tome:spell-debug-property-hovered', property: null
@updateMarker()
updateMarker: ->
@ -124,8 +133,11 @@ module.exports = class DebugView extends View
for prop, i in chain
if prop is "this"
value = @thang
else if i is 0
value = @variableStates[prop]
if typeof value is "undefined" then value = @globals[prop]
else
value = (if i is 0 then @variableStates else value)[prop]
value = value[prop]
keys.push prop
break unless value
if theClass = serializedClasses[value.CN]

View file

@ -17,6 +17,7 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView
events:
'click .spell-list-button': 'onDropdownClick'
'click .reload-code': 'onCodeReload'
'click .beautify-code': 'onBeautifyClick'
constructor: (options) ->
super options
@ -105,6 +106,9 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView
onCodeReload: ->
Backbone.Mediator.publish "tome:reload-code", spell: @spell
onBeautifyClick: ->
Backbone.Mediator.publish "spell-beautify", spell: @spell
updateReloadButton: ->
changed = @spell.hasChanged null, @spell.getSource()
@$el.find('.reload-code').css('display', if changed then 'inline-block' else 'none')

View file

@ -66,6 +66,7 @@ module.exports = class SpellPaletteEntryView extends View
'surface:frame-changed': "onFrameChanged"
'tome:palette-hovered': "onPaletteHovered"
'tome:palette-pin-toggled': "onPalettePinToggled"
'tome:spell-debug-property-hovered': 'onSpellDebugPropertyHovered'
events:
'mouseenter': 'onMouseEnter'
@ -83,7 +84,11 @@ module.exports = class SpellPaletteEntryView extends View
@doc.shortName = @doc.shorterName = @doc.title = @doc.name
else
@doc.owner ?= 'this'
suffix = if @doc.type is 'function' then '()' else ''
suffix = ''
if @doc.type is 'function'
argNames = (arg.name for arg in @doc.args ? []).join(', ')
argNames = '...' if argNames.length > 6
suffix = "(#{argNames})"
@doc.shortName = "#{@doc.owner}.#{@doc.name}#{suffix};"
if @doc.owner is 'this' or options.tabbify
@doc.shorterName = "#{@doc.name}#{suffix}"
@ -184,6 +189,16 @@ module.exports = class SpellPaletteEntryView extends View
return if e.entry is @
@otherPopoverPinned = e.pinned
onSpellDebugPropertyHovered: (e) ->
matched = e.property is @doc.name and e.owner is @doc.owner
if matched and not @debugHovered
@debugHovered = true
@togglePinned() unless @popoverPinned
else if @debugHovered and not matched
@debugHovered = false
@togglePinned() if @popoverPinned
null
destroy: ->
$('.popover.pinned').remove() if @popoverPinned # @$el.popover('destroy') doesn't work
@togglePinned() if @popoverPinned

View file

@ -28,6 +28,7 @@ module.exports = class SpellView extends View
'modal-closed': 'focus'
'focus-editor': 'focus'
'tome:spell-statement-index-updated': 'onStatementIndexUpdated'
'spell-beautify': 'onSpellBeautify'
events:
'mouseout': 'onMouseOut'
@ -46,7 +47,7 @@ module.exports = class SpellView extends View
@createACE()
@createACEShortcuts()
@fillACE()
if @session.get 'multiplayer'
if @session.get('multiplayer')
@createFirepad()
else
# needs to happen after the code generating this view is complete
@ -123,13 +124,17 @@ module.exports = class SpellView extends View
name: 'spell-step-backward'
bindKey: {win: 'Ctrl-Alt-[', mac: 'Command-Alt-[|Ctrl-Alt-]'}
exec: -> Backbone.Mediator.publish 'spell-step-backward'
addCommand
name: 'spell-beautify'
bindKey: {win: 'Ctrl-Shift-B', mac: 'Command-Shift-B|Ctrl-Shift-B'}
exec: -> Backbone.Mediator.publish 'spell-beautify'
fillACE: ->
@ace.setValue @spell.source
@ace.clearSelection()
onMultiplayerChanged: ->
if @session.get 'multiplayer'
if @session.get('multiplayer')
@createFirepad()
else
@firepad?.dispose()
@ -331,7 +336,9 @@ module.exports = class SpellView extends View
#console.log ' and we could do the visualization', aether.visualization unless _.isEmpty aether.visualization
# Could use the user-code-problem style... or we could leave that to other places.
@ace[if @problems.length then 'setStyle' else 'unsetStyle'] 'user-code-problem'
@ace[if isCast then 'setStyle' else 'unsetStyle'] 'spell-cast'
Backbone.Mediator.publish 'tome:problems-updated', spell: @spell, problems: @problems, isCast: isCast
@ace.resize()
# Autocast:
# Goes immediately if the code is a) changed and b) complete/valid and c) the cursor is at beginning or end of a line
@ -345,7 +352,7 @@ module.exports = class SpellView extends View
#@recompileValid = not aether.getAllProblems().length
valid = not aether.getAllProblems().length
cursorPosition = @ace.getCursorPosition()
currentLine = @aceDoc.$lines[cursorPosition.row].replace(/[ \t]*\/\/[^"']*/g, '').trimRight() # trim // unless inside "
currentLine = _.string.rtrim(@aceDoc.$lines[cursorPosition.row].replace(/[ \t]*\/\/[^"']*/g, '')) # trim // unless inside "
endOfLine = cursorPosition.column >= currentLine.length # just typed a semicolon or brace, for example
beginningOfLine = not currentLine.substr(0, cursorPosition.column).trim().length # uncommenting code, for example
#console.log "finished?", valid, endOfLine, beginningOfLine, cursorPosition, currentLine.length, aether, new Date() - 0, currentLine
@ -445,11 +452,11 @@ module.exports = class SpellView extends View
markerRange.end.detach()
@aceSession.removeMarker markerRange.id
@markerRanges = []
@debugView.setVariableStates {}
@aceSession.removeGutterDecoration row, 'executing' for row in [0 ... @aceSession.getLength()]
$(@ace.container).find('.ace_gutter-cell.executing').removeClass('executing')
if not executed.length or (@spell.name is "plan" and @spellThang.castAether.metrics.statementsExecuted < 20)
@toolbarView?.toggleFlow false
@debugView.setVariableStates {}
return
lastExecuted = _.last executed
@toolbarView?.toggleFlow true
@ -457,6 +464,7 @@ module.exports = class SpellView extends View
@toolbarView?.setCallState states[currentCallIndex], statementIndex, currentCallIndex, @spellThang.castAether.metrics
marked = {}
lastExecuted = lastExecuted[0 .. @toolbarView.statementIndex] if @toolbarView?.statementIndex?
gotVariableStates = false
for state, i in lastExecuted
[start, end] = state.range
clazz = if i is lastExecuted.length - 1 then 'executing' else 'executed'
@ -466,6 +474,7 @@ module.exports = class SpellView extends View
markerType = "fullLine"
else
@debugView.setVariableStates state.variables
gotVariableStates = true
markerType = "text"
markerRange = new Range start.row, start.col, end.row, end.col
markerRange.start = @aceDoc.createAnchor markerRange.start
@ -473,6 +482,7 @@ module.exports = class SpellView extends View
markerRange.id = @aceSession.addMarker markerRange, clazz, markerType
@markerRanges.push markerRange
@aceSession.addGutterDecoration start.row, clazz if clazz is 'executing'
@debugView.setVariableStates {} unless gotVariableStates
null
highlightComments: ->
@ -513,6 +523,12 @@ module.exports = class SpellView extends View
filters.revertImage background if @controlsEnabled
filters.darkenImage background, 0.8 unless @controlsEnabled
onSpellBeautify: (e) ->
return unless @spellThang and (@ace.isFocused() or e.spell is @spell)
ugly = @getSource()
pretty = @spellThang.aether.beautify ugly
@ace.setValue pretty
dismiss: ->
@recompile() if @spell.hasChangedSignificantly @getSource()

View file

@ -21,6 +21,7 @@ module.exports = class ThangListEntryView extends View
'surface:frame-changed': "onFrameChanged"
'level-set-letterbox': 'onSetLetterbox'
'tome:thang-list-entry-popover-shown': 'onThangListEntryPopoverShown'
'surface:coordinates-shown': 'onSurfaceCoordinatesShown'
events:
'click': 'onClick'
@ -86,38 +87,47 @@ module.exports = class ThangListEntryView extends View
onMouseEnter: (e) ->
return unless @controlsEnabled and @spells.length
@showSpells()
@clearTimeouts()
@showSpellsTimeout = _.delay @showSpells, 100
onMouseLeave: (e) ->
return unless @controlsEnabled and @spells.length
clearTimeout @hideSpellsTimeout if @hideSpellsTimeout
@clearTimeouts()
@hideSpellsTimeout = _.delay @hideSpells, 100
clearTimeouts: ->
clearTimeout @showSpellsTimeout if @showSpellsTimeout
clearTimeout @hideSpellsTimeout if @hideSpellsTimeout
@showSpellsTimeout = @hideSpellsTimeout = null
onThangListEntryPopoverShown: (e) ->
# I couldn't figure out how to get the mouseenter / mouseleave to always work, so this is a fallback
# to hide our popover is another Thang's popover gets shown.
return if e.entry is @
@hideSpells()
onSurfaceCoordinatesShown: (e) ->
# Definitely aren't hovering over this.
@hideSpells()
showSpells: =>
@clearTimeouts()
@sortSpells()
@$el.data('bs.popover').options.content = @getSpellListHTML()
@$el.popover('setContent').popover('show')
@$el.parent().parent().parent().i18n()
clearTimeout @hideSpellsTimeout if @hideSpellsTimeout
@hideSpellsTimeout = null
@popover = @$el.parent().parent().parent().find('.popover')
@popover.off 'mouseenter mouseleave'
@popover.mouseenter (e) => @onMouseEnter()
@popover.mouseleave (e) => @onMouseLeave()
@popover.mouseenter (e) => @showSpells() if @controlsEnabled
@popover.mouseleave (e) => @hideSpells()
thangID = @thang.id
@popover.find('code').click (e) ->
Backbone.Mediator.publish "level-select-sprite", thangID: thangID, spellName: $(@).data 'spell-name'
Backbone.Mediator.publish 'tome:thang-list-entry-popover-shown', entry: @
hideSpells: =>
@clearTimeouts()
@$el.popover('hide')
@hideSpellsTimeout = null
getSpellListHTML: ->
spellsPopoverTemplate {spells: @spells}
@ -129,13 +139,16 @@ module.exports = class ThangListEntryView extends View
onSetLetterbox: (e) ->
if e.on then @reasonsToBeDisabled.letterbox = true else delete @reasonsToBeDisabled.letterbox
@updateControls()
onDisableControls: (e) ->
return if e.controls and not ('surface' in e.controls) # disable selection?
@reasonsToBeDisabled.controls = true
@updateControls()
onEnableControls: (e) ->
delete @reasonsToBeDisabled.controls
@updateControls()
updateControls: ->
enabled = _.keys(@reasonsToBeDisabled).length is 0
return if enabled is @controlsEnabled

View file

@ -151,9 +151,15 @@ module.exports = class TomeView extends View
@cast()
cast: ->
for spellKey, spell of @spells
for thangID, spellThang of spell.thangs
spellThang.aether.options.includeFlow = spellThang.aether.originalOptions.includeFlow = spellThang is @spellView?.spellThang
if @options.levelID is 'project-dota'
# For performance reasons, only includeFlow on the currently Thang.
for spellKey, spell of @spells
for thangID, spellThang of spell.thangs
hadFlow = Boolean spellThang.aether.options.includeFlow
willHaveFlow = spellThang is @spellView?.spellThang
spellThang.aether.options.includeFlow = spellThang.aether.originalOptions.includeFlow = willHaveFlow
spellThang.aether.transpile spell.source unless hadFlow is willHaveFlow
#console.log "set includeFlow to", spellThang.aether.options.includeFlow, "for", thangID, "of", spellKey
Backbone.Mediator.publish 'tome:cast-spells', spells: @spells
onToggleSpellList: (e) ->

View file

@ -116,6 +116,10 @@ module.exports = class PlayLevelView extends View
getRenderData: ->
c = super()
c.world = @world
if me.get('hourOfCode') and me.lang() is 'en-US'
# Show the Hour of Code footer explanation until it's been more than a day
elapsed = (new Date() - new Date(me.get('dateCreated')))
c.explainHourOfCode = elapsed < 86400 * 1000
c
afterRender: ->
@ -143,6 +147,9 @@ module.exports = class PlayLevelView extends View
c = opponentCode[spell]
if c then myCode[spell] = c else delete myCode[spell]
@session.set('code', myCode)
if @session.get('multiplayer') and otherSession?
# For now, ladderGame will disallow multiplayer, because session code combining doesn't play nice yet.
@session.set 'multiplayer', false
@levelLoader.destroy()
@levelLoader = null
@ -153,13 +160,16 @@ module.exports = class PlayLevelView extends View
@initSurface()
@initGoalManager()
@initScriptManager()
@insertSubviews()
@insertSubviews ladderGame: otherSession?
@initVolume()
@session.on 'change:multiplayer', @onMultiplayerChanged, @
@originalSessionState = _.cloneDeep(@session.get('state'))
@register()
@controlBar.setBus(@bus)
@surface.showLevel()
if otherSession
# TODO: colorize name and cloud by team, colorize wizard by user's color config
@surface.createOpponentWizard id: otherSession.get('creator'), name: otherSession.get('creatorName'), team: otherSession.get('team')
onSupermodelLoadedOne: =>
@modelsLoaded ?= 0
@ -175,15 +185,15 @@ module.exports = class PlayLevelView extends View
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.fillText("Loaded #{@modelsLoaded} thingies",50,50)
insertSubviews: ->
@insertSubView @tome = new TomeView levelID: @levelID, session: @session, thangs: @world.thangs, supermodel: @supermodel
insertSubviews: (subviewOptions) ->
@insertSubView @tome = new TomeView levelID: @levelID, session: @session, thangs: @world.thangs, supermodel: @supermodel, ladderGame: subviewOptions.ladderGame
@insertSubView new PlaybackView {}
@insertSubView new GoalsView {}
@insertSubView new GoldView {}
@insertSubView new HUDView {}
@insertSubView new ChatView levelID: @levelID, sessionID: @session.id, session: @session
worldName = @level.get('i18n')?[me.lang()]?.name ? @level.get('name')
@controlBar = @insertSubView new ControlBarView {worldName: worldName, session: @session, level: @level, supermodel: @supermodel, playableTeams: @world.playableTeams}
@controlBar = @insertSubView new ControlBarView {worldName: worldName, session: @session, level: @level, supermodel: @supermodel, playableTeams: @world.playableTeams, ladderGame: subviewOptions.ladderGame}
#Backbone.Mediator.publish('level-set-debug', debug: true) if me.displayName() is 'Nick!'
afterInsert: ->

View file

@ -23,6 +23,25 @@ connectToScoringQueue = ->
if error? then throw new Error "There was an error registering the scoring queue: #{error}"
scoringTaskQueue = data
log.info "Connected to scoring task queue!"
module.exports.addPairwiseTaskToQueue = (req, res) ->
taskPair = req.body.sessions
#unless isUserAdmin req then return errors.forbidden res, "You do not have the permissions to submit that game to the leaderboard"
#fetch both sessions
LevelSession.findOne(_id:taskPair[0]).lean().exec (err, firstSession) =>
if err? then return errors.serverError res, "There was an error fetching the first session in the pair"
LevelSession.find(_id:taskPair[1]).exec (err, secondSession) =>
if err? then return errors.serverError res, "There was an error fetching the second session"
try
taskPairs = generateTaskPairs(secondSession, firstSession)
catch e
if e then return errors.serverError res, "There was an error generating the task pairs"
sendEachTaskPairToTheQueue taskPairs, (taskPairError) ->
if taskPairError? then return errors.serverError res, "There was an error sending the task pairs to the queue"
sendResponseObject req, res, {"message":"All task pairs were succesfully sent to the queue"}
module.exports.createNewTask = (req, res) ->
requestSessionID = req.body.session

View file

@ -6,9 +6,13 @@ scoringQueue = require '../queues/scoring'
module.exports.setup = (app) ->
scoringQueue.setup()
#app.post '/queue/scoring/pairwise', (req, res) ->
# handler = loadQueueHandler 'scoring'
# handler.addPairwiseTaskToQueue req, res
app.all '/queue/*', (req, res) ->
setResponseHeaderToJSONContentType res
queueName = getQueueNameFromPath req.path
try
handler = loadQueueHandler queueName
@ -23,6 +27,7 @@ module.exports.setup = (app) ->
catch error
log.error error
sendQueueError req, res, error
setResponseHeaderToJSONContentType = (res) -> res.setHeader('Content-Type', 'application/json')