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] o.fontSize = {D: 25, S: 12, N: 24}[st]
fontFamily = {D: 'Arial', S: 'Arial', N: 'Arial'}[st] fontFamily = {D: 'Arial', S: 'Arial', N: 'Arial'}[st]
o.fontDescriptor = "#{o.fontWeight} #{o.fontSize}px #{fontFamily}" 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.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.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] 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 bar.scaleX = healthPct / @options.floatingLayer.resolutionFactor
if @thang.showsName if @thang.showsName
@setNameLabel(if @thang.health <= 0 then '' else @thang.id) @setNameLabel(if @thang.health <= 0 then '' else @thang.id)
else if @options.playerName # Let's try just using the DuelStatsView instead of this.
@setNameLabel @options.playerName #else if @options.playerName
# @setNameLabel @options.playerName
configureMouse: -> configureMouse: ->
@sprite.cursor = 'pointer' if @thang?.isSelectable @sprite.cursor = 'pointer' if @thang?.isSelectable

View file

@ -234,43 +234,43 @@ module.exports = nativeDescription: "български език", englishDescri
control_bar_join_game: "Присъединяване" control_bar_join_game: "Присъединяване"
reload: "Презареди" reload: "Презареди"
reload_title: "Презареди целият код?" reload_title: "Презареди целият код?"
# reload_really: "Are you sure you want to reload this level back to the beginning?" reload_really: "Сигурен ли сте, че искате да презаредите нивото и да започнете отначало?"
reload_confirm: "Презареди всички" reload_confirm: "Презареди всички"
victory: "Победа" victory: "Победа"
# victory_title_prefix: "" victory_title_prefix: "Ниво "
# victory_title_suffix: " Complete" victory_title_suffix: " завършено!"
victory_sign_up: "Регистрирай се за да запишеш напредъка си" victory_sign_up: "Регистрирай се за да запишеш напредъка си"
# victory_sign_up_poke: "Want to save your code? Create a free account!" victory_sign_up_poke: "Регистрирайте се безплатно за да запазите прогреса си!"
# victory_rate_the_level: "Rate the level: " # Only in old-style levels. victory_rate_the_level: "Оценете нивото: " # Only in old-style levels.
# victory_return_to_ladder: "Return to Ladder" victory_return_to_ladder: "Обратно към Стълбата"
victory_play_continue: "Продължи" victory_play_continue: "Продължи"
victory_saving_progress: "Записване на напредъка" victory_saving_progress: "Записване на напредъка"
# victory_go_home: "Go Home" victory_go_home: "На Главната"
# victory_review: "Tell us more!" victory_review: "Разкажи ни повече!"
# victory_review_placeholder: "How was the level?" victory_review_placeholder: "Как беше нивото?"
victory_hour_of_code_done: "Готов ли си?" victory_hour_of_code_done: "Готов ли си?"
victory_hour_of_code_done_yes: "Да аз съм готов с моят Hour of Code™!" victory_hour_of_code_done_yes: "Да аз съм готов с моят Hour of Code™!"
victory_experience_gained: "Спечелен опит" victory_experience_gained: "Спечелен опит"
victory_gems_gained: "Спечелени скъпоценни камъни" victory_gems_gained: "Спечелени скъпоценни камъни"
# victory_new_item: "New Item" victory_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_viking_code_school: "О да - това ниво беше наистина тежко! Ти или си програмист, или обезателно трябва да станеш такъв! Току що се доближи до приемането си във Викингското Училище по Програмиране, където ще научиш много нови неща и ще станеш професионален уеб програмист за 14 седмици."
# victory_become_a_viking: "Become a Viking" victory_become_a_viking: "Стани Викинг"
guide_title: "Упътване" guide_title: "Упътване"
# tome_minion_spells: "Your Minions' Spells" # Only in old-style levels. tome_minion_spells: "Заклинания на вашите Миньони' Spells" # Only in old-style levels.
# tome_read_only_spells: "Read-Only Spells" # Only in old-style levels. tome_read_only_spells: "Read-Only Заклинания" # Only in old-style levels.
# tome_other_units: "Other Units" # Only in old-style levels. tome_other_units: "Други Модули" # Only in old-style levels.
# tome_cast_button_run: "Run" tome_cast_button_run: "Стартиране"
# tome_cast_button_running: "Running" tome_cast_button_running: "В Процес..."
# tome_cast_button_ran: "Ran" tome_cast_button_ran: "Стартирано"
# tome_submit_button: "Submit" tome_submit_button: "Изпращане"
# tome_reload_method: "Reload original code for this method" # Title text for individual method reload button. tome_reload_method: "Презареди оригиналния код за този метод" # Title text for individual method reload button.
# tome_select_method: "Select a Method" tome_select_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_see_all_methods: "Виж всички методи, които можеш да редактираш" # Title text for method list selector (shown when there are multiple programmable methods).
# tome_select_a_thang: "Select Someone for " tome_select_a_thang: "Избери някого за "
# tome_available_spells: "Available Spells" tome_available_spells: "Достъпни Заклинания"
tome_your_skills: "Твоите Умения" tome_your_skills: "Твоите Умения"
tome_help: "Помощ" tome_help: "Помощ"
# tome_current_method: "Current Method" tome_current_method: "Текущ Метод"
hud_continue_short: "Продължи" hud_continue_short: "Продължи"
code_saved: "Кодът е записан" code_saved: "Кодът е записан"
skip_tutorial: "Пропусни (esc)" skip_tutorial: "Пропусни (esc)"
@ -280,43 +280,43 @@ module.exports = nativeDescription: "български език", englishDescri
problem_alert_title: "Оправи си кода." problem_alert_title: "Оправи си кода."
problem_alert_help: "Помощ" problem_alert_help: "Помощ"
time_current: "Текущо време:" time_current: "Текущо време:"
# time_total: "Max:" time_total: "Максимално:"
# time_goto: "Go to:" time_goto: "Иди на:"
# non_user_code_problem_title: "Unable to Load Level" non_user_code_problem_title: "Нивото не може да се зареди"
# infinite_loop_title: "Infinite Loop Detected" infinite_loop_title: "Открит е безкраен цикъл"
# 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." infinite_loop_description: "Кодът за сътворение на света никога не свършва. Или е много бавен, или има безкраен цикъл. Или може да има бъг. Можете да опитате да стартирате този код отново, или да нулирате кода до изходното му състояние. Ако нещата не се оправят, моля, съобщете ни."
# check_dev_console: "You can also open the developer console to see what might be going wrong." check_dev_console: "Също така можете да отворите конзолата за разработчици, за да видите какво не е наред."
# check_dev_console_link: "(instructions)" check_dev_console_link: "(инструкции)"
infinite_loop_try_again: "Пробвай отново" infinite_loop_try_again: "Пробвай отново"
infinite_loop_reset_level: "Ресетване на Ниво" infinite_loop_reset_level: "Нулиране на Ниво"
infinite_loop_comment_out: "Коментирай моят Код" infinite_loop_comment_out: "Коментирай моят Код"
# tip_toggle_play: "Toggle play/paused with Ctrl+P." tip_toggle_play: "Превключвайте възпроизвеждане/пауза с Ctrl+P."
# tip_scrub_shortcut: "Use Ctrl+[ and Ctrl+] to rewind and fast-forward." tip_scrub_shortcut: "Използвайте Ctrl+[ и Ctrl+] за бързо превъртане напред и назад."
# tip_guide_exists: "Click the guide, inside game menu (at the top of the page), for useful info." tip_guide_exists: "Кликнете на ръководството в менюто(в горната част на страницата), за полезна информация."
tip_open_source: "CodeCombat e 100% проект с отворен код!" 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_beta_launch: "CodeCombat стартира своята beta през Октомври, 2013."
tip_think_solution: "Помисли върху решението,не проблема." tip_think_solution: "Помисли върху решението, не проблема."
# tip_theory_practice: "In theory, there is no difference between theory and practice. But in practice, there is. - Yogi Berra" tip_theory_practice: "На теория няма разлика между теорията и практиката. Но на практика има. - Yogi Berra"
# tip_error_free: "There are two ways to write error-free programs; only the third one works. - Alan Perlis" tip_error_free: "Има само два начина да напишеш безгрешна програма; само третия работи. - 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_debugging_program: "Ако дебъгването е процес на премахване на бъгове, тогава програмирането трябва да е процес на поставянето им. - Edsger W. Dijkstra"
# tip_forums: "Head over to the forums and tell us what you think!" tip_forums: "Идете на форумите и кажете какво мислите!"
# tip_baby_coders: "In the future, even babies will be Archmages." tip_baby_coders: "В бъдещето дори бебетата ще са Архимагове."
# tip_morale_improves: "Loading will continue until morale improves." tip_morale_improves: "Зареждането ще продължи докато бойният дух не се възстанови."
# tip_all_species: "We believe in equal opportunities to learn programming for all species." tip_all_species: "Ние вярваме в равните възможности на всички видове да се научат да програмират."
# tip_reticulating: "Reticulating spines." tip_reticulating: "Да замрежим бодлите!"
# tip_harry: "Yer a Wizard, " tip_harry: "Ти си Магьосник, "
# tip_great_responsibility: "With great coding skill comes great debug responsibility." tip_great_responsibility: "С големите програмистки умения идват големите отговорности по дебъга."
# tip_munchkin: "If you don't eat your vegetables, a munchkin will come after you while you're asleep." tip_munchkin: "Ако не си изядеш зеленчуците, Торбалан ще дойде и ще те вземе, когато заспиш."
# tip_binary: "There are only 10 types of people in the world: those who understand binary, and those who don't." tip_binary: "Има само 10 типа хора по света - тези, които разбират двоичната система, и тези, които не я разбират."
# tip_commitment_yoda: "A programmer must have the deepest commitment, the most serious mind. ~ Yoda" tip_commitment_yoda: "Програмистът на прининципите верен трябва да е - и със ум сериозен. ~ Йода"
# tip_no_try: "Do. Or do not. There is no try. - Yoda" tip_no_try: "Прави. Или не прави. Недей опитва. - Йода"
# tip_patience: "Patience you must have, young Padawan. - Yoda" tip_patience: "Търпение да имаш трябва, млади Падуане. - Йода"
# tip_documented_bug: "A documented bug is not a bug; it is a feature." tip_documented_bug: "Документирания бъг не е бъг - той е фичър."
# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela" tip_impossible: "Винаги изглежда невъзможно - докато не се направи. - Нелсън Мандела"
# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds" tip_talk_is_cheap: "Приказките са вятър и мъгла. Покажи ми кода. - Линус Торвалдс"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay" tip_first_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_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_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_premature_optimization: "Premature optimization is the root of all evil. - Donald Knuth"
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson" # 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." sys_requirements_2: "CodeCombat no está soportado en iPad aún."
teachers_survey: teachers_survey:
# title: "Teacher Survey" title: "Encuesta para profesores"
# must_be_logged: "You must be logged in first. Please create an account or log in from the menu above." 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: "Retrieving information..." retrieving: "Obteniendo información..."
# being_reviewed_1: "Your application for a free trial subscription is being" being_reviewed_1: "Su solicitud para una prueba gratuita de subscripción está siendo"
# being_reviewed_2: "reviewed." being_reviewed_2: "revisada."
# approved_1: "Your application for a free trial subscription was" approved_1: "Su solicitud para una prueba gratuita de subscripción fue" #since about 1993 fué can use no tilde
approved_2: "Aprobada." approved_2: "Aprobada."
# approved_3: "Further instructions have been sent to" approved_3: "Instruccciones posteriores han sido enviadas a"
# denied_1: "Your application for a free trial subscription has been" denied_1: "Su solicitud para una prueba gratuita de subscripción fue"
denied_2: "denegadae." denied_2: "denegada."
contact_1: "Porfavor contactarse" contact_1: "Por favor contáctenos"
# contact_2: "if you have further questions." 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_1: "We offer free subscriptions to teachers for evaluation purposes. You can find more information on our"
# description_2: "teachers" description_2: "página"
# description_3: "page." description_3: "de maestros."
# description_4: "Please fill out this quick survey and well email you setup instructions." # description_4: "Please fill out this quick survey and well email you setup instructions."
email: "Dirección de email" email: "Dirección de email"
school: "Nombre del colegio" school: "Nombre del colegio"
location: "Nombre de la ciudad" location: "Nombre de la ciudad"
age_students: "¿Qué edad tienen tus estudiantes?" age_students: "¿Qué edad tienen tus estudiantes?"
# under: "Under" under: "Menor" #under like underage = menor as menor de edad
# other: "Other:" other: "Otro:"
amount_students: "¿A cuantos alumnos les enseñas?" amount_students: "¿A cuantos alumnos les enseñas?"
hear_about: "¿Donde escuchaste sobre CodeCombat?" hear_about: "¿Donde escuchaste sobre CodeCombat?"
fill_fields: "Porfavor llenar todos los campos." 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: "Nueva Contraseña"
new_password_verify: "Verificar" new_password_verify: "Verificar"
type_in_email: "Ingrese su correo electrónico para confirmar la eliminación" # {change} 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: "Suscripciones de Email"
email_subscriptions_none: "No tienes suscripciones." email_subscriptions_none: "No tienes suscripciones."
email_announcements: "Noticias" email_announcements: "Noticias"
@ -782,7 +782,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
make_private: "Hacer clan privado" make_private: "Hacer clan privado"
subs_only: "solo suscriptores" subs_only: "solo suscriptores"
create_clan: "Crear nuevo clan" create_clan: "Crear nuevo clan"
# private_preview: "Preview" private_preview: "Previsualizar"
public_clans: "Clanes publicos" public_clans: "Clanes publicos"
my_clans: "Mis Clanes" my_clans: "Mis Clanes"
clan_name: "Nombre del clan" clan_name: "Nombre del clan"
@ -794,7 +794,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
edit_name: "editar nombre" edit_name: "editar nombre"
edit_description: "editar descripción" edit_description: "editar descripción"
private: "(privado)" private: "(privado)"
# summary: "Summary" summary: "Resumen"
average_level: "Nivel Promedio" average_level: "Nivel Promedio"
average_achievements: "Logros Promedio" average_achievements: "Logros Promedio"
delete_clan: "Borrar Clan" delete_clan: "Borrar Clan"
@ -853,8 +853,8 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
indoor: "Interior" indoor: "Interior"
desert: "Desierto" desert: "Desierto"
grassy: "Herboso" grassy: "Herboso"
# mountain: "Mountain" mountain: "Mountaña"
# glacier: "Glacier" glacier: "Glaciar"
small: "Pequeño" small: "Pequeño"
large: "Grande" large: "Grande"
fork_title: "Fork de Nueva Versión" fork_title: "Fork de Nueva Versión"

View file

@ -47,7 +47,10 @@ $level-resize-transition-time: 0.5s
line-height: 2vw line-height: 2vw
img img
width: 1.8vw width: 1.8vw
heighT: 1.8vw height: 1.8vw
#duel-stats-view
right: calc(1% + 100px)
bottom: 50px
#control-bar-view .title #control-bar-view .title
left: 20% left: 20%
width: 60% 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 display: none
#gold-view #gold-view
right: 1% right: 1%
#duel-stats-view
right: 230px
bottom: 80px
@include scale(2)
#control-bar-view #control-bar-view
width: 100% width: 100%

View file

@ -29,6 +29,8 @@
#multiplayer-status-view #multiplayer-status-view
#duel-stats-view
#playback-view #playback-view
#thang-hud #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) 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) div(class="gold-amount team-" + team)

View file

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

View file

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

View file

@ -78,6 +78,7 @@ module.exports = class PlayHeroesModal extends ModalView
afterRender: -> afterRender: ->
super() super()
return unless @supermodel.finished() return unless @supermodel.finished()
@playSound 'game-menu-open'
@$el.find('.hero-avatar').addClass 'ie' if @isIE() @$el.find('.hero-avatar').addClass 'ie' if @isIE()
heroes = @heroes.models heroes = @heroes.models
@$el.find('.hero-indicator').each -> @$el.find('.hero-indicator').each ->
@ -334,7 +335,7 @@ module.exports = class PlayHeroesModal extends ModalView
onHidden: -> onHidden: ->
super() super()
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'game-menu-close', volume: 1 @playSound 'game-menu-close'
destroy: -> destroy: ->
clearInterval @heroAnimationInterval 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.standardDeviation = 25 / 3
league.stats.numberOfWinsAndTies = 0 league.stats.numberOfWinsAndTies = 0
league.stats.numberOfLosses = 0 league.stats.numberOfLosses = 0
league.stats.meanStrength ?= 25
league.stats.totalScore ?= 10
newLeagues.push(league) newLeagues.push(league)
unless _.isEqual newLeagues, sessionToUpdate.leagues unless _.isEqual newLeagues, sessionToUpdate.leagues
sessionUpdateObject.leagues = sessionToUpdate.leagues = newLeagues 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. 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 return sampleByLevel callback unless leagueIDs.length and Math.random() > 1 / leagueIDs.length
leagueID = _.sample leagueIDs leagueID = _.sample leagueIDs
findRandomSession {'leagues.leagueID': leagueID, favorRecent: true}, (err, session) -> findRandomSession {'leagues.leagueID': leagueID}, (err, session) ->
if err then return callback err if err then return callback err
unless session then return sampleByLevel callback unless session then return sampleByLevel callback
otherTeam = scoringUtils.calculateOpposingTeam session.team otherTeam = scoringUtils.calculateOpposingTeam session.team