mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-23 23:58:02 -05:00
A ton of misc bug fixes and performance improvements, getting ready to merge world streaming and flags back in.
This commit is contained in:
parent
1a7e4554f0
commit
718d586f07
21 changed files with 110 additions and 79 deletions
|
@ -27,8 +27,7 @@ init = ->
|
||||||
# Set up Backbone.Mediator schemas
|
# Set up Backbone.Mediator schemas
|
||||||
setUpDefinitions()
|
setUpDefinitions()
|
||||||
setUpChannels()
|
setUpChannels()
|
||||||
#Backbone.Mediator.setValidationEnabled document.location.href.search(/codecombat.com/) is -1
|
Backbone.Mediator.setValidationEnabled document.location.href.search(/codecombat.com/) is -1
|
||||||
Backbone.Mediator.setValidationEnabled false # STREAM: Should change back
|
|
||||||
app.initialize()
|
app.initialize()
|
||||||
Backbone.history.start({ pushState: true })
|
Backbone.history.start({ pushState: true })
|
||||||
handleNormalUrls()
|
handleNormalUrls()
|
||||||
|
|
|
@ -91,7 +91,7 @@ module.exports = class God extends CocoClass
|
||||||
userCodeMap = {}
|
userCodeMap = {}
|
||||||
for spellKey, spell of spells
|
for spellKey, spell of spells
|
||||||
for thangID, spellThang of spell.thangs
|
for thangID, spellThang of spell.thangs
|
||||||
continue if spellThang.thang.programmableMethods[spell.name].cloneOf
|
continue if spellThang.thang?.programmableMethods[spell.name].cloneOf
|
||||||
(userCodeMap[thangID] ?= {})[spell.name] = spellThang.aether.serialize()
|
(userCodeMap[thangID] ?= {})[spell.name] = spellThang.aether.serialize()
|
||||||
userCodeMap
|
userCodeMap
|
||||||
|
|
||||||
|
|
|
@ -184,7 +184,7 @@ module.exports = class Simulator extends CocoClass
|
||||||
try
|
try
|
||||||
@commenceSimulationAndSetupCallback()
|
@commenceSimulationAndSetupCallback()
|
||||||
catch err
|
catch err
|
||||||
console.error 'There was an error in simulation:', err, "-- trying again in #{@retryDelayInSeconds} seconds"
|
console.error 'There was an error in simulation:', err, err.stack, "-- trying again in #{@retryDelayInSeconds} seconds"
|
||||||
@simulateAnotherTaskAfterDelay()
|
@simulateAnotherTaskAfterDelay()
|
||||||
|
|
||||||
assignWorldAndLevelFromLevelLoaderAndDestroyIt: ->
|
assignWorldAndLevelFromLevelLoaderAndDestroyIt: ->
|
||||||
|
|
|
@ -59,7 +59,8 @@ module.exports = class WizardSprite extends IndieSprite
|
||||||
|
|
||||||
toggle: (to) ->
|
toggle: (to) ->
|
||||||
@imageObject?.visible = to
|
@imageObject?.visible = to
|
||||||
@labels.name?[if to then 'show' else 'hide']()
|
label[if to then 'show' else 'hide']() for name, label of @labels
|
||||||
|
mark.mark?.visible = to for name, mark of @marks
|
||||||
|
|
||||||
onPlayerStatesChanged: (e) ->
|
onPlayerStatesChanged: (e) ->
|
||||||
for playerID, state of e.states
|
for playerID, state of e.states
|
||||||
|
|
|
@ -47,7 +47,6 @@ module.exports = class ThangState
|
||||||
value = @specialKeysToValues[specialKey]
|
value = @specialKeysToValues[specialKey]
|
||||||
else if type is 'Thang'
|
else if type is 'Thang'
|
||||||
specialKey = storage[@frameIndex]
|
specialKey = storage[@frameIndex]
|
||||||
console.error "couldn't find world from thang", @thang, "for", @specialKeysToValues[specialKey] unless @thang.world
|
|
||||||
value = @thang.world.getThangByID @specialKeysToValues[specialKey]
|
value = @thang.world.getThangByID @specialKeysToValues[specialKey]
|
||||||
else if type is 'array'
|
else if type is 'array'
|
||||||
specialKey = storage[@frameIndex]
|
specialKey = storage[@frameIndex]
|
||||||
|
@ -174,7 +173,6 @@ module.exports = class ThangState
|
||||||
# Optimize like no tomorrow--most performance-sensitive part of the whole app, called once per WorldFrame per Thang per trackedProperty, blocking the UI
|
# Optimize like no tomorrow--most performance-sensitive part of the whole app, called once per WorldFrame per Thang per trackedProperty, blocking the UI
|
||||||
ts = new ThangState
|
ts = new ThangState
|
||||||
ts.thang = thang
|
ts.thang = thang
|
||||||
console.error "couldn't find thang!", @ unless thang
|
|
||||||
ts.frameIndex = frameIndex
|
ts.frameIndex = frameIndex
|
||||||
ts.trackedPropertyKeys = trackedPropertyKeys
|
ts.trackedPropertyKeys = trackedPropertyKeys
|
||||||
ts.trackedPropertyTypes = trackedPropertyTypes
|
ts.trackedPropertyTypes = trackedPropertyTypes
|
||||||
|
|
|
@ -71,9 +71,11 @@ module.exports = class World
|
||||||
@thangs[i] = thang
|
@thangs[i] = thang
|
||||||
@thangMap[thang.id] = thang
|
@thangMap[thang.id] = thang
|
||||||
|
|
||||||
thangDialogueSounds: ->
|
thangDialogueSounds: (startFrame=0) ->
|
||||||
|
return [] unless startFrame < @frames.length
|
||||||
[sounds, seen] = [[], {}]
|
[sounds, seen] = [[], {}]
|
||||||
for frame in @frames
|
for frameIndex in [startFrame ... @frames.length]
|
||||||
|
frame = @frames[frameIndex]
|
||||||
for thangID, state of frame.thangStateMap
|
for thangID, state of frame.thangStateMap
|
||||||
continue unless state.thang.say and sayMessage = state.getStateForProp 'sayMessage'
|
continue unless state.thang.say and sayMessage = state.getStateForProp 'sayMessage'
|
||||||
soundKey = state.thang.spriteName + ':' + sayMessage
|
soundKey = state.thang.spriteName + ':' + sayMessage
|
||||||
|
@ -90,64 +92,30 @@ module.exports = class World
|
||||||
|
|
||||||
loadFrames: (loadedCallback, errorCallback, loadProgressCallback, skipDeferredLoading, loadUntilFrame) ->
|
loadFrames: (loadedCallback, errorCallback, loadProgressCallback, skipDeferredLoading, loadUntilFrame) ->
|
||||||
return if @aborted
|
return if @aborted
|
||||||
unless @thangs.length
|
console.log 'Warning: loadFrames called on empty World (no thangs).' unless @thangs.length
|
||||||
console.log 'Warning: loadFrames called on empty World (no thangs).'
|
|
||||||
t1 = now()
|
t1 = now()
|
||||||
@t0 ?= t1
|
@t0 ?= t1
|
||||||
@worldLoadStartTime ?= t1
|
@worldLoadStartTime ?= t1
|
||||||
@lastRealTimeUpdate ?= 0
|
@lastRealTimeUpdate ?= 0
|
||||||
if loadUntilFrame
|
continueLaterFn = =>
|
||||||
frameToLoadUntil = loadUntilFrame + 1
|
@loadFrames(loadedCallback, errorCallback, loadProgressCallback, skipDeferredLoading, loadUntilFrame) unless @destroyed
|
||||||
else
|
frameToLoadUntil = if loadUntilFrame then loadUntilFrame + 1 else @totalFrames # Might stop early if debugging.
|
||||||
frameToLoadUntil = @totalFrames
|
|
||||||
i = @frames.length
|
i = @frames.length
|
||||||
while i < frameToLoadUntil and i < @totalFrames
|
while i < frameToLoadUntil and i < @totalFrames
|
||||||
t2 = now()
|
return unless @shouldContinueLoading t1, loadProgressCallback, skipDeferredLoading, continueLaterFn
|
||||||
if @realTime
|
@adjustFlowSettings loadUntilFrame if @debugging
|
||||||
shouldUpdateProgress = @shouldUpdateRealTimePlayback t2
|
|
||||||
shouldDelayRealTimeSimulation = not shouldUpdateProgress and @shouldDelayRealTimeSimulation t2
|
|
||||||
else
|
|
||||||
shouldUpdateProgress = t2 - t1 > PROGRESS_UPDATE_INTERVAL
|
|
||||||
shouldDelayRealTimeSimulation = false
|
|
||||||
if shouldUpdateProgress or shouldDelayRealTimeSimulation
|
|
||||||
if shouldUpdateProgress
|
|
||||||
@lastRealTimeUpdate = i * @dt if @realTime
|
|
||||||
#console.log 'we think it is now', (t2 - @worldLoadStartTime) / 1000, 'so delivering', @lastRealTimeUpdate
|
|
||||||
loadProgressCallback? i / @totalFrames unless @preloading
|
|
||||||
t1 = t2
|
|
||||||
if t2 - @t0 > 1000
|
|
||||||
console.log ' Loaded', i, 'of', @totalFrames, '(+' + (t2 - @t0).toFixed(0) + 'ms)' unless @realTime
|
|
||||||
@t0 = t2
|
|
||||||
continueFn = =>
|
|
||||||
return if @destroyed
|
|
||||||
if loadUntilFrame
|
|
||||||
@loadFrames(loadedCallback,errorCallback,loadProgressCallback, skipDeferredLoading, loadUntilFrame)
|
|
||||||
else
|
|
||||||
@loadFrames(loadedCallback, errorCallback, loadProgressCallback, skipDeferredLoading)
|
|
||||||
if skipDeferredLoading
|
|
||||||
continueFn()
|
|
||||||
else
|
|
||||||
delay = if shouldDelayRealTimeSimulation then REAL_TIME_BUFFERED_WAIT_INTERVAL else 0
|
|
||||||
setTimeout(continueFn, delay)
|
|
||||||
return
|
|
||||||
|
|
||||||
if @debugging
|
|
||||||
for thang in @thangs when thang.isProgrammable
|
|
||||||
userCode = @userCodeMap[thang.id] ? {}
|
|
||||||
for methodName, aether of userCode
|
|
||||||
framesToLoadFlowBefore = if methodName is 'plan' or methodName is 'makeBid' then 200 else 1 # Adjust if plan() is taking even longer
|
|
||||||
aether._shouldSkipFlow = i < loadUntilFrame - framesToLoadFlowBefore
|
|
||||||
try
|
try
|
||||||
@getFrame(i)
|
@getFrame(i)
|
||||||
++i # increment this after we have succeeded in getting the frame, otherwise we'll have to do that frame again
|
++i # Increment this after we have succeeded in getting the frame, otherwise we'll have to do that frame again
|
||||||
catch error
|
catch error
|
||||||
# Not an Aether.errors.UserCodeError; maybe we can't recover
|
@addError error # Not an Aether.errors.UserCodeError; maybe we can't recover
|
||||||
@addError error
|
|
||||||
unless @preloading or @debugging
|
unless @preloading or @debugging
|
||||||
for error in (@unhandledRuntimeErrors ? [])
|
for error in (@unhandledRuntimeErrors ? [])
|
||||||
return unless errorCallback error # errorCallback tells us whether the error is recoverable
|
return unless errorCallback error # errorCallback tells us whether the error is recoverable
|
||||||
@unhandledRuntimeErrors = []
|
@unhandledRuntimeErrors = []
|
||||||
|
@finishLoadingFrames loadProgressCallback, loadedCallback
|
||||||
|
|
||||||
|
finishLoadingFrames: (loadProgressCallback, loadedCallback) ->
|
||||||
unless @debugging
|
unless @debugging
|
||||||
@ended = true
|
@ended = true
|
||||||
system.finish @thangs for system in @systems
|
system.finish @thangs for system in @systems
|
||||||
|
@ -170,6 +138,38 @@ module.exports = class World
|
||||||
remainingBuffer = @lastRealTimeUpdate * 1000 - timeSinceStart
|
remainingBuffer = @lastRealTimeUpdate * 1000 - timeSinceStart
|
||||||
remainingBuffer < REAL_TIME_BUFFER_MIN
|
remainingBuffer < REAL_TIME_BUFFER_MIN
|
||||||
|
|
||||||
|
shouldContinueLoading: (t1, loadProgressCallback, skipDeferredLoading, continueLaterFn) ->
|
||||||
|
t2 = now()
|
||||||
|
if @realTime
|
||||||
|
shouldUpdateProgress = @shouldUpdateRealTimePlayback t2
|
||||||
|
shouldDelayRealTimeSimulation = not shouldUpdateProgress and @shouldDelayRealTimeSimulation t2
|
||||||
|
else
|
||||||
|
shouldUpdateProgress = t2 - t1 > PROGRESS_UPDATE_INTERVAL
|
||||||
|
shouldDelayRealTimeSimulation = false
|
||||||
|
return true unless shouldUpdateProgress or shouldDelayRealTimeSimulation
|
||||||
|
# Stop loading frames for now; continue in a moment.
|
||||||
|
if shouldUpdateProgress
|
||||||
|
@lastRealTimeUpdate = @frames.length * @dt if @realTime
|
||||||
|
#console.log 'we think it is now', (t2 - @worldLoadStartTime) / 1000, 'so delivering', @lastRealTimeUpdate
|
||||||
|
loadProgressCallback? @frames.length / @totalFrames unless @preloading
|
||||||
|
t1 = t2
|
||||||
|
if t2 - @t0 > 1000
|
||||||
|
console.log ' Loaded', @frames.length, 'of', @totalFrames, '(+' + (t2 - @t0).toFixed(0) + 'ms)' unless @realTime
|
||||||
|
@t0 = t2
|
||||||
|
if skipDeferredLoading
|
||||||
|
continueLaterFn()
|
||||||
|
else
|
||||||
|
delay = if shouldDelayRealTimeSimulation then REAL_TIME_BUFFERED_WAIT_INTERVAL else 0
|
||||||
|
setTimeout continueLaterFn, delay
|
||||||
|
false
|
||||||
|
|
||||||
|
adjustFlowSettings: (loadUntilFrame) ->
|
||||||
|
for thang in @thangs when thang.isProgrammable
|
||||||
|
userCode = @userCodeMap[thang.id] ? {}
|
||||||
|
for methodName, aether of userCode
|
||||||
|
framesToLoadFlowBefore = if methodName is 'plan' or methodName is 'makeBid' then 200 else 1 # Adjust if plan() is taking even longer
|
||||||
|
aether._shouldSkipFlow = @frames.length < loadUntilFrame - framesToLoadFlowBefore
|
||||||
|
|
||||||
finalizePreload: (loadedCallback) ->
|
finalizePreload: (loadedCallback) ->
|
||||||
@preloading = false
|
@preloading = false
|
||||||
loadedCallback() if @ended
|
loadedCallback() if @ended
|
||||||
|
|
|
@ -498,7 +498,9 @@
|
||||||
space: "Space"
|
space: "Space"
|
||||||
enter: "Enter"
|
enter: "Enter"
|
||||||
escape: "Escape"
|
escape: "Escape"
|
||||||
|
shift: "Shift"
|
||||||
cast_spell: "Cast current spell."
|
cast_spell: "Cast current spell."
|
||||||
|
run_real_time: "Run in real time."
|
||||||
continue_script: "Continue past current script."
|
continue_script: "Continue past current script."
|
||||||
skip_scripts: "Skip past all skippable scripts."
|
skip_scripts: "Skip past all skippable scripts."
|
||||||
toggle_playback: "Toggle play/pause."
|
toggle_playback: "Toggle play/pause."
|
||||||
|
|
|
@ -63,6 +63,7 @@ module.exports = class ThangType extends CocoModel
|
||||||
options = _.clone options
|
options = _.clone options
|
||||||
options.resolutionFactor ?= SPRITE_RESOLUTION_FACTOR
|
options.resolutionFactor ?= SPRITE_RESOLUTION_FACTOR
|
||||||
options.async ?= false
|
options.async ?= false
|
||||||
|
options.thang = null # Don't hold onto any bad Thang references.
|
||||||
options
|
options
|
||||||
|
|
||||||
buildSpriteSheet: (options) ->
|
buildSpriteSheet: (options) ->
|
||||||
|
@ -188,7 +189,7 @@ module.exports = class ThangType extends CocoModel
|
||||||
portrait = if portrait then '(Portrait)' else ''
|
portrait = if portrait then '(Portrait)' else ''
|
||||||
name = _.string.rpad @get('name'), 20
|
name = _.string.rpad @get('name'), 20
|
||||||
time = _.string.lpad '' + new Date().getTime() - startTime, 6
|
time = _.string.lpad '' + new Date().getTime() - startTime, 6
|
||||||
#console.debug "Built sheet: #{name} #{time}ms #{kind} #{portrait}" # STREAM: uncomment
|
console.debug "Built sheet: #{name} #{time}ms #{kind} #{portrait}"
|
||||||
|
|
||||||
spriteSheetKey: (options) ->
|
spriteSheetKey: (options) ->
|
||||||
colorConfigs = []
|
colorConfigs = []
|
||||||
|
|
|
@ -62,9 +62,10 @@ module.exports =
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
color:
|
color:
|
||||||
type: 'string'
|
oneOf: [
|
||||||
enum: ['green', 'black', 'violet']
|
{type: 'null'}
|
||||||
description: 'The flag color to place next, or omitted/null if deselected.'
|
{type: 'string', enum: ['green', 'black', 'violet'], description: 'The flag color to place next, or omitted/null if deselected.'}
|
||||||
|
]
|
||||||
pos:
|
pos:
|
||||||
type: 'object'
|
type: 'object'
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
|
|
@ -11,10 +11,11 @@ module.exports =
|
||||||
type: "object"
|
type: "object"
|
||||||
preload:
|
preload:
|
||||||
type: "boolean"
|
type: "boolean"
|
||||||
|
realTime:
|
||||||
|
type: "boolean"
|
||||||
required: []
|
required: []
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
|
||||||
# TODO do we really need both 'cast-spell' and 'cast-spells'?
|
|
||||||
"tome:cast-spells":
|
"tome:cast-spells":
|
||||||
title: "Cast Spells"
|
title: "Cast Spells"
|
||||||
$schema: "http://json-schema.org/draft-04/schema#"
|
$schema: "http://json-schema.org/draft-04/schema#"
|
||||||
|
@ -25,6 +26,8 @@ module.exports =
|
||||||
type: "object"
|
type: "object"
|
||||||
preload:
|
preload:
|
||||||
type: "boolean"
|
type: "boolean"
|
||||||
|
realTime:
|
||||||
|
type: "boolean"
|
||||||
required: []
|
required: []
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
|
||||||
|
@ -33,7 +36,9 @@ module.exports =
|
||||||
$schema: "http://json-schema.org/draft-04/schema#"
|
$schema: "http://json-schema.org/draft-04/schema#"
|
||||||
description: "Published when you wish to manually recast all spells"
|
description: "Published when you wish to manually recast all spells"
|
||||||
type: "object"
|
type: "object"
|
||||||
properties: {}
|
properties:
|
||||||
|
realTime:
|
||||||
|
type: "boolean"
|
||||||
required: []
|
required: []
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
|
||||||
|
|
|
@ -26,4 +26,4 @@
|
||||||
color: black
|
color: black
|
||||||
&.violet-flag
|
&.violet-flag
|
||||||
color: violet
|
color: violet
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,10 @@ block modal-body-content
|
||||||
dt(title="Shift+" + enter)
|
dt(title="Shift+" + enter)
|
||||||
code ⇧+#{enter}
|
code ⇧+#{enter}
|
||||||
dd(data-i18n="keyboard_shortcuts.cast_spell") Cast current spell.
|
dd(data-i18n="keyboard_shortcuts.cast_spell") Cast current spell.
|
||||||
|
dl.dl-horizontal
|
||||||
|
dt(title=ctrlName + "+Shift+" + enter)
|
||||||
|
code #{ctrl}+⇧+#{enter}
|
||||||
|
dd(data-i18n="keyboard_shortcuts.run_real_time") Run in real time.
|
||||||
dl.dl-horizontal
|
dl.dl-horizontal
|
||||||
dt(title="Shift+" + space)
|
dt(title="Shift+" + space)
|
||||||
code ⇧+#{space}
|
code ⇧+#{space}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
div.btn-group.btn-group-lg.cast-button-group
|
div.btn-group.btn-group-lg.cast-button-group
|
||||||
.button-progress-overlay
|
.button-progress-overlay
|
||||||
button.btn.btn-inverse.banner.cast-button(title=castShortcutVerbose + ": Cast current spell", data-i18n="play_level.tome_cast_button_cast") Spell Cast
|
button.btn.btn-inverse.banner.cast-button(title=castVerbose, data-i18n="play_level.tome_cast_button_cast") Spell Cast
|
||||||
button.btn.btn-inverse.banner.cast-real-time-button(title=castRealTimeShortcutVerbose + ": Cast in real time")
|
button.btn.btn-inverse.banner.cast-real-time-button(title=castRealTimeVerbose)
|
||||||
i.glyphicon.glyphicon-play
|
i.glyphicon.glyphicon-play
|
|
@ -197,8 +197,9 @@ module.exports = class LadderTabView extends CocoView
|
||||||
|
|
||||||
formatCount = d3.format(',.0')
|
formatCount = d3.format(',.0')
|
||||||
|
|
||||||
x = d3.scale.linear().domain([-3000, 6000]).range([0, width])
|
minX = Math.floor(Math.min(histogramData...) / 1000) * 1000
|
||||||
|
maxX = Math.ceil(Math.max(histogramData...) / 1000) * 1000
|
||||||
|
x = d3.scale.linear().domain([minX, maxX]).range([0, width])
|
||||||
data = d3.layout.histogram().bins(x.ticks(20))(histogramData)
|
data = d3.layout.histogram().bins(x.ticks(20))(histogramData)
|
||||||
y = d3.scale.linear().domain([0, d3.max(data, (d) -> d.y)]).range([height, 10])
|
y = d3.scale.linear().domain([0, d3.max(data, (d) -> d.y)]).range([height, 10])
|
||||||
|
|
||||||
|
|
|
@ -37,12 +37,13 @@ module.exports = class LevelFlagsView extends CocoView
|
||||||
@flagHistory = []
|
@flagHistory = []
|
||||||
|
|
||||||
onRealTimePlaybackEnded: (e) ->
|
onRealTimePlaybackEnded: (e) ->
|
||||||
@realTime = false
|
|
||||||
@onFlagSelected color: null
|
@onFlagSelected color: null
|
||||||
|
@realTime = false
|
||||||
@$el.hide()
|
@$el.hide()
|
||||||
|
|
||||||
onFlagSelected: (e) ->
|
onFlagSelected: (e) ->
|
||||||
return if @flagColor is e.color
|
return unless @realTime
|
||||||
|
return if @flagColor is e.color and e.source is 'shortcut'
|
||||||
color = if e.source is 'button' and e.color is @flagColor then null else e.color
|
color = if e.source is 'button' and e.color is @flagColor then null else e.color
|
||||||
@flagColor = color
|
@flagColor = color
|
||||||
Backbone.Mediator.publish 'level:flag-color-selected', color: color
|
Backbone.Mediator.publish 'level:flag-color-selected', color: color
|
||||||
|
@ -72,4 +73,4 @@ module.exports = class LevelFlagsView extends CocoView
|
||||||
|
|
||||||
onNewWorld: (event) ->
|
onNewWorld: (event) ->
|
||||||
return unless event.world.name is @world.name
|
return unless event.world.name is @world.name
|
||||||
@world = event.world
|
@world = @options.world = event.world
|
||||||
|
|
|
@ -22,7 +22,7 @@ module.exports = class LevelPlaybackView extends CocoView
|
||||||
'level-toggle-grid': 'onToggleGrid'
|
'level-toggle-grid': 'onToggleGrid'
|
||||||
'surface:frame-changed': 'onFrameChanged'
|
'surface:frame-changed': 'onFrameChanged'
|
||||||
'god:new-world-created': 'onNewWorld'
|
'god:new-world-created': 'onNewWorld'
|
||||||
'god:streaming-world-updated': 'onNewWorld' # Maybe?
|
'god:streaming-world-updated': 'onNewWorld'
|
||||||
'level-set-letterbox': 'onSetLetterbox'
|
'level-set-letterbox': 'onSetLetterbox'
|
||||||
'tome:cast-spells': 'onTomeCast'
|
'tome:cast-spells': 'onTomeCast'
|
||||||
'playback:real-time-playback-ended': 'onRealTimePlaybackEnded'
|
'playback:real-time-playback-ended': 'onRealTimePlaybackEnded'
|
||||||
|
|
|
@ -512,7 +512,12 @@ module.exports = class PlayLevelView extends RootView
|
||||||
@world = e.world
|
@world = e.world
|
||||||
@world.scripts = scripts
|
@world.scripts = scripts
|
||||||
thangTypes = @supermodel.getModels(ThangType)
|
thangTypes = @supermodel.getModels(ThangType)
|
||||||
for [spriteName, message] in @world.thangDialogueSounds()
|
startFrame = @lastWorldFramesLoaded ? 0
|
||||||
|
if @world.frames.length is @world.totalFrames # Finished loading
|
||||||
|
@lastWorldFramesLoaded = 0
|
||||||
|
else
|
||||||
|
@lastWorldFramesLoaded = @world.frames.length
|
||||||
|
for [spriteName, message] in @world.thangDialogueSounds startFrame
|
||||||
continue unless thangType = _.find thangTypes, (m) -> m.get('name') is spriteName
|
continue unless thangType = _.find thangTypes, (m) -> m.get('name') is spriteName
|
||||||
continue unless sound = AudioPlayer.soundForDialogue message, thangType.get('soundTriggers')
|
continue unless sound = AudioPlayer.soundForDialogue message, thangType.get('soundTriggers')
|
||||||
AudioPlayer.preloadSoundReference sound
|
AudioPlayer.preloadSoundReference sound
|
||||||
|
|
|
@ -21,13 +21,15 @@ module.exports = class CastButtonView extends CocoView
|
||||||
@spells = options.spells
|
@spells = options.spells
|
||||||
@levelID = options.levelID
|
@levelID = options.levelID
|
||||||
@castShortcut = '⇧↵'
|
@castShortcut = '⇧↵'
|
||||||
@castShortcutVerbose = 'Shift+Enter'
|
|
||||||
@castRealTimeShortcutVerbose = 'Ctrl+Shift+Enter'
|
|
||||||
|
|
||||||
getRenderData: (context={}) ->
|
getRenderData: (context={}) ->
|
||||||
context = super context
|
context = super context
|
||||||
context.castShortcutVerbose = @castShortcutVerbose
|
shift = $.i18n.t 'keyboard_shortcuts.shift'
|
||||||
context.castRealTimeShortcutVerbose = @castRealTimeShortcutVerbose
|
enter = $.i18n.t 'keyboard_shortcuts.enter'
|
||||||
|
castShortcutVerbose = "#{shift}+#{enter}"
|
||||||
|
castRealTimeShortcutVerbose = (if @isMac() then 'Cmd' else 'Ctrl') + '+' + castShortcutVerbose
|
||||||
|
context.castVerbose = castShortcutVerbose + ': ' + $.i18n.t('keyboard_shortcuts.cast_spell')
|
||||||
|
context.castRealTimeVerbose = castRealTimeShortcutVerbose + ': ' + $.i18n.t('keyboard_shortcuts.run_real_time')
|
||||||
context
|
context
|
||||||
|
|
||||||
afterRender: ->
|
afterRender: ->
|
||||||
|
@ -101,6 +103,6 @@ module.exports = class CastButtonView extends CocoView
|
||||||
@autocastDelay = delay = parseInt delay
|
@autocastDelay = delay = parseInt delay
|
||||||
me.set('autocastDelay', delay)
|
me.set('autocastDelay', delay)
|
||||||
me.patch()
|
me.patch()
|
||||||
spell.view.setAutocastDelay delay for spellKey, spell of @spells
|
spell.view?.setAutocastDelay delay for spellKey, spell of @spells
|
||||||
@castOptions.find('a').each ->
|
@castOptions.find('a').each ->
|
||||||
$(@).toggleClass('selected', parseInt($(@).attr('data-delay')) is delay)
|
$(@).toggleClass('selected', parseInt($(@).attr('data-delay')) is delay)
|
||||||
|
|
|
@ -40,10 +40,13 @@ module.exports = class Spell
|
||||||
if @permissions.readwrite.length and sessionSource = @session.getSourceFor(@spellKey)
|
if @permissions.readwrite.length and sessionSource = @session.getSourceFor(@spellKey)
|
||||||
@source = sessionSource
|
@source = sessionSource
|
||||||
@thangs = {}
|
@thangs = {}
|
||||||
@view = new SpellView {spell: @, session: @session, worker: @worker}
|
if true # @canRead() # Surely we could avoid creating these if we'll never use them? TODO
|
||||||
@view.render() # Get it ready and code loaded in advance
|
@view = new SpellView {spell: @, session: @session, worker: @worker}
|
||||||
@tabView = new SpellListTabEntryView spell: @, supermodel: @supermodel, language: @language
|
@view.render() # Get it ready and code loaded in advance
|
||||||
@tabView.render()
|
@tabView = new SpellListTabEntryView spell: @, supermodel: @supermodel, language: @language
|
||||||
|
@tabView.render()
|
||||||
|
#else
|
||||||
|
# @spell.loaded = true
|
||||||
@team = @permissions.readwrite[0] ? 'common'
|
@team = @permissions.readwrite[0] ? 'common'
|
||||||
Backbone.Mediator.publish 'tome:spell-created', spell: @
|
Backbone.Mediator.publish 'tome:spell-created', spell: @
|
||||||
|
|
||||||
|
|
|
@ -517,7 +517,7 @@ module.exports = class SpellView extends CocoView
|
||||||
spellThang.castAether = aether
|
spellThang.castAether = aether
|
||||||
spellThang.aether = @spell.createAether thang
|
spellThang.aether = @spell.createAether thang
|
||||||
#console.log thangID, @spell.spellKey, 'ran', aether.metrics.callsExecuted, 'times over', aether.metrics.statementsExecuted, 'statements, with max recursion depth', aether.metrics.maxDepth, 'and full flow/metrics', aether.metrics, aether.flow
|
#console.log thangID, @spell.spellKey, 'ran', aether.metrics.callsExecuted, 'times over', aether.metrics.statementsExecuted, 'statements, with max recursion depth', aether.metrics.maxDepth, 'and full flow/metrics', aether.metrics, aether.flow
|
||||||
@spell.transpile()
|
@spell.transpile() # TODO: is there any way we can avoid doing this if it hasn't changed? Causes a slight hang.
|
||||||
@updateAether false, false
|
@updateAether false, false
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -29,6 +29,8 @@ module.exports = class ThangListView extends CocoView
|
||||||
false
|
false
|
||||||
), @sortScoreForThang
|
), @sortScoreForThang
|
||||||
@muggleThangs = _.sortBy _.without(@thangs, @readwriteThangs..., @readThangs...), @sortScoreForThang
|
@muggleThangs = _.sortBy _.without(@thangs, @readwriteThangs..., @readThangs...), @sortScoreForThang
|
||||||
|
if @muggleThangs.length > 15
|
||||||
|
@muggleThangs = [] # Don't render a zillion of these. Slow, too long, maybe not useful.
|
||||||
|
|
||||||
sortScoreForThang: (t) =>
|
sortScoreForThang: (t) =>
|
||||||
# Sort by my team, then most spells and fewest shared Thangs per spell,
|
# Sort by my team, then most spells and fewest shared Thangs per spell,
|
||||||
|
@ -73,6 +75,12 @@ module.exports = class ThangListView extends CocoView
|
||||||
null
|
null
|
||||||
|
|
||||||
adjustThangs: (spells, thangs) ->
|
adjustThangs: (spells, thangs) ->
|
||||||
|
# TODO: it would be nice to not have to do this any more, like if we migrate to the hero levels.
|
||||||
|
# Recreating all the ThangListEntryViews and their ThangAvatarViews is pretty slow.
|
||||||
|
# So they aren't even kept up-to-date during world streaming.
|
||||||
|
# Updating the existing subviews? Would be kind of complicated to get all the new thangs and spells propagated.
|
||||||
|
# I would do it, if I didn't think we were perhaps soon to not do the ThangList any more.
|
||||||
|
# Will temporary reduce the number of muggle thangs we're willing to draw.
|
||||||
@spells = @options.spells = spells
|
@spells = @options.spells = spells
|
||||||
for entry in @entries
|
for entry in @entries
|
||||||
entry.$el.remove()
|
entry.$el.remove()
|
||||||
|
|
Loading…
Reference in a new issue