mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-28 18:15:52 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
b50704597a
19 changed files with 116 additions and 633 deletions
|
@ -210,12 +210,12 @@ module.exports = LevelOptions =
|
||||||
'drop-the-flag':
|
'drop-the-flag':
|
||||||
requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', 'right-hand': 'builders-hammer'}
|
requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', 'right-hand': 'builders-hammer'}
|
||||||
restrictedGear: {'right-hand': 'longsword'}
|
restrictedGear: {'right-hand': 'longsword'}
|
||||||
'rich-forager':
|
|
||||||
requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', torso: 'leather-tunic', 'right-hand': 'longsword', 'left-hand': 'bronze-shield'}
|
|
||||||
restrictedGear: {'right-hand': 'builders-hammer'}
|
|
||||||
'deadly-pursuit':
|
'deadly-pursuit':
|
||||||
requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', 'right-hand': 'builders-hammer'}
|
requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', 'right-hand': 'builders-hammer'}
|
||||||
restrictedGear: {'right-hand': 'longsword'}
|
restrictedGear: {'right-hand': 'longsword'}
|
||||||
|
'rich-forager':
|
||||||
|
requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', torso: 'leather-tunic', 'right-hand': 'longsword', 'left-hand': 'bronze-shield'}
|
||||||
|
restrictedGear: {'right-hand': 'builders-hammer'}
|
||||||
'multiplayer-treasure-grove':
|
'multiplayer-treasure-grove':
|
||||||
requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', torso: 'leather-tunic'}
|
requiredGear: {'programming-book': 'programmaticon-i', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', torso: 'leather-tunic'}
|
||||||
restrictedGear: {}
|
restrictedGear: {}
|
||||||
|
|
|
@ -59,7 +59,8 @@ module.exports = Lank = class Lank extends CocoClass
|
||||||
|
|
||||||
constructor: (@thangType, options) ->
|
constructor: (@thangType, options) ->
|
||||||
super()
|
super()
|
||||||
@isMissile = @thangType.get('name') in ['Arrow', 'Spear']
|
spriteName = @thangType.get('name')
|
||||||
|
@isMissile = /(Missile|Arrow|Spear)/.test(spriteName) and not /Tower/.test(spriteName)
|
||||||
@options = _.extend($.extend(true, {}, @options), options)
|
@options = _.extend($.extend(true, {}, @options), options)
|
||||||
@setThang @options.thang
|
@setThang @options.thang
|
||||||
if @thang?
|
if @thang?
|
||||||
|
|
|
@ -13,14 +13,14 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
||||||
|
|
||||||
nav:
|
nav:
|
||||||
play: "Livelli" # The top nav bar entry where players choose which levels to play
|
play: "Livelli" # The top nav bar entry where players choose which levels to play
|
||||||
# community: "Community"
|
community: "Comunità"
|
||||||
editor: "Editor"
|
editor: "Editor"
|
||||||
blog: "Blog"
|
blog: "Blog"
|
||||||
forum: "Forum"
|
forum: "Forum"
|
||||||
account: "Account"
|
account: "Account"
|
||||||
profile: "Profilo"
|
profile: "Profilo"
|
||||||
stats: "Statistiche"
|
stats: "Statistiche"
|
||||||
# code: "Code"
|
# code: "Codice"
|
||||||
admin: "Amministratore" # Only shows up when you are an admin
|
admin: "Amministratore" # Only shows up when you are an admin
|
||||||
home: "Pagina iniziale"
|
home: "Pagina iniziale"
|
||||||
contribute: "Contribuisci"
|
contribute: "Contribuisci"
|
||||||
|
@ -28,7 +28,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
||||||
about: "Informazioni"
|
about: "Informazioni"
|
||||||
contact: "Contatti"
|
contact: "Contatti"
|
||||||
twitter_follow: "Segui"
|
twitter_follow: "Segui"
|
||||||
# teachers: "Teachers"
|
teachers: "Docenti"
|
||||||
|
|
||||||
modal:
|
modal:
|
||||||
close: "Chiudi"
|
close: "Chiudi"
|
||||||
|
@ -50,22 +50,22 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
||||||
spectate: "Spettatore" # Ladder page
|
spectate: "Spettatore" # Ladder page
|
||||||
players: "giocatori" # Hover over a level on /play
|
players: "giocatori" # Hover over a level on /play
|
||||||
hours_played: "ore di gioco" # Hover over a level on /play
|
hours_played: "ore di gioco" # Hover over a level on /play
|
||||||
# items: "Items" # Tooltip on item shop button from /play
|
items: "Oggetti" # Tooltip on item shop button from /play
|
||||||
# unlock: "Unlock" # For purchasing items and heroes
|
unlock: "Sblocca" # For purchasing items and heroes
|
||||||
# confirm: "Confirm"
|
confirm: "Conferma"
|
||||||
# owned: "Owned" # For items you own
|
owned: "In tuo possesso" # For items you own
|
||||||
# locked: "Locked"
|
locked: "Bloccato"
|
||||||
# available: "Available"
|
available: "Disponibile"
|
||||||
# skills_granted: "Skills Granted" # Property documentation details
|
# skills_granted: "Skills Granted" # Property documentation details
|
||||||
# heroes: "Heroes" # Tooltip on hero shop button from /play
|
heroes: "Eroi" # Tooltip on hero shop button from /play
|
||||||
# achievements: "Achievements" # Tooltip on achievement list button from /play
|
# achievements: "Achievements" # Tooltip on achievement list button from /play
|
||||||
# account: "Account" # Tooltip on account button from /play
|
account: "Account" # Tooltip on account button from /play
|
||||||
# settings: "Settings" # Tooltip on settings button from /play
|
settings: "Impostazioni" # Tooltip on settings button from /play
|
||||||
# next: "Next" # Go from choose hero to choose inventory before playing a level
|
next: "Procedi" # Go from choose hero to choose inventory before playing a level
|
||||||
# change_hero: "Change Hero" # Go back from choose inventory to choose hero
|
change_hero: "Cambia Eroe" # Go back from choose inventory to choose hero
|
||||||
# choose_inventory: "Equip Items"
|
# choose_inventory: "Equip Items"
|
||||||
# older_campaigns: "Older Campaigns"
|
older_campaigns: "Campagne precedenti"
|
||||||
# anonymous: "Anonymous Player"
|
anonymous: "Giocatore Anonimo"
|
||||||
level_difficulty: "Difficoltà: "
|
level_difficulty: "Difficoltà: "
|
||||||
campaign_beginner: "Campagne per principianti"
|
campaign_beginner: "Campagne per principianti"
|
||||||
choose_your_level: "Scegli il tuo livello" # The rest of this section is the old play view at /play-old and isn't very important.
|
choose_your_level: "Scegli il tuo livello" # The rest of this section is the old play view at /play-old and isn't very important.
|
||||||
|
@ -82,8 +82,8 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
||||||
campaign_player_created_description: "... nei quali affronterai la creatività dei tuoi compagni <a href=\"/contribute#artisan\">Stregoni Artigiani</a>."
|
campaign_player_created_description: "... nei quali affronterai la creatività dei tuoi compagni <a href=\"/contribute#artisan\">Stregoni Artigiani</a>."
|
||||||
campaign_classic_algorithms: "Algoritmi classici"
|
campaign_classic_algorithms: "Algoritmi classici"
|
||||||
# campaign_classic_algorithms_description: "... in which you learn the most popular algorithms in Computer Science."
|
# campaign_classic_algorithms_description: "... in which you learn the most popular algorithms in Computer Science."
|
||||||
# campaign_forest: "Forest Campaign"
|
campaign_forest: "Campagna nella Foresta"
|
||||||
# campaign_dungeon: "Dungeon Campaign"
|
campaign_dungeon: "Campagna nelle Segrete"
|
||||||
|
|
||||||
login:
|
login:
|
||||||
sign_up: "Crea account"
|
sign_up: "Crea account"
|
||||||
|
@ -109,13 +109,13 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
||||||
send_password: "Invia password di recupero"
|
send_password: "Invia password di recupero"
|
||||||
# recovery_sent: "Recovery email sent."
|
# recovery_sent: "Recovery email sent."
|
||||||
|
|
||||||
# items:
|
items:
|
||||||
# primary: "Primary"
|
primary: "Primario"
|
||||||
# secondary: "Secondary"
|
secondary: "Secondario"
|
||||||
# armor: "Armor"
|
armor: "Armatura"
|
||||||
# accessories: "Accessories"
|
accessories: "Accessori"
|
||||||
# misc: "Misc"
|
misc: "Varie"
|
||||||
# books: "Books"
|
books: "Libri"
|
||||||
|
|
||||||
common:
|
common:
|
||||||
loading: "Caricamento in corso..."
|
loading: "Caricamento in corso..."
|
||||||
|
@ -137,17 +137,17 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
||||||
general:
|
general:
|
||||||
and: "e"
|
and: "e"
|
||||||
name: "Nome"
|
name: "Nome"
|
||||||
# date: "Date"
|
date: "Data"
|
||||||
body: "Testo"
|
body: "Testo"
|
||||||
version: "Versione"
|
version: "Versione"
|
||||||
# commit_msg: "Commit Message"
|
commit_msg: "Messaggio del Commit"
|
||||||
# version_history: "Version History"
|
# version_history: "Version History"
|
||||||
# version_history_for: "Version History for: "
|
# version_history_for: "Version History for: "
|
||||||
# result: "Result"
|
result: "Risultato"
|
||||||
results: "Risultati"
|
results: "Risultati"
|
||||||
description: "Descrizione"
|
description: "Descrizione"
|
||||||
or: "o"
|
or: "o"
|
||||||
# subject: "Subject"
|
subject: "Oggetto"
|
||||||
email: "Email"
|
email: "Email"
|
||||||
password: "Password"
|
password: "Password"
|
||||||
message: "Messaggio"
|
message: "Messaggio"
|
||||||
|
@ -159,11 +159,11 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
||||||
score: "Punteggio"
|
score: "Punteggio"
|
||||||
win: "Vittoria"
|
win: "Vittoria"
|
||||||
loss: "Sconfitta"
|
loss: "Sconfitta"
|
||||||
# tie: "Tie"
|
tie: "Pareggio"
|
||||||
easy: "Facile"
|
easy: "Facile"
|
||||||
medium: "Medio"
|
medium: "Medio"
|
||||||
hard: "Difficile"
|
hard: "Difficile"
|
||||||
# player: "Player"
|
player: "Giocatore"
|
||||||
|
|
||||||
units:
|
units:
|
||||||
second: "secondo"
|
second: "secondo"
|
||||||
|
@ -184,21 +184,21 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
||||||
play_level:
|
play_level:
|
||||||
done: "Fatto"
|
done: "Fatto"
|
||||||
home: "Pagina iniziale" # Not used any more, will be removed soon.
|
home: "Pagina iniziale" # Not used any more, will be removed soon.
|
||||||
# level: "Level" # Like "Level: Dungeons of Kithgard"
|
level: "Livello" # Like "Level: Dungeons of Kithgard"
|
||||||
# skip: "Skip"
|
# skip: "Skip"
|
||||||
game_menu: "Menu"
|
game_menu: "Menu"
|
||||||
guide: "Guida"
|
guide: "Guida"
|
||||||
restart: "Ricomincia"
|
restart: "Ricomincia"
|
||||||
goals: "Obiettivi"
|
goals: "Obiettivi"
|
||||||
# goal: "Goal"
|
goal: "Obiettivo"
|
||||||
# running: "Running..."
|
running: "Eseguo..."
|
||||||
# success: "Success!"
|
success: "Successo!"
|
||||||
incomplete: "Incompleto"
|
incomplete: "Incompleto"
|
||||||
timed_out: "Tempo Scaduto"
|
timed_out: "Tempo Scaduto"
|
||||||
# failing: "Failing"
|
# failing: "Failing"
|
||||||
action_timeline: "Barra temporale delle azioni"
|
action_timeline: "Barra temporale delle azioni"
|
||||||
click_to_select: "Clicca un'unità per selezionarla."
|
click_to_select: "Clicca un'unità per selezionarla."
|
||||||
# reload: "Reload"
|
reload: "Ricarica"
|
||||||
reload_title: "Ricarica tutto il codice?"
|
reload_title: "Ricarica tutto il codice?"
|
||||||
reload_really: "Sei sicuro di voler ricominciare il livello?"
|
reload_really: "Sei sicuro di voler ricominciare il livello?"
|
||||||
reload_confirm: "Ricarica tutto"
|
reload_confirm: "Ricarica tutto"
|
||||||
|
@ -208,7 +208,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
||||||
victory_sign_up_poke: "Vuoi ricevere le ultime novità per email? Crea un account gratuito e ti terremo aggiornato!"
|
victory_sign_up_poke: "Vuoi ricevere le ultime novità per email? Crea un account gratuito e ti terremo aggiornato!"
|
||||||
victory_rate_the_level: "Vota il livello: " # Only in old-style levels.
|
victory_rate_the_level: "Vota il livello: " # Only in old-style levels.
|
||||||
# victory_return_to_ladder: "Return to Ladder"
|
# victory_return_to_ladder: "Return to Ladder"
|
||||||
# victory_play_continue: "Continue"
|
victory_play_continue: "Continua"
|
||||||
# victory_play_skip: "Skip Ahead"
|
# victory_play_skip: "Skip Ahead"
|
||||||
victory_play_next_level: "Gioca il prossimo livello"
|
victory_play_next_level: "Gioca il prossimo livello"
|
||||||
# victory_play_more_practice: "More Practice"
|
# victory_play_more_practice: "More Practice"
|
||||||
|
@ -235,13 +235,13 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
||||||
tome_available_spells: "Incantesimi disponibili"
|
tome_available_spells: "Incantesimi disponibili"
|
||||||
# tome_your_skills: "Your Skills"
|
# tome_your_skills: "Your Skills"
|
||||||
# tome_current_method: "Current Method"
|
# tome_current_method: "Current Method"
|
||||||
# hud_continue_short: "Continue"
|
hud_continue_short: "Continua"
|
||||||
# code_saved: "Code Saved"
|
# code_saved: "Code Saved"
|
||||||
skip_tutorial: "Salta (esc)"
|
skip_tutorial: "Salta (esc)"
|
||||||
# keyboard_shortcuts: "Key Shortcuts"
|
# keyboard_shortcuts: "Key Shortcuts"
|
||||||
loading_ready: "Pronto!"
|
loading_ready: "Pronto!"
|
||||||
# loading_start: "Start Level"
|
# loading_start: "Start Level"
|
||||||
# problem_alert_title: "Fix Your Code"
|
problem_alert_title: "Sistema il codice"
|
||||||
# time_current: "Now:"
|
# time_current: "Now:"
|
||||||
# time_total: "Max:"
|
# time_total: "Max:"
|
||||||
# time_goto: "Go to:"
|
# time_goto: "Go to:"
|
||||||
|
@ -277,7 +277,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
||||||
# 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"
|
||||||
customize_wizard: "Personalizza stregone"
|
customize_wizard: "Personalizza il mago"
|
||||||
|
|
||||||
game_menu:
|
game_menu:
|
||||||
inventory_tab: "Inventario"
|
inventory_tab: "Inventario"
|
||||||
|
|
|
@ -276,7 +276,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
tip_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: "Поспешная оптимизация - корень всех зол. - Donald Knuth"
|
tip_premature_optimization: "Поспешная оптимизация - корень всех зол. - Donald Knuth"
|
||||||
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
|
tip_brute_force: "Когда сомневаешься используй грубую силу. - Кен Томпсон"
|
||||||
customize_wizard: "Настройки волшебника"
|
customize_wizard: "Настройки волшебника"
|
||||||
|
|
||||||
game_menu:
|
game_menu:
|
||||||
|
@ -301,7 +301,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
should_equip: "(двойной клик чтобы одеть)"
|
should_equip: "(двойной клик чтобы одеть)"
|
||||||
equipped: "(выбранный)"
|
equipped: "(выбранный)"
|
||||||
locked: "(заблокированный)"
|
locked: "(заблокированный)"
|
||||||
# restricted: "(restricted in this level)"
|
restricted: "(запрещен в этом уровне)"
|
||||||
|
|
||||||
choose_hero:
|
choose_hero:
|
||||||
choose_hero: "Выберите героя"
|
choose_hero: "Выберите героя"
|
||||||
|
@ -315,9 +315,9 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
io_blurb: "Простой, но непонятный."
|
io_blurb: "Простой, но непонятный."
|
||||||
status: "Статус"
|
status: "Статус"
|
||||||
weapons: "Оружие"
|
weapons: "Оружие"
|
||||||
# weapons_warrior: "Swords - Short Range, No Magic"
|
weapons_warrior: "Меч - ближний бой, не магический"
|
||||||
# weapons_ranger: "Crossbows, Guns - Long Range, No Magic"
|
weapons_ranger: "Арбалеты, ружья - дальнобойные, не магические"
|
||||||
# weapons_wizard: "Wands, Staffs - Long Range, Magic"
|
weapons_wizard: "Палочки, посохи - дальнобойные, магические"
|
||||||
attack: "Урон" # Can also translate as "Attack"
|
attack: "Урон" # Can also translate as "Attack"
|
||||||
health: "Жизнь"
|
health: "Жизнь"
|
||||||
speed: "Скорость"
|
speed: "Скорость"
|
||||||
|
|
|
@ -97,19 +97,23 @@ module.exports = class Level extends CocoModel
|
||||||
placeholdersUsed[placeholderComponent.original] = true
|
placeholdersUsed[placeholderComponent.original] = true
|
||||||
placeholderConfig = placeholderComponent.config ? {}
|
placeholderConfig = placeholderComponent.config ? {}
|
||||||
if placeholderConfig.pos # Pull in Physical pos x and y
|
if placeholderConfig.pos # Pull in Physical pos x and y
|
||||||
|
levelThangComponent.config ?= {}
|
||||||
levelThangComponent.config.pos ?= {}
|
levelThangComponent.config.pos ?= {}
|
||||||
levelThangComponent.config.pos.x = placeholderConfig.pos.x
|
levelThangComponent.config.pos.x = placeholderConfig.pos.x
|
||||||
levelThangComponent.config.pos.y = placeholderConfig.pos.y
|
levelThangComponent.config.pos.y = placeholderConfig.pos.y
|
||||||
levelThangComponent.config.rotation = placeholderConfig.rotation
|
levelThangComponent.config.rotation = placeholderConfig.rotation
|
||||||
else if placeholderConfig.team # Pull in Allied team
|
else if placeholderConfig.team # Pull in Allied team
|
||||||
|
levelThangComponent.config ?= {}
|
||||||
levelThangComponent.config.team = placeholderConfig.team
|
levelThangComponent.config.team = placeholderConfig.team
|
||||||
else if placeholderConfig.significantProperty # For levels where we cheat on what counts as an enemy
|
else if placeholderConfig.significantProperty # For levels where we cheat on what counts as an enemy
|
||||||
|
levelThangComponent.config ?= {}
|
||||||
levelThangComponent.config.significantProperty = placeholderConfig.significantProperty
|
levelThangComponent.config.significantProperty = placeholderConfig.significantProperty
|
||||||
else if placeholderConfig.programmableMethods
|
else if placeholderConfig.programmableMethods
|
||||||
# Take the ThangType default Programmable and merge level-specific Component config into it
|
# Take the ThangType default Programmable and merge level-specific Component config into it
|
||||||
copy = $.extend true, {}, placeholderConfig
|
copy = $.extend true, {}, placeholderConfig
|
||||||
levelThangComponent.config = _.merge copy, levelThangComponent.config
|
levelThangComponent.config = _.merge copy, levelThangComponent.config
|
||||||
else if placeholderConfig.extraHUDProperties
|
else if placeholderConfig.extraHUDProperties
|
||||||
|
levelThangComponent.config ?= {}
|
||||||
levelThangComponent.config.extraHUDProperties = _.union(levelThangComponent.config.extraHUDProperties ? [], placeholderConfig.extraHUDProperties)
|
levelThangComponent.config.extraHUDProperties = _.union(levelThangComponent.config.extraHUDProperties ? [], placeholderConfig.extraHUDProperties)
|
||||||
|
|
||||||
if isHero
|
if isHero
|
||||||
|
|
|
@ -19,6 +19,7 @@ module.exports = class ThangType extends CocoModel
|
||||||
'robot-walker': '5301696ad82649ec2c0c9b0d'
|
'robot-walker': '5301696ad82649ec2c0c9b0d'
|
||||||
'michael-heasell': '53e126a4e06b897606d38bef'
|
'michael-heasell': '53e126a4e06b897606d38bef'
|
||||||
'ian-elliott': '53e12be0d042f23505c3023b'
|
'ian-elliott': '53e12be0d042f23505c3023b'
|
||||||
|
'ninja': '52fc0ed77e01835453bd8f6c'
|
||||||
@items:
|
@items:
|
||||||
'simple-boots': '53e237bf53457600003e3f05'
|
'simple-boots': '53e237bf53457600003e3f05'
|
||||||
urlRoot: '/db/thang.type'
|
urlRoot: '/db/thang.type'
|
||||||
|
@ -305,7 +306,7 @@ module.exports = class ThangType extends CocoModel
|
||||||
['Warrior', 'Ranger', 'Wizard']
|
['Warrior', 'Ranger', 'Wizard']
|
||||||
|
|
||||||
getHeroStats: ->
|
getHeroStats: ->
|
||||||
# Translate from raw hero properties into appropriate display values for the ChooseHeroView.
|
# Translate from raw hero properties into appropriate display values for the PlayHeroesModal.
|
||||||
# Adapted from https://docs.google.com/a/codecombat.com/spreadsheets/d/1BGI1bzT4xHvWA81aeyIaCKWWw9zxn7-MwDdydmB5vw4/edit#gid=809922675
|
# Adapted from https://docs.google.com/a/codecombat.com/spreadsheets/d/1BGI1bzT4xHvWA81aeyIaCKWWw9zxn7-MwDdydmB5vw4/edit#gid=809922675
|
||||||
return unless heroClass = @get('heroClass')
|
return unless heroClass = @get('heroClass')
|
||||||
components = @get('components') or []
|
components = @get('components') or []
|
||||||
|
|
|
@ -85,7 +85,10 @@ module.exports = class User extends CocoModel
|
||||||
gemsSpent = @get('spent') ? 0
|
gemsSpent = @get('spent') ? 0
|
||||||
gemsEarned + gemsPurchased - gemsSpent
|
gemsEarned + gemsPurchased - gemsSpent
|
||||||
|
|
||||||
heroes: -> (me.get('earned')?.heroes ? []).concat(me.get('purchased')?.heroes ? [])
|
heroes: ->
|
||||||
|
heroes = (me.get('earned')?.heroes ? []).concat(me.get('purchased')?.heroes ? []).concat([ThangType.heroes.captain, ThangType.heroes.knight])
|
||||||
|
heroes = heroes.concat [ThangType.heroes.ninja, ThangType.heroes.librarian] if me.isAdmin()
|
||||||
|
heroes
|
||||||
items: -> (me.get('earned')?.items ? []).concat(me.get('purchased')?.items ? []).concat([ThangType.items['simple-boots']])
|
items: -> (me.get('earned')?.items ? []).concat(me.get('purchased')?.items ? []).concat([ThangType.items['simple-boots']])
|
||||||
levels: -> (me.get('earned')?.levels ? []).concat(me.get('purchased')?.levels ? [])
|
levels: -> (me.get('earned')?.levels ? []).concat(me.get('purchased')?.levels ? [])
|
||||||
ownsHero: (heroOriginal) -> heroOriginal in @heroes()
|
ownsHero: (heroOriginal) -> heroOriginal in @heroes()
|
||||||
|
|
|
@ -1,176 +0,0 @@
|
||||||
@import "app/styles/mixins"
|
|
||||||
@import "app/styles/bootstrap/variables"
|
|
||||||
|
|
||||||
$maxHeroPortraitSize: 100px
|
|
||||||
$minHeroPortraitSize: 50px
|
|
||||||
|
|
||||||
$heroCanvasHeight: 265px
|
|
||||||
|
|
||||||
#choose-hero-view
|
|
||||||
|
|
||||||
#hero-carousel
|
|
||||||
margin: 0 auto 20px auto
|
|
||||||
|
|
||||||
.carousel-indicator-container
|
|
||||||
height: $maxHeroPortraitSize
|
|
||||||
text-align: center
|
|
||||||
width: 100%
|
|
||||||
margin-bottom: 10px
|
|
||||||
margin-top: 10px
|
|
||||||
position: relative
|
|
||||||
z-index: 1
|
|
||||||
|
|
||||||
.carousel-indicators
|
|
||||||
position: static
|
|
||||||
height: $maxHeroPortraitSize
|
|
||||||
width: 100%
|
|
||||||
margin-left: 0
|
|
||||||
background-repeat: no-repeat
|
|
||||||
|
|
||||||
.hero-indicator
|
|
||||||
width: $maxHeroPortraitSize
|
|
||||||
height: $maxHeroPortraitSize
|
|
||||||
margin: 0px 3px
|
|
||||||
border: 2px solid black
|
|
||||||
border-radius: 2px
|
|
||||||
position: relative
|
|
||||||
|
|
||||||
.hero-avatar
|
|
||||||
width: 100%
|
|
||||||
height: 100%
|
|
||||||
background-size: contain
|
|
||||||
|
|
||||||
&.initialized
|
|
||||||
@include transition(0.5s ease)
|
|
||||||
|
|
||||||
&.active
|
|
||||||
border-color: gold
|
|
||||||
|
|
||||||
&.locked
|
|
||||||
.hero-avatar
|
|
||||||
@include filter(contrast(50%) brightness(65%))
|
|
||||||
|
|
||||||
.lock-indicator
|
|
||||||
position: absolute
|
|
||||||
width: 40%
|
|
||||||
left: 30%
|
|
||||||
top: 30%
|
|
||||||
@include filter(invert(90%))
|
|
||||||
|
|
||||||
.hero-item
|
|
||||||
|
|
||||||
&.locked
|
|
||||||
@include opacity(0.6)
|
|
||||||
|
|
||||||
canvas, .hero-feature-image, .hero-stats
|
|
||||||
width: 45%
|
|
||||||
height: $heroCanvasHeight
|
|
||||||
float: left
|
|
||||||
|
|
||||||
canvas, .hero-feature-image
|
|
||||||
margin-left: 5%
|
|
||||||
|
|
||||||
.hero-feature-image
|
|
||||||
display: none
|
|
||||||
text-align: center
|
|
||||||
|
|
||||||
img
|
|
||||||
height: $heroCanvasHeight
|
|
||||||
|
|
||||||
.hero-stats
|
|
||||||
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.6)
|
|
||||||
|
|
||||||
.hero-class, .hero-status, .hero-skills
|
|
||||||
font-size: 14px
|
|
||||||
|
|
||||||
.hero-stat
|
|
||||||
margin: 10px 0
|
|
||||||
|
|
||||||
.progress
|
|
||||||
width: 90%
|
|
||||||
text-align: center
|
|
||||||
height: 26px
|
|
||||||
position: relative
|
|
||||||
margin: 0
|
|
||||||
|
|
||||||
.hero-stat-label
|
|
||||||
position: absolute
|
|
||||||
width: 100%
|
|
||||||
font-size: 18px
|
|
||||||
text-transform: uppercase
|
|
||||||
color: white
|
|
||||||
text-shadow: 0px 1px 0px black, 0px -1px 0px black, -1px 0px 0px black, 1px 0px 0px black
|
|
||||||
|
|
||||||
.carousel-control.left
|
|
||||||
border-top-left-radius: 10px
|
|
||||||
border-bottom-left-radius: 10px
|
|
||||||
|
|
||||||
.carousel-control.right
|
|
||||||
border-top-right-radius: 10px
|
|
||||||
border-bottom-right-radius: 10px
|
|
||||||
|
|
||||||
.carousel-control
|
|
||||||
height: 75%
|
|
||||||
top: 30%
|
|
||||||
width: 10%
|
|
||||||
|
|
||||||
.select-group
|
|
||||||
display: inline-block
|
|
||||||
min-height: 20px
|
|
||||||
margin-top: 10px
|
|
||||||
margin-bottom: 10px
|
|
||||||
padding-left: 20px
|
|
||||||
vertical-align: middle
|
|
||||||
|
|
||||||
label
|
|
||||||
margin-right: 20px
|
|
||||||
margin-bottom: 0
|
|
||||||
text-align: top
|
|
||||||
|
|
||||||
&[for="option-code-language"]
|
|
||||||
vertical-align: top
|
|
||||||
margin-top: 10px
|
|
||||||
|
|
||||||
select
|
|
||||||
font-size: 18px
|
|
||||||
|
|
||||||
.fancy-select
|
|
||||||
display: inline-block
|
|
||||||
|
|
||||||
.trigger, .options
|
|
||||||
text-transform: none
|
|
||||||
background-color: #def
|
|
||||||
|
|
||||||
.options
|
|
||||||
padding-left: 5px
|
|
||||||
overflow: visible
|
|
||||||
|
|
||||||
.selected
|
|
||||||
color: #111
|
|
||||||
|
|
||||||
.hover
|
|
||||||
color: #111
|
|
||||||
background-color: #abc
|
|
||||||
|
|
||||||
.options
|
|
||||||
li
|
|
||||||
padding-left: 40px
|
|
||||||
background: transparent url(/images/common/code_languages/javascript_small.png) no-repeat left center
|
|
||||||
background-size: 32px 32px
|
|
||||||
margin-bottom: -1px
|
|
||||||
|
|
||||||
&[data-value="python"]
|
|
||||||
background-image: url(/images/common/code_languages/python_small.png)
|
|
||||||
&[data-value="coffeescript"]
|
|
||||||
background-image: url(/images/common/code_languages/coffeescript_small.png)
|
|
||||||
&[data-value="clojure"]
|
|
||||||
background-image: url(/images/common/code_languages/clojure_small.png)
|
|
||||||
&[data-value="lua"]
|
|
||||||
background-image: url(/images/common/code_languages/lua_small.png)
|
|
||||||
&[data-value="io"]
|
|
||||||
background-image: url(/images/common/code_languages/io_small.png)
|
|
||||||
|
|
||||||
body.ipad #choose-hero-view
|
|
||||||
// iPad is Python-only for now.
|
|
||||||
.form
|
|
||||||
display: none
|
|
|
@ -152,7 +152,7 @@
|
||||||
.hamburger span.icon-bar
|
.hamburger span.icon-bar
|
||||||
background-color: $control-yellow-highlight
|
background-color: $control-yellow-highlight
|
||||||
|
|
||||||
#level-done-button, #next-game-button
|
#level-done-button, #next-game-button, #control-bar-sign-up-button
|
||||||
top: 7px
|
top: 7px
|
||||||
font-size: 13px
|
font-size: 13px
|
||||||
height: 24px
|
height: 24px
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
#hero-carousel.carousel.slide(data-interval=0)
|
|
||||||
.carousel-indicator-container
|
|
||||||
ol.carousel-indicators
|
|
||||||
for hero, index in heroes
|
|
||||||
li(data-hero-id=hero.get('original'), title=hero.get('name'), data-slide-to=index, data-target="#hero-carousel", class="hero-indicator" + (hero.locked ? " locked" : ""))
|
|
||||||
.hero-avatar
|
|
||||||
if hero.locked
|
|
||||||
img.lock-indicator(src="/images/pages/game-menu/lock.png")
|
|
||||||
|
|
||||||
.carousel-inner
|
|
||||||
for hero in heroes
|
|
||||||
- var info = heroInfo[hero.get('slug')]
|
|
||||||
div(class="item hero-item" + (hero.locked ? " locked" : ""), data-hero-id=hero.get('original'))
|
|
||||||
canvas.hero-canvas
|
|
||||||
.hero-feature-image
|
|
||||||
img
|
|
||||||
.hero-stats
|
|
||||||
h2= info.fullName
|
|
||||||
//.hero-description= info.description // Not until we have written the descriptions.
|
|
||||||
.hero-status
|
|
||||||
span(data-i18n="choose_hero.status") Status
|
|
||||||
span.spr :
|
|
||||||
if hero.locked
|
|
||||||
| #{info.status}
|
|
||||||
else
|
|
||||||
| Available
|
|
||||||
.hero-class
|
|
||||||
span(data-i18n="choose_hero.weapons") Weapons
|
|
||||||
span.spr :
|
|
||||||
| #{info.weapons}
|
|
||||||
for statInfo in [{name: 'attack', color: 'danger'}, {name: 'health', color: 'info'}, {name: 'speed', color: 'success'}]
|
|
||||||
- var tooltip = "";
|
|
||||||
- if (statInfo.name == 'attack')
|
|
||||||
- tooltip = Math.round(100 * info[statInfo.name + 'Factor']) + '% ' + info.class.toLowerCase() + ' weapon damage';
|
|
||||||
- else if (statInfo.name == 'health')
|
|
||||||
- tooltip = Math.round(100 * info[statInfo.name + 'Factor']) + '% ' + info.class.toLowerCase() + ' armor health';
|
|
||||||
- else if (statInfo.name == 'speed')
|
|
||||||
- tooltip = info.speedAbsolute + ' meters per second';
|
|
||||||
.hero-stat(title=tooltip)
|
|
||||||
.progress
|
|
||||||
div(class="progress-bar progress-bar-" + statInfo.color, style="width: " + (10 * info[statInfo.name]) + "%")
|
|
||||||
.hero-stat-label
|
|
||||||
span(data-i18n="choose_hero." + statInfo.name)
|
|
||||||
span.spr :
|
|
||||||
| #{info[statInfo.name]}
|
|
||||||
|
|
||||||
if info.skills
|
|
||||||
.hero-skills
|
|
||||||
span(data-i18n="choose_hero.skills") Skills
|
|
||||||
span.spr :
|
|
||||||
for skill in info.skills
|
|
||||||
code.spl.spr= skill
|
|
||||||
a.carousel-control.left(role="button", data-slide="prev", href="#hero-carousel")
|
|
||||||
span.glyphicon.glyphicon-chevron-left
|
|
||||||
a.carousel-control.right(role="button", data-slide="next", href="#hero-carousel")
|
|
||||||
span.glyphicon.glyphicon-chevron-right
|
|
||||||
|
|
||||||
|
|
||||||
.form
|
|
||||||
.form-group.select-group
|
|
||||||
//span.help-block(data-i18n="choose_hero.programming_language_description") Which programming language do you want to use?
|
|
||||||
label.control-label(for="option-code-language", data-i18n="choose_hero.programming_language") Programming Language
|
|
||||||
select#option-code-language(name="code-language")
|
|
||||||
for option in codeLanguages
|
|
||||||
option(value=option.id, selected=codeLanguage === option.id)= option.name
|
|
|
@ -27,3 +27,6 @@
|
||||||
button.btn.btn-xs.btn-inverse.banner#next-game-button(title="Next Game", data-i18n="play_level.next-game") Next game!
|
button.btn.btn-xs.btn-inverse.banner#next-game-button(title="Next Game", data-i18n="play_level.next-game") Next game!
|
||||||
|
|
||||||
button.btn.btn-xs.btn-primary.banner#level-done-button(data-i18n="play_level.done") Done
|
button.btn.btn-xs.btn-primary.banner#level-done-button(data-i18n="play_level.done") Done
|
||||||
|
|
||||||
|
if me.get('anonymous')
|
||||||
|
button.btn.btn-xs.btn-primary.banner#control-bar-sign-up-button(data-toggle='coco-modal', data-target='modal/AuthModal', data-i18n="signup.sign_up")
|
||||||
|
|
|
@ -1,293 +0,0 @@
|
||||||
CocoView = require 'views/kinds/CocoView'
|
|
||||||
template = require 'templates/game-menu/choose-hero-view'
|
|
||||||
{me} = require 'lib/auth'
|
|
||||||
ThangType = require 'models/ThangType'
|
|
||||||
CocoCollection = require 'collections/CocoCollection'
|
|
||||||
SpriteBuilder = require 'lib/sprites/SpriteBuilder'
|
|
||||||
AudioPlayer = require 'lib/AudioPlayer'
|
|
||||||
|
|
||||||
module.exports = class ChooseHeroView extends CocoView
|
|
||||||
id: 'choose-hero-view'
|
|
||||||
className: 'tab-pane'
|
|
||||||
template: template
|
|
||||||
|
|
||||||
events:
|
|
||||||
'slide.bs.carousel #hero-carousel': 'onHeroChanged'
|
|
||||||
'change #option-code-language': 'onCodeLanguageChanged'
|
|
||||||
|
|
||||||
shortcuts:
|
|
||||||
'left': -> @$el.find('#hero-carousel').carousel('prev') if @heroes.models.length and not @$el.hasClass 'secret'
|
|
||||||
'right': -> @$el.find('#hero-carousel').carousel('next') if @heroes.models.length and not @$el.hasClass 'secret'
|
|
||||||
|
|
||||||
constructor: (options) ->
|
|
||||||
super options
|
|
||||||
@heroes = new CocoCollection([], {model: ThangType})
|
|
||||||
@heroes.url = '/db/thang.type?view=heroes&project=original,name,slug,soundTriggers,featureImage,gems,heroClass,description,components'
|
|
||||||
@supermodel.loadCollection(@heroes, 'heroes')
|
|
||||||
@stages = {}
|
|
||||||
|
|
||||||
destroy: ->
|
|
||||||
for heroIndex, stage of @stages
|
|
||||||
createjs.Ticker.removeEventListener "tick", stage
|
|
||||||
stage.removeAllChildren()
|
|
||||||
super()
|
|
||||||
|
|
||||||
getRenderData: (context={}) ->
|
|
||||||
context = super(context)
|
|
||||||
context.heroes = @heroes.models
|
|
||||||
hero.locked = temporaryHeroInfo[hero.get('slug')].status is 'Locked' and not me.ownsHero hero.get('original') for hero in context.heroes
|
|
||||||
context.codeLanguages = [
|
|
||||||
{id: 'python', name: 'Python (Default)'}
|
|
||||||
{id: 'javascript', name: 'JavaScript'}
|
|
||||||
{id: 'coffeescript', name: 'CoffeeScript'}
|
|
||||||
{id: 'clojure', name: 'Clojure (Experimental)'}
|
|
||||||
{id: 'lua', name: 'Lua (Experimental)'}
|
|
||||||
{id: 'io', name: 'Io (Experimental)'}
|
|
||||||
]
|
|
||||||
context.codeLanguage = @codeLanguage = @options.session.get('codeLanguage') ? me.get('aceConfig')?.language ? 'python'
|
|
||||||
context.heroInfo = temporaryHeroInfo
|
|
||||||
context
|
|
||||||
|
|
||||||
afterRender: ->
|
|
||||||
super()
|
|
||||||
return unless @supermodel.finished()
|
|
||||||
heroes = @heroes.models
|
|
||||||
@$el.find('.hero-indicator').each ->
|
|
||||||
heroID = $(@).data('hero-id')
|
|
||||||
hero = _.find heroes, (hero) -> hero.get('original') is heroID
|
|
||||||
$(@).find('.hero-avatar').css('background-image', "url(#{hero.getPortraitURL()})").tooltip()
|
|
||||||
_.defer => $(@).addClass 'initialized'
|
|
||||||
@canvasWidth = 313 # @$el.find('canvas').width() # unreliable, whatever
|
|
||||||
@canvasHeight = @$el.find('canvas').height()
|
|
||||||
heroConfig = @options.session.get('heroConfig') ? me.get('heroConfig') ? {}
|
|
||||||
heroIndex = Math.max 0, _.findIndex(heroes, ((hero) -> hero.get('original') is heroConfig.thangType))
|
|
||||||
@$el.find(".hero-item:nth-child(#{heroIndex + 1}), .hero-indicator:nth-child(#{heroIndex + 1})").addClass('active')
|
|
||||||
@onHeroChanged direction: null, relatedTarget: @$el.find('.hero-item')[heroIndex]
|
|
||||||
@$el.find('.hero-stat').tooltip()
|
|
||||||
@buildCodeLanguages()
|
|
||||||
|
|
||||||
onHeroChanged: (e) ->
|
|
||||||
direction = e.direction # 'left' or 'right'
|
|
||||||
heroItem = $(e.relatedTarget)
|
|
||||||
hero = _.find @heroes.models, (hero) -> hero.get('original') is heroItem.data('hero-id')
|
|
||||||
return console.error "Couldn't find hero from heroItem:", heroItem unless hero
|
|
||||||
heroIndex = heroItem.index()
|
|
||||||
@$el.find('.hero-indicator').each ->
|
|
||||||
distance = Math.min 3, Math.abs $(@).index() - heroIndex
|
|
||||||
size = 100 - (50 / 3) * distance
|
|
||||||
$(@).css width: size, height: size, top: -(100 - size) / 2
|
|
||||||
heroInfo = temporaryHeroInfo[hero.get('slug')]
|
|
||||||
locked = heroInfo.status is 'Locked' and not me.ownsHero ThangType.heroes[hero.get('slug')]
|
|
||||||
hero = @loadHero hero, heroIndex
|
|
||||||
@preloadHero heroIndex + 1
|
|
||||||
@preloadHero heroIndex - 1
|
|
||||||
@selectedHero = hero unless locked
|
|
||||||
Backbone.Mediator.publish 'level:hero-selection-updated', hero: @selectedHero
|
|
||||||
$('#choose-inventory-button').prop 'disabled', locked
|
|
||||||
|
|
||||||
getFullHero: (original) ->
|
|
||||||
url = "/db/thang.type/#{original}/version"
|
|
||||||
if fullHero = @supermodel.getModel url
|
|
||||||
return fullHero
|
|
||||||
fullHero = new ThangType()
|
|
||||||
fullHero.setURL url
|
|
||||||
fullHero = (@supermodel.loadModel fullHero, 'thang').model
|
|
||||||
fullHero
|
|
||||||
|
|
||||||
preloadHero: (heroIndex) ->
|
|
||||||
return unless hero = @heroes.models[heroIndex]
|
|
||||||
@loadHero hero, heroIndex, true
|
|
||||||
|
|
||||||
loadHero: (hero, heroIndex, preloading=false) ->
|
|
||||||
createjs.Ticker.removeEventListener 'tick', stage for stage in _.values @stages
|
|
||||||
if featureImage = hero.get 'featureImage'
|
|
||||||
$(".hero-item[data-hero-id='#{hero.get('original')}'] canvas").hide()
|
|
||||||
$(".hero-item[data-hero-id='#{hero.get('original')}'] .hero-feature-image").show().find('img').prop('src', '/file/' + featureImage)
|
|
||||||
@playSelectionSound hero unless preloading
|
|
||||||
return hero
|
|
||||||
createjs.Ticker.setFPS 30 # In case we paused it from being inactive somewhere else
|
|
||||||
if stage = @stages[heroIndex]
|
|
||||||
unless preloading
|
|
||||||
_.defer -> createjs.Ticker.addEventListener 'tick', stage # Deferred, otherwise it won't start updating for some reason.
|
|
||||||
@playSelectionSound hero
|
|
||||||
return hero
|
|
||||||
fullHero = @getFullHero hero.get 'original'
|
|
||||||
onLoaded = =>
|
|
||||||
return unless canvas = $(".hero-item[data-hero-id='#{fullHero.get('original')}'] canvas")
|
|
||||||
canvas.show().prop width: @canvasWidth, height: @canvasHeight
|
|
||||||
builder = new SpriteBuilder(fullHero)
|
|
||||||
movieClip = builder.buildMovieClip(fullHero.get('actions').attack?.animation ? fullHero.get('actions').idle.animation)
|
|
||||||
movieClip.scaleX = movieClip.scaleY = canvas.prop('height') / 120 # Average hero height is ~110px tall at normal resolution
|
|
||||||
if fullHero.get('name') in ['Knight', 'Robot Walker'] # These are too big, so shrink them.
|
|
||||||
movieClip.scaleX *= 0.7
|
|
||||||
movieClip.scaleY *= 0.7
|
|
||||||
movieClip.regX = -fullHero.get('positions').registration.x
|
|
||||||
movieClip.regY = -fullHero.get('positions').registration.y
|
|
||||||
movieClip.x = canvas.prop('width') * 0.5
|
|
||||||
movieClip.y = canvas.prop('height') * 0.925 # This is where the feet go.
|
|
||||||
stage = new createjs.Stage(canvas[0])
|
|
||||||
@stages[heroIndex] = stage
|
|
||||||
stage.addChild movieClip
|
|
||||||
stage.update()
|
|
||||||
movieClip.gotoAndPlay 0
|
|
||||||
unless preloading
|
|
||||||
createjs.Ticker.addEventListener 'tick', stage
|
|
||||||
@playSelectionSound hero
|
|
||||||
if fullHero.loaded
|
|
||||||
_.defer onLoaded
|
|
||||||
else
|
|
||||||
@listenToOnce fullHero, 'sync', onLoaded
|
|
||||||
fullHero
|
|
||||||
|
|
||||||
playSelectionSound: (hero) ->
|
|
||||||
return if @$el.hasClass 'secret'
|
|
||||||
@currentSoundInstance?.stop()
|
|
||||||
return unless sounds = hero.get('soundTriggers')?.selected
|
|
||||||
return unless sound = sounds[Math.floor Math.random() * sounds.length]
|
|
||||||
name = AudioPlayer.nameForSoundReference sound
|
|
||||||
AudioPlayer.preloadSoundReference sound
|
|
||||||
@currentSoundInstance = AudioPlayer.playSound name, 1
|
|
||||||
@currentSoundInstance
|
|
||||||
|
|
||||||
buildCodeLanguages: ->
|
|
||||||
$select = @$el.find('#option-code-language')
|
|
||||||
$select.fancySelect().parent().find('.options li').each ->
|
|
||||||
languageName = $(@).text()
|
|
||||||
languageID = $(@).data('value')
|
|
||||||
blurb = $.i18n.t("choose_hero.#{languageID}_blurb")
|
|
||||||
$(@).text("#{languageName} - #{blurb}")
|
|
||||||
|
|
||||||
onCodeLanguageChanged: (e) ->
|
|
||||||
@codeLanguage = @$el.find('#option-code-language').val()
|
|
||||||
@codeLanguageChanged = true
|
|
||||||
|
|
||||||
onShown: ->
|
|
||||||
# Called when we switch tabs to this within the modal
|
|
||||||
|
|
||||||
onHidden: ->
|
|
||||||
# Called when the modal itself is dismissed
|
|
||||||
|
|
||||||
|
|
||||||
temporaryHeroInfo =
|
|
||||||
knight:
|
|
||||||
fullName: 'Tharin Thunderfist'
|
|
||||||
weapons: 'Swords - Short Range, No Magic'
|
|
||||||
class: 'Warrior'
|
|
||||||
description: 'Beefcake! Beefcaaake!'
|
|
||||||
status: 'Available'
|
|
||||||
attack: 8
|
|
||||||
attackFactor: 1.2
|
|
||||||
health: 8.5
|
|
||||||
healthFactor: 1.4
|
|
||||||
speed: 1.5
|
|
||||||
speedAbsolute: 6
|
|
||||||
|
|
||||||
captain:
|
|
||||||
fullName: 'Captain Anya Weston'
|
|
||||||
weapons: 'Swords - Short Range, No Magic'
|
|
||||||
class: 'Warrior'
|
|
||||||
description: 'Don\'t bother me, I\'m winning this fight for you.'
|
|
||||||
status: 'Available'
|
|
||||||
attack: 8
|
|
||||||
attackFactor: 1.2
|
|
||||||
health: 8.5
|
|
||||||
healthFactor: 1.4
|
|
||||||
speed: 1.5
|
|
||||||
speedAbsolute: 6
|
|
||||||
|
|
||||||
thoktar:
|
|
||||||
fullName: 'Thoktar the Devourer'
|
|
||||||
weapons: 'Wands, Staffs - Long Range, Magic'
|
|
||||||
class: 'Wizard'
|
|
||||||
description: '???'
|
|
||||||
status: 'Locked'
|
|
||||||
attack: 5
|
|
||||||
attackFactor: 2
|
|
||||||
health: 4.5
|
|
||||||
healthFactor: 1.4
|
|
||||||
speed: 2.5
|
|
||||||
speedAbsolute: 7
|
|
||||||
skills: ['summonElemental', 'devour']
|
|
||||||
|
|
||||||
equestrian:
|
|
||||||
fullName: 'Rider Reynaldo'
|
|
||||||
weapons: 'Crossbows, Guns - Long Range, No Magic'
|
|
||||||
class: 'Ranger'
|
|
||||||
description: '???'
|
|
||||||
status: 'Locked'
|
|
||||||
attack: 6
|
|
||||||
attackFactor: 1.4
|
|
||||||
health: 7
|
|
||||||
healthFactor: 1.8
|
|
||||||
speed: 1.5
|
|
||||||
speedAbsolute: 6
|
|
||||||
skills: ['hide']
|
|
||||||
|
|
||||||
'potion-master':
|
|
||||||
fullName: 'Master Snake'
|
|
||||||
weapons: 'Wands, Staffs - Long Range, Magic'
|
|
||||||
class: 'Wizard'
|
|
||||||
description: '???'
|
|
||||||
status: 'Locked'
|
|
||||||
attack: 2
|
|
||||||
attackFactor: 0.833
|
|
||||||
health: 4
|
|
||||||
healthFactor: 1.2
|
|
||||||
speed: 6
|
|
||||||
speedAbsolute: 11
|
|
||||||
skills: ['brewPotion']
|
|
||||||
|
|
||||||
librarian:
|
|
||||||
fullName: 'Hushbaum'
|
|
||||||
weapons: 'Wands, Staffs - Long Range, Magic'
|
|
||||||
class: 'Wizard'
|
|
||||||
description: '???'
|
|
||||||
status: 'Locked'
|
|
||||||
attack: 3
|
|
||||||
attackFactor: 1.2
|
|
||||||
health: 4.5
|
|
||||||
healthFactor: 1.4
|
|
||||||
speed: 2.5
|
|
||||||
speedAbsolute: 7
|
|
||||||
|
|
||||||
'robot-walker':
|
|
||||||
fullName: '???'
|
|
||||||
weapons: '???'
|
|
||||||
class: 'Ranger'
|
|
||||||
description: '???'
|
|
||||||
status: 'Locked'
|
|
||||||
attack: 6.5
|
|
||||||
attackFactor: 1.6
|
|
||||||
health: 5.5
|
|
||||||
healthFactor: 1.2
|
|
||||||
speed: 6
|
|
||||||
speedAbsolute: 11
|
|
||||||
skills: ['???', '???', '???']
|
|
||||||
|
|
||||||
'michael-heasell':
|
|
||||||
fullName: '???'
|
|
||||||
weapons: '???'
|
|
||||||
class: 'Ranger'
|
|
||||||
description: '???'
|
|
||||||
status: 'Locked'
|
|
||||||
attack: 4
|
|
||||||
attackFactor: 0.714
|
|
||||||
health: 5
|
|
||||||
healthFactor: 1
|
|
||||||
speed: 10
|
|
||||||
speedAbsolute: 16
|
|
||||||
skills: ['???', '???']
|
|
||||||
|
|
||||||
'ian-elliott':
|
|
||||||
fullName: '???'
|
|
||||||
weapons: 'Swords - Short Range, No Magic'
|
|
||||||
class: 'Warrior'
|
|
||||||
description: '???'
|
|
||||||
status: 'Locked'
|
|
||||||
attack: 9.5
|
|
||||||
attackFactor: 1.8
|
|
||||||
health: 6.5
|
|
||||||
healthFactor: 0.714
|
|
||||||
speed: 3.5
|
|
||||||
speedAbsolute: 8
|
|
||||||
skills: ['trueStrike']
|
|
|
@ -357,35 +357,47 @@ module.exports = class InventoryModal extends ModalView
|
||||||
@remainingRequiredEquipment = []
|
@remainingRequiredEquipment = []
|
||||||
@$el.find('.should-equip').removeClass('should-equip')
|
@$el.find('.should-equip').removeClass('should-equip')
|
||||||
inWorldMap = $('#world-map-view').length
|
inWorldMap = $('#world-map-view').length
|
||||||
|
if heroClass = @selectedHero?.get('heroClass')
|
||||||
|
for slot, item of _.clone equipment
|
||||||
|
itemModel = @items.findWhere original: item
|
||||||
|
unless itemModel and heroClass in itemModel.classes
|
||||||
|
console.log 'Unequipping', itemModel.get('heroClass'), 'item', itemModel.get('name'), 'from slot due to class restrictions.'
|
||||||
|
@unequipItemFromSlot @$el.find(".item-slot[data-slot='#{slot}']")
|
||||||
for slot, item of restrictedGear
|
for slot, item of restrictedGear
|
||||||
equipped = equipment[slot]
|
equipped = equipment[slot]
|
||||||
if equipped and equipped is gear[restrictedGear[slot]]
|
if equipped and equipped is gear[restrictedGear[slot]]
|
||||||
console.log 'Unequipping restricted item', restrictedGear[slot], 'for', slot, 'before level', @options.levelID
|
console.log 'Unequipping restricted item', restrictedGear[slot], 'for', slot, 'before level', @options.levelID
|
||||||
@unequipItemFromSlot @$el.find(".item-slot[data-slot='#{slot}']")
|
@unequipItemFromSlot @$el.find(".item-slot[data-slot='#{slot}']")
|
||||||
for slot, item of requiredGear
|
if heroClass is 'Warrior'
|
||||||
#continue if item is 'leather-tunic' and inWorldMap and @options.levelID is 'the-raised-sword' # Don't tell them they need it until they need it in the level # ... when we make it so that you can buy it
|
# After they switch to a ranger or wizard, we stop being so finicky about gear.
|
||||||
equipped = equipment[slot]
|
for slot, item of requiredGear
|
||||||
continue if equipped and not (
|
#continue if item is 'leather-tunic' and inWorldMap and @options.levelID is 'the-raised-sword' # Don't tell them they need it until they need it in the level # ... when we make it so that you can buy it
|
||||||
(item is 'builders-hammer' and equipped in [gear['simple-sword'], gear['long-sword']]) or
|
equipped = equipment[slot]
|
||||||
(item in ['simple-sword', 'long-sword'] and equipped is gear['builders-hammer']) or
|
continue if equipped and not (
|
||||||
(item is 'leather-boots' and equipped is gear['simple-boots']) or
|
(item is 'builders-hammer' and equipped in [gear['simple-sword'], gear['long-sword']]) or
|
||||||
(item is 'simple-boots' and equipped is gear['leather-boots'])
|
(item in ['simple-sword', 'long-sword'] and equipped is gear['builders-hammer']) or
|
||||||
)
|
(item is 'leather-boots' and equipped is gear['simple-boots']) or
|
||||||
itemModel = @items.findWhere {slug: item}
|
(item is 'simple-boots' and equipped is gear['leather-boots'])
|
||||||
continue unless itemModel
|
)
|
||||||
availableSlotSelector = "#unequipped .item[data-item-id='#{itemModel.id}']"
|
itemModel = @items.findWhere {slug: item}
|
||||||
@highlightElement availableSlotSelector, delay: 500, sides: ['right'], rotation: Math.PI / 2
|
continue unless itemModel
|
||||||
@$el.find(availableSlotSelector).addClass 'should-equip'
|
availableSlotSelector = "#unequipped .item[data-item-id='#{itemModel.id}']"
|
||||||
@$el.find("#equipped div[data-slot='#{slot}']").addClass 'should-equip'
|
@highlightElement availableSlotSelector, delay: 500, sides: ['right'], rotation: Math.PI / 2
|
||||||
@$el.find('#double-click-hint').removeClass('secret')
|
@$el.find(availableSlotSelector).addClass 'should-equip'
|
||||||
@remainingRequiredEquipment.push slot: slot, item: gear[item]
|
@$el.find("#equipped div[data-slot='#{slot}']").addClass 'should-equip'
|
||||||
|
@$el.find('#double-click-hint').removeClass('secret')
|
||||||
|
@remainingRequiredEquipment.push slot: slot, item: gear[item]
|
||||||
if hadRequired and not @remainingRequiredEquipment.length
|
if hadRequired and not @remainingRequiredEquipment.length
|
||||||
@endHighlight()
|
@endHighlight()
|
||||||
@highlightElement '#play-level-button', duration: 5000
|
@highlightElement '#play-level-button', duration: 5000
|
||||||
$('#play-level-button').prop('disabled', @remainingRequiredEquipment.length > 0)
|
$('#play-level-button').prop('disabled', @remainingRequiredEquipment.length > 0)
|
||||||
|
|
||||||
setHero: (@selectedHero) ->
|
setHero: (@selectedHero) ->
|
||||||
|
if @selectedHero.loading
|
||||||
|
@listenToOnce @selectedHero, 'sync', => @setHero? @selectedHero
|
||||||
|
return
|
||||||
@$el.removeClass('Warrior Ranger Wizard').addClass(@selectedHero.get('heroClass'))
|
@$el.removeClass('Warrior Ranger Wizard').addClass(@selectedHero.get('heroClass'))
|
||||||
|
@requireLevelEquipment()
|
||||||
@render()
|
@render()
|
||||||
|
|
||||||
onShown: ->
|
onShown: ->
|
||||||
|
@ -418,8 +430,11 @@ module.exports = class InventoryModal extends ModalView
|
||||||
inventory = @getCurrentEquipmentConfig()
|
inventory = @getCurrentEquipmentConfig()
|
||||||
patchSession = patchMe = false
|
patchSession = patchMe = false
|
||||||
patchSession ||= not _.isEqual inventory, sessionHeroConfig.inventory
|
patchSession ||= not _.isEqual inventory, sessionHeroConfig.inventory
|
||||||
patchMe ||= not _.isEqual inventory, lastHeroConfig.inventory
|
|
||||||
sessionHeroConfig.inventory = inventory
|
sessionHeroConfig.inventory = inventory
|
||||||
|
if hero = @selectedHero.get('original')
|
||||||
|
patchSession ||= not _.isEqual hero, sessionHeroConfig.thangType
|
||||||
|
sessionHeroConfig.thangType = hero
|
||||||
|
patchMe ||= not _.isEqual inventory, lastHeroConfig.inventory
|
||||||
lastHeroConfig.inventory = inventory
|
lastHeroConfig.inventory = inventory
|
||||||
if patchMe
|
if patchMe
|
||||||
console.log 'setting me.heroConfig to', JSON.stringify(lastHeroConfig)
|
console.log 'setting me.heroConfig to', JSON.stringify(lastHeroConfig)
|
||||||
|
|
|
@ -708,21 +708,10 @@ forest = [
|
||||||
id: 'drop-the-flag'
|
id: 'drop-the-flag'
|
||||||
description: 'it is hot'
|
description: 'it is hot'
|
||||||
disabled: not me.isAdmin()
|
disabled: not me.isAdmin()
|
||||||
nextLevels:
|
|
||||||
continue: 'rich-forager'
|
|
||||||
x: 77.54
|
|
||||||
y: 50.94
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name: 'Rich Forager'
|
|
||||||
type: 'hero'
|
|
||||||
id: 'rich-forager'
|
|
||||||
description: 'if i were a rich man'
|
|
||||||
disabled: not me.isAdmin()
|
|
||||||
nextLevels:
|
nextLevels:
|
||||||
continue: 'deadly-pursuit'
|
continue: 'deadly-pursuit'
|
||||||
x: 77.54
|
x: 77.54
|
||||||
y: 45.94
|
y: 50.94
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name: 'Deadly Pursuit'
|
name: 'Deadly Pursuit'
|
||||||
|
@ -731,10 +720,21 @@ forest = [
|
||||||
description: 'what is a dirt nap? it is death.'
|
description: 'what is a dirt nap? it is death.'
|
||||||
disabled: not me.isAdmin()
|
disabled: not me.isAdmin()
|
||||||
nextLevels:
|
nextLevels:
|
||||||
continue: 'multiplayer-treasure-grove'
|
continue: 'rich-forager'
|
||||||
x: 77.54
|
x: 77.54
|
||||||
y: 40.94
|
y: 40.94
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
name: 'Rich Forager'
|
||||||
|
type: 'hero'
|
||||||
|
id: 'rich-forager'
|
||||||
|
description: 'if i were a rich man'
|
||||||
|
disabled: not me.isAdmin()
|
||||||
|
nextLevels:
|
||||||
|
continue: 'multiplayer-treasure-grove'
|
||||||
|
x: 77.54
|
||||||
|
y: 45.94
|
||||||
|
}
|
||||||
{
|
{
|
||||||
name: 'Multiplayer Treasure Grove'
|
name: 'Multiplayer Treasure Grove'
|
||||||
type: 'hero'
|
type: 'hero'
|
||||||
|
|
|
@ -63,6 +63,7 @@ module.exports = class ControlBarView extends CocoView
|
||||||
@homeLink = c.homeLink = '/'
|
@homeLink = c.homeLink = '/'
|
||||||
@homeViewClass = require 'views/HomeView'
|
@homeViewClass = require 'views/HomeView'
|
||||||
c.editorLink = "/editor/level/#{@level.get('slug')}"
|
c.editorLink = "/editor/level/#{@level.get('slug')}"
|
||||||
|
c.homeLink = @homeLink
|
||||||
c
|
c
|
||||||
|
|
||||||
showGameMenuModal: ->
|
showGameMenuModal: ->
|
||||||
|
|
|
@ -98,8 +98,8 @@ module.exports = class LevelHUDView extends CocoView
|
||||||
@stage?.stopTalking()
|
@stage?.stopTalking()
|
||||||
|
|
||||||
createProperties: ->
|
createProperties: ->
|
||||||
if @thang.id is 'Hero Placeholder'
|
if @thang.id in ['Hero Placeholder', 'Hero Placeholder 1']
|
||||||
name = {knight: 'Tharin', captain: 'Anya'}[@thang.type] ? 'Hero'
|
name = {knight: 'Tharin', captain: 'Anya', librarian: 'Hushbaum', sorcerer: 'Pender', 'potion-master': 'Omarn', samurai: 'Hattori', ninja: 'Amara'}[@thang.type] ? 'Hero'
|
||||||
else
|
else
|
||||||
name = if @thang.type then "#{@thang.id} - #{@thang.type}" else @thang.id
|
name = if @thang.type then "#{@thang.id} - #{@thang.type}" else @thang.id
|
||||||
@$el.find('.thang-name').text name
|
@$el.find('.thang-name').text name
|
||||||
|
|
|
@ -29,6 +29,7 @@ module.exports = class PlayHeroesModal extends ModalView
|
||||||
@heroes = new CocoCollection([], {model: ThangType})
|
@heroes = new CocoCollection([], {model: ThangType})
|
||||||
@heroes.url = '/db/thang.type?view=heroes'
|
@heroes.url = '/db/thang.type?view=heroes'
|
||||||
@heroes.setProjection ['original','name','slug','soundTriggers','featureImage','gems','heroClass','description','components','extendedName']
|
@heroes.setProjection ['original','name','slug','soundTriggers','featureImage','gems','heroClass','description','components','extendedName']
|
||||||
|
@heroes.comparator = 'gems'
|
||||||
@listenToOnce @heroes, 'sync', @onHeroesLoaded
|
@listenToOnce @heroes, 'sync', @onHeroesLoaded
|
||||||
@supermodel.loadCollection(@heroes, 'heroes')
|
@supermodel.loadCollection(@heroes, 'heroes')
|
||||||
@stages = {}
|
@stages = {}
|
||||||
|
|
|
@ -1,17 +1,6 @@
|
||||||
ThangType = require './ThangType'
|
ThangType = require './ThangType'
|
||||||
Handler = require '../../commons/Handler'
|
Handler = require '../../commons/Handler'
|
||||||
|
|
||||||
heroes =
|
|
||||||
captain: '529ec584c423d4e83b000014'
|
|
||||||
knight: '529ffbf1cf1818f2be000001'
|
|
||||||
librarian: '52fbf74b7e01835453bd8d8e'
|
|
||||||
equestrian: '52e95b4222efc8e70900175d'
|
|
||||||
'potion-master': '52e9adf7427172ae56002172'
|
|
||||||
thoktar: '52a00542cf1818f2be000006'
|
|
||||||
'robot-walker': '5301696ad82649ec2c0c9b0d'
|
|
||||||
'michael-heasell': '53e126a4e06b897606d38bef'
|
|
||||||
'ian-elliott': '53e12be0d042f23505c3023b'
|
|
||||||
|
|
||||||
ThangTypeHandler = class ThangTypeHandler extends Handler
|
ThangTypeHandler = class ThangTypeHandler extends Handler
|
||||||
modelClass: ThangType
|
modelClass: ThangType
|
||||||
jsonSchema: require '../../../app/schemas/models/thang_type'
|
jsonSchema: require '../../../app/schemas/models/thang_type'
|
||||||
|
@ -64,8 +53,7 @@ ThangTypeHandler = class ThangTypeHandler extends Handler
|
||||||
query.kind = 'Item'
|
query.kind = 'Item'
|
||||||
query.tier = {$exists: true} # Items without a tier don't show up anywhere, whereas items without gems don't show up in the store
|
query.tier = {$exists: true} # Items without a tier don't show up anywhere, whereas items without gems don't show up in the store
|
||||||
else if req.query.view is 'heroes'
|
else if req.query.view is 'heroes'
|
||||||
#query.kind = 'Hero' # TODO: when ChooseHeroView is refactored, just use this
|
query.kind = 'Hero'
|
||||||
query.original = {$in: _.values heroes} # TODO: when ChooseHeroView is refactored, don't do this
|
|
||||||
else if req.query.view is 'i18n-coverage'
|
else if req.query.view is 'i18n-coverage'
|
||||||
query.i18nCoverage = {$exists: true}
|
query.i18nCoverage = {$exists: true}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ PurchaseHandler = class PurchaseHandler extends Handler
|
||||||
addPurchaseToUser: (req) ->
|
addPurchaseToUser: (req) ->
|
||||||
user = req.user
|
user = req.user
|
||||||
purchased = user.get('purchased') or {}
|
purchased = user.get('purchased') or {}
|
||||||
purchased = _.clone purchased
|
purchased = _.cloneDeep purchased
|
||||||
item = req.purchasedItem
|
item = req.purchasedItem
|
||||||
|
|
||||||
group = switch item.get('kind')
|
group = switch item.get('kind')
|
||||||
|
|
Loading…
Reference in a new issue