Merge branch 'master' into production

This commit is contained in:
Nick Winter 2015-08-20 15:21:52 -07:00
commit 8c3f4d92d2
18 changed files with 443 additions and 91 deletions

View file

@ -78,7 +78,11 @@ module.exports = class Label extends CocoClass
o.fontSize = {D: 25, S: 12, N: 24}[st]
fontFamily = {D: 'Arial', S: 'Arial', N: 'Arial'}[st]
o.fontDescriptor = "#{o.fontWeight} #{o.fontSize}px #{fontFamily}"
o.fontColor = {D: '#000', S: '#FFF', N: '#00a'}[st]
o.fontColor = {D: '#000', S: '#FFF', N: '#0a0'}[st]
if @style is 'name' and @sprite?.thang?.team is 'humans'
o.fontColor = '#a00'
else if @style is 'name' and @sprite?.thang?.team is 'ogres'
o.fontColor = '#00a'
o.backgroundFillColor = {D: 'white', S: 'rgba(0,0,0,0.4)', N: 'rgba(255,255,255,0.5)'}[st]
o.backgroundStrokeColor = {D: 'black', S: 'rgba(0,0,0,0.6)', N: 'rgba(0,0,0,0)'}[st]
o.backgroundStrokeStyle = {D: 2, S: 1, N: 1}[st]

View file

@ -476,8 +476,9 @@ module.exports = Lank = class Lank extends CocoClass
bar.scaleX = healthPct / @options.floatingLayer.resolutionFactor
if @thang.showsName
@setNameLabel(if @thang.health <= 0 then '' else @thang.id)
else if @options.playerName
@setNameLabel @options.playerName
# Let's try just using the DuelStatsView instead of this.
#else if @options.playerName
# @setNameLabel @options.playerName
configureMouse: ->
@sprite.cursor = 'pointer' if @thang?.isSelectable

View file

@ -234,43 +234,43 @@ module.exports = nativeDescription: "български език", englishDescri
control_bar_join_game: "Присъединяване"
reload: "Презареди"
reload_title: "Презареди целият код?"
# reload_really: "Are you sure you want to reload this level back to the beginning?"
reload_really: "Сигурен ли сте, че искате да презаредите нивото и да започнете отначало?"
reload_confirm: "Презареди всички"
victory: "Победа"
# victory_title_prefix: ""
# victory_title_suffix: " Complete"
victory_title_prefix: "Ниво "
victory_title_suffix: " завършено!"
victory_sign_up: "Регистрирай се за да запишеш напредъка си"
# victory_sign_up_poke: "Want to save your code? Create a free account!"
# victory_rate_the_level: "Rate the level: " # Only in old-style levels.
# victory_return_to_ladder: "Return to Ladder"
victory_sign_up_poke: "Регистрирайте се безплатно за да запазите прогреса си!"
victory_rate_the_level: "Оценете нивото: " # Only in old-style levels.
victory_return_to_ladder: "Обратно към Стълбата"
victory_play_continue: "Продължи"
victory_saving_progress: "Записване на напредъка"
# victory_go_home: "Go Home"
# victory_review: "Tell us more!"
# victory_review_placeholder: "How was the level?"
victory_go_home: "На Главната"
victory_review: "Разкажи ни повече!"
victory_review_placeholder: "Как беше нивото?"
victory_hour_of_code_done: "Готов ли си?"
victory_hour_of_code_done_yes: "Да аз съм готов с моят Hour of Code™!"
victory_experience_gained: "Спечелен опит"
victory_gems_gained: "Спечелени скъпоценни камъни"
# victory_new_item: "New Item"
# victory_viking_code_school: "Holy smokes, that was a hard level you just beat! If you aren't already a software developer, you should be. You just got fast-tracked for acceptance with Viking Code School, where you can take your skills to the next level and become a professional web developer in 14 weeks."
# victory_become_a_viking: "Become a Viking"
victory_new_item: "Нов Предмет"
victory_viking_code_school: "О да - това ниво беше наистина тежко! Ти или си програмист, или обезателно трябва да станеш такъв! Току що се доближи до приемането си във Викингското Училище по Програмиране, където ще научиш много нови неща и ще станеш професионален уеб програмист за 14 седмици."
victory_become_a_viking: "Стани Викинг"
guide_title: "Упътване"
# tome_minion_spells: "Your Minions' Spells" # Only in old-style levels.
# tome_read_only_spells: "Read-Only Spells" # Only in old-style levels.
# tome_other_units: "Other Units" # Only in old-style levels.
# tome_cast_button_run: "Run"
# tome_cast_button_running: "Running"
# tome_cast_button_ran: "Ran"
# tome_submit_button: "Submit"
# tome_reload_method: "Reload original code for this method" # Title text for individual method reload button.
# tome_select_method: "Select a Method"
# tome_see_all_methods: "See all methods you can edit" # Title text for method list selector (shown when there are multiple programmable methods).
# tome_select_a_thang: "Select Someone for "
# tome_available_spells: "Available Spells"
tome_minion_spells: "Заклинания на вашите Миньони' Spells" # Only in old-style levels.
tome_read_only_spells: "Read-Only Заклинания" # Only in old-style levels.
tome_other_units: "Други Модули" # Only in old-style levels.
tome_cast_button_run: "Стартиране"
tome_cast_button_running: "В Процес..."
tome_cast_button_ran: "Стартирано"
tome_submit_button: "Изпращане"
tome_reload_method: "Презареди оригиналния код за този метод" # Title text for individual method reload button.
tome_select_method: "Избери Метод"
tome_see_all_methods: "Виж всички методи, които можеш да редактираш" # Title text for method list selector (shown when there are multiple programmable methods).
tome_select_a_thang: "Избери някого за "
tome_available_spells: "Достъпни Заклинания"
tome_your_skills: "Твоите Умения"
tome_help: "Помощ"
# tome_current_method: "Current Method"
tome_current_method: "Текущ Метод"
hud_continue_short: "Продължи"
code_saved: "Кодът е записан"
skip_tutorial: "Пропусни (esc)"
@ -280,43 +280,43 @@ module.exports = nativeDescription: "български език", englishDescri
problem_alert_title: "Оправи си кода."
problem_alert_help: "Помощ"
time_current: "Текущо време:"
# time_total: "Max:"
# time_goto: "Go to:"
# non_user_code_problem_title: "Unable to Load Level"
# infinite_loop_title: "Infinite Loop Detected"
# infinite_loop_description: "The initial code to build the world never finished running. It's probably either really slow or has an infinite loop. Or there might be a bug. You can either try running this code again or reset the code to the default state. If that doesn't fix it, please let us know."
# check_dev_console: "You can also open the developer console to see what might be going wrong."
# check_dev_console_link: "(instructions)"
time_total: "Максимално:"
time_goto: "Иди на:"
non_user_code_problem_title: "Нивото не може да се зареди"
infinite_loop_title: "Открит е безкраен цикъл"
infinite_loop_description: "Кодът за сътворение на света никога не свършва. Или е много бавен, или има безкраен цикъл. Или може да има бъг. Можете да опитате да стартирате този код отново, или да нулирате кода до изходното му състояние. Ако нещата не се оправят, моля, съобщете ни."
check_dev_console: "Също така можете да отворите конзолата за разработчици, за да видите какво не е наред."
check_dev_console_link: "(инструкции)"
infinite_loop_try_again: "Пробвай отново"
infinite_loop_reset_level: "Ресетване на Ниво"
infinite_loop_reset_level: "Нулиране на Ниво"
infinite_loop_comment_out: "Коментирай моят Код"
# tip_toggle_play: "Toggle play/paused with Ctrl+P."
# tip_scrub_shortcut: "Use Ctrl+[ and Ctrl+] to rewind and fast-forward."
# tip_guide_exists: "Click the guide, inside game menu (at the top of the page), for useful info."
tip_toggle_play: "Превключвайте възпроизвеждане/пауза с Ctrl+P."
tip_scrub_shortcut: "Използвайте Ctrl+[ и Ctrl+] за бързо превъртане напред и назад."
tip_guide_exists: "Кликнете на ръководството в менюто(в горната част на страницата), за полезна информация."
tip_open_source: "CodeCombat e 100% проект с отворен код!"
# tip_tell_friends: "Enjoying CodeCombat? Tell your friends about us!"
tip_tell_friends: "Насладихте ли се на CodeCombat? Разкажете на приятелите си за нас!"
tip_beta_launch: "CodeCombat стартира своята beta през Октомври, 2013."
tip_think_solution: "Помисли върху решението,не проблема."
# tip_theory_practice: "In theory, there is no difference between theory and practice. But in practice, there is. - Yogi Berra"
# tip_error_free: "There are two ways to write error-free programs; only the third one works. - Alan Perlis"
# tip_debugging_program: "If debugging is the process of removing bugs, then programming must be the process of putting them in. - Edsger W. Dijkstra"
# tip_forums: "Head over to the forums and tell us what you think!"
# tip_baby_coders: "In the future, even babies will be Archmages."
# tip_morale_improves: "Loading will continue until morale improves."
# tip_all_species: "We believe in equal opportunities to learn programming for all species."
# tip_reticulating: "Reticulating spines."
# tip_harry: "Yer a Wizard, "
# tip_great_responsibility: "With great coding skill comes great debug responsibility."
# tip_munchkin: "If you don't eat your vegetables, a munchkin will come after you while you're asleep."
# tip_binary: "There are only 10 types of people in the world: those who understand binary, and those who don't."
# tip_commitment_yoda: "A programmer must have the deepest commitment, the most serious mind. ~ Yoda"
# tip_no_try: "Do. Or do not. There is no try. - Yoda"
# tip_patience: "Patience you must have, young Padawan. - Yoda"
# tip_documented_bug: "A documented bug is not a bug; it is a feature."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
# tip_hardware_problem: "Q: How many programmers does it take to change a light bulb? A: None, it's a hardware problem."
tip_think_solution: "Помисли върху решението, не проблема."
tip_theory_practice: "На теория няма разлика между теорията и практиката. Но на практика има. - Yogi Berra"
tip_error_free: "Има само два начина да напишеш безгрешна програма; само третия работи. - Alan Perlis"
tip_debugging_program: "Ако дебъгването е процес на премахване на бъгове, тогава програмирането трябва да е процес на поставянето им. - Edsger W. Dijkstra"
tip_forums: "Идете на форумите и кажете какво мислите!"
tip_baby_coders: "В бъдещето дори бебетата ще са Архимагове."
tip_morale_improves: "Зареждането ще продължи докато бойният дух не се възстанови."
tip_all_species: "Ние вярваме в равните възможности на всички видове да се научат да програмират."
tip_reticulating: "Да замрежим бодлите!"
tip_harry: "Ти си Магьосник, "
tip_great_responsibility: "С големите програмистки умения идват големите отговорности по дебъга."
tip_munchkin: "Ако не си изядеш зеленчуците, Торбалан ще дойде и ще те вземе, когато заспиш."
tip_binary: "Има само 10 типа хора по света - тези, които разбират двоичната система, и тези, които не я разбират."
tip_commitment_yoda: "Програмистът на прининципите верен трябва да е - и със ум сериозен. ~ Йода"
tip_no_try: "Прави. Или не прави. Недей опитва. - Йода"
tip_patience: "Търпение да имаш трябва, млади Падуане. - Йода"
tip_documented_bug: "Документирания бъг не е бъг - той е фичър."
tip_impossible: "Винаги изглежда невъзможно - докато не се направи. - Нелсън Мандела"
tip_talk_is_cheap: "Приказките са вятър и мъгла. Покажи ми кода. - Линус Торвалдс"
tip_first_language: "Най-пагубното нещо, което можеш да научиш е първият ти език за програмиране. - Alan Kay"
tip_hardware_problem: "Въпр.: Колко програмиста са нужни, за да сменят електрическа крушка? Отг.: Николко, това е хардуерен проблем."
# tip_hofstadters_law: "Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law."
# tip_premature_optimization: "Premature optimization is the root of all evil. - Donald Knuth"
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"

View file

@ -634,28 +634,28 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
sys_requirements_2: "CodeCombat no está soportado en iPad aún."
teachers_survey:
# title: "Teacher Survey"
# must_be_logged: "You must be logged in first. Please create an account or log in from the menu above."
# retrieving: "Retrieving information..."
# being_reviewed_1: "Your application for a free trial subscription is being"
# being_reviewed_2: "reviewed."
# approved_1: "Your application for a free trial subscription was"
title: "Encuesta para profesores"
must_be_logged: "Debe iniiciar sesión primero. Por favor cree una cuenta o inicie sesión desde el menú en la parte superior."
retrieving: "Obteniendo información..."
being_reviewed_1: "Su solicitud para una prueba gratuita de subscripción está siendo"
being_reviewed_2: "revisada."
approved_1: "Su solicitud para una prueba gratuita de subscripción fue" #since about 1993 fué can use no tilde
approved_2: "Aprobada."
# approved_3: "Further instructions have been sent to"
# denied_1: "Your application for a free trial subscription has been"
denied_2: "denegadae."
contact_1: "Porfavor contactarse"
# contact_2: "if you have further questions."
approved_3: "Instruccciones posteriores han sido enviadas a"
denied_1: "Su solicitud para una prueba gratuita de subscripción fue"
denied_2: "denegada."
contact_1: "Por favor contáctenos"
contact_2: "si tiene más preguntas."
# description_1: "We offer free subscriptions to teachers for evaluation purposes. You can find more information on our"
# description_2: "teachers"
# description_3: "page."
description_2: "página"
description_3: "de maestros."
# description_4: "Please fill out this quick survey and well email you setup instructions."
email: "Dirección de email"
school: "Nombre del colegio"
location: "Nombre de la ciudad"
age_students: "¿Qué edad tienen tus estudiantes?"
# under: "Under"
# other: "Other:"
under: "Menor" #under like underage = menor as menor de edad
other: "Otro:"
amount_students: "¿A cuantos alumnos les enseñas?"
hear_about: "¿Donde escuchaste sobre CodeCombat?"
fill_fields: "Porfavor llenar todos los campos."
@ -707,7 +707,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
new_password: "Nueva Contraseña"
new_password_verify: "Verificar"
type_in_email: "Ingrese su correo electrónico para confirmar la eliminación" # {change}
# type_in_password: "Also, type in your password."
type_in_password: "También, escribe tu password."
email_subscriptions: "Suscripciones de Email"
email_subscriptions_none: "No tienes suscripciones."
email_announcements: "Noticias"
@ -782,7 +782,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
make_private: "Hacer clan privado"
subs_only: "solo suscriptores"
create_clan: "Crear nuevo clan"
# private_preview: "Preview"
private_preview: "Previsualizar"
public_clans: "Clanes publicos"
my_clans: "Mis Clanes"
clan_name: "Nombre del clan"
@ -794,7 +794,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
edit_name: "editar nombre"
edit_description: "editar descripción"
private: "(privado)"
# summary: "Summary"
summary: "Resumen"
average_level: "Nivel Promedio"
average_achievements: "Logros Promedio"
delete_clan: "Borrar Clan"
@ -853,8 +853,8 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
indoor: "Interior"
desert: "Desierto"
grassy: "Herboso"
# mountain: "Mountain"
# glacier: "Glacier"
mountain: "Mountaña"
glacier: "Glaciar"
small: "Pequeño"
large: "Grande"
fork_title: "Fork de Nueva Versión"

View file

@ -45,9 +45,12 @@ $level-resize-transition-time: 0.5s
.team-gold
font-size: 2vw
line-height: 2vw
img
width: 1.8vw
heighT: 1.8vw
img
width: 1.8vw
height: 1.8vw
#duel-stats-view
right: calc(1% + 100px)
bottom: 50px
#control-bar-view .title
left: 20%
width: 60%

View file

@ -0,0 +1,154 @@
@import "app/styles/mixins"
@import "app/styles/bootstrap/variables"
#duel-stats-view
position: absolute
right: 44.3%
bottom: 133px
z-index: 3
@include transition(opacity .2s linear)
@include user-select(none)
padding: 4px 10px 0 4px
background: transparent url(/images/level/hud_background.png) no-repeat
background-size: 100% auto
border-radius: 4px
width: 500px
height: 60px
display: flex
flex-direction: row
&:hover
opacity: 0.1
.player-container
width: 50%
height: 50px
display: flex
flex-direction: row
align-items: center
text-transform: uppercase
font-family: $headings-font-family
font-weight: bold
font-size: 18px
color: hsla(4,80%,51%,1)
text-shadow: 0px 1px 0px black, 0px -1px 0px black, 1px 0px 0px black, -1px 0px 0px black
&.team-humans
padding-right: 10px
.player-power
margin-right: 5px
&.team-ogres
padding-left: 10px
flex-direction: row-reverse
color: hsla(205,100%,51%,1)
.name-and-power
flex-direction: row-reverse
.player-name
text-align: right
.player-power
margin-left: 5px
flex-direction: row-reverse
text-align: right
.player-health
flex-direction: row-reverse
.health-bar-container .health-bar
background: hsla(205,100%,51%,1)
.name-and-power
display: flex
flex-direction: row
.player-portrait
margin: 0 12px
.thang-avatar-view
width: 30px
.player-name
height: 50%
text-align: left
overflow: hidden
text-overflow: ellipsis
white-space: nowrap
max-width: 130px
$iconSize: 16px
.health-icon, .power-icon
display: inline-block
width: $iconSize
height: $iconSize
background: transparent url(/images/level/hud_info_icons.png) no-repeat
background-size: auto $iconSize
.player-health, .player-power
height: 50%
display: flex
flex-direction: row
height: 18px
.player-health
line-height: 16px
.health-bar-container
width: 100px
display: inline-block
margin: 1px 5px
height: 16px
background: rgb(32, 27, 21)
padding: 4px
border-radius: 8px
border: 0
overflow: hidden
.health-bar
background: rgb(234, 35, 45)
width: 100%
height: 8px
border-radius: 4px
.health-value
vertical-align: top
.player-power
.power-icon
margin-top: 4px
background-position: (-5 * $iconSize) 0px
.power-value
min-width: 20px
margin: 0px 5px
//&.team-humans .team-gold
// color: hsla(4,80%,51%,1)
//
//&.team-ogres .team-gold
// color: hsla(205,100%,51%,1)
//
//.team-gold
// font-size: 1.4vw
// line-height: 1.4vw
// margin: 0
// color: hsla(205,0%,51%,1)
// display: inline-block
// padding: 0px 4px
//
// img
// width: 1.2vw
// height: 1.2vw
// border-radius: 2px
// padding: 0.1vw
// margin-top: -0.2vw
// margin-right: 0.1vw
//
// .gold-amount
// display: inline-block
// min-width: 20px

View file

@ -12,6 +12,10 @@
display: none
#gold-view
right: 1%
#duel-stats-view
right: 230px
bottom: 80px
@include scale(2)
#control-bar-view
width: 100%

View file

@ -29,6 +29,8 @@
#multiplayer-status-view
#duel-stats-view
#playback-view
#thang-hud

View file

@ -0,0 +1,21 @@
for player in players
div(class="player-container team-" + player.team)
.player-portrait
.thang-avatar-placeholder
.player-info
.name-and-power
.player-power
.power-icon
.power-value
.player-name= player.name
.player-health
.health-icon
.health-bar-container
.health-bar
.health-value
//.player-gold
// .team-gold
// img(src="/images/level/gold_icon.png", alt="", draggable="false")
// .gold-amount

View file

@ -1,3 +1,3 @@
div(class="team-gold team-" + team)
img(src="/images/level/gold_icon.png", alt="")
img(src="/images/level/gold_icon.png", alt="", draggable="false")
div(class="gold-amount team-" + team)

View file

@ -9,5 +9,6 @@
#canvas-top-gradient.gradient
#gold-view.secret.expanded
#level-chat-view
#duel-stats-view
#playback-view
#thang-hud

View file

@ -28,6 +28,7 @@ ControlBarView = require './level/ControlBarView'
PlaybackView = require './level/LevelPlaybackView'
GoalsView = require './level/LevelGoalsView'
GoldView = require './level/LevelGoldView'
DuelStatsView = require './level/DuelStatsView'
VictoryModal = require './level/modal/VictoryModal'
InfiniteLoopModal = require './level/modal/InfiniteLoopModal'
@ -179,8 +180,8 @@ module.exports = class SpectateLevelView extends RootView
@insertSubView new GoldView {}
@insertSubView new HUDView {level: @level}
worldName = utils.i18n @level.attributes, 'name'
@controlBar = @insertSubView new ControlBarView {worldName: worldName, session: @session, level: @level, supermodel: @supermodel, spectateGame: true}
@insertSubView new DuelStatsView level: @level, session: @session, otherSession: @otherSession, supermodel: @supermodel, thangs: @world.thangs if @level.get('type') in ['hero-ladder', 'course-ladder']
@insertSubView @controlBar = new ControlBarView {worldName: utils.i18n(@level.attributes, 'name'), session: @session, level: @level, supermodel: @supermodel, spectateGame: true}
# callbacks

View file

@ -0,0 +1,120 @@
CocoView = require 'views/core/CocoView'
template = require 'templates/play/level/duel-stats-view'
ThangAvatarView = require 'views/play/level/ThangAvatarView'
utils = require 'core/utils'
# TODO:
# - if a hero is dead, a big indication that they are dead
# - each hero's current action?
# - if one player is you, an indicator that it's you?
# - indication of which team won (not always hero dead--ties and other victory conditions)
# - army composition or power or attack/defense (for certain levels): experiment with something simple, not like the previous unit list thing
module.exports = class DuelStatsView extends CocoView
id: 'duel-stats-view'
template: template
subscriptions:
#'surface:gold-changed': 'onGoldChanged'
'god:new-world-created': 'onNewWorld'
'god:streaming-world-updated': 'onNewWorld'
'surface:frame-changed': 'onFrameChanged'
constructor: (options) ->
super options
options.thangs = _.filter options.thangs, 'inThangList'
unless options.otherSession
options.otherSession = get: (prop) -> {
creatorName: $.i18n.t 'ladder.simple_ai'
team: if options.session.get('team') is 'humans' then 'ogres' else 'humans'
heroConfig: options.session.get('heroConfig')
}[prop]
#@teamGold = {}
#@teamGoldEarned = {}
getRenderData: (c) ->
c = super c
c.players = @players = (@formatPlayer team for team in ['humans', 'ogres'])
c
formatPlayer: (team) ->
p = team: team
session = _.find [@options.session, @options.otherSession], (s) -> s.get('team') is team
p.name = session.get 'creatorName'
p.heroThangType = (session.get('heroConfig') ? {}).thangType or '529ffbf1cf1818f2be000001'
p.heroID = if team is 'ogres' then 'Hero Placeholder 1' else 'Hero Placeholder'
p
afterRender: ->
super()
for player in @players
@buildAvatar player.heroID, player.team
buildAvatar: (heroID, team) ->
@avatars ?= {}
return if @avatars[team]
thang = _.find @options.thangs, id: heroID
@avatars[team] = avatar = new ThangAvatarView thang: thang, includeName: false, supermodel: @supermodel
@$find(team, '.thang-avatar-placeholder').replaceWith avatar.$el
avatar.render()
onNewWorld: (e) ->
@options.thangs = _.filter e.world.thangs, 'inThangList'
onFrameChanged: (e) ->
@update()
update: ->
for player in @players
thang = _.find @options.thangs, id: @avatars[player.team].thang.id
@updateHealth thang
@updatePower()
updateHealth: (thang) ->
$health = @$find thang.team, '.player-health'
$health.find('.health-bar').css 'width', Math.max(0, Math.min(100, 100 * thang.health / thang.maxHealth)) + '%'
utils.replaceText $health.find('.health-value'), Math.round thang.health
updatePower: ->
# Right now we just display the army cost of all living units as opposed to doing something more sophisticate to measure power.
@costTable ?=
soldier: 20
archer: 25
decoy: 25
'griffin-rider': 50
paladin: 80
artillery: 75
'arrow-tower': 75
palisade: 10
peasant: 50
powers = humans: 0, ogres: 0
for thang in @options.thangs when thang.health > 0
powers[thang.team] += @costTable[thang.type] or 0 if powers[thang.team]?
for player in @players
utils.replaceText @$find(player.team, '.power-value'), powers[player.team]
$find: (team, selector) ->
@$el.find(".player-container.team-#{team} " + selector)
destroy: ->
avatar.destroy() for team, avatar of @avatars ? {}
super()
#onGoldChanged: (e) ->
# return if @teamGold[e.team] is e.gold and @teamGoldEarned[e.team] is e.goldEarned
# @teamGold[e.team] = e.gold
# @teamGoldEarned[e.team] = e.goldEarned
# goldEl = @$find e.team, '.gold-amount'
# text = '' + e.gold
# if e.goldEarned and e.goldEarned > e.gold
# text += " (#{e.goldEarned})"
# goldEl.text text
# @updateTitle()
#
#updateTitle: ->
# for team, gold of @teamGold
# if @teamGoldEarned[team]
# title = "Team '#{team}' has #{gold} now of #{@teamGoldEarned[team]} gold earned."
# else
# title = "Team '#{team}' has #{gold} gold."
# @$find(team, '.player-gold').attr 'title', title

View file

@ -32,6 +32,7 @@ LevelPlaybackView = require './LevelPlaybackView'
GoalsView = require './LevelGoalsView'
LevelFlagsView = require './LevelFlagsView'
GoldView = require './LevelGoldView'
DuelStatsView = require './DuelStatsView'
VictoryModal = require './modal/VictoryModal'
HeroVictoryModal = require './modal/HeroVictoryModal'
InfiniteLoopModal = require './modal/InfiniteLoopModal'
@ -246,8 +247,8 @@ module.exports = class PlayLevelView extends RootView
@insertSubView new LevelDialogueView {level: @level, sessionID: @session.id}
@insertSubView new ChatView levelID: @levelID, sessionID: @session.id, session: @session
@insertSubView new ProblemAlertView session: @session, level: @level, supermodel: @supermodel
worldName = utils.i18n @level.attributes, 'name'
@controlBar = @insertSubView new ControlBarView {worldName: worldName, session: @session, level: @level, supermodel: @supermodel}
@insertSubView new DuelStatsView level: @level, session: @session, otherSession: @otherSession, supermodel: @supermodel, thangs: @world.thangs if @level.get('type') in ['hero-ladder', 'course-ladder']
@insertSubView @controlBar = new ControlBarView {worldName: utils.i18n(@level.attributes, 'name'), session: @session, level: @level, supermodel: @supermodel}
#_.delay (=> Backbone.Mediator.publish('level:set-debug', debug: true)), 5000 if @isIPadApp() # if me.displayName() is 'Nick'
initVolume: ->

View file

@ -78,6 +78,7 @@ module.exports = class PlayHeroesModal extends ModalView
afterRender: ->
super()
return unless @supermodel.finished()
@playSound 'game-menu-open'
@$el.find('.hero-avatar').addClass 'ie' if @isIE()
heroes = @heroes.models
@$el.find('.hero-indicator').each ->
@ -334,7 +335,7 @@ module.exports = class PlayHeroesModal extends ModalView
onHidden: ->
super()
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'game-menu-close', volume: 1
@playSound 'game-menu-close'
destroy: ->
clearInterval @heroAnimationInterval

View file

@ -0,0 +1,37 @@
// Add clan leagues to sessions
// Usage:
// mongo <address>:<port>/<database> <script file> -u <username> -p <password>
//
// It just goes through all users in clans, then adds their clans to all their multiplayer sessions.
migrateClans();
function migrateClans() {
print("Adding clan leagues to sessions...");
var cursor = db.users.find({emailLower: {$exists: true}, clans: {$exists: true}}, {clans: 1, name: 1});
print("Users with clans found: " + cursor.count());
var users = cursor.toArray();
var arenas = [
"5442ba0e1e835500007eb1c7",
"550363b4ec31df9c691ab629",
"5469643c37600b40e0e09c5b",
"54b83c2629843994803c838e",
"544437e0645c0c0000c3291d"
];
users.forEach(function (user, userIndex) {
var leagues = [];
for (var i = 0; i < user.clans.length; ++i) {
leagues.push({leagueID: user.clans[i] + '', stats: {standardDeviation: 25 / 3, numberOfWinsAndTies: 0, numberOfLosses: 0, totalScore: 10, meanStrength: 25}});
};
//var sessions = db.level.sessions.find({creator: user._id + '', 'level.original': {$in: arenas}, submitted: true}, {clans: 1}).toArray();
//print("Found sessions", sessions, "for user", user._id, user.name, 'who has clans', user.clans.join(', '));
//print("Going to set leagues to...")
//printjson(leagues);
var conditions = {creator: user._id + '', 'level.original': {$in: arenas}, submitted: true};
var operations = {$set: {leagues: leagues}};
var result = db.level.sessions.update(conditions, operations, {multi: true});
if (userIndex % 1000 === 0)
print("Done", userIndex, "\tof", users.length, "users.");
});
print("Done.");
}

View file

@ -74,6 +74,8 @@ updateSessionToSubmit = (transpiledCode, user, sessionToUpdate, callback) ->
league.stats.standardDeviation = 25 / 3
league.stats.numberOfWinsAndTies = 0
league.stats.numberOfLosses = 0
league.stats.meanStrength ?= 25
league.stats.totalScore ?= 10
newLeagues.push(league)
unless _.isEqual newLeagues, sessionToUpdate.leagues
sessionUpdateObject.leagues = sessionToUpdate.leagues = newLeagues

View file

@ -42,7 +42,7 @@ getRandomSessions = (user, callback) ->
leagueIDs = (leagueID + '' for leagueID in leagueIDs) # Make sure to fetch them as strings.
return sampleByLevel callback unless leagueIDs.length and Math.random() > 1 / leagueIDs.length
leagueID = _.sample leagueIDs
findRandomSession {'leagues.leagueID': leagueID, favorRecent: true}, (err, session) ->
findRandomSession {'leagues.leagueID': leagueID}, (err, session) ->
if err then return callback err
unless session then return sampleByLevel callback
otherTeam = scoringUtils.calculateOpposingTeam session.team