diff --git a/app/application.coffee b/app/application.coffee
index 860aee96e..caf648679 100644
--- a/app/application.coffee
+++ b/app/application.coffee
@@ -44,11 +44,12 @@ Application = initialize: ->
}, (t) =>
@router = new Router()
@router.subscribe()
+ onIdleChanged = (to) => => Backbone.Mediator.publish 'application:idle-changed', idle: @userIsIdle = to
@idleTracker = new Idle
- onAway: => @userIsIdle = true
- onAwayBack: => @userIsIdle = false
- onHidden: => @userIsIdle = true
- onVisible: => @userIsIdle = false
+ onAway: onIdleChanged true
+ onAwayBack: onIdleChanged false
+ onHidden: onIdleChanged true
+ onVisible: onIdleChanged false
awayTimeout: 5 * 60 * 1000
@idleTracker.start()
diff --git a/app/lib/LevelLoader.coffee b/app/lib/LevelLoader.coffee
index a0e1d78b7..5651917a5 100644
--- a/app/lib/LevelLoader.coffee
+++ b/app/lib/LevelLoader.coffee
@@ -27,6 +27,7 @@ module.exports = class LevelLoader extends CocoClass
@opponentSessionID = options.opponentSessionID
@team = options.team
@headless = options.headless
+ @spectateMode = options.spectateMode ? false
@loadSession()
@loadLevelModels()
@@ -116,7 +117,7 @@ module.exports = class LevelLoader extends CocoClass
@updateCompleted = true
denormalizeSession: ->
- return if @sessionDenormalized
+ return if @sessionDenormalized or @spectateMode
patch =
'levelName': @level.get('name')
'levelID': @level.get('slug') or @level.id
diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee
index 54b94adc6..33860e1c0 100644
--- a/app/lib/surface/CocoSprite.coffee
+++ b/app/lib/surface/CocoSprite.coffee
@@ -62,6 +62,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
@actionQueue = []
@marks = {}
@labels = {}
+ @handledAoEs = {}
@age = 0
@displayObject = new createjs.Container()
if @thangType.get('actions')
@@ -172,15 +173,41 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
return if @stillLoading
@updatePosition()
if frameChanged
- @updateScale()
+ @updateScale() # must happen before rotation
@updateAlpha()
@updateRotation()
@updateAction()
@updateStats()
@updateGold()
+ @showAreaOfEffects()
@updateMarks()
@updateLabels()
+ showAreaOfEffects: ->
+ return unless @thang?.currentEvents
+ for event in @thang.currentEvents
+ continue unless event.startsWith 'aoe-'
+ continue if @handledAoEs[event]
+
+ @handledAoEs[event] = true
+ args = JSON.parse(event[4...])
+ pos = @options.camera.worldToSurface {x:args[0], y:args[1]}
+ circle = new createjs.Shape()
+ circle.graphics.beginFill(args[3]).drawCircle(0, 0, args[2]*Camera.PPM)
+ circle.x = pos.x
+ circle.y = pos.y
+ circle.scaleY = @options.camera.y2x * 0.7
+ circle.scaleX = 0.7
+ circle.alpha = 0.2
+ circle
+ @options.groundLayer.addChild circle
+ createjs.Tween.get(circle)
+ .to({alpha: 0.6, scaleY: @options.camera.y2x, scaleX: 1}, 100, createjs.Ease.circOut)
+ .to({alpha: 0, scaleY: 0, scaleX: 0}, 700, createjs.Ease.circIn)
+ .call =>
+ @options.groundLayer.removeChild circle
+ delete @handledAoEs[event]
+
cache: ->
bounds = @imageObject.getBounds()
@displayObject.cache 0, 0, bounds.width, bounds.height
diff --git a/app/lib/utils.coffee b/app/lib/utils.coffee
index 8fe47dbee..96a74599b 100644
--- a/app/lib/utils.coffee
+++ b/app/lib/utils.coffee
@@ -44,4 +44,4 @@ module.exports.hslToHex = (hsl) ->
toHex = (n) ->
h = Math.floor(n).toString(16)
h = '0'+h if h.length is 1
- h
\ No newline at end of file
+ h
diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index 8931cf74e..37b209b8f 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -81,6 +81,7 @@ module.exports = nativeDescription: "English", englishDescription: "English", tr
campaign_player_created: "Player-Created"
campaign_player_created_description: "... in which you battle against the creativity of your fellow Artisan Wizards."
level_difficulty: "Difficulty: "
+ play_as: "Play As "
contact:
contact_us: "Contact CodeCombat"
@@ -275,6 +276,7 @@ module.exports = nativeDescription: "English", englishDescription: "English", tr
commit_msg: "Commit Message"
history: "History"
version_history_for: "Version History for: "
+ result: "Result"
results: "Results"
description: "Description"
or: "or"
@@ -282,6 +284,17 @@ module.exports = nativeDescription: "English", englishDescription: "English", tr
password: "Password"
message: "Message"
code: "Code"
+ ladder: "Ladder"
+ when: "When"
+ rank: "Rank"
+ score: "Score"
+ win: "Win"
+ loss: "Loss"
+ tie: "Tie"
+ easy: "Easy"
+ medium: "Medium"
+ hard: "Hard"
+
about:
who_is_codecombat: "Who is CodeCombat?"
@@ -475,3 +488,35 @@ module.exports = nativeDescription: "English", englishDescription: "English", tr
ambassador_title_description: "(Support)"
counselor_title: "Counselor"
counselor_title_description: "(Expert/Teacher)"
+
+ ladder:
+ please_login: "Please log in first before playing a ladder game."
+ my_matches: "My Matches"
+ simulate: "Simulate"
+ simulation_explanation: "By simulating games you can get your game ranked faster!"
+ simulate_games: "Simulate Games!"
+ simulate_all: "RESET AND SIMULATE GAMES"
+ leaderboard: "Leaderboard"
+ battle_as: "Battle as "
+ summary_your: "Your "
+ summary_matches: "Matches - "
+ summary_wins: " Wins, "
+ summary_losses: " Losses"
+ rank_no_code: "No New Code to Rank"
+ rank_my_game: "Rank My Game!"
+ rank_submitting: "Submitting..."
+ rank_submitted: "Submitted for Ranking"
+ rank_failed: "Failed to Rank"
+ rank_being_ranked: "Game Being Ranked"
+ code_being_simulated: "Your new code is being simulated by other players for ranking. This will refresh as new matches come in."
+ no_ranked_matches_pre: "No ranked matches for the "
+ no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
+ choose_opponent: "Choose an Opponent"
+ tutorial_play: "Play Tutorial"
+ tutorial_recommended: "Recommended if you've never played before"
+ tutorial_skip: "Skip Tutorial"
+ tutorial_not_sure: "Not sure what's going on?"
+ tutorial_play_first: "Play the Tutorial first."
+ simple_ai: "Simple AI"
+ warmup: "Warmup"
+ vs: "VS"
diff --git a/app/locale/nl.coffee b/app/locale/nl.coffee
index 199315d9c..aef80d8f9 100644
--- a/app/locale/nl.coffee
+++ b/app/locale/nl.coffee
@@ -269,12 +269,23 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
commit_msg: "Commit Bericht"
history: "Geschiedenis"
version_history_for: "Versie geschiedenis voor: "
+ result: "Resultaat"
results: "Resultaten"
description: "Beschrijving"
or: "of"
email: "Email"
message: "Bericht"
code: "Code"
+ ladder: "Ladder"
+ when: "Wanneer"
+ rank: "Rang"
+ score: "Score"
+ win: "Win"
+ loss: "Verlies"
+ tie: "Gelijk"
+ easy: "Gemakkelijk"
+ medium: "Medium"
+ hard: "Moeilijk"
about:
who_is_codecombat: "Wie is CodeCombat?"
@@ -468,3 +479,35 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
ambassador_title_description: "(Ondersteuning)"
counselor_title: "Raadgever"
counselor_title_description: "(Expert/Leraar)"
+
+ ladder:
+ please_login: "Log alstublieft eerst in voordat u een ladderspel speelt."
+ my_matches: "Mijn Wedstrijden"
+ simulate: "Simuleer"
+ simulation_explanation: "Door spellen te simuleren kan je zelf sneller beoordeeld worden!"
+ simulate_games: "Simuleer spellen!"
+ simulate_all: "RESET EN SIMULEER SPELLEN"
+ leaderboard: "Leaderboard"
+ battle_as: "Vecht als "
+ summary_your: "Jouw "
+ summary_matches: "Wedstrijden - "
+ summary_wins: " Overwinningen, "
+ summary_losses: " Nederlagen"
+ rank_no_code: "Geen nieuwe code om te Beoordelen!"
+ rank_my_game: "Beoordeel mijn spel!"
+ rank_submitting: "Verzenden..."
+ rank_submitted: "Verzonden voor Beoordeling"
+ rank_failed: "Beoordeling mislukt"
+ rank_being_ranked: "Spel wordt Beoordeeld"
+ code_being_simulated: "Uw nieuwe code wordt gesimuleerd door andere spelers om te beoordelen. Dit wordt vernieuwd zodra nieuwe matches binnenkomen."
+ no_ranked_matches_pre: "Geen beoordeelde wedstrijden voor het"
+ no_ranked_matches_post: " team! Speel tegen enkele tegenstanders en kom terug hier om uw spel te laten beoordelen."
+ choose_opponent: "Kies een tegenstander"
+ tutorial_play: "Speel de Tutorial"
+ tutorial_recommended: "Aanbevolen als je nog niet eerder hebt gespeeld"
+ tutorial_skip: "Sla Tutorial over"
+ tutorial_not_sure: "Niet zeker wat er aan de gang is?"
+ tutorial_play_first: "Speel eerst de Tutorial."
+ simple_ai: "Simpele AI"
+ warmup: "Opwarming"
+ vs: "tegen"
diff --git a/app/locale/ro.coffee b/app/locale/ro.coffee
index 5a6ce33ae..1919608ba 100644
--- a/app/locale/ro.coffee
+++ b/app/locale/ro.coffee
@@ -53,7 +53,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
signup:
create_account_title: "Crează cont pentru a salva progresul"
- description: "Este gratis. Doar un scurt formular inainte si poți continua:"#contextual translation a bit off, could be better# It's free. Just need a couple things and you'll be good to go:"
+ description: "Este gratis. Doar un scurt formular inainte si poți continua:"
email_announcements: "Primește notificări prin emaill"
coppa: "13+ sau non-USA "
coppa_why: "(De ce?)"
@@ -62,15 +62,15 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
log_in: "loghează-te cu parola"
home:
- slogan: "Învață sa scri JavaScript jucându-te"# again sounds funny# Learn to Code JavaScript by Playing a Game"
+ slogan: "Învață sa scri JavaScript jucându-te"
no_ie: "CodeCombat nu merge pe Internet Explorer 9 sau mai vechi. Scuze!"
no_mobile: "CodeCombat nu a fost proiectat pentru dispozitive mobile si s-ar putea sa nu meargâ!"
play: "Joacâ"
play:
choose_your_level: "Alege nivelul"
- adventurer_prefix: "Poți să sari la orice nivel de mai jos"#what do you mean by discuss?# You can jump to any level below, or discuss the levels on "
- adventurer_forum: "forumul Aventurierului"#sonds waaaaaay too funny#the Adventurer forum"
+ adventurer_prefix: "Poți să sari la orice nivel de mai jos"
+ adventurer_forum: "forumul Aventurierului"
adventurer_suffix: "."
campaign_beginner: "Campanie pentru Începători"
campaign_beginner_description: "... în care se învață tainele programării."
@@ -150,7 +150,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
gravatar_not_found_mine: "N-am putut găsi profilul asociat cu:"
gravatar_not_found_email_suffix: "."
gravatar_signup_prefix: "Înscrie-te la "
- gravatar_signup_suffix: " pentru a fi gata!" #sounds funny # to get set up!"
+ gravatar_signup_suffix: " pentru a fi gata!"
gravatar_not_found_other: "Din păcate nu este asociat nici un profil cu această adresă de email."
gravatar_contact: "Contact"
gravatar_websites: "Website-uri"
@@ -294,7 +294,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
opensource_description_center: "și ajută-ne dacă îți place! CodeCombat este construit peste o mulțime de proiecte open source, care noi le iubim. Vizitați"
archmage_wiki_url: "Archmage wiki"
opensource_description_suffix: "pentru o listă cu software-ul care face acest joc posibil."
-# practices_title: "Respectful Best Practices" #not sure what you mean here? other word for /practices/?
+ practices_title: "Convenții"
practices_description: "Acestea sunt promisiunile noastre către tine, jucătorul, fără așa mulți termeni legali."
privacy_title: "Confidenţialitate şi termeni"
privacy_description: "Noi nu vom vinde nici o informație personală. Intenționăm să obținem profit prin recrutare eventual, dar stați liniștiți , nu vă vom vinde informațiile personale companiilor interesate fără consimțământul vostru explicit."
@@ -328,7 +328,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
art_music: "Muzică"
art_sound: "Sunet"
art_artwork: "Artwork"
- art_sprites: "Sprites" #can t be translated, either suggest alternative name or must be left like this
+ art_sprites: "Sprites"
art_other: "Orice si toate celelalte creații non-cod care sunt disponibile când se crează nivele."
art_access: "Momentan nu există nici un sistem universal,ușor pentru preluarea acestor bunuri. În general, preluați-le precum site-ul din URL-urile folosite, contactați-ne pentru asistență, sau ajutați-ne sa extindem site-ul pentru a face aceste bunuri mai ușor accesibile."
art_paragraph_1: "Pentru atribuire, vă rugăm numiți și lăsați referire link la codecombat.com unde este folosită sursa sau unde este adecvat pentru mediu. De exemplu:"
diff --git a/app/styles/play/spectate.sass b/app/styles/play/spectate.sass
index a70c059b9..dd8ee775c 100644
--- a/app/styles/play/spectate.sass
+++ b/app/styles/play/spectate.sass
@@ -1,26 +1,49 @@
@import "app/styles/bootstrap/mixins"
@import "app/styles/mixins"
-body
- height: 100%
-
+
+
#spectate-level-view
+ #playback-view
+ width: 100%
+ #restart-button
+ display: none
+ #multiplayer-button
+ display: none
+ #docs-button
+ display: none
+
+ #control-bar-view
+ width: 100%
+
+ .title
+ position: absolute
+ display: inline-block
+ margin-left: 50%
+ right: 0
+ color: #BEBEBE
+ line-height: 15px
+ left: 0
+
+
margin: 0 auto
- height: 100%
@include user-select(none)
.level-content
position: relative
#canvas-wrapper
- width: 55%
+ height: 100%
position: relative
margin: 0 auto
canvas#surface
background-color: #ddd
- width: 100%
+ max-height: calc(100% - 60px)
+ height: auto
+ max-width: 100%
display: block
z-index: 1
+ margin: 0 auto
//max-width: 1680px // guideline, but for now let's let it stretch out
@@ -30,11 +53,9 @@ body
margin: 0 auto
#thang-hud
margin: 0 auto
+ display: none
- #control-bar-view
- margin: 0 auto
- .title
- margin-left: 500px
+
#pointer
position: absolute
left: 0
diff --git a/app/templates/play.jade b/app/templates/play.jade
index 454ea8ca0..6f3a77edd 100644
--- a/app/templates/play.jade
+++ b/app/templates/play.jade
@@ -19,10 +19,10 @@ block content
each campaign in campaigns
.campaign-container.col-sm-6
h1
- a(href="/play/level/#{campaign.levels[0].id}", data-i18n="play.campaign_#{campaign.id}")= campaign.name
+ a(href="/play/#{campaign.levels[0].levelPath || 'level'}/#{campaign.levels[0].id}", data-i18n="play.campaign_#{campaign.id}")= campaign.name
p.campaign-description(data-i18n="[html]play.campaign_#{campaign.id}_description")!= campaign.description
each level in campaign.levels
- a(href=level.disabled ? "/play" : "/play/level/#{level.id}", disabled=level.disabled)
+ a(href=level.disabled ? "/play" : "/play/#{level.levelPath || 'level'}/#{level.id}", disabled=level.disabled)
.level.row
if level.image
img.level-image(src="#{level.image}", alt="#{level.name}")
diff --git a/app/templates/play/ladder.jade b/app/templates/play/ladder.jade
index b7de9c539..234804ed6 100644
--- a/app/templates/play/ladder.jade
+++ b/app/templates/play/ladder.jade
@@ -10,7 +10,7 @@ block content
if me.get('anonymous')
div#must-log-in
p
- strong Please log in first before playing a ladder game.
+ strong(data-i18n="ladder.please_login") Please log in first before playing a ladder game.
button.btn.btn-primary(data-toggle="coco-modal", data-target="modal/login", data-i18n="login.log_in") Log In
button.btn.btn-primary(data-toggle="coco-modal", data-target="modal/signup", data-i18n="login.sign_up") Create Account
@@ -21,7 +21,7 @@ block content
for team in teams
div.column.col-md-4
a(style="background-color: #{team.primaryColor}", data-team=team.id).play-button.btn.btn-danger.btn-block.btn-lg
- span Play As
+ span(data-i18n="play.play_as") Play As
span= team.name
div.column.col-md-2
@@ -29,11 +29,11 @@ block content
ul.nav.nav-pills
li.active
- a(href="#ladder", data-toggle="tab") Ladder
+ a(href="#ladder", data-toggle="tab", data-i18n="general.ladder") Ladder
li
- a(href="#my-matches", data-toggle="tab") My Matches
+ a(href="#my-matches", data-toggle="tab", data-i18n="ladder.my_matches") My Matches
li
- a(href="#simulate", data-toggle="tab") Simulate
+ a(href="#simulate", data-toggle="tab", data-i18n="ladder.simulate") Simulate
div.tab-content
.tab-pane.active.well#ladder
@@ -45,9 +45,9 @@ block content
if simulationStatus
| #{simulationStatus}
else
- | By simulating games you can get your game ranked faster!
+ span(data-i18n="ladder.simulation_explanation") By simulating games you can get your game ranked faster!
p
- button.btn.btn-warning.btn-lg.highlight#simulate-button() Simulate Games!
+ button(data-i18n="ladder.simulate_games").btn.btn-warning.btn-lg.highlight#simulate-button Simulate Games!
if me.isAdmin()
p
- button.btn.btn-danger.btn-lg.highlight#simulate-all-button() RESET AND SIMULATE GAMES
\ No newline at end of file
+ button(data-i18n="ladder.simulate_all").btn.btn-danger.btn-lg.highlight#simulate-all-button RESET AND SIMULATE GAMES
\ No newline at end of file
diff --git a/app/templates/play/ladder/ladder_tab.jade b/app/templates/play/ladder/ladder_tab.jade
index 9fc48c340..141979920 100644
--- a/app/templates/play/ladder/ladder_tab.jade
+++ b/app/templates/play/ladder/ladder_tab.jade
@@ -5,11 +5,11 @@ div#columns.row
tr
th(colspan=4, style="color: #{team.primaryColor}")
span= team.name
- span Leaderboard
+ span(data-i18n="ladder.leaderboard") Leaderboard
tr
- th Rank
- th Score
- th.name-col-cell Name
+ th(data-i18n="general.rank") Rank
+ th(data-i18n="general.score") Score
+ th(data-i18n="general.name").name-col-cell Name
th
for session, rank in team.leaderboard.topPlayers.models
@@ -20,4 +20,5 @@ div#columns.row
td.name-col-cell= session.get('creatorName') || "Anonymous"
td
a(href="/play/level/#{level.get('slug') || level.id}/?team=#{team.otherTeam}&opponent=#{session.id}")
- span Battle as #{team.otherTeam}!
\ No newline at end of file
+ span(data-i18n="ladder.battle_as") Battle as
+ | #{team.otherTeam}!
\ No newline at end of file
diff --git a/app/templates/play/ladder/my_matches_tab.jade b/app/templates/play/ladder/my_matches_tab.jade
index b9cf618a2..b9cf4d459 100644
--- a/app/templates/play/ladder/my_matches_tab.jade
+++ b/app/templates/play/ladder/my_matches_tab.jade
@@ -11,16 +11,22 @@ div#columns.row
tr
th(colspan=4, style="color: #{team.primaryColor}")
- span Your #{team.name} Matches - #{team.wins} Wins, #{team.losses} Losses
+ span(data-i18n="ladder.summary_your") Your
+ |#{team.name}
+ span(data-i18n="ladder.summary_matches") Matches -
+ |#{team.wins}
+ span(data-i18n="ladder.summary_wins") Wins,
+ |#{team.losses}
+ span(data-i18n="ladder.summary_losses") Losses
if team.session
button.btn.btn-sm.btn-warning.pull-right.rank-button(data-session-id=team.session.id)
- span.unavailable.hidden No New Code to Rank
- span.rank.hidden Rank My Game!
- span.submitting.hidden Submitting...
- span.submitted.hidden Submitted for Ranking
- span.failed.hidden Failed to Rank
- span.ranking.hidden Game Being Ranked
+ span(data-i18n="ladder.rank_no_code").unavailable.hidden No New Code to Rank
+ span(data-i18n="ladder.rank_my_game").rank.hidden Rank My Game!
+ span(data-i18n="ladder.rank_submitting").submitting.hidden Submitting...
+ span(data-i18n="ladder.rank_submitted").submitted.hidden Submitted for Ranking
+ span(data-i18n="ladder.rank_failed").failed.hidden Failed to Rank
+ span(data-i18n="ladder.rank_being_ranked").ranking.hidden Game Being Ranked
if team.chartData
tr
@@ -28,19 +34,19 @@ div#columns.row
img(src="https://chart.googleapis.com/chart?chs=450x125&cht=lxy&chco=#{team.chartColor}&chtt=Score%3A+#{team.currentScore}&chts=#{team.chartColor},16,r&chf=a,s,000000FF&chls=2&chm=o,#{team.chartColor},0,4&chd=t:#{team.chartData}")
tr
- th Result
- th Opponent
- th When
+ th(data-i18n="general.result") Result
+ th(data-i18n="general.opponent") Opponent
+ th(data-i18n="general.when") When
th
for match in team.matches
tr(class=(match.stale ? "stale " : "") + match.state)
td.state-cell
if match.state === 'win'
- span.win Win
+ span(data-i18n="general.win").win Win
if match.state === 'loss'
- span.loss Loss
+ span(data-i18n="general.loss").loss Loss
if match.state === 'tie'
- span.tie Tie
+ span(data-i18n="general.tie").tie Tie
td.name-cell= match.opponentName || "Anonymous"
td.time-cell= match.when
td.battle-cell
@@ -51,10 +57,12 @@ div#columns.row
tr
if team.isRanking
td(colspan=4).alert.alert-info
- | Your new code is being simulated by other players for ranking.
- | This will refresh as new matches come in.
+ span(data-i18n="ladder.code_being_simulated")
+ | Your new code is being simulated by other players for ranking.
+ | This will refresh as new matches come in.
else
td(colspan=4).alert.alert-warning
- | No ranked matches for the #{team.name} team!
- | Play against some competitors and then come back here to get your game ranked.
+ span(data-i18n="ladder.no_ranked_matches_pre") No ranked matches for the
+ | #{team.name}
+ span(data-i18n="ladder.no_ranked_matches_post") team! Play against some competitors and then come back here to get your game ranked.
diff --git a/app/templates/play/ladder/play_modal.jade b/app/templates/play/ladder/play_modal.jade
index 25d492b6f..72cc45267 100644
--- a/app/templates/play/ladder/play_modal.jade
+++ b/app/templates/play/ladder/play_modal.jade
@@ -1,23 +1,23 @@
extends /templates/modal/modal_base
block modal-header-content
- h3 Choose an Opponent
+ h3(data-i18n="ladder.choose_opponent") Choose an Opponent
block modal-body-content
div#noob-view.secret
a(href="/play/level/#{levelID}-tutorial").btn.btn-success.btn-block.btn-lg
p
- strong Play Tutorial
- span Recommended if you've never played before
- span.btn.btn-primary.btn-block.btn-lg#skip-tutorial-button Skip Tutorial
+ strong(data-i18n="ladder.tutorial_play") Play Tutorial
+ span(data-i18n="ladder.tutorial_recommended") Recommended if you've never played before
+ span.btn.btn-primary.btn-block.btn-lg#skip-tutorial-button(data-i18n="ladder.tutorial_skip") Skip Tutorial
div#normal-view
p.tutorial-suggestion
- strong Not sure what's going on?
+ strong(data-i18n="ladder.tutorial_not_sure") Not sure what's going on?
|
- a(href="/play/level/#{levelID}-tutorial") Play the tutorial first.
+ a(href="/play/level/#{levelID}-tutorial", data-i18n="ladder.tutorial_play_first") Play the tutorial first.
a(href="/play/level/#{levelID}?team=#{teamID}")
div.play-option
@@ -28,10 +28,10 @@ block modal-body-content
div.my-name.name-label.only-one
span= myName
div.opponent-name.name-label
- span Simple AI
+ span(data-i18n="ladder.simple_ai") Simple AI
div.difficulty
- span Warmup
- div.vs VS
+ span(data-i18n="ladder.warmup") Warmup
+ div(data-i18n="ladder.vs").vs VS
if challengers.easy
a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.easy.sessionID}")
@@ -45,8 +45,8 @@ block modal-body-content
div.opponent-name.name-label
span= challengers.easy.opponentName
div.difficulty
- span Easy
- div.vs VS
+ span(data-i18n="general.easy") Easy
+ div(data-i18n="ladder.vs").vs VS
if challengers.medium
a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.medium.sessionID}")
@@ -60,8 +60,8 @@ block modal-body-content
div.opponent-name.name-label
span= challengers.medium.opponentName
div.difficulty
- span Medium
- div.vs VS
+ span(data-i18n="general.medium") Medium
+ div(data-i18n="ladder.vs").vs VS
if challengers.hard
a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.hard.sessionID}")
@@ -75,7 +75,7 @@ block modal-body-content
div.opponent-name.name-label
span= challengers.hard.opponentName
div.difficulty
- span Hard
- div.vs VS
+ span(data-i18n="general.hard") Hard
+ div(data-i18n="ladder.vs").vs VS
block modal-footer
\ No newline at end of file
diff --git a/app/templates/play/level/control_bar.jade b/app/templates/play/level/control_bar.jade
index 1cc3af07d..13670857b 100644
--- a/app/templates/play/level/control_bar.jade
+++ b/app/templates/play/level/control_bar.jade
@@ -12,5 +12,7 @@ if ladderGame
button.btn.btn-xs.btn-inverse.banner#multiplayer-button(title="Leaderboard", data-i18n="play_level.leaderboard") Leaderboard
else
button.btn.btn-xs.btn-inverse.banner#multiplayer-button(title="Multiplayer", data-i18n="play_level.multiplayer") Multiplayer
+if spectateGame
+ 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#restart-button(title="Reload all custom code to reset level", data-i18n="play_level.restart") Restart
\ No newline at end of file
diff --git a/app/views/editor/thang/edit.coffee b/app/views/editor/thang/edit.coffee
index 03babdfd4..23fa7f38d 100644
--- a/app/views/editor/thang/edit.coffee
+++ b/app/views/editor/thang/edit.coffee
@@ -270,7 +270,7 @@ module.exports = class ThangTypeEditView extends View
@$el.find('.rotation-label').text " #{value}° "
if @currentSprite
@currentSprite.rotation = value
- @currentSprite.update()
+ @currentSprite.update(true)
updateScale: =>
value = (@scaleSlider.slider('value') + 1) / 10
diff --git a/app/views/play/ladder_view.coffee b/app/views/play/ladder_view.coffee
index 0323d3ec5..e275d0613 100644
--- a/app/views/play/ladder_view.coffee
+++ b/app/views/play/ladder_view.coffee
@@ -25,6 +25,9 @@ module.exports = class LadderView extends RootView
template: require 'templates/play/ladder'
startsLoading: true
+ subscriptions:
+ 'application:idle-changed': 'onIdleChanged'
+
events:
'click #simulate-button': 'onSimulateButtonClick'
'click #simulate-all-button': 'onSimulateAllButtonClick'
@@ -70,10 +73,14 @@ module.exports = class LadderView extends RootView
@sessions.fetch({"success": @refreshViews})
refreshViews: =>
- return if @destroyed or application.userIsIdle
+ return if @destroyed or application.userIsIdle or new Date() - 2000 < @lastRefreshTime
+ @lastRefreshTime = new Date()
@ladderTab.refreshLadder()
@myMatchesTab.refreshMatches()
- console.log "refreshed views!"
+ console.log "Refreshing ladder and matches views."
+
+ onIdleChanged: (e) ->
+ @refreshViews() unless e.idle
# Simulations
diff --git a/app/views/play/level/control_bar_view.coffee b/app/views/play/level/control_bar_view.coffee
index bae8753b6..6e6bd6d2e 100644
--- a/app/views/play/level/control_bar_view.coffee
+++ b/app/views/play/level/control_bar_view.coffee
@@ -24,6 +24,9 @@ module.exports = class ControlBarView extends View
'click #restart-button': ->
window.tracker?.trackEvent 'Clicked Restart', level: @worldName, label: @worldName
@showRestartModal()
+
+ 'click #next-game-button': ->
+ Backbone.Mediator.publish 'next-game-pressed'
'click': -> Backbone.Mediator.publish 'focus-editor'
@@ -33,6 +36,7 @@ module.exports = class ControlBarView extends View
@level = options.level
@playableTeams = options.playableTeams
@ladderGame = options.ladderGame
+ @spectateGame = options.spectateGame ? false
super options
setBus: (@bus) ->
@@ -52,6 +56,7 @@ module.exports = class ControlBarView extends View
c.worldName = @worldName
c.multiplayerEnabled = @session.get('multiplayer')
c.ladderGame = @ladderGame
+ c.spectateGame = @spectateGame
c.homeLink = "/"
levelID = @level.get('slug')
if levelID in ["brawlwood", "brawlwood-tutorial", "dungeon-arena", "dungeon-arena-tutorial"]
diff --git a/app/views/play/level_view.coffee b/app/views/play/level_view.coffee
index a7faa74cb..1282297ba 100644
--- a/app/views/play/level_view.coffee
+++ b/app/views/play/level_view.coffee
@@ -128,7 +128,8 @@ module.exports = class PlayLevelView extends View
onLevelLoaderProgressChanged: ->
return if @seenDocs
- return unless showFrequency = @levelLoader.level.get('showGuide')
+ return unless @levelLoader.session.loaded and @levelLoader.level.loaded
+ return unless showFrequency = @levelLoader.level.get('showsGuide')
session = @levelLoader.session
diff = new Date().getTime() - new Date(session.get('created')).getTime()
return if showFrequency is 'first-time' and diff > (5 * 60 * 1000)
diff --git a/app/views/play/spectate_view.coffee b/app/views/play/spectate_view.coffee
index 85749e9f1..00a6803b6 100644
--- a/app/views/play/spectate_view.coffee
+++ b/app/views/play/spectate_view.coffee
@@ -11,7 +11,6 @@ Surface = require 'lib/surface/Surface'
God = require 'lib/God'
GoalManager = require 'lib/world/GoalManager'
ScriptManager = require 'lib/scripts/ScriptManager'
-LevelBus = require('lib/LevelBus')
LevelLoader = require 'lib/LevelLoader'
LevelSession = require 'models/LevelSession'
Level = require 'models/Level'
@@ -45,8 +44,6 @@ module.exports = class SpectateLevelView extends View
subscriptions:
'level-set-volume': (e) -> createjs.Sound.setVolume(e.volume)
- 'level-show-victory': 'onShowVictory'
- 'restart-level': 'onRestartLevel'
'level-highlight-dom': 'onHighlightDom'
'end-level-highlight-dom': 'onEndHighlight'
'level-focus-dom': 'onFocusDom'
@@ -56,11 +53,10 @@ module.exports = class SpectateLevelView extends View
'god:infinite-loop': 'onInfiniteLoop'
'level-reload-from-data': 'onLevelReloadFromData'
'play-next-level': 'onPlayNextLevel'
- 'edit-wizard-settings': 'showWizardSettingsModal'
'surface:world-set-up': 'onSurfaceSetUpNewWorld'
- 'level:session-will-save': 'onSessionWillSave'
'level:set-team': 'setTeam'
'god:new-world-created': 'loadSoundsForWorld'
+ 'next-game-pressed': 'onNextGamePressed'
events:
'click #level-done-button': 'onDonePressed'
@@ -73,8 +69,6 @@ module.exports = class SpectateLevelView extends View
super options
@sessionOne = @getQueryVariable 'session-one'
@sessionTwo = @getQueryVariable 'session-two'
-
- @sessionID = @sessionOne
$(window).on('resize', @onWindowResize)
@supermodel.once 'error', @onLevelLoadError
@@ -93,7 +87,13 @@ module.exports = class SpectateLevelView extends View
@load()
load: ->
- @levelLoader = new LevelLoader supermodel: @supermodel, levelID: @levelID, sessionID: @sessionID, opponentSessionID: @sessionTwo, team: @getQueryVariable("team")
+ @levelLoader = new LevelLoader
+ supermodel: @supermodel
+ levelID: @levelID
+ sessionID: @sessionOne
+ opponentSessionID: @sessionTwo
+ spectateMode: true
+ team: @getQueryVariable("team")
@levelLoader.once 'loaded-all', @onLevelLoaderLoaded, @
@levelLoader.on 'progress', @onLevelLoaderProgressChanged, @
@god = new God()
@@ -138,6 +138,7 @@ module.exports = class SpectateLevelView extends View
return Backbone.Mediator.subscribeOnce 'modal-closed', @onLevelLoaderLoaded, @
@grabLevelLoaderData()
+ #at this point, all requisite data is loaded, and sessions are not denormalized
team = @world.teamForPlayer(0)
@loadOpponentTeam(team)
@loadingScreen.destroy()
@@ -153,9 +154,17 @@ module.exports = class SpectateLevelView extends View
@register()
@controlBar.setBus(@bus)
@surface.showLevel()
- if @otherSession
- # TODO: colorize name and cloud by team, colorize wizard by user's color config
- @surface.createOpponentWizard id: @otherSession.get('creator'), name: @otherSession.get('creatorName'), team: @otherSession.get('team')
+ if me.id isnt @session.get 'creator'
+ @surface.createOpponentWizard
+ id: @session.get('creator')
+ name: @session.get('creatorName')
+ team: @session.get('team')
+
+ @surface.createOpponentWizard
+ id: @otherSession.get('creator')
+ name: @otherSession.get('creatorName')
+ team: @otherSession.get('team')
+
grabLevelLoaderData: ->
@session = @levelLoader.session
@@ -172,7 +181,7 @@ module.exports = class SpectateLevelView extends View
opponentSpells = opponentSpells.concat spells
opponentCode = @otherSession?.get('submittedCode') or {}
- myCode = @session.get('code') or {}
+ myCode = @session.get('submittedCode') or {}
for spell in opponentSpells
[thang, spell] = spell.split '/'
c = opponentCode[thang]?[spell]
@@ -205,12 +214,11 @@ module.exports = class SpectateLevelView extends View
@insertSubView new GoldView {}
@insertSubView new HUDView {}
worldName = @level.get('i18n')?[me.lang()]?.name ? @level.get('name')
- @controlBar = @insertSubView new ControlBarView {worldName: worldName, session: @session, level: @level, supermodel: @supermodel, playableTeams: @world.playableTeams, ladderGame: subviewOptions.ladderGame}
+ @controlBar = @insertSubView new ControlBarView {worldName: worldName, session: @session, level: @level, supermodel: @supermodel, playableTeams: @world.playableTeams, spectateGame: true}
#Backbone.Mediator.publish('level-set-debug', debug: true) if me.displayName() is 'Nick!'
afterInsert: ->
super()
- @showWizardSettingsModal() if not me.get('name')
# callbacks
@@ -252,12 +260,6 @@ module.exports = class SpectateLevelView extends View
@openModalView(docs)
window.tracker?.trackEvent 'Saw Victory', level: @world.name, label: @world.name
- onRestartLevel: ->
- @tome.reloadAllCode()
- Backbone.Mediator.publish 'level:restarted'
- $('#level-done-button', @$el).hide()
- window.tracker?.trackEvent 'Confirmed Restart', level: @world.name, label: @world.name
-
onNewWorld: (e) ->
@world = e.world
@@ -394,23 +396,11 @@ module.exports = class SpectateLevelView extends View
if state.playing?
Backbone.Mediator.publish 'level-set-playing', { playing: state.playing }
- preloadNextLevel: =>
- # TODO: Loading models in the middle of gameplay causes stuttering. Most of the improvement in loading time is simply from passing the supermodel from this level to the next, but if we can find a way to populate the level early without it being noticeable, that would be even better.
-# return if @destroyed
-# return if @preloaded
-# nextLevel = @getNextLevel()
-# @supermodel.populateModel nextLevel
-# @preloaded = true
-
- register: ->
- @bus = LevelBus.get(@levelID, @session.id)
- @bus.setSession(@session)
- @bus.setSpells @tome.spells
- @bus.connect() if @session.get('multiplayer')
+ register: -> return
onSessionWillSave: (e) ->
# Something interesting has happened, so (at a lower frequency), we'll save a screenshot.
- @saveScreenshot e.session
+ console.log "Session is saving but shouldn't save!!!!!!!"
# Throttled
saveScreenshot: (session) =>
@@ -433,8 +423,16 @@ module.exports = class SpectateLevelView extends View
continue unless thangType = _.find thangTypes, (m) -> m.get('name') is spriteName
continue unless sound = AudioPlayer.soundForDialogue message, thangType.get('soundTriggers')
AudioPlayer.preloadSoundReference sound
+
+ onNextGamePressed: (e) ->
+ console.log "You want to see the next game!"
+ @sessionOne = "53193c8f7a89df21c4d968e9"
+ @sessionTwo = "531aa613026834331eac5e7e"
+ @destroy(true)
+ @load()
+ @afterRender()
- destroy: ->
+ destroy: (destroyHalfway)->
@supermodel?.off 'error', @onLevelLoadError
@levelLoader?.off 'loaded-all', @onLevelLoaderLoaded
@levelLoader?.destroy()
@@ -442,11 +440,11 @@ module.exports = class SpectateLevelView extends View
@god?.destroy()
@goalManager?.destroy()
@scriptManager?.destroy()
- $(window).off('resize', @onWindowResize)
+ unless destroyHalfway
+ $(window).off('resize', @onWindowResize)
delete window.world # not sure where this is set, but this is one way to clean it up
clearInterval(@pointerInterval)
- @bus?.destroy()
- #@instance.save() unless @instance.loading
+
console.profileEnd?() if PROFILE_ME
@session?.off 'change:multiplayer', @onMultiplayerChanged, @
@onLevelLoadError = null
@@ -454,4 +452,5 @@ module.exports = class SpectateLevelView extends View
@onSupermodelLoadedOne = null
@preloadNextLevel = null
@saveScreenshot = null
- super()
+ unless destroyHalfway
+ super()
diff --git a/app/views/play_view.coffee b/app/views/play_view.coffee
index f220427ea..123fc6fac 100644
--- a/app/views/play_view.coffee
+++ b/app/views/play_view.coffee
@@ -111,14 +111,6 @@ module.exports = class PlayView extends View
id: 'molotov-medic'
description: "Tharin must play support in this dungeon battle."
}
-# {
-# name: 'The Herd'
-# id: 'the-herd'
-# description: "Stop an ogre stampede with deadly artillery."
-# image: '/images/generic-icon.png'
-# difficulty: 3
-# disabled: true
-# }
{
name: 'Gridmancer'
id: 'gridmancer'
@@ -128,16 +120,24 @@ module.exports = class PlayView extends View
}
]
-# arenas = [
-# {
-# name: 'Forest Arena'
-# difficulty: 3
-# id: 'forest-arena'
-# image: '/images/levels/forest_arena_icon.png'
-# description: "Play head-to-head against friends!"
-# disabled: true
-# }
-# ]
+ arenas = [
+ {
+ name: 'Dungeon Arena'
+ difficulty: 3
+ id: 'dungeon-arena'
+ image: '/file/db/level/526ae95c1e5cd30000000008/zone_of_danger_icon.png'
+ description: "Play head-to-head against fellow Wizards in a dungeon melee!"
+ levelPath: 'ladder'
+ }
+ {
+ name: 'Brawlwood'
+ difficulty: 4
+ id: 'brawlwood'
+ image: '/file/db/level/525ef8ef06e1ab0962000003/commanding_followers_icon.png'
+ description: "Combat the armies of other Wizards in a strategic forest arena! (Fast computer required.)"
+ levelPath: 'ladder'
+ }
+ ]
playerCreated = [
{
@@ -168,21 +168,27 @@ module.exports = class PlayView extends View
image: '/file/db/level/525dc5589a0765e496000006/drink_me_icon.png'
description: 'Kill the ogres and save the peasants and their cattle. - by Prabh Simran Singh Baweja'
}
-
{
- name: 'Enemy Artillery'
- difficulty: 1
- id: 'enemy-artillery'
- image: '/file/db/level/526dba94a188322044000a40/mobile_artillery_icon.png'
- description: "Take cover while shells fly, then strike! - by mcdavid1991"
- disabled: true
+ name: 'Ogres of Hanoi'
+ difficulty: 3
+ id: 'ogres-of-hanoi'
+ image: '/file/db/level/526fd3043c637ece50001bb2/the_herd_icon.png'
+ description: "Transfer a stack of ogres while preserving their honor. - by Alexandru"
}
+ #{
+ # name: 'Enemy Artillery'
+ # difficulty: 1
+ # id: 'enemy-artillery'
+ # image: '/file/db/level/526dba94a188322044000a40/mobile_artillery_icon.png'
+ # description: "Take cover while shells fly, then strike! - by mcdavid1991"
+ # disabled: true
+ #}
]
context.campaigns = [
{id: "beginner", name: "Beginner Campaign", description: "... in which you learn the wizardry of programming.", levels: tutorials}
+ {id: "multiplayer", name: "Multiplayer Arenas", description: "... in which you code head-to-head against other players.", levels: arenas}
{id: "dev", name: "Random Harder Levels", description: "... in which you learn the interface while doing something a little harder.", levels: experienced}
-# {id: "multiplayer", name: "Multiplayer Arenas", description: "... in which you code head-to-head against other players.", levels: arenas}
{id: "player_created", name: "Player-Created", description: "... in which you battle against the creativity of your fellow Artisan Wizards.", levels: playerCreated}
]