2014-07-17 20:20:11 -04:00
|
|
|
CocoView = require 'views/kinds/CocoView'
|
2014-01-03 13:32:13 -05:00
|
|
|
template = require 'templates/play/level/tome/cast_button'
|
|
|
|
{me} = require 'lib/auth'
|
2014-11-10 15:47:24 -05:00
|
|
|
LevelOptions = require 'lib/LevelOptions'
|
2014-01-03 13:32:13 -05:00
|
|
|
|
2014-07-17 20:20:11 -04:00
|
|
|
module.exports = class CastButtonView extends CocoView
|
2014-01-03 13:32:13 -05:00
|
|
|
id: 'cast-button-view'
|
|
|
|
template: template
|
|
|
|
|
2014-03-24 13:11:27 -04:00
|
|
|
events:
|
|
|
|
'click .cast-button': 'onCastButtonClick'
|
2014-09-22 17:05:13 -04:00
|
|
|
'click .submit-button': 'onCastRealTimeButtonClick'
|
2014-11-10 18:16:28 -05:00
|
|
|
'click .done-button': 'onDoneButtonClick'
|
2014-03-24 13:11:27 -04:00
|
|
|
|
2014-01-03 13:32:13 -05:00
|
|
|
subscriptions:
|
2014-06-30 22:16:26 -04:00
|
|
|
'tome:spell-changed': 'onSpellChanged'
|
2014-01-03 13:32:13 -05:00
|
|
|
'tome:cast-spells': 'onCastSpells'
|
|
|
|
'god:new-world-created': 'onNewWorld'
|
2014-10-31 19:33:43 -04:00
|
|
|
'real-time-multiplayer:created-game': 'onJoinedRealTimeMultiplayerGame'
|
2014-08-29 18:10:04 -04:00
|
|
|
'real-time-multiplayer:joined-game': 'onJoinedRealTimeMultiplayerGame'
|
|
|
|
'real-time-multiplayer:left-game': 'onLeftRealTimeMultiplayerGame'
|
2014-09-22 17:05:13 -04:00
|
|
|
'goal-manager:new-goal-states': 'onNewGoalStates'
|
2014-09-23 21:21:27 -04:00
|
|
|
'god:goals-calculated': 'onGoalsCalculated'
|
2014-01-03 13:32:13 -05:00
|
|
|
|
|
|
|
constructor: (options) ->
|
|
|
|
super options
|
|
|
|
@spells = options.spells
|
2014-02-19 17:00:54 -05:00
|
|
|
@levelID = options.levelID
|
2014-06-30 22:16:26 -04:00
|
|
|
@castShortcut = '⇧↵'
|
2014-11-10 18:16:28 -05:00
|
|
|
@levelOptions = LevelOptions[@options.levelID] ? {}
|
|
|
|
@initButtonTextABTest() unless @levelOptions.hidesRealTimePlayback
|
2014-01-03 13:32:13 -05:00
|
|
|
|
2014-02-11 17:58:45 -05:00
|
|
|
getRenderData: (context={}) ->
|
2014-01-03 13:32:13 -05:00
|
|
|
context = super context
|
2014-08-25 00:39:34 -04:00
|
|
|
shift = $.i18n.t 'keyboard_shortcuts.shift'
|
|
|
|
enter = $.i18n.t 'keyboard_shortcuts.enter'
|
|
|
|
castShortcutVerbose = "#{shift}+#{enter}"
|
|
|
|
castRealTimeShortcutVerbose = (if @isMac() then 'Cmd' else 'Ctrl') + '+' + castShortcutVerbose
|
2014-11-07 19:04:35 -05:00
|
|
|
context.castVerbose = castShortcutVerbose + ': ' + $.i18n.t('keyboard_shortcuts.run_code')
|
2014-08-25 00:39:34 -04:00
|
|
|
context.castRealTimeVerbose = castRealTimeShortcutVerbose + ': ' + $.i18n.t('keyboard_shortcuts.run_real_time')
|
2014-11-06 17:44:56 -05:00
|
|
|
# A/B test submit button text
|
2014-11-08 00:56:49 -05:00
|
|
|
context.testSubmitText = @testButtonsText.submit if @testGroup? and @testGroup isnt 0
|
2014-01-03 13:32:13 -05:00
|
|
|
context
|
|
|
|
|
|
|
|
afterRender: ->
|
|
|
|
super()
|
2014-02-12 15:41:41 -05:00
|
|
|
@castButton = $('.cast-button', @$el)
|
|
|
|
@castOptions = $('.autocast-delays', @$el)
|
2014-09-15 14:56:29 -04:00
|
|
|
#delay = me.get('autocastDelay') # No more autocast
|
|
|
|
delay = 90019001
|
2014-01-03 13:32:13 -05:00
|
|
|
@setAutocastDelay delay
|
2014-11-10 18:16:28 -05:00
|
|
|
if @levelOptions.hidesSubmitUntilRun or @levelOptions.hidesRealTimePlayback
|
|
|
|
@$el.find('.submit-button').hide() # Hide Submit for the first few until they run it once.
|
|
|
|
if @options.session.get('state')?.complete and @levelOptions.hidesRealTimePlayback
|
|
|
|
@$el.find('.done-button').show()
|
|
|
|
if @options.levelID is 'thornbush-farm'# and not @options.session.get('state')?.complete
|
|
|
|
@$el.find('.submit-button').hide() # Hide submit until first win so that script can explain it.
|
2014-01-03 13:32:13 -05:00
|
|
|
|
2014-01-25 18:11:29 -05:00
|
|
|
attachTo: (spellView) ->
|
|
|
|
@$el.detach().prependTo(spellView.toolbarView.$el).show()
|
|
|
|
|
2014-02-12 23:45:29 -05:00
|
|
|
onCastButtonClick: (e) ->
|
|
|
|
Backbone.Mediator.publish 'tome:manual-cast', {}
|
|
|
|
|
2014-08-23 17:31:38 -04:00
|
|
|
onCastRealTimeButtonClick: (e) ->
|
2014-11-17 18:07:10 -05:00
|
|
|
if @inRealTimeMultiplayerSession
|
2014-08-29 18:10:04 -04:00
|
|
|
Backbone.Mediator.publish 'real-time-multiplayer:manual-cast', {}
|
Real-time multiplayer initial commit
Simple matchmaking, synchronous multiplayer PVP, flags!
Rough matchmaking is under the game menu multiplayer tab, for ladder
games only. After creating a 2-person game there, you can exit that
modal and real-time cast to play against each other.
If you’re the first person to cast, you’ll sit at the real-time level
playback view waiting until the other player casts. When they do, you
both should start the real-time playback (and start placing flags like
crazy people).
If in a multiplayer session, the real-time simulation runs the players’
code against each other. Your multiplayer opponent’s name should be up
near the level name.
Multiplayer sessions are stored completely in Firebase for now, and
removed if both players leave the game. There’s plenty of bugs,
synchronization issues, and minimal polish to add before we push it to
master.
2014-08-29 02:34:07 -04:00
|
|
|
else
|
|
|
|
Backbone.Mediator.publish 'tome:manual-cast', {realTime: true}
|
2014-08-23 17:31:38 -04:00
|
|
|
|
2014-11-10 18:16:28 -05:00
|
|
|
onDoneButtonClick: (e) ->
|
|
|
|
Backbone.Mediator.publish 'level:show-victory', showModal: true
|
|
|
|
|
2014-01-03 13:32:13 -05:00
|
|
|
onSpellChanged: (e) ->
|
|
|
|
@updateCastButton()
|
|
|
|
|
|
|
|
onCastSpells: (e) ->
|
2014-05-11 20:42:32 -04:00
|
|
|
return if e.preload
|
2014-01-03 13:32:13 -05:00
|
|
|
@casting = true
|
2014-05-20 00:53:14 -04:00
|
|
|
if @hasStartedCastingOnce # Don't play this sound the first time
|
2014-08-27 15:24:03 -04:00
|
|
|
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'cast', volume: 0.5
|
2014-05-20 00:53:14 -04:00
|
|
|
@hasStartedCastingOnce = true
|
2014-01-03 13:32:13 -05:00
|
|
|
@updateCastButton()
|
|
|
|
|
|
|
|
onNewWorld: (e) ->
|
|
|
|
@casting = false
|
2014-05-20 00:53:14 -04:00
|
|
|
if @hasCastOnce # Don't play this sound the first time
|
2014-08-27 15:24:03 -04:00
|
|
|
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'cast-end', volume: 0.5
|
2014-05-20 00:53:14 -04:00
|
|
|
@hasCastOnce = true
|
2014-01-03 13:32:13 -05:00
|
|
|
@updateCastButton()
|
|
|
|
|
2014-09-22 17:05:13 -04:00
|
|
|
onNewGoalStates: (e) ->
|
2014-11-02 17:51:01 -05:00
|
|
|
winnable = e.overallStatus is 'success'
|
|
|
|
return if @winnable is winnable
|
|
|
|
@winnable = winnable
|
2014-09-22 17:05:13 -04:00
|
|
|
@$el.toggleClass 'winnable', @winnable
|
2014-11-02 17:51:01 -05:00
|
|
|
Backbone.Mediator.publish 'tome:winnability-updated', winnable: @winnable
|
2014-11-10 18:16:28 -05:00
|
|
|
if @levelOptions.hidesRealTimePlayback
|
|
|
|
@$el.find('.done-button').toggle @winnable
|
|
|
|
else if @winnable and @options.levelID is 'thornbush-farm'
|
|
|
|
@$el.find('.submit-button').show() # Hide submit until first win so that script can explain it.
|
2014-09-22 17:05:13 -04:00
|
|
|
|
2014-09-23 21:21:27 -04:00
|
|
|
onGoalsCalculated: (e) ->
|
2014-11-10 18:16:28 -05:00
|
|
|
# When preloading, with real-time playback enabled, we highlight the submit button when we think they'll win.
|
2014-09-23 21:21:27 -04:00
|
|
|
return unless e.preload
|
2014-11-10 18:16:28 -05:00
|
|
|
return if @levelOptions.hidesRealTimePlayback
|
|
|
|
return if @options.levelID is 'thornbush-farm' # Don't show it until they actually win for this first one.
|
2014-09-23 21:21:27 -04:00
|
|
|
@onNewGoalStates e
|
|
|
|
|
2014-01-03 13:32:13 -05:00
|
|
|
updateCastButton: ->
|
|
|
|
return if _.some @spells, (spell) => not spell.loaded
|
2014-04-22 14:04:56 -04:00
|
|
|
|
2014-04-22 11:54:35 -04:00
|
|
|
async.some _.values(@spells), (spell, callback) =>
|
|
|
|
spell.hasChangedSignificantly spell.getSource(), null, callback
|
|
|
|
, (castable) =>
|
2014-05-19 13:08:12 -04:00
|
|
|
Backbone.Mediator.publish 'tome:spell-has-changed-significantly-calculation', hasChangedSignificantly: castable
|
2014-09-22 17:05:13 -04:00
|
|
|
@castButton.toggleClass('castable', castable).toggleClass('casting', @casting)
|
2014-11-07 19:04:35 -05:00
|
|
|
|
2014-11-06 17:44:56 -05:00
|
|
|
# A/B testing cast button text for en-US
|
2014-11-08 00:56:49 -05:00
|
|
|
unless @testGroup? and @testGroup isnt 0
|
2014-11-06 17:44:56 -05:00
|
|
|
if @casting
|
|
|
|
castText = $.i18n.t('play_level.tome_cast_button_running')
|
|
|
|
else if castable or true
|
|
|
|
castText = $.i18n.t('play_level.tome_cast_button_run')
|
2014-11-10 18:16:28 -05:00
|
|
|
unless @levelOptions.hidesRunShortcut # Hide for first few.
|
2014-11-06 17:44:56 -05:00
|
|
|
castText += ' ' + @castShortcut
|
|
|
|
else
|
|
|
|
castText = $.i18n.t('play_level.tome_cast_button_ran')
|
2014-04-22 11:54:35 -04:00
|
|
|
else
|
2014-11-06 17:44:56 -05:00
|
|
|
castText = @testButtonsText.run
|
|
|
|
@castButton.text castText
|
2014-11-05 21:06:21 -05:00
|
|
|
#@castButton.prop 'disabled', not castable
|
2014-01-03 13:32:13 -05:00
|
|
|
|
|
|
|
setAutocastDelay: (delay) ->
|
2014-06-30 22:16:26 -04:00
|
|
|
#console.log 'Set autocast delay to', delay
|
2014-01-03 13:32:13 -05:00
|
|
|
return unless delay
|
2014-09-15 14:56:29 -04:00
|
|
|
delay = 90019001 # No more autocast
|
2014-01-03 13:32:13 -05:00
|
|
|
@autocastDelay = delay = parseInt delay
|
2014-03-21 16:04:16 -04:00
|
|
|
me.set('autocastDelay', delay)
|
2014-06-11 17:17:31 -04:00
|
|
|
me.patch()
|
2014-08-25 00:39:34 -04:00
|
|
|
spell.view?.setAutocastDelay delay for spellKey, spell of @spells
|
2014-01-03 13:32:13 -05:00
|
|
|
@castOptions.find('a').each ->
|
|
|
|
$(@).toggleClass('selected', parseInt($(@).attr('data-delay')) is delay)
|
Real-time multiplayer initial commit
Simple matchmaking, synchronous multiplayer PVP, flags!
Rough matchmaking is under the game menu multiplayer tab, for ladder
games only. After creating a 2-person game there, you can exit that
modal and real-time cast to play against each other.
If you’re the first person to cast, you’ll sit at the real-time level
playback view waiting until the other player casts. When they do, you
both should start the real-time playback (and start placing flags like
crazy people).
If in a multiplayer session, the real-time simulation runs the players’
code against each other. Your multiplayer opponent’s name should be up
near the level name.
Multiplayer sessions are stored completely in Firebase for now, and
removed if both players leave the game. There’s plenty of bugs,
synchronization issues, and minimal polish to add before we push it to
master.
2014-08-29 02:34:07 -04:00
|
|
|
|
2014-08-29 18:10:04 -04:00
|
|
|
onJoinedRealTimeMultiplayerGame: (e) ->
|
2014-11-17 18:07:10 -05:00
|
|
|
@inRealTimeMultiplayerSession = true
|
Real-time multiplayer initial commit
Simple matchmaking, synchronous multiplayer PVP, flags!
Rough matchmaking is under the game menu multiplayer tab, for ladder
games only. After creating a 2-person game there, you can exit that
modal and real-time cast to play against each other.
If you’re the first person to cast, you’ll sit at the real-time level
playback view waiting until the other player casts. When they do, you
both should start the real-time playback (and start placing flags like
crazy people).
If in a multiplayer session, the real-time simulation runs the players’
code against each other. Your multiplayer opponent’s name should be up
near the level name.
Multiplayer sessions are stored completely in Firebase for now, and
removed if both players leave the game. There’s plenty of bugs,
synchronization issues, and minimal polish to add before we push it to
master.
2014-08-29 02:34:07 -04:00
|
|
|
|
2014-08-29 18:10:04 -04:00
|
|
|
onLeftRealTimeMultiplayerGame: (e) ->
|
2014-11-17 18:07:10 -05:00
|
|
|
@inRealTimeMultiplayerSession = false
|
2014-11-06 17:44:56 -05:00
|
|
|
|
2014-11-21 12:53:38 -05:00
|
|
|
# https://mixpanel.com/report/227350/segmentation/#action:segment,arb_event:'Saw%20Victory',bool_op:or,chart_type:bar,from_date:-9,segfilter:!((filter:(operand:!('Ogre%20Encampment'),operator:%3D%3D),property:level,selected_property_type:string,type:string),(property:castButtonTextGroup,selected_property_type:number,type:number)),segment_type:number,to_date:0,type:unique,unit:day
|
2014-11-06 17:44:56 -05:00
|
|
|
initButtonTextABTest: ->
|
2014-11-08 00:56:49 -05:00
|
|
|
return if me.isAdmin()
|
|
|
|
return unless $.i18n.lng() is 'en-US'
|
|
|
|
# A/B test buttons text
|
|
|
|
# Only testing 'en-US' for simplicity and it accounts for a significant % of users
|
|
|
|
# Test group 0 is existing behavior
|
|
|
|
# Intentionally leaving out cast shortcut for test groups for simplicity
|
|
|
|
@testGroup = me.getCastButtonTextGroup()
|
|
|
|
@testButtonsText = switch @testGroup
|
|
|
|
when 0 then run: 'Run/Running', submit: 'Submit'
|
|
|
|
when 1 then run: 'Run', submit: 'Submit'
|
|
|
|
when 2 then run: 'Test', submit: 'Submit'
|
|
|
|
when 3 then run: 'Run', submit: 'Continue'
|
|
|
|
when 4 then run: 'Test', submit: 'Continue'
|
|
|
|
when 5 then run: 'Run', submit: 'Finish'
|
|
|
|
when 6 then run: 'Test', submit: 'Finish'
|
2014-11-10 00:47:51 -05:00
|
|
|
application.tracker?.trackEvent 'Cast Button',
|
2014-11-08 00:56:49 -05:00
|
|
|
levelID: @levelID
|
|
|
|
castButtonText: @testButtonsText.run + ' ' + @testButtonsText.submit
|
2014-11-10 00:47:51 -05:00
|
|
|
castButtonTextGroup: @testGroup
|