diff --git a/app/lib/surface/Label.coffee b/app/lib/surface/Label.coffee index 1aeed7d1c..1f134ef2b 100644 --- a/app/lib/surface/Label.coffee +++ b/app/lib/surface/Label.coffee @@ -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] diff --git a/app/lib/surface/Lank.coffee b/app/lib/surface/Lank.coffee index a606054e1..0409316b2 100644 --- a/app/lib/surface/Lank.coffee +++ b/app/lib/surface/Lank.coffee @@ -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 diff --git a/app/locale/bg.coffee b/app/locale/bg.coffee index 889ff849d..7e366f29c 100644 --- a/app/locale/bg.coffee +++ b/app/locale/bg.coffee @@ -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" diff --git a/app/locale/es-419.coffee b/app/locale/es-419.coffee index fd9ff3469..a168b7ac1 100644 --- a/app/locale/es-419.coffee +++ b/app/locale/es-419.coffee @@ -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 we’ll 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" diff --git a/app/styles/play/level.sass b/app/styles/play/level.sass index cd1ba311e..82ad555d4 100644 --- a/app/styles/play/level.sass +++ b/app/styles/play/level.sass @@ -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% diff --git a/app/styles/play/level/duel-stats-view.sass b/app/styles/play/level/duel-stats-view.sass new file mode 100644 index 000000000..7d0cbb1ec --- /dev/null +++ b/app/styles/play/level/duel-stats-view.sass @@ -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 diff --git a/app/styles/play/spectate.sass b/app/styles/play/spectate.sass index 74b94a609..ee8280831 100644 --- a/app/styles/play/spectate.sass +++ b/app/styles/play/spectate.sass @@ -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% diff --git a/app/templates/play/level.jade b/app/templates/play/level.jade index 9b8dca111..b47086c20 100644 --- a/app/templates/play/level.jade +++ b/app/templates/play/level.jade @@ -29,6 +29,8 @@ #multiplayer-status-view + #duel-stats-view + #playback-view #thang-hud diff --git a/app/templates/play/level/duel-stats-view.jade b/app/templates/play/level/duel-stats-view.jade new file mode 100644 index 000000000..e96f4be47 --- /dev/null +++ b/app/templates/play/level/duel-stats-view.jade @@ -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 + + diff --git a/app/templates/play/level/team_gold.jade b/app/templates/play/level/team_gold.jade index 41d773717..08b0d1b34 100644 --- a/app/templates/play/level/team_gold.jade +++ b/app/templates/play/level/team_gold.jade @@ -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) diff --git a/app/templates/play/spectate.jade b/app/templates/play/spectate.jade index 432c8ad4d..3b1990282 100644 --- a/app/templates/play/spectate.jade +++ b/app/templates/play/spectate.jade @@ -9,5 +9,6 @@ #canvas-top-gradient.gradient #gold-view.secret.expanded #level-chat-view + #duel-stats-view #playback-view #thang-hud diff --git a/app/views/play/SpectateView.coffee b/app/views/play/SpectateView.coffee index edf6796d5..0c7111630 100644 --- a/app/views/play/SpectateView.coffee +++ b/app/views/play/SpectateView.coffee @@ -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 diff --git a/app/views/play/level/DuelStatsView.coffee b/app/views/play/level/DuelStatsView.coffee new file mode 100644 index 000000000..47466a695 --- /dev/null +++ b/app/views/play/level/DuelStatsView.coffee @@ -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 diff --git a/app/views/play/level/PlayLevelView.coffee b/app/views/play/level/PlayLevelView.coffee index 69e866845..024e09498 100644 --- a/app/views/play/level/PlayLevelView.coffee +++ b/app/views/play/level/PlayLevelView.coffee @@ -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: -> diff --git a/app/views/play/modal/PlayHeroesModal.coffee b/app/views/play/modal/PlayHeroesModal.coffee index 63c9258f8..32d0d90fa 100644 --- a/app/views/play/modal/PlayHeroesModal.coffee +++ b/app/views/play/modal/PlayHeroesModal.coffee @@ -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 diff --git a/scripts/mongodb/migrations/2015-09-19-add-clan-leagues-to-sessions.js b/scripts/mongodb/migrations/2015-09-19-add-clan-leagues-to-sessions.js new file mode 100644 index 000000000..a081bd1a7 --- /dev/null +++ b/scripts/mongodb/migrations/2015-09-19-add-clan-leagues-to-sessions.js @@ -0,0 +1,37 @@ +// Add clan leagues to sessions +// Usage: +// mongo
:/