mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-29 18:45:48 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
11a725e992
351 changed files with 4534 additions and 4681 deletions
|
@ -27,7 +27,7 @@ elementAcceptsKeystrokes = (el) ->
|
||||||
type = el.type?.toLowerCase()
|
type = el.type?.toLowerCase()
|
||||||
textInputTypes = ['text', 'password', 'file', 'number', 'search', 'url', 'tel', 'email', 'date', 'month', 'week', 'time', 'datetimelocal']
|
textInputTypes = ['text', 'password', 'file', 'number', 'search', 'url', 'tel', 'email', 'date', 'month', 'week', 'time', 'datetimelocal']
|
||||||
# not radio, checkbox, range, or color
|
# not radio, checkbox, range, or color
|
||||||
return (tag is 'textarea' or (tag is 'input' and type in textInputTypes) or el.contentEditable in ["", "true"]) and not (el.readOnly or el.disabled)
|
return (tag is 'textarea' or (tag is 'input' and type in textInputTypes) or el.contentEditable in ['', 'true']) and not (el.readOnly or el.disabled)
|
||||||
|
|
||||||
COMMON_FILES = ['/images/pages/base/modal_background.png', '/images/level/code_palette_background.png', '/images/level/popover_background.png', '/images/level/code_editor_background.png']
|
COMMON_FILES = ['/images/pages/base/modal_background.png', '/images/level/code_palette_background.png', '/images/level/popover_background.png', '/images/level/code_editor_background.png']
|
||||||
preload = (arrayOfImages) ->
|
preload = (arrayOfImages) ->
|
||||||
|
@ -49,7 +49,7 @@ Application = initialize: ->
|
||||||
resStore: locale
|
resStore: locale
|
||||||
#debug: true
|
#debug: true
|
||||||
#sendMissing: true
|
#sendMissing: true
|
||||||
#sendMissingTo: "current"
|
#sendMissingTo: 'current'
|
||||||
#resPostPath: '/languages/add/__lng__/__ns__'
|
#resPostPath: '/languages/add/__lng__/__ns__'
|
||||||
}, (t) =>
|
}, (t) =>
|
||||||
@router = new Router()
|
@router = new Router()
|
||||||
|
|
|
@ -3,9 +3,9 @@ File = require 'models/File'
|
||||||
|
|
||||||
module.exports = class ModelFiles extends CocoCollection
|
module.exports = class ModelFiles extends CocoCollection
|
||||||
model: File
|
model: File
|
||||||
|
|
||||||
constructor: (model) ->
|
constructor: (model) ->
|
||||||
super()
|
super()
|
||||||
url = model.constructor.prototype.urlRoot
|
url = model.constructor.prototype.urlRoot
|
||||||
url += "/#{model.get('original') or model.id}/files"
|
url += "/#{model.get('original') or model.id}/files"
|
||||||
@url = url
|
@url = url
|
||||||
|
|
|
@ -3,8 +3,7 @@ CocoCollection = require 'collections/CocoCollection'
|
||||||
|
|
||||||
module.exports = class PatchesCollection extends CocoCollection
|
module.exports = class PatchesCollection extends CocoCollection
|
||||||
model: PatchModel
|
model: PatchModel
|
||||||
|
|
||||||
initialize: (models, options, forModel, @status='pending') ->
|
initialize: (models, options, forModel, @status='pending') ->
|
||||||
super(arguments...)
|
super(arguments...)
|
||||||
@url = "#{forModel.urlRoot}/#{forModel.get('original')}/patches?status=#{@status}"
|
@url = "#{forModel.urlRoot}/#{forModel.get('original')}/patches?status=#{@status}"
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ module.exports = class ThangNamesCollection extends CocoCollection
|
||||||
isCachable: false
|
isCachable: false
|
||||||
|
|
||||||
constructor: (@ids) -> super()
|
constructor: (@ids) -> super()
|
||||||
|
|
||||||
fetch: (options) ->
|
fetch: (options) ->
|
||||||
options ?= {}
|
options ?= {}
|
||||||
_.extend options, {type:'POST', data:{ids:@ids}}
|
_.extend options, {type:'POST', data:{ids:@ids}}
|
||||||
|
|
|
@ -22,7 +22,7 @@ init = ->
|
||||||
testing = path.startsWith '/test'
|
testing = path.startsWith '/test'
|
||||||
demoing = path.startsWith '/demo'
|
demoing = path.startsWith '/demo'
|
||||||
initializeServices() unless testing or demoing
|
initializeServices() unless testing or demoing
|
||||||
|
|
||||||
# Set up Backbone.Mediator schemas
|
# Set up Backbone.Mediator schemas
|
||||||
setUpDefinitions()
|
setUpDefinitions()
|
||||||
setUpChannels()
|
setUpChannels()
|
||||||
|
@ -35,10 +35,10 @@ init = ->
|
||||||
treemaExt.setup()
|
treemaExt.setup()
|
||||||
|
|
||||||
$ -> init()
|
$ -> init()
|
||||||
|
|
||||||
handleNormalUrls = ->
|
handleNormalUrls = ->
|
||||||
# http://artsy.github.com/blog/2012/06/25/replacing-hashbang-routes-with-pushstate/
|
# http://artsy.github.com/blog/2012/06/25/replacing-hashbang-routes-with-pushstate/
|
||||||
$(document).on "click", "a[href^='/']", (event) ->
|
$(document).on 'click', "a[href^='/']", (event) ->
|
||||||
|
|
||||||
href = $(event.currentTarget).attr('href')
|
href = $(event.currentTarget).attr('href')
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ module.exports = class Angel extends CocoClass
|
||||||
constructor: (@shared) ->
|
constructor: (@shared) ->
|
||||||
super()
|
super()
|
||||||
@say 'Got my wings.'
|
@say 'Got my wings.'
|
||||||
if window.navigator and (window.navigator.userAgent.search("MSIE") isnt -1 or window.navigator.appName is 'Microsoft Internet Explorer')
|
if window.navigator and (window.navigator.userAgent.search('MSIE') isnt -1 or window.navigator.appName is 'Microsoft Internet Explorer')
|
||||||
@infiniteLoopIntervalDuration *= 10 # since it's so slow to serialize without transferable objects, we can't trust it
|
@infiniteLoopIntervalDuration *= 10 # since it's so slow to serialize without transferable objects, we can't trust it
|
||||||
@infiniteLoopTimeoutDuration *= 10
|
@infiniteLoopTimeoutDuration *= 10
|
||||||
@abortTimeoutDuration *= 10
|
@abortTimeoutDuration *= 10
|
||||||
|
@ -40,7 +40,7 @@ module.exports = class Angel extends CocoClass
|
||||||
return if @destroyed
|
return if @destroyed
|
||||||
clearTimeout @condemnTimeout
|
clearTimeout @condemnTimeout
|
||||||
@condemnTimeout = _.delay @infinitelyLooped, @infiniteLoopTimeoutDuration
|
@condemnTimeout = _.delay @infinitelyLooped, @infiniteLoopTimeoutDuration
|
||||||
@say "Let's give it", @infiniteLoopTimeoutDuration, "to not loop."
|
@say 'Let\'s give it', @infiniteLoopTimeoutDuration, 'to not loop.'
|
||||||
@worker.postMessage func: 'reportIn'
|
@worker.postMessage func: 'reportIn'
|
||||||
|
|
||||||
onWorkerMessage: (event) =>
|
onWorkerMessage: (event) =>
|
||||||
|
@ -58,7 +58,7 @@ module.exports = class Angel extends CocoClass
|
||||||
when 'start-load-frames'
|
when 'start-load-frames'
|
||||||
clearTimeout @condemnTimeout
|
clearTimeout @condemnTimeout
|
||||||
when 'report-in'
|
when 'report-in'
|
||||||
@say "Worker reported in."
|
@say 'Worker reported in.'
|
||||||
clearTimeout @condemnTimeout
|
clearTimeout @condemnTimeout
|
||||||
when 'end-load-frames'
|
when 'end-load-frames'
|
||||||
clearTimeout @condemnTimeout
|
clearTimeout @condemnTimeout
|
||||||
|
@ -84,7 +84,7 @@ module.exports = class Angel extends CocoClass
|
||||||
when 'new-world'
|
when 'new-world'
|
||||||
@beholdWorld event.data.serialized, event.data.goalStates
|
@beholdWorld event.data.serialized, event.data.goalStates
|
||||||
when 'abort'
|
when 'abort'
|
||||||
@say "Aborted.", event.data
|
@say 'Aborted.', event.data
|
||||||
clearTimeout @abortTimeout
|
clearTimeout @abortTimeout
|
||||||
@aborting = false
|
@aborting = false
|
||||||
@running = false
|
@running = false
|
||||||
|
@ -92,7 +92,7 @@ module.exports = class Angel extends CocoClass
|
||||||
@doWork()
|
@doWork()
|
||||||
|
|
||||||
else
|
else
|
||||||
@log "Received unsupported message:", event.data
|
@log 'Received unsupported message:', event.data
|
||||||
|
|
||||||
beholdGoalStates: (goalStates) ->
|
beholdGoalStates: (goalStates) ->
|
||||||
return if @aborting
|
return if @aborting
|
||||||
|
@ -125,37 +125,37 @@ module.exports = class Angel extends CocoClass
|
||||||
@doWork()
|
@doWork()
|
||||||
|
|
||||||
finalizePreload: ->
|
finalizePreload: ->
|
||||||
@say "Finalize preload."
|
@say 'Finalize preload.'
|
||||||
@worker.postMessage func: 'finalizePreload'
|
@worker.postMessage func: 'finalizePreload'
|
||||||
|
|
||||||
infinitelyLooped: =>
|
infinitelyLooped: =>
|
||||||
@say "On infinitely looped! Aborting?", @aborting
|
@say 'On infinitely looped! Aborting?', @aborting
|
||||||
return if @aborting
|
return if @aborting
|
||||||
problem = type: "runtime", level: "error", id: "runtime_InfiniteLoop", message: "Code never finished. It's either really slow or has an infinite loop."
|
problem = type: 'runtime', level: 'error', id: 'runtime_InfiniteLoop', message: 'Code never finished. It\'s either really slow or has an infinite loop.'
|
||||||
Backbone.Mediator.publish 'god:user-code-problem', problem: problem
|
Backbone.Mediator.publish 'god:user-code-problem', problem: problem
|
||||||
Backbone.Mediator.publish 'god:infinite-loop', firstWorld: @shared.firstWorld
|
Backbone.Mediator.publish 'god:infinite-loop', firstWorld: @shared.firstWorld
|
||||||
@fireWorker()
|
@fireWorker()
|
||||||
|
|
||||||
doWork: ->
|
doWork: ->
|
||||||
return if @aborting
|
return if @aborting
|
||||||
return @say "Not initialized for work yet." unless @initialized
|
return @say 'Not initialized for work yet.' unless @initialized
|
||||||
if @shared.workQueue.length
|
if @shared.workQueue.length
|
||||||
@work = @shared.workQueue.shift()
|
@work = @shared.workQueue.shift()
|
||||||
return _.defer @simulateSync, @work if @work.synchronous
|
return _.defer @simulateSync, @work if @work.synchronous
|
||||||
@say "Running world..."
|
@say 'Running world...'
|
||||||
@running = true
|
@running = true
|
||||||
@shared.busyAngels.push @
|
@shared.busyAngels.push @
|
||||||
@worker.postMessage func: 'runWorld', args: @work
|
@worker.postMessage func: 'runWorld', args: @work
|
||||||
clearTimeout @purgatoryTimer
|
clearTimeout @purgatoryTimer
|
||||||
@say "Infinite loop timer started at interval of", @infiniteLoopIntervalDuration
|
@say 'Infinite loop timer started at interval of', @infiniteLoopIntervalDuration
|
||||||
@purgatoryTimer = setInterval @testWorker, @infiniteLoopIntervalDuration
|
@purgatoryTimer = setInterval @testWorker, @infiniteLoopIntervalDuration
|
||||||
else
|
else
|
||||||
@say "No work to do."
|
@say 'No work to do.'
|
||||||
@hireWorker()
|
@hireWorker()
|
||||||
|
|
||||||
abort: ->
|
abort: ->
|
||||||
return unless @worker and @running
|
return unless @worker and @running
|
||||||
@say "Aborting..."
|
@say 'Aborting...'
|
||||||
@running = false
|
@running = false
|
||||||
@work = null
|
@work = null
|
||||||
_.remove @shared.busyAngels, @
|
_.remove @shared.busyAngels, @
|
||||||
|
@ -172,14 +172,14 @@ module.exports = class Angel extends CocoClass
|
||||||
@worker = null
|
@worker = null
|
||||||
clearTimeout @condemnTimeout
|
clearTimeout @condemnTimeout
|
||||||
clearInterval @purgatoryTimer
|
clearInterval @purgatoryTimer
|
||||||
@say "Fired worker."
|
@say 'Fired worker.'
|
||||||
@initialized = false
|
@initialized = false
|
||||||
@work = null
|
@work = null
|
||||||
@hireWorker() if rehire
|
@hireWorker() if rehire
|
||||||
|
|
||||||
hireWorker: ->
|
hireWorker: ->
|
||||||
return if @worker
|
return if @worker
|
||||||
@say "Hiring worker."
|
@say 'Hiring worker.'
|
||||||
@worker = new Worker @shared.workerCode
|
@worker = new Worker @shared.workerCode
|
||||||
@worker.addEventListener 'message', @onWorkerMessage
|
@worker.addEventListener 'message', @onWorkerMessage
|
||||||
@worker.creationTime = new Date()
|
@worker.creationTime = new Date()
|
||||||
|
@ -199,7 +199,7 @@ module.exports = class Angel extends CocoClass
|
||||||
testWorld.setGoalManager testGM
|
testWorld.setGoalManager testGM
|
||||||
@doSimulateWorld work
|
@doSimulateWorld work
|
||||||
console?.profileEnd?() if imitateIE9?
|
console?.profileEnd?() if imitateIE9?
|
||||||
console.log "Construction:", (work.t1 - work.t0).toFixed(0), "ms. Simulation:", (work.t2 - work.t1).toFixed(0), "ms --", ((work.t2 - work.t1) / testWorld.frames.length).toFixed(3), "ms per frame, profiled."
|
console.log 'Construction:', (work.t1 - work.t0).toFixed(0), 'ms. Simulation:', (work.t2 - work.t1).toFixed(0), 'ms --', ((work.t2 - work.t1) / testWorld.frames.length).toFixed(3), 'ms per frame, profiled.'
|
||||||
|
|
||||||
# If performance was really a priority in IE9, we would rework things to be able to skip this step.
|
# If performance was really a priority in IE9, we would rework things to be able to skip this step.
|
||||||
goalStates = testGM?.getGoalStates()
|
goalStates = testGM?.getGoalStates()
|
||||||
|
@ -212,7 +212,7 @@ module.exports = class Angel extends CocoClass
|
||||||
doSimulateWorld: (work) ->
|
doSimulateWorld: (work) ->
|
||||||
work.t1 = now()
|
work.t1 = now()
|
||||||
Math.random = work.testWorld.rand.randf # so user code is predictable
|
Math.random = work.testWorld.rand.randf # so user code is predictable
|
||||||
Aether.replaceBuiltin("Math", Math)
|
Aether.replaceBuiltin('Math', Math)
|
||||||
i = 0
|
i = 0
|
||||||
while i < work.testWorld.totalFrames
|
while i < work.testWorld.totalFrames
|
||||||
frame = work.testWorld.getFrame i++
|
frame = work.testWorld.getFrame i++
|
||||||
|
|
|
@ -6,17 +6,17 @@
|
||||||
# super()
|
# super()
|
||||||
# @indexLists = []
|
# @indexLists = []
|
||||||
# @initClone()
|
# @initClone()
|
||||||
#
|
#
|
||||||
# initClone: () ->
|
# initClone: () ->
|
||||||
# @target = AsyncCloner.cloneToDepth(@source, @depth)
|
# @target = AsyncCloner.cloneToDepth(@source, @depth)
|
||||||
# @indexLists = [_.keys(@target)] if _.isObject @target
|
# @indexLists = [_.keys(@target)] if _.isObject @target
|
||||||
#
|
#
|
||||||
# @cloneToDepth: (value, depth) ->
|
# @cloneToDepth: (value, depth) ->
|
||||||
# value = _.clone(value)
|
# value = _.clone(value)
|
||||||
# return value unless depth and _.isObject value
|
# return value unless depth and _.isObject value
|
||||||
# value[key] = @cloneToDepth(value[key], depth-1) for key in _.keys value
|
# value[key] = @cloneToDepth(value[key], depth-1) for key in _.keys value
|
||||||
# value
|
# value
|
||||||
#
|
#
|
||||||
# clone: ->
|
# clone: ->
|
||||||
# while @indexLists.length
|
# while @indexLists.length
|
||||||
# #console.log 'Clone loop:', JSON.stringify @indexLists
|
# #console.log 'Clone loop:', JSON.stringify @indexLists
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
# @cloneOne()
|
# @cloneOne()
|
||||||
# @moveIndexForwardOne()
|
# @moveIndexForwardOne()
|
||||||
# break if @done() or @timeToSleep()
|
# break if @done() or @timeToSleep()
|
||||||
#
|
#
|
||||||
# moveIndexForward: ->
|
# moveIndexForward: ->
|
||||||
# while @indexLists.length
|
# while @indexLists.length
|
||||||
# nextValue = @getNextValue()
|
# nextValue = @getNextValue()
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
# # push a new list if it's a collection
|
# # push a new list if it's a collection
|
||||||
# @indexLists.push _.keys(nextValue)
|
# @indexLists.push _.keys(nextValue)
|
||||||
# continue
|
# continue
|
||||||
# else
|
# else
|
||||||
# break # we done, the next value needs to be deep cloned
|
# break # we done, the next value needs to be deep cloned
|
||||||
# #console.log 'Skipping:', @getNextPath()
|
# #console.log 'Skipping:', @getNextPath()
|
||||||
# @moveIndexForwardOne() # move past this value otherwise
|
# @moveIndexForwardOne() # move past this value otherwise
|
||||||
|
@ -44,15 +44,15 @@
|
||||||
# value = @target
|
# value = @target
|
||||||
# value = value[indexList[0]] for indexList in @indexLists
|
# value = value[indexList[0]] for indexList in @indexLists
|
||||||
# value
|
# value
|
||||||
#
|
#
|
||||||
# getNextParent: ->
|
# getNextParent: ->
|
||||||
# parent = @target
|
# parent = @target
|
||||||
# parent = parent[indexList[0]] for indexList in @indexLists[...-1]
|
# parent = parent[indexList[0]] for indexList in @indexLists[...-1]
|
||||||
# parent
|
# parent
|
||||||
#
|
#
|
||||||
# getNextPath: ->
|
# getNextPath: ->
|
||||||
# (indexList[0] for indexList in @indexLists when indexList.length).join '.'
|
# (indexList[0] for indexList in @indexLists when indexList.length).join '.'
|
||||||
#
|
#
|
||||||
# moveIndexForwardOne: ->
|
# moveIndexForwardOne: ->
|
||||||
# @indexLists[@indexLists.length-1].shift() # move the index forward one
|
# @indexLists[@indexLists.length-1].shift() # move the index forward one
|
||||||
# # if we reached the end of an index list, trim down through all finished lists
|
# # if we reached the end of an index list, trim down through all finished lists
|
||||||
|
@ -69,7 +69,7 @@
|
||||||
# #console.log 'Deep Cloned:', @getNextPath()
|
# #console.log 'Deep Cloned:', @getNextPath()
|
||||||
#
|
#
|
||||||
# done: -> not @indexLists.length
|
# done: -> not @indexLists.length
|
||||||
#
|
#
|
||||||
# timeToSleep: -> false
|
# timeToSleep: -> false
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,4 +79,4 @@
|
||||||
Clone that one, popping it off the list.
|
Clone that one, popping it off the list.
|
||||||
If the last list is now empty, pop that list and every subsequent list if needed.
|
If the last list is now empty, pop that list and every subsequent list if needed.
|
||||||
Check for doneness, or timeout.
|
Check for doneness, or timeout.
|
||||||
###
|
###
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
CocoClass = require 'lib/CocoClass'
|
CocoClass = require 'lib/CocoClass'
|
||||||
cache = {}
|
cache = {}
|
||||||
{me} = require('lib/auth')
|
{me} = require 'lib/auth'
|
||||||
|
|
||||||
# Top 20 obscene words (plus 'fiddlesticks') will trigger swearing Simlish with *beeps*.
|
# Top 20 obscene words (plus 'fiddlesticks') will trigger swearing Simlish with *beeps*.
|
||||||
# Didn't like leaving so much profanity lying around in the source, so rot13'd.
|
# Didn't like leaving so much profanity lying around in the source, so rot13'd.
|
||||||
rot13 = (s) -> s.replace /[A-z]/g, (c) -> String.fromCharCode c.charCodeAt(0) + (if c.toUpperCase() <= "M" then 13 else -13)
|
rot13 = (s) -> s.replace /[A-z]/g, (c) -> String.fromCharCode c.charCodeAt(0) + (if c.toUpperCase() <= 'M' then 13 else -13)
|
||||||
swears = (rot13 s for s in ["nefrubyr", "nffubyr", "onfgneq", "ovgpu", "oybbql", "obyybpxf", "ohttre", "pbpx", "penc", "phag", "qnza", "qnea", "qvpx", "qbhpur", "snt", "shpx", "cvff", "chffl", "fuvg", "fyhg", "svqqyrfgvpxf"])
|
swears = (rot13 s for s in ['nefrubyr', 'nffubyr', 'onfgneq', 'ovgpu', 'oybbql', 'obyybpxf', 'ohttre', 'pbpx', 'penc', 'phag', 'qnza', 'qnea', 'qvpx', 'qbhpur', 'snt', 'shpx', 'cvff', 'chffl', 'fuvg', 'fyhg', 'svqqyrfgvpxf'])
|
||||||
|
|
||||||
createjs.Sound.registerPlugins([createjs.WebAudioPlugin, createjs.FlashPlugin, createjs.HTMLAudioPlugin])
|
createjs.Sound.registerPlugins([createjs.WebAudioPlugin, createjs.FlashPlugin, createjs.HTMLAudioPlugin])
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ class AudioPlayer extends CocoClass
|
||||||
console.error 'Could not load sound', e
|
console.error 'Could not load sound', e
|
||||||
|
|
||||||
notifyProgressChanged: ->
|
notifyProgressChanged: ->
|
||||||
Backbone.Mediator.publish('audio-player:loaded', {sender:@})
|
Backbone.Mediator.publish('audio-player:loaded', {sender: @})
|
||||||
|
|
||||||
getStatus: (src) ->
|
getStatus: (src) ->
|
||||||
return cache[src] or null
|
return cache[src] or null
|
||||||
|
|
|
@ -26,9 +26,9 @@ module.exports = Bus = class Bus extends CocoClass
|
||||||
@notifyStateChanges()
|
@notifyStateChanges()
|
||||||
|
|
||||||
connect: ->
|
connect: ->
|
||||||
Backbone.Mediator.publish 'bus:connecting', {bus:@}
|
Backbone.Mediator.publish 'bus:connecting', {bus: @}
|
||||||
Firebase.goOnline()
|
Firebase.goOnline()
|
||||||
@fireRef = new Firebase(Bus.fireHost + "/" + @docName)
|
@fireRef = new Firebase(Bus.fireHost + '/' + @docName)
|
||||||
@fireRef.once 'value', @onFireOpen
|
@fireRef.once 'value', @onFireOpen
|
||||||
|
|
||||||
onFireOpen: (snapshot) =>
|
onFireOpen: (snapshot) =>
|
||||||
|
@ -36,7 +36,7 @@ module.exports = Bus = class Bus extends CocoClass
|
||||||
console.log("Leaving '#{@docName}' because class has been destroyed.")
|
console.log("Leaving '#{@docName}' because class has been destroyed.")
|
||||||
return
|
return
|
||||||
@init()
|
@init()
|
||||||
Backbone.Mediator.publish 'bus:connected', {bus:@}
|
Backbone.Mediator.publish 'bus:connected', {bus: @}
|
||||||
|
|
||||||
disconnect: ->
|
disconnect: ->
|
||||||
Firebase.goOffline()
|
Firebase.goOffline()
|
||||||
|
@ -49,7 +49,7 @@ module.exports = Bus = class Bus extends CocoClass
|
||||||
@myConnection?.off()
|
@myConnection?.off()
|
||||||
@myConnection = null
|
@myConnection = null
|
||||||
@joined = false
|
@joined = false
|
||||||
Backbone.Mediator.publish 'bus:disconnected', {bus:@}
|
Backbone.Mediator.publish 'bus:disconnected', {bus: @}
|
||||||
|
|
||||||
init: ->
|
init: ->
|
||||||
"""
|
"""
|
||||||
|
@ -59,7 +59,7 @@ module.exports = Bus = class Bus extends CocoClass
|
||||||
@firePlayersRef = @fireRef.child('players')
|
@firePlayersRef = @fireRef.child('players')
|
||||||
@join()
|
@join()
|
||||||
@listenForChanges()
|
@listenForChanges()
|
||||||
@sendMessage("/me joined.", true)
|
@sendMessage('/me joined.', true)
|
||||||
|
|
||||||
join: ->
|
join: ->
|
||||||
@joined = true
|
@joined = true
|
||||||
|
@ -75,13 +75,13 @@ module.exports = Bus = class Bus extends CocoClass
|
||||||
@firePlayersRef.on 'child_changed', @onPlayerChanged
|
@firePlayersRef.on 'child_changed', @onPlayerChanged
|
||||||
|
|
||||||
onChatAdded: (snapshot) =>
|
onChatAdded: (snapshot) =>
|
||||||
Backbone.Mediator.publish('bus:new-message', {message:snapshot.val(), bus:@})
|
Backbone.Mediator.publish('bus:new-message', {message: snapshot.val(), bus: @})
|
||||||
|
|
||||||
onPlayerJoined: (snapshot) =>
|
onPlayerJoined: (snapshot) =>
|
||||||
player = snapshot.val()
|
player = snapshot.val()
|
||||||
return unless player.connected
|
return unless player.connected
|
||||||
@players[player.id] = player
|
@players[player.id] = player
|
||||||
Backbone.Mediator.publish('bus:player-joined', {player:player, bus:@})
|
Backbone.Mediator.publish('bus:player-joined', {player: player, bus: @})
|
||||||
|
|
||||||
onPlayerLeft: (snapshot) =>
|
onPlayerLeft: (snapshot) =>
|
||||||
val = snapshot.val()
|
val = snapshot.val()
|
||||||
|
@ -89,7 +89,7 @@ module.exports = Bus = class Bus extends CocoClass
|
||||||
player = @players[val.id]
|
player = @players[val.id]
|
||||||
return unless player
|
return unless player
|
||||||
delete @players[player.id]
|
delete @players[player.id]
|
||||||
Backbone.Mediator.publish('bus:player-left', {player:player, bus:@})
|
Backbone.Mediator.publish('bus:player-left', {player: player, bus: @})
|
||||||
|
|
||||||
onPlayerChanged: (snapshot) =>
|
onPlayerChanged: (snapshot) =>
|
||||||
player = snapshot.val()
|
player = snapshot.val()
|
||||||
|
@ -97,7 +97,7 @@ module.exports = Bus = class Bus extends CocoClass
|
||||||
@players[player.id] = player
|
@players[player.id] = player
|
||||||
@onPlayerLeft(snapshot) if wasConnected and not player.connected
|
@onPlayerLeft(snapshot) if wasConnected and not player.connected
|
||||||
@onPlayerJoined(snapshot) if player.connected and not wasConnected
|
@onPlayerJoined(snapshot) if player.connected and not wasConnected
|
||||||
Backbone.Mediator.publish('bus:player-states-changed', {states:@players, bus:@})
|
Backbone.Mediator.publish('bus:player-states-changed', {states: @players, bus: @})
|
||||||
|
|
||||||
onMeSynced: =>
|
onMeSynced: =>
|
||||||
@myConnection?.child('name').set(me.get('name'))
|
@myConnection?.child('name').set(me.get('name'))
|
||||||
|
@ -118,9 +118,9 @@ module.exports = Bus = class Bus extends CocoClass
|
||||||
sendMessage: (content, system=false) ->
|
sendMessage: (content, system=false) ->
|
||||||
MAX_MESSAGE_LENGTH = 400
|
MAX_MESSAGE_LENGTH = 400
|
||||||
message =
|
message =
|
||||||
content:content[... MAX_MESSAGE_LENGTH]
|
content: content[... MAX_MESSAGE_LENGTH]
|
||||||
authorName:me.displayName()
|
authorName: me.displayName()
|
||||||
authorID:me.id
|
authorID: me.id
|
||||||
dateMade: new Date()
|
dateMade: new Date()
|
||||||
message.system = system if system
|
message.system = system if system
|
||||||
@fireChatRef.push(message)
|
@fireChatRef.push(message)
|
||||||
|
@ -128,7 +128,7 @@ module.exports = Bus = class Bus extends CocoClass
|
||||||
# TEARDOWN
|
# TEARDOWN
|
||||||
|
|
||||||
destroy: ->
|
destroy: ->
|
||||||
@sendMessage("/me left.", true) if @joined
|
@sendMessage('/me left.', true) if @joined
|
||||||
delete Bus.activeBuses[@docName] if @docName of Bus.activeBuses
|
delete Bus.activeBuses[@docName] if @docName of Bus.activeBuses
|
||||||
@disconnect()
|
@disconnect()
|
||||||
super()
|
super()
|
||||||
|
|
|
@ -9,7 +9,7 @@ module.exports = class CocoClass
|
||||||
@nicksUsed: {}
|
@nicksUsed: {}
|
||||||
@remainingNicks: []
|
@remainingNicks: []
|
||||||
@nextNick: ->
|
@nextNick: ->
|
||||||
return (@name or "CocoClass") + " " + classCount unless @nicks.length
|
return (@name or 'CocoClass') + ' ' + classCount unless @nicks.length
|
||||||
@remainingNicks = if @remainingNicks.length then @remainingNicks else @nicks.slice()
|
@remainingNicks = if @remainingNicks.length then @remainingNicks else @nicks.slice()
|
||||||
baseNick = @remainingNicks.splice(Math.floor(Math.random() * @remainingNicks.length), 1)[0]
|
baseNick = @remainingNicks.splice(Math.floor(Math.random() * @remainingNicks.length), 1)[0]
|
||||||
i = 0
|
i = 0
|
||||||
|
|
|
@ -44,7 +44,7 @@ module.exports = FacebookHandler = class FacebookHandler extends CocoClass
|
||||||
me.set('gender', r.gender) if r.gender
|
me.set('gender', r.gender) if r.gender
|
||||||
me.set('email', r.email) if r.email
|
me.set('email', r.email) if r.email
|
||||||
me.set('facebookID', r.id) if r.id
|
me.set('facebookID', r.id) if r.id
|
||||||
|
|
||||||
Backbone.Mediator.publish('logging-in-with-facebook')
|
Backbone.Mediator.publish('logging-in-with-facebook')
|
||||||
window.tracker?.trackEvent 'Facebook Login'
|
window.tracker?.trackEvent 'Facebook Login'
|
||||||
window.tracker?.identify()
|
window.tracker?.identify()
|
||||||
|
|
|
@ -14,8 +14,8 @@ userPropsToSave =
|
||||||
fieldsToFetch = 'displayName,gender,image,name(familyName,givenName),id'
|
fieldsToFetch = 'displayName,gender,image,name(familyName,givenName),id'
|
||||||
plusURL = '/plus/v1/people/me?fields='+fieldsToFetch
|
plusURL = '/plus/v1/people/me?fields='+fieldsToFetch
|
||||||
revokeUrl = 'https://accounts.google.com/o/oauth2/revoke?token='
|
revokeUrl = 'https://accounts.google.com/o/oauth2/revoke?token='
|
||||||
clientID = "800329290710-j9sivplv2gpcdgkrsis9rff3o417mlfa.apps.googleusercontent.com"
|
clientID = '800329290710-j9sivplv2gpcdgkrsis9rff3o417mlfa.apps.googleusercontent.com'
|
||||||
scope = "https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email"
|
scope = 'https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email'
|
||||||
|
|
||||||
module.exports = GPlusHandler = class GPlusHandler extends CocoClass
|
module.exports = GPlusHandler = class GPlusHandler extends CocoClass
|
||||||
constructor: ->
|
constructor: ->
|
||||||
|
@ -32,7 +32,7 @@ module.exports = GPlusHandler = class GPlusHandler extends CocoClass
|
||||||
# We need to check the current state, given our access token
|
# We need to check the current state, given our access token
|
||||||
gapi.auth.setToken 'token', @accessToken
|
gapi.auth.setToken 'token', @accessToken
|
||||||
session_state = @accessToken.session_state
|
session_state = @accessToken.session_state
|
||||||
gapi.auth.checkSessionState({client_id:clientID, session_state:session_state}, @onCheckedSessionState)
|
gapi.auth.checkSessionState({client_id: clientID, session_state: session_state}, @onCheckedSessionState)
|
||||||
else
|
else
|
||||||
# If we ran checkSessionState, it might return true, that the user is logged into Google, but has not authorized us
|
# If we ran checkSessionState, it might return true, that the user is logged into Google, but has not authorized us
|
||||||
@loggedIn = false
|
@loggedIn = false
|
||||||
|
@ -57,7 +57,7 @@ module.exports = GPlusHandler = class GPlusHandler extends CocoClass
|
||||||
|
|
||||||
# email and profile data loaded separately
|
# email and profile data loaded separately
|
||||||
@responsesComplete = 0
|
@responsesComplete = 0
|
||||||
gapi.client.request(path:plusURL, callback:@onPersonEntityReceived)
|
gapi.client.request(path: plusURL, callback: @onPersonEntityReceived)
|
||||||
gapi.client.load('oauth2', 'v2', =>
|
gapi.client.load('oauth2', 'v2', =>
|
||||||
gapi.client.oauth2.userinfo.get().execute(@onEmailReceived))
|
gapi.client.oauth2.userinfo.get().execute(@onEmailReceived))
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ module.exports = GPlusHandler = class GPlusHandler extends CocoClass
|
||||||
loadFriends: (friendsCallback) ->
|
loadFriends: (friendsCallback) ->
|
||||||
return friendsCallback() unless @loggedIn
|
return friendsCallback() unless @loggedIn
|
||||||
expiresIn = if @accessToken then parseInt(@accessToken.expires_at) - new Date().getTime()/1000 else -1
|
expiresIn = if @accessToken then parseInt(@accessToken.expires_at) - new Date().getTime()/1000 else -1
|
||||||
onReauthorized = => gapi.client.request({path:'/plus/v1/people/me/people/visible', callback: friendsCallback})
|
onReauthorized = => gapi.client.request({path: '/plus/v1/people/me/people/visible', callback: friendsCallback})
|
||||||
if expiresIn < 0
|
if expiresIn < 0
|
||||||
# TODO: this tries to open a popup window, which might not ever finish or work, so the callback may never be called.
|
# TODO: this tries to open a popup window, which might not ever finish or work, so the callback may never be called.
|
||||||
@reauthorize()
|
@reauthorize()
|
||||||
|
|
|
@ -8,7 +8,7 @@ CocoClass = require 'lib/CocoClass'
|
||||||
Angel = require 'lib/Angel'
|
Angel = require 'lib/Angel'
|
||||||
|
|
||||||
module.exports = class God extends CocoClass
|
module.exports = class God extends CocoClass
|
||||||
@nicks: ['Athena', 'Baldr', 'Crom', 'Dagr', 'Eris', 'Freyja', 'Great Gish', 'Hades', 'Ishtar', 'Janus', 'Khronos', 'Loki', 'Marduk', 'Negafook', 'Odin', 'Poseidon', 'Quetzalcoatl', 'Ra', 'Shiva', 'Thor', 'Umvelinqangi', 'Týr', 'Vishnu', 'Wepwawet', 'Xipe Totec', 'Yahweh', 'Zeus', '上帝', 'Tiamat', '盘古', 'Phoebe', 'Artemis', 'Osiris', "嫦娥", 'Anhur', 'Teshub', 'Enlil', 'Perkele', 'Chaos', 'Hera', 'Iris', 'Theia', 'Uranus', 'Stribog', 'Sabazios', 'Izanagi', 'Ao', 'Tāwhirimātea', 'Tengri', 'Inmar', 'Torngarsuk', 'Centzonhuitznahua', 'Hunab Ku', 'Apollo', 'Helios', 'Thoth', 'Hyperion', 'Alectrona', 'Eos', 'Mitra', 'Saranyu', 'Freyr', 'Koyash', 'Atropos', 'Clotho', 'Lachesis', 'Tyche', 'Skuld', 'Urðr', 'Verðandi', 'Camaxtli', 'Huhetotl', 'Set', 'Anu', 'Allah', 'Anshar', 'Hermes', 'Lugh', 'Brigit', 'Manannan Mac Lir', 'Persephone', 'Mercury', 'Venus', 'Mars', 'Azrael', 'He-Man', 'Anansi', 'Issek', 'Mog', 'Kos', 'Amaterasu Omikami', 'Raijin', 'Susanowo', 'Blind Io', 'The Lady', 'Offler', 'Ptah', 'Anubis', 'Ereshkigal', 'Nergal', 'Thanatos', 'Macaria', 'Angelos', 'Erebus', 'Hecate', 'Hel', 'Orcus', 'Ishtar-Deela Nakh', 'Prometheus', 'Hephaestos', 'Sekhmet', 'Ares', 'Enyo', 'Otrera', 'Pele', 'Hadúr', 'Hachiman', 'Dayisun Tngri', 'Ullr', 'Lua', 'Minerva']
|
@nicks: ['Athena', 'Baldr', 'Crom', 'Dagr', 'Eris', 'Freyja', 'Great Gish', 'Hades', 'Ishtar', 'Janus', 'Khronos', 'Loki', 'Marduk', 'Negafook', 'Odin', 'Poseidon', 'Quetzalcoatl', 'Ra', 'Shiva', 'Thor', 'Umvelinqangi', 'Týr', 'Vishnu', 'Wepwawet', 'Xipe Totec', 'Yahweh', 'Zeus', '上帝', 'Tiamat', '盘古', 'Phoebe', 'Artemis', 'Osiris', '嫦娥', 'Anhur', 'Teshub', 'Enlil', 'Perkele', 'Chaos', 'Hera', 'Iris', 'Theia', 'Uranus', 'Stribog', 'Sabazios', 'Izanagi', 'Ao', 'Tāwhirimātea', 'Tengri', 'Inmar', 'Torngarsuk', 'Centzonhuitznahua', 'Hunab Ku', 'Apollo', 'Helios', 'Thoth', 'Hyperion', 'Alectrona', 'Eos', 'Mitra', 'Saranyu', 'Freyr', 'Koyash', 'Atropos', 'Clotho', 'Lachesis', 'Tyche', 'Skuld', 'Urðr', 'Verðandi', 'Camaxtli', 'Huhetotl', 'Set', 'Anu', 'Allah', 'Anshar', 'Hermes', 'Lugh', 'Brigit', 'Manannan Mac Lir', 'Persephone', 'Mercury', 'Venus', 'Mars', 'Azrael', 'He-Man', 'Anansi', 'Issek', 'Mog', 'Kos', 'Amaterasu Omikami', 'Raijin', 'Susanowo', 'Blind Io', 'The Lady', 'Offler', 'Ptah', 'Anubis', 'Ereshkigal', 'Nergal', 'Thanatos', 'Macaria', 'Angelos', 'Erebus', 'Hecate', 'Hel', 'Orcus', 'Ishtar-Deela Nakh', 'Prometheus', 'Hephaestos', 'Sekhmet', 'Ares', 'Enyo', 'Otrera', 'Pele', 'Hadúr', 'Hachiman', 'Dayisun Tngri', 'Ullr', 'Lua', 'Minerva']
|
||||||
|
|
||||||
subscriptions:
|
subscriptions:
|
||||||
'tome:cast-spells': 'onTomeCast'
|
'tome:cast-spells': 'onTomeCast'
|
||||||
|
@ -98,7 +98,7 @@ module.exports = class God extends CocoClass
|
||||||
retrieveValueFromFrame: (args) =>
|
retrieveValueFromFrame: (args) =>
|
||||||
return if @destroyed
|
return if @destroyed
|
||||||
return unless args.thangID and args.spellID and args.variableChain
|
return unless args.thangID and args.spellID and args.variableChain
|
||||||
return console.error "Tried to retrieve debug value with no currentUserCodeMap" unless @currentUserCodeMap
|
return console.error 'Tried to retrieve debug value with no currentUserCodeMap' unless @currentUserCodeMap
|
||||||
@debugWorker ?= @createDebugWorker()
|
@debugWorker ?= @createDebugWorker()
|
||||||
args.frame ?= @angelsShare.world.age / @angelsShare.world.dt
|
args.frame ?= @angelsShare.world.age / @angelsShare.world.dt
|
||||||
@debugWorker.postMessage
|
@debugWorker.postMessage
|
||||||
|
|
|
@ -43,7 +43,7 @@ module.exports = class LevelBus extends Bus
|
||||||
incrementSessionPlaytime: =>
|
incrementSessionPlaytime: =>
|
||||||
if @playerIsIdle then return
|
if @playerIsIdle then return
|
||||||
@changedSessionProperties.playtime = true
|
@changedSessionProperties.playtime = true
|
||||||
@session.set("playtime",@session.get("playtime") + 1)
|
@session.set('playtime', @session.get('playtime') + 1)
|
||||||
|
|
||||||
onPoint: ->
|
onPoint: ->
|
||||||
return true unless @session?.get('multiplayer')
|
return true unless @session?.get('multiplayer')
|
||||||
|
@ -123,7 +123,7 @@ module.exports = class LevelBus extends Bus
|
||||||
@changedSessionProperties.teamSpells = true
|
@changedSessionProperties.teamSpells = true
|
||||||
@session.set({'teamSpells': @teamSpellMap})
|
@session.set({'teamSpells': @teamSpellMap})
|
||||||
@saveSession()
|
@saveSession()
|
||||||
if spellTeam is me.team or spellTeam is "common"
|
if spellTeam is me.team or spellTeam is 'common'
|
||||||
@onSpellChanged e # Save the new spell to the session, too.
|
@onSpellChanged e # Save the new spell to the session, too.
|
||||||
|
|
||||||
onScriptStateChanged: (e) ->
|
onScriptStateChanged: (e) ->
|
||||||
|
@ -233,7 +233,7 @@ module.exports = class LevelBus extends Bus
|
||||||
|
|
||||||
# since updates are coming fast and loose for session objects
|
# since updates are coming fast and loose for session objects
|
||||||
# don't let what the server returns overwrite changes since the save began
|
# don't let what the server returns overwrite changes since the save began
|
||||||
tempSession = new LevelSession _id:@session.id
|
tempSession = new LevelSession _id: @session.id
|
||||||
tempSession.save(patch, {patch: true})
|
tempSession.save(patch, {patch: true})
|
||||||
|
|
||||||
destroy: ->
|
destroy: ->
|
||||||
|
|
|
@ -48,7 +48,7 @@ module.exports = class LevelLoader extends CocoClass
|
||||||
# Apparently the jingle, when it tries to play immediately during all this loading, you can't hear it.
|
# Apparently the jingle, when it tries to play immediately during all this loading, you can't hear it.
|
||||||
# Add the timeout to fix this weird behavior.
|
# Add the timeout to fix this weird behavior.
|
||||||
f = ->
|
f = ->
|
||||||
jingles = ["ident_1", "ident_2"]
|
jingles = ['ident_1', 'ident_2']
|
||||||
AudioPlayer.playInterfaceSound jingles[Math.floor Math.random() * jingles.length]
|
AudioPlayer.playInterfaceSound jingles[Math.floor Math.random() * jingles.length]
|
||||||
setTimeout f, 500
|
setTimeout f, 500
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ module.exports = class LevelLoader extends CocoClass
|
||||||
url += "?team=#{@team}" if @team
|
url += "?team=#{@team}" if @team
|
||||||
|
|
||||||
session = new LevelSession().setURL url
|
session = new LevelSession().setURL url
|
||||||
@sessionResource = @supermodel.loadModel(session, 'level_session', {cache:false})
|
@sessionResource = @supermodel.loadModel(session, 'level_session', {cache: false})
|
||||||
@session = @sessionResource.model
|
@session = @sessionResource.model
|
||||||
@session.once 'sync', -> @url = -> '/db/level.session/' + @id
|
@session.once 'sync', -> @url = -> '/db/level.session/' + @id
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ module.exports = class LevelLoader extends CocoClass
|
||||||
continue if thangType.isFullyLoaded()
|
continue if thangType.isFullyLoaded()
|
||||||
thangType.fetch()
|
thangType.fetch()
|
||||||
thangType = @supermodel.loadModel(thangType, 'thang').model
|
thangType = @supermodel.loadModel(thangType, 'thang').model
|
||||||
res = @supermodel.addSomethingResource "sprite_sheet", 5
|
res = @supermodel.addSomethingResource 'sprite_sheet', 5
|
||||||
res.thangType = thangType
|
res.thangType = thangType
|
||||||
res.markLoading()
|
res.markLoading()
|
||||||
@spriteSheetsToBuild.push res
|
@spriteSheetsToBuild.push res
|
||||||
|
@ -246,7 +246,7 @@ module.exports = class LevelLoader extends CocoClass
|
||||||
break
|
break
|
||||||
unless @teamConfigs
|
unless @teamConfigs
|
||||||
# Hack: pulled from Alliance System code. TODO: put in just one place.
|
# Hack: pulled from Alliance System code. TODO: put in just one place.
|
||||||
@teamConfigs = {"humans":{"superteam":"humans","color":{"hue":0,"saturation":0.75,"lightness":0.5},"playable":true},"ogres":{"superteam":"ogres","color":{"hue":0.66,"saturation":0.75,"lightness":0.5},"playable":false},"neutral":{"superteam":"neutral","color":{"hue":0.33,"saturation":0.75,"lightness":0.5}}}
|
@teamConfigs = {'humans': {'superteam': 'humans', 'color': {'hue': 0, 'saturation': 0.75, 'lightness': 0.5}, 'playable': true}, 'ogres': {'superteam': 'ogres', 'color': {'hue': 0.66, 'saturation': 0.75, 'lightness': 0.5}, 'playable': false}, 'neutral': {'superteam': 'neutral', 'color': {'hue': 0.33, 'saturation': 0.75, 'lightness': 0.5}}}
|
||||||
@teamConfigs
|
@teamConfigs
|
||||||
|
|
||||||
buildSpriteSheet: (thangType, options) ->
|
buildSpriteSheet: (thangType, options) ->
|
||||||
|
@ -263,13 +263,13 @@ module.exports = class LevelLoader extends CocoClass
|
||||||
@world.levelSessionIDs = if @opponentSessionID then [@sessionID, @opponentSessionID] else [@sessionID]
|
@world.levelSessionIDs = if @opponentSessionID then [@sessionID, @opponentSessionID] else [@sessionID]
|
||||||
serializedLevel = @level.serialize(@supermodel)
|
serializedLevel = @level.serialize(@supermodel)
|
||||||
@world.loadFromLevel serializedLevel, false
|
@world.loadFromLevel serializedLevel, false
|
||||||
console.log "World has been initialized from level loader."
|
console.log 'World has been initialized from level loader.'
|
||||||
|
|
||||||
# Initial Sound Loading
|
# Initial Sound Loading
|
||||||
|
|
||||||
loadAudio: ->
|
loadAudio: ->
|
||||||
return if @headless
|
return if @headless
|
||||||
AudioPlayer.preloadInterfaceSounds ["victory"]
|
AudioPlayer.preloadInterfaceSounds ['victory']
|
||||||
|
|
||||||
loadLevelSounds: ->
|
loadLevelSounds: ->
|
||||||
return if @headless
|
return if @headless
|
||||||
|
|
|
@ -12,20 +12,20 @@ module.exports = LinkedInHandler = class LinkedInHandler extends CocoClass
|
||||||
'linkedin-loaded': 'onLinkedInLoaded'
|
'linkedin-loaded': 'onLinkedInLoaded'
|
||||||
|
|
||||||
onLinkedInLoaded: (e) ->
|
onLinkedInLoaded: (e) ->
|
||||||
IN.Event.on IN, "auth", @onLinkedInAuth
|
IN.Event.on IN, 'auth', @onLinkedInAuth
|
||||||
|
|
||||||
onLinkedInAuth: (e) => console.log "Authorized with LinkedIn"
|
onLinkedInAuth: (e) => console.log 'Authorized with LinkedIn'
|
||||||
|
|
||||||
constructEmployerAgreementObject: (cb) =>
|
constructEmployerAgreementObject: (cb) =>
|
||||||
IN.API.Profile("me")
|
IN.API.Profile('me')
|
||||||
.fields(["positions","public-profile-url","id","first-name","last-name","email-address"])
|
.fields(['positions', 'public-profile-url', 'id', 'first-name', 'last-name', 'email-address'])
|
||||||
.error(cb)
|
.error(cb)
|
||||||
.result (profiles) =>
|
.result (profiles) =>
|
||||||
cb null, profiles.values[0]
|
cb null, profiles.values[0]
|
||||||
|
|
||||||
getProfileData: (cb) =>
|
getProfileData: (cb) =>
|
||||||
IN.API.Profile("me")
|
IN.API.Profile('me')
|
||||||
.fields(["formatted-name","educations","skills","headline","summary","positions","public-profile-url"])
|
.fields(['formatted-name', 'educations', 'skills', 'headline', 'summary', 'positions', 'public-profile-url'])
|
||||||
.error(cb)
|
.error(cb)
|
||||||
.result (profiles) =>
|
.result (profiles) =>
|
||||||
cb null, profiles.values[0]
|
cb null, profiles.values[0]
|
||||||
|
|
|
@ -7,9 +7,9 @@ class NameLoader extends CocoClass
|
||||||
toLoad = _.uniq (id for id in ids when not namesCache[id])
|
toLoad = _.uniq (id for id in ids when not namesCache[id])
|
||||||
return false unless toLoad.length
|
return false unless toLoad.length
|
||||||
jqxhrOptions = {
|
jqxhrOptions = {
|
||||||
url: '/db/user/x/names',
|
url: '/db/user/x/names',
|
||||||
type:'POST',
|
type: 'POST',
|
||||||
data:{ids:toLoad},
|
data: {ids: toLoad},
|
||||||
success: @loadedNames
|
success: @loadedNames
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ class NameLoader extends CocoClass
|
||||||
|
|
||||||
loadedNames: (newNames) =>
|
loadedNames: (newNames) =>
|
||||||
_.extend namesCache, newNames
|
_.extend namesCache, newNames
|
||||||
|
|
||||||
getName: (id) -> namesCache[id]?.name or id
|
getName: (id) -> namesCache[id]?.name or id
|
||||||
|
|
||||||
module.exports = new NameLoader()
|
module.exports = new NameLoader()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
gplusClientID = "800329290710-j9sivplv2gpcdgkrsis9rff3o417mlfa.apps.googleusercontent.com"
|
gplusClientID = '800329290710-j9sivplv2gpcdgkrsis9rff3o417mlfa.apps.googleusercontent.com'
|
||||||
|
|
||||||
go = (path) -> -> @routeDirectly path, arguments
|
go = (path) -> -> @routeDirectly path, arguments
|
||||||
|
|
||||||
|
@ -75,16 +75,16 @@ module.exports = class CocoRouter extends Backbone.Router
|
||||||
gapi.plusone.go?() # Handles +1 button
|
gapi.plusone.go?() # Handles +1 button
|
||||||
for gplusButton in $('.gplus-login-button')
|
for gplusButton in $('.gplus-login-button')
|
||||||
params = {
|
params = {
|
||||||
callback:"signinCallback",
|
callback: 'signinCallback',
|
||||||
clientid:gplusClientID,
|
clientid: gplusClientID,
|
||||||
cookiepolicy:"single_host_origin",
|
cookiepolicy: 'single_host_origin',
|
||||||
scope:"https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email",
|
scope: 'https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email',
|
||||||
height: "short",
|
height: 'short',
|
||||||
}
|
}
|
||||||
if gapi.signin?.render
|
if gapi.signin?.render
|
||||||
gapi.signin.render(gplusButton, params)
|
gapi.signin.render(gplusButton, params)
|
||||||
else
|
else
|
||||||
console.warn "Didn't have gapi.signin to render G+ login button. (DoNotTrackMe extension?)"
|
console.warn 'Didn\'t have gapi.signin to render G+ login button. (DoNotTrackMe extension?)'
|
||||||
|
|
||||||
getViewFromCache: (route) ->
|
getViewFromCache: (route) ->
|
||||||
if route of @cache
|
if route of @cache
|
||||||
|
@ -106,7 +106,7 @@ module.exports = class CocoRouter extends Backbone.Router
|
||||||
|
|
||||||
getView: (route, suffix='_view') ->
|
getView: (route, suffix='_view') ->
|
||||||
# iteratively breaks down the url pieces looking for the view
|
# iteratively breaks down the url pieces looking for the view
|
||||||
# passing the broken off pieces as args. This way views like "resource/14394893"
|
# passing the broken off pieces as args. This way views like 'resource/14394893'
|
||||||
# will get passed to the resource view with arg '14394893'
|
# will get passed to the resource view with arg '14394893'
|
||||||
pieces = _.string.words(route, '/')
|
pieces = _.string.words(route, '/')
|
||||||
split = Math.max(1, pieces.length-1)
|
split = Math.max(1, pieces.length-1)
|
||||||
|
|
|
@ -5,6 +5,6 @@ namesCache = {}
|
||||||
class SystemNameLoader extends CocoClass
|
class SystemNameLoader extends CocoClass
|
||||||
getName: (id) -> namesCache[id]?.name
|
getName: (id) -> namesCache[id]?.name
|
||||||
|
|
||||||
setName: (system) -> namesCache[system.get('original')] = {name:system.get('name')}
|
setName: (system) -> namesCache[system.get('original')] = {name: system.get('name')}
|
||||||
|
|
||||||
module.exports = new SystemNameLoader()
|
module.exports = new SystemNameLoader()
|
||||||
|
|
|
@ -5,14 +5,14 @@ debugAnalytics = false
|
||||||
module.exports = class Tracker
|
module.exports = class Tracker
|
||||||
constructor: ->
|
constructor: ->
|
||||||
if window.tracker
|
if window.tracker
|
||||||
console.error "Overwrote our Tracker!", window.tracker
|
console.error 'Overwrote our Tracker!', window.tracker
|
||||||
window.tracker = @
|
window.tracker = @
|
||||||
@isProduction = document.location.href.search("codecombat.com") isnt -1
|
@isProduction = document.location.href.search('codecombat.com') isnt -1
|
||||||
@identify()
|
@identify()
|
||||||
@updateOlark()
|
@updateOlark()
|
||||||
|
|
||||||
identify: (traits) ->
|
identify: (traits) ->
|
||||||
console.log "Would identify", traits if debugAnalytics
|
console.log 'Would identify', traits if debugAnalytics
|
||||||
return unless me and @isProduction and analytics?
|
return unless me and @isProduction and analytics?
|
||||||
# https://segment.io/docs/methods/identify
|
# https://segment.io/docs/methods/identify
|
||||||
traits ?= {}
|
traits ?= {}
|
||||||
|
@ -23,8 +23,8 @@ module.exports = class Tracker
|
||||||
updateOlark: ->
|
updateOlark: ->
|
||||||
return unless me and olark?
|
return unless me and olark?
|
||||||
olark 'api.chat.updateVisitorStatus', snippet: ["User ID: #{me.id}"]
|
olark 'api.chat.updateVisitorStatus', snippet: ["User ID: #{me.id}"]
|
||||||
return if me.get("anonymous")
|
return if me.get('anonymous')
|
||||||
olark 'api.visitor.updateEmailAddress', emailAddress: me.get("email") if me.get('email')
|
olark 'api.visitor.updateEmailAddress', emailAddress: me.get('email') if me.get('email')
|
||||||
olark 'api.chat.updateVisitorNickname', snippet: me.displayName()
|
olark 'api.chat.updateVisitorNickname', snippet: me.displayName()
|
||||||
|
|
||||||
updatePlayState: (level, session) ->
|
updatePlayState: (level, session) ->
|
||||||
|
@ -41,13 +41,13 @@ module.exports = class Tracker
|
||||||
trackPageView: ->
|
trackPageView: ->
|
||||||
return unless @isProduction and analytics?
|
return unless @isProduction and analytics?
|
||||||
url = Backbone.history.getFragment()
|
url = Backbone.history.getFragment()
|
||||||
console.log "Going to track visit for", "/#{url}" if debugAnalytics
|
console.log 'Going to track visit for', "/#{url}" if debugAnalytics
|
||||||
analytics.pageview "/#{url}"
|
analytics.pageview "/#{url}"
|
||||||
|
|
||||||
trackEvent: (event, properties, includeProviders=null) =>
|
trackEvent: (event, properties, includeProviders=null) =>
|
||||||
console.log "Would track analytics event:", event, properties if debugAnalytics
|
console.log 'Would track analytics event:', event, properties if debugAnalytics
|
||||||
return unless me and @isProduction and analytics?
|
return unless me and @isProduction and analytics?
|
||||||
console.log "Going to track analytics event:", event, properties if debugAnalytics
|
console.log 'Going to track analytics event:', event, properties if debugAnalytics
|
||||||
properties = properties or {}
|
properties = properties or {}
|
||||||
context = {}
|
context = {}
|
||||||
if includeProviders
|
if includeProviders
|
||||||
|
@ -60,5 +60,5 @@ module.exports = class Tracker
|
||||||
trackTiming: (duration, category, variable, label, samplePercentage=5) ->
|
trackTiming: (duration, category, variable, label, samplePercentage=5) ->
|
||||||
# https://developers.google.com/analytics/devguides/collection/gajs/gaTrackingTiming
|
# https://developers.google.com/analytics/devguides/collection/gajs/gaTrackingTiming
|
||||||
return console.warn "Duration #{duration} invalid for trackTiming call." unless duration >= 0 and duration < 60 * 60 * 1000
|
return console.warn "Duration #{duration} invalid for trackTiming call." unless duration >= 0 and duration < 60 * 60 * 1000
|
||||||
console.log "Would track timing event:", arguments if debugAnalytics
|
console.log 'Would track timing event:', arguments if debugAnalytics
|
||||||
window._gaq?.push ['_trackTiming', category, variable, duration, label, samplePercentage]
|
window._gaq?.push ['_trackTiming', category, variable, duration, label, samplePercentage]
|
||||||
|
|
|
@ -12,13 +12,13 @@ init = ->
|
||||||
me.set 'testGroupNumber', Math.floor(Math.random() * 256)
|
me.set 'testGroupNumber', Math.floor(Math.random() * 256)
|
||||||
me.patch()
|
me.patch()
|
||||||
|
|
||||||
Backbone.listenTo(me, 'sync', Backbone.Mediator.publish('me:synced', {me:me}))
|
Backbone.listenTo(me, 'sync', Backbone.Mediator.publish('me:synced', {me: me}))
|
||||||
|
|
||||||
module.exports.createUser = (userObject, failure=backboneFailure, nextURL=null) ->
|
module.exports.createUser = (userObject, failure=backboneFailure, nextURL=null) ->
|
||||||
user = new User(userObject)
|
user = new User(userObject)
|
||||||
user.notyErrors = false
|
user.notyErrors = false
|
||||||
user.save({}, {
|
user.save({}, {
|
||||||
error: (model,jqxhr,options) ->
|
error: (model, jqxhr, options) ->
|
||||||
error = parseServerError(jqxhr.responseText)
|
error = parseServerError(jqxhr.responseText)
|
||||||
property = error.property if error.property
|
property = error.property if error.property
|
||||||
if jqxhr.status is 409 and property is 'name'
|
if jqxhr.status is 409 and property is 'name'
|
||||||
|
@ -34,14 +34,14 @@ module.exports.createUserWithoutReload = (userObject, failure=backboneFailure) -
|
||||||
user.save({}, {
|
user.save({}, {
|
||||||
error: failure
|
error: failure
|
||||||
success: ->
|
success: ->
|
||||||
Backbone.Mediator.publish("created-user-without-reload")
|
Backbone.Mediator.publish('created-user-without-reload')
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports.loginUser = (userObject, failure=genericFailure) ->
|
module.exports.loginUser = (userObject, failure=genericFailure) ->
|
||||||
jqxhr = $.post('/auth/login',
|
jqxhr = $.post('/auth/login',
|
||||||
{
|
{
|
||||||
username:userObject.email,
|
username: userObject.email,
|
||||||
password:userObject.password
|
password: userObject.password
|
||||||
},
|
},
|
||||||
(model) -> window.location.reload()
|
(model) -> window.location.reload()
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,8 +2,8 @@ module.exports.sendContactMessage = (contactMessageObject, modal) ->
|
||||||
modal.find('.sending-indicator').show()
|
modal.find('.sending-indicator').show()
|
||||||
jqxhr = $.post '/contact', contactMessageObject, (response) ->
|
jqxhr = $.post '/contact', contactMessageObject, (response) ->
|
||||||
modal.find('.sending-indicator').hide()
|
modal.find('.sending-indicator').hide()
|
||||||
modal.find('#contact-message').val("Thanks!")
|
modal.find('#contact-message').val('Thanks!')
|
||||||
_.delay ->
|
_.delay ->
|
||||||
modal.find('#contact-message').val("")
|
modal.find('#contact-message').val('')
|
||||||
modal.modal 'hide'
|
modal.modal 'hide'
|
||||||
, 1000
|
, 1000
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
SystemNameLoader = require 'lib/SystemNameLoader'
|
SystemNameLoader = require 'lib/SystemNameLoader'
|
||||||
###
|
###
|
||||||
Good-to-knows:
|
Good-to-knows:
|
||||||
dataPath: an array of keys that walks you up a JSON object that's being patched
|
dataPath: an array of keys that walks you up a JSON object that's being patched
|
||||||
ex: ['scripts', 0, 'description']
|
ex: ['scripts', 0, 'description']
|
||||||
deltaPath: an array of keys that walks you up a JSON Diff Patch object.
|
deltaPath: an array of keys that walks you up a JSON Diff Patch object.
|
||||||
ex: ['scripts', '_0', 'description']
|
ex: ['scripts', '_0', 'description']
|
||||||
###
|
###
|
||||||
|
|
||||||
module.exports.expandDelta = (delta, left, schema) ->
|
module.exports.expandDelta = (delta, left, schema) ->
|
||||||
flattenedDeltas = flattenDelta(delta)
|
flattenedDeltas = flattenDelta(delta)
|
||||||
(expandFlattenedDelta(fd, left, schema) for fd in flattenedDeltas)
|
(expandFlattenedDelta(fd, left, schema) for fd in flattenedDeltas)
|
||||||
|
|
||||||
|
|
||||||
flattenDelta = (delta, dataPath=null, deltaPath=null) ->
|
flattenDelta = (delta, dataPath=null, deltaPath=null) ->
|
||||||
# takes a single jsondiffpatch delta and returns an array of objects with
|
# takes a single jsondiffpatch delta and returns an array of objects with
|
||||||
return [] unless delta
|
return [] unless delta
|
||||||
dataPath ?= []
|
dataPath ?= []
|
||||||
deltaPath ?= []
|
deltaPath ?= []
|
||||||
return [{dataPath:dataPath, deltaPath: deltaPath, o:delta}] if _.isArray delta
|
return [{dataPath: dataPath, deltaPath: deltaPath, o: delta}] if _.isArray delta
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
affectingArray = delta._t is 'a'
|
affectingArray = delta._t is 'a'
|
||||||
|
@ -27,12 +27,12 @@ flattenDelta = (delta, dataPath=null, deltaPath=null) ->
|
||||||
results = results.concat flattenDelta(
|
results = results.concat flattenDelta(
|
||||||
childDelta, dataPath.concat([dataIndex]), deltaPath.concat([deltaIndex]))
|
childDelta, dataPath.concat([dataIndex]), deltaPath.concat([deltaIndex]))
|
||||||
results
|
results
|
||||||
|
|
||||||
|
|
||||||
expandFlattenedDelta = (delta, left, schema) ->
|
expandFlattenedDelta = (delta, left, schema) ->
|
||||||
# takes a single flattened delta and converts into an object that can be
|
# takes a single flattened delta and converts into an object that can be
|
||||||
# easily formatted into something human readable.
|
# easily formatted into something human readable.
|
||||||
|
|
||||||
delta.action = '???'
|
delta.action = '???'
|
||||||
o = delta.o # the raw jsondiffpatch delta
|
o = delta.o # the raw jsondiffpatch delta
|
||||||
|
|
||||||
|
@ -80,58 +80,72 @@ expandFlattenedDelta = (delta, left, schema) ->
|
||||||
humanPath.push humanKey
|
humanPath.push humanKey
|
||||||
parentLeft = childLeft
|
parentLeft = childLeft
|
||||||
parentSchema = childSchema
|
parentSchema = childSchema
|
||||||
|
|
||||||
delta.humanPath = humanPath.join(' :: ')
|
delta.humanPath = humanPath.join(' :: ')
|
||||||
delta.schema = childSchema
|
delta.schema = childSchema
|
||||||
delta.left = childLeft
|
delta.left = childLeft
|
||||||
delta.right = jsondiffpatch.patch childLeft, delta.o unless delta.action is 'moved-index'
|
delta.right = jsondiffpatch.patch childLeft, delta.o unless delta.action is 'moved-index'
|
||||||
|
|
||||||
delta
|
delta
|
||||||
|
|
||||||
module.exports.makeJSONDiffer = ->
|
module.exports.makeJSONDiffer = ->
|
||||||
hasher = (obj) -> obj.name || obj.id || obj._id || JSON.stringify(_.keys(obj))
|
hasher = (obj) -> obj.name || obj.id || obj._id || JSON.stringify(_.keys(obj))
|
||||||
jsondiffpatch.create({objectHash:hasher})
|
jsondiffpatch.create({objectHash: hasher})
|
||||||
|
|
||||||
module.exports.getConflicts = (headDeltas, pendingDeltas) ->
|
module.exports.getConflicts = (headDeltas, pendingDeltas) ->
|
||||||
# headDeltas and pendingDeltas should be lists of deltas returned by interpretDelta
|
# headDeltas and pendingDeltas should be lists of deltas returned by expandDelta
|
||||||
# Returns a list of conflict objects with properties:
|
# Returns a list of conflict objects with properties:
|
||||||
# headDelta
|
# headDelta
|
||||||
# pendingDelta
|
# pendingDelta
|
||||||
# The deltas that have conflicts also have conflict properties pointing to one another.
|
# The deltas that have conflicts also have conflict properties pointing to one another.
|
||||||
|
|
||||||
headPathMap = groupDeltasByAffectingPaths(headDeltas)
|
headPathMap = groupDeltasByAffectingPaths(headDeltas)
|
||||||
pendingPathMap = groupDeltasByAffectingPaths(pendingDeltas)
|
pendingPathMap = groupDeltasByAffectingPaths(pendingDeltas)
|
||||||
paths = _.keys(headPathMap).concat(_.keys(pendingPathMap))
|
paths = _.keys(headPathMap).concat(_.keys(pendingPathMap))
|
||||||
|
|
||||||
# Here's my thinking: conflicts happen when one delta path is a substring of another delta path
|
# Here's my thinking: conflicts happen when one delta path is a substring of another delta path
|
||||||
# So, sort paths from both deltas together, which will naturally make conflicts adjacent,
|
# So, sort paths from both deltas together, which will naturally make conflicts adjacent,
|
||||||
# and if one is identified, one path is from the headDeltas, the other is from pendingDeltas
|
# and if one is identified AND one path is from the headDeltas AND the other is from pendingDeltas
|
||||||
# This is all to avoid an O(nm) brute force search.
|
# This is all to avoid an O(nm) brute force search.
|
||||||
|
|
||||||
conflicts = []
|
conflicts = []
|
||||||
paths.sort()
|
paths.sort()
|
||||||
for path, i in paths
|
for path, i in paths
|
||||||
continue if i + 1 is paths.length
|
offset = 1
|
||||||
nextPath = paths[i+1]
|
while i + offset < paths.length
|
||||||
if nextPath.startsWith path
|
# Look at the neighbor
|
||||||
headDelta = (headPathMap[path] or headPathMap[nextPath])[0].delta
|
nextPath = paths[i+offset]
|
||||||
pendingDelta = (pendingPathMap[path] or pendingPathMap[nextPath])[0].delta
|
offset += 1
|
||||||
conflicts.push({headDelta:headDelta, pendingDelta:pendingDelta})
|
|
||||||
pendingDelta.conflict = headDelta
|
# these stop being substrings of each other? Then conflict DNE
|
||||||
headDelta.conflict = pendingDelta
|
if not (nextPath.startsWith path) then break
|
||||||
|
|
||||||
|
# check if these two are from the same group, but we still need to check for more beyond
|
||||||
|
unless headPathMap[path] or headPathMap[nextPath] then continue
|
||||||
|
unless pendingPathMap[path] or pendingPathMap[nextPath] then continue
|
||||||
|
|
||||||
|
# Okay, we found two deltas from different groups which conflict
|
||||||
|
for headMetaDelta in (headPathMap[path] or headPathMap[nextPath])
|
||||||
|
headDelta = headMetaDelta.delta
|
||||||
|
for pendingMetaDelta in (pendingPathMap[path] or pendingPathMap[nextPath])
|
||||||
|
pendingDelta = pendingMetaDelta.delta
|
||||||
|
conflicts.push({headDelta: headDelta, pendingDelta: pendingDelta})
|
||||||
|
pendingDelta.conflict = headDelta
|
||||||
|
headDelta.conflict = pendingDelta
|
||||||
|
|
||||||
return conflicts if conflicts.length
|
return conflicts if conflicts.length
|
||||||
|
|
||||||
groupDeltasByAffectingPaths = (deltas) ->
|
groupDeltasByAffectingPaths = (deltas) ->
|
||||||
metaDeltas = []
|
metaDeltas = []
|
||||||
for delta in deltas
|
for delta in deltas
|
||||||
conflictPaths = []
|
conflictPaths = []
|
||||||
|
# We're being fairly liberal with what's a conflict, because the alternative is worse
|
||||||
if delta.action is 'moved-index'
|
if delta.action is 'moved-index'
|
||||||
# every other action affects just the data path, but moved indexes affect a swath
|
# If you moved items around in an array, mark the whole array as a gonner
|
||||||
indices = [delta.originalIndex, delta.destinationIndex]
|
conflictPaths.push delta.dataPath.slice(0, delta.dataPath.length-1)
|
||||||
indices.sort()
|
else if delta.action in ['deleted', 'added'] and _.isNumber(delta.dataPath[delta.dataPath.length-1])
|
||||||
for index in _.range(indices[0], indices[1]+1)
|
# If you remove or add items in an array, mark the whole thing as a gonner
|
||||||
conflictPaths.push delta.dataPath.slice(0, delta.dataPath.length-1).concat(index)
|
conflictPaths.push delta.dataPath.slice(0, delta.dataPath.length-1)
|
||||||
else
|
else
|
||||||
conflictPaths.push delta.dataPath
|
conflictPaths.push delta.dataPath
|
||||||
for path in conflictPaths
|
for path in conflictPaths
|
||||||
|
@ -139,39 +153,21 @@ groupDeltasByAffectingPaths = (deltas) ->
|
||||||
delta: delta
|
delta: delta
|
||||||
path: (item.toString() for item in path).join('/')
|
path: (item.toString() for item in path).join('/')
|
||||||
}
|
}
|
||||||
|
|
||||||
map = _.groupBy metaDeltas, 'path'
|
map = _.groupBy metaDeltas, 'path'
|
||||||
|
return map
|
||||||
|
|
||||||
# Turns out there are cases where a single delta can include paths
|
|
||||||
# that 'conflict' with each other, ie one is a substring of the other
|
|
||||||
# because of moved indices. To handle this case, go through and prune
|
|
||||||
# out all deeper paths that conflict with more shallow paths, so
|
|
||||||
# getConflicts path checking works properly.
|
|
||||||
|
|
||||||
paths = _.keys(map)
|
|
||||||
return map unless paths.length
|
|
||||||
paths.sort()
|
|
||||||
prunedMap = {}
|
|
||||||
previousPath = paths[0]
|
|
||||||
for path, i in paths
|
|
||||||
continue if i is 0
|
|
||||||
continue if path.startsWith previousPath
|
|
||||||
prunedMap[path] = map[path]
|
|
||||||
previousPath = path
|
|
||||||
|
|
||||||
prunedMap
|
|
||||||
|
|
||||||
module.exports.pruneConflictsFromDelta = (delta, conflicts) ->
|
module.exports.pruneConflictsFromDelta = (delta, conflicts) ->
|
||||||
expandedDeltas = (conflict.pendingDelta for conflict in conflicts)
|
expandedDeltas = (conflict.pendingDelta for conflict in conflicts)
|
||||||
module.exports.pruneExpandedDeltasFromDelta delta, expandedDeltas
|
module.exports.pruneExpandedDeltasFromDelta delta, expandedDeltas
|
||||||
|
|
||||||
module.exports.pruneExpandedDeltasFromDelta = (delta, expandedDeltas) ->
|
module.exports.pruneExpandedDeltasFromDelta = (delta, expandedDeltas) ->
|
||||||
# the jsondiffpatch delta mustn't include any dangling nodes,
|
# the jsondiffpatch delta mustn't include any dangling nodes,
|
||||||
# or else things will get removed which shouldn't be, or errors will occur
|
# or else things will get removed which shouldn't be, or errors will occur
|
||||||
for expandedDelta in expandedDeltas
|
for expandedDelta in expandedDeltas
|
||||||
prunePath delta, expandedDelta.deltaPath
|
prunePath delta, expandedDelta.deltaPath
|
||||||
if _.isEmpty delta then undefined else delta
|
if _.isEmpty delta then undefined else delta
|
||||||
|
|
||||||
prunePath = (delta, path) ->
|
prunePath = (delta, path) ->
|
||||||
if path.length is 1
|
if path.length is 1
|
||||||
delete delta[path]
|
delete delta[path]
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
errorModalTemplate = require('templates/modal/error')
|
errorModalTemplate = require 'templates/modal/error'
|
||||||
{applyErrorsToForm} = require('lib/forms')
|
{applyErrorsToForm} = require 'lib/forms'
|
||||||
|
|
||||||
module.exports.parseServerError = (text) ->
|
module.exports.parseServerError = (text) ->
|
||||||
try
|
try
|
||||||
error = JSON.parse(text) or {message:"Unknown error."}
|
error = JSON.parse(text) or {message: 'Unknown error.'}
|
||||||
catch SyntaxError
|
catch SyntaxError
|
||||||
error = {message:text or "Unknown error."}
|
error = {message: text or 'Unknown error.'}
|
||||||
error = error[0] if _.isArray(error)
|
error = error[0] if _.isArray(error)
|
||||||
error
|
error
|
||||||
|
|
||||||
module.exports.genericFailure = (jqxhr) ->
|
module.exports.genericFailure = (jqxhr) ->
|
||||||
Backbone.Mediator.publish('server-error', {response:jqxhr})
|
Backbone.Mediator.publish('server-error', {response: jqxhr})
|
||||||
return connectionFailure() if not jqxhr.status
|
return connectionFailure() if not jqxhr.status
|
||||||
|
|
||||||
error = module.exports.parseServerError(jqxhr.responseText)
|
error = module.exports.parseServerError(jqxhr.responseText)
|
||||||
|
@ -24,8 +24,8 @@ module.exports.genericFailure = (jqxhr) ->
|
||||||
existingForm.append($('<div class="alert alert-danger"></div>').text(error.message))
|
existingForm.append($('<div class="alert alert-danger"></div>').text(error.message))
|
||||||
else
|
else
|
||||||
res = errorModalTemplate(
|
res = errorModalTemplate(
|
||||||
status:jqxhr.status
|
status: jqxhr.status
|
||||||
statusText:jqxhr.statusText
|
statusText: jqxhr.statusText
|
||||||
message: message
|
message: message
|
||||||
)
|
)
|
||||||
showErrorModal(res)
|
showErrorModal(res)
|
||||||
|
@ -36,7 +36,7 @@ module.exports.backboneFailure = (model, jqxhr, options) ->
|
||||||
module.exports.connectionFailure = connectionFailure = ->
|
module.exports.connectionFailure = connectionFailure = ->
|
||||||
html = errorModalTemplate(
|
html = errorModalTemplate(
|
||||||
status: 0
|
status: 0
|
||||||
statusText:'Connection Gone'
|
statusText: 'Connection Gone'
|
||||||
message: 'No response from the CoCo servers, captain.'
|
message: 'No response from the CoCo servers, captain.'
|
||||||
)
|
)
|
||||||
showErrorModal(html)
|
showErrorModal(html)
|
||||||
|
|
|
@ -16,13 +16,13 @@ module.exports.applyErrorsToForm = (el, errors) ->
|
||||||
if error.dataPath
|
if error.dataPath
|
||||||
prop = error.dataPath[1..]
|
prop = error.dataPath[1..]
|
||||||
message = error.message
|
message = error.message
|
||||||
|
|
||||||
else
|
else
|
||||||
message = "#{error.property} #{error.message}."
|
message = "#{error.property} #{error.message}."
|
||||||
message = message[0].toUpperCase() + message[1..]
|
message = message[0].toUpperCase() + message[1..]
|
||||||
message = error.message if error.formatted
|
message = error.message if error.formatted
|
||||||
prop = error.property
|
prop = error.property
|
||||||
|
|
||||||
input = $("[name='#{prop}']", el)
|
input = $("[name='#{prop}']", el)
|
||||||
if not input.length
|
if not input.length
|
||||||
missingErrors.push(error)
|
missingErrors.push(error)
|
||||||
|
@ -35,4 +35,4 @@ module.exports.applyErrorsToForm = (el, errors) ->
|
||||||
module.exports.clearFormAlerts = (el) ->
|
module.exports.clearFormAlerts = (el) ->
|
||||||
$('.has-error', el).removeClass('has-error')
|
$('.has-error', el).removeClass('has-error')
|
||||||
$('.alert.alert-danger', el).remove()
|
$('.alert.alert-danger', el).remove()
|
||||||
el.find('.help-block.error-help-block').remove()
|
el.find('.help-block.error-help-block').remove()
|
||||||
|
|
|
@ -6,9 +6,9 @@ Filters.getPixels = (img) ->
|
||||||
c = @getCanvas(img.naturalWidth, img.naturalHeight)
|
c = @getCanvas(img.naturalWidth, img.naturalHeight)
|
||||||
ctx = c.getContext('2d')
|
ctx = c.getContext('2d')
|
||||||
ctx.drawImage(img, 0, 0)
|
ctx.drawImage(img, 0, 0)
|
||||||
return ctx.getImageData(0,0,c.width,c.height)
|
return ctx.getImageData(0, 0, c.width, c.height)
|
||||||
|
|
||||||
Filters.getCanvas = (w,h) ->
|
Filters.getCanvas = (w, h) ->
|
||||||
c = document.createElement('canvas')
|
c = document.createElement('canvas')
|
||||||
c.width = w
|
c.width = w
|
||||||
c.height = h
|
c.height = h
|
||||||
|
@ -34,7 +34,7 @@ module.exports.darkenImage = darkenImage = (img, pct=0.5) ->
|
||||||
return img.src = cachedValue if cachedValue
|
return img.src = cachedValue if cachedValue
|
||||||
jqimg.data('original', img.src) unless jqimg.data('original')
|
jqimg.data('original', img.src) unless jqimg.data('original')
|
||||||
if not (img.naturalWidth > 0 and img.naturalHeight > 0)
|
if not (img.naturalWidth > 0 and img.naturalHeight > 0)
|
||||||
console.warn "Tried to darken image", img, "but it has natural dimensions", img.naturalWidth, img.naturalHeight
|
console.warn 'Tried to darken image', img, 'but it has natural dimensions', img.naturalWidth, img.naturalHeight
|
||||||
return img
|
return img
|
||||||
imageData = Filters.filterImage(Filters.brightness, img, pct)
|
imageData = Filters.filterImage(Filters.brightness, img, pct)
|
||||||
c = Filters.getCanvas(img.naturalWidth, img.naturalHeight)
|
c = Filters.getCanvas(img.naturalWidth, img.naturalHeight)
|
||||||
|
|
|
@ -9,7 +9,7 @@ module.exports.getParentFolders = (subPath, urlPrefix='/test/') ->
|
||||||
url: urlPrefix + parts.join('/')
|
url: urlPrefix + parts.join('/')
|
||||||
}
|
}
|
||||||
paths
|
paths
|
||||||
|
|
||||||
module.exports.parseImmediateChildren = (allChildren, subPath, baseRequirePath='test/app/', urlPrefix='/test/') ->
|
module.exports.parseImmediateChildren = (allChildren, subPath, baseRequirePath='test/app/', urlPrefix='/test/') ->
|
||||||
return [] unless allChildren
|
return [] unless allChildren
|
||||||
folders = {}
|
folders = {}
|
||||||
|
@ -34,14 +34,14 @@ module.exports.parseImmediateChildren = (allChildren, subPath, baseRequirePath='
|
||||||
|
|
||||||
for name in _.keys(folders)
|
for name in _.keys(folders)
|
||||||
children.push {
|
children.push {
|
||||||
type:'folder',
|
type: 'folder',
|
||||||
url: urlPrefix+name
|
url: urlPrefix+name
|
||||||
name: name+'/'
|
name: name+'/'
|
||||||
size: folders[name]
|
size: folders[name]
|
||||||
}
|
}
|
||||||
for name in _.keys(files)
|
for name in _.keys(files)
|
||||||
children.push {
|
children.push {
|
||||||
type:'file',
|
type: 'file',
|
||||||
url: urlPrefix+name
|
url: urlPrefix+name
|
||||||
name: name
|
name: name
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,8 @@ module.exports = class DOMScriptModule extends ScriptModule
|
||||||
|
|
||||||
endNotes: ->
|
endNotes: ->
|
||||||
notes = []
|
notes = []
|
||||||
notes.push({ 'channel': 'end-level-highlight-dom' }) if @noteGroup.dom.highlight?
|
notes.push({'channel': 'end-level-highlight-dom'}) if @noteGroup.dom.highlight?
|
||||||
notes.push({ 'channel': 'level-enable-controls' }) if @noteGroup.dom.lock?
|
notes.push({'channel': 'level-enable-controls'}) if @noteGroup.dom.lock?
|
||||||
return notes
|
return notes
|
||||||
|
|
||||||
skipNotes: ->
|
skipNotes: ->
|
||||||
|
@ -60,7 +60,7 @@ module.exports = class DOMScriptModule extends ScriptModule
|
||||||
lock = @noteGroup.dom.lock
|
lock = @noteGroup.dom.lock
|
||||||
event.controls = lock if _.isArray lock # array: subset of controls
|
event.controls = lock if _.isArray lock # array: subset of controls
|
||||||
channel = if lock then 'level-disable-controls' else 'level-enable-controls'
|
channel = if lock then 'level-disable-controls' else 'level-enable-controls'
|
||||||
return { channel: channel, event: event }
|
return {channel: channel, event: event}
|
||||||
|
|
||||||
letterboxNote: ->
|
letterboxNote: ->
|
||||||
return { channel: 'level-set-letterbox', event: { on: @noteGroup.dom.letterbox } }
|
return {channel: 'level-set-letterbox', event: {on: @noteGroup.dom.letterbox}}
|
||||||
|
|
|
@ -76,10 +76,10 @@ module.exports = ScriptManager = class ScriptManager extends CocoClass
|
||||||
script.id = (idNum++).toString() unless script.id
|
script.id = (idNum++).toString() unless script.id
|
||||||
callback = makeCallback(script.channel) # curry in the channel argument
|
callback = makeCallback(script.channel) # curry in the channel argument
|
||||||
@addNewSubscription(script.channel, callback)
|
@addNewSubscription(script.channel, callback)
|
||||||
|
|
||||||
beginTicking: ->
|
beginTicking: ->
|
||||||
@tickInterval = setInterval @tick, 5000
|
@tickInterval = setInterval @tick, 5000
|
||||||
|
|
||||||
tick: =>
|
tick: =>
|
||||||
scriptStates = {}
|
scriptStates = {}
|
||||||
now = new Date()
|
now = new Date()
|
||||||
|
@ -87,7 +87,7 @@ module.exports = ScriptManager = class ScriptManager extends CocoClass
|
||||||
scriptStates[script.id] =
|
scriptStates[script.id] =
|
||||||
timeSinceLastEnded: (if script.lastEnded then now - script.lastEnded else 0) / 1000
|
timeSinceLastEnded: (if script.lastEnded then now - script.lastEnded else 0) / 1000
|
||||||
timeSinceLastTriggered: (if script.lastTriggered then now - script.lastTriggered else 0) / 1000
|
timeSinceLastTriggered: (if script.lastTriggered then now - script.lastTriggered else 0) / 1000
|
||||||
|
|
||||||
stateEvent =
|
stateEvent =
|
||||||
scriptRunning: @currentNoteGroup?.scriptID or ''
|
scriptRunning: @currentNoteGroup?.scriptID or ''
|
||||||
noteGroupRunning: @currentNoteGroup?.name or ''
|
noteGroupRunning: @currentNoteGroup?.name or ''
|
||||||
|
@ -123,7 +123,7 @@ module.exports = ScriptManager = class ScriptManager extends CocoClass
|
||||||
for scriptID in scriptsToSkip
|
for scriptID in scriptsToSkip
|
||||||
script = _.find @scripts, {id: scriptID}
|
script = _.find @scripts, {id: scriptID}
|
||||||
unless script
|
unless script
|
||||||
console.warn "Couldn't find script for", scriptID, "from scripts", @scripts, "when restoring session scripts."
|
console.warn 'Couldn\'t find script for', scriptID, 'from scripts', @scripts, 'when restoring session scripts.'
|
||||||
continue
|
continue
|
||||||
continue if script.repeats # repeating scripts are not 'rerun'
|
continue if script.repeats # repeating scripts are not 'rerun'
|
||||||
@triggered.push(scriptID)
|
@triggered.push(scriptID)
|
||||||
|
|
|
@ -1,31 +1,31 @@
|
||||||
CocoClass = require 'lib/CocoClass'
|
CocoClass = require 'lib/CocoClass'
|
||||||
|
|
||||||
module.exports = class ScriptModule extends CocoClass
|
module.exports = class ScriptModule extends CocoClass
|
||||||
|
|
||||||
scrubbingTime = 0
|
scrubbingTime = 0
|
||||||
movementTime = 0
|
movementTime = 0
|
||||||
|
|
||||||
constructor: (@noteGroup) ->
|
constructor: (@noteGroup) ->
|
||||||
super()
|
super()
|
||||||
if not @noteGroup.prepared
|
if not @noteGroup.prepared
|
||||||
@analyzeNoteGroup(noteGroup)
|
@analyzeNoteGroup(noteGroup)
|
||||||
@noteGroup.notes ?= []
|
@noteGroup.notes ?= []
|
||||||
@noteGroup.prepared = true
|
@noteGroup.prepared = true
|
||||||
|
|
||||||
# subclass should overwrite these
|
# subclass should overwrite these
|
||||||
|
|
||||||
@neededFor: -> false
|
@neededFor: -> false
|
||||||
startNotes: -> []
|
startNotes: -> []
|
||||||
endNotes: -> []
|
endNotes: -> []
|
||||||
skipNotes: -> @endNotes()
|
skipNotes: -> @endNotes()
|
||||||
|
|
||||||
# common logic
|
# common logic
|
||||||
|
|
||||||
analyzeNoteGroup: ->
|
analyzeNoteGroup: ->
|
||||||
# some notes need to happen after others. Calculate the delays
|
# some notes need to happen after others. Calculate the delays
|
||||||
@movementTime = @calculateMovementMax(@noteGroup)
|
@movementTime = @calculateMovementMax(@noteGroup)
|
||||||
@scrubbingTime = @noteGroup.playback?.scrub?.duration or 0
|
@scrubbingTime = @noteGroup.playback?.scrub?.duration or 0
|
||||||
|
|
||||||
calculateMovementMax: ->
|
calculateMovementMax: ->
|
||||||
sums = {}
|
sums = {}
|
||||||
for sprite in @noteGroup.sprites
|
for sprite in @noteGroup.sprites
|
||||||
|
@ -36,4 +36,4 @@ module.exports = class ScriptModule extends CocoClass
|
||||||
Math.max(0, sums...)
|
Math.max(0, sums...)
|
||||||
|
|
||||||
maybeApplyDelayToNote: (note) ->
|
maybeApplyDelayToNote: (note) ->
|
||||||
note.delay = (@scrubbingTime + @movementTime) or 0
|
note.delay = (@scrubbingTime + @movementTime) or 0
|
||||||
|
|
|
@ -26,7 +26,7 @@ module.exports = class SoundScriptModule extends ScriptModule
|
||||||
channel: 'level-suppress-selection-sounds'
|
channel: 'level-suppress-selection-sounds'
|
||||||
event: {suppress: @noteGroup.sound.suppressSelectionSounds}
|
event: {suppress: @noteGroup.sound.suppressSelectionSounds}
|
||||||
return note
|
return note
|
||||||
|
|
||||||
addMusicNote: ->
|
addMusicNote: ->
|
||||||
note =
|
note =
|
||||||
channel: 'level-play-music'
|
channel: 'level-play-music'
|
||||||
|
|
|
@ -45,7 +45,7 @@ module.exports = class SpritesScriptModule extends ScriptModule
|
||||||
event:
|
event:
|
||||||
message: text
|
message: text
|
||||||
blurb: blurb
|
blurb: blurb
|
||||||
mood: sprite.say.mood or "explain"
|
mood: sprite.say.mood or 'explain'
|
||||||
responses: responses
|
responses: responses
|
||||||
spriteID: sprite.id
|
spriteID: sprite.id
|
||||||
sound: sound
|
sound: sound
|
||||||
|
|
|
@ -1,42 +1,42 @@
|
||||||
module.exports = initializeFacebook = ->
|
module.exports = initializeFacebook = ->
|
||||||
# Additional JS functions here
|
# Additional JS functions here
|
||||||
window.fbAsyncInit = ->
|
window.fbAsyncInit = ->
|
||||||
Backbone.Mediator.publish "fbapi-loaded"
|
|
||||||
FB.init
|
FB.init
|
||||||
appId: (if document.location.origin is "http://localhost:3000" then "607435142676437" else "148832601965463") # App ID
|
appId: (if document.location.origin is 'http://localhost:3000' then '607435142676437' else '148832601965463') # App ID
|
||||||
channelUrl: document.location.origin + "/channel.html" # Channel File
|
channelUrl: document.location.origin + '/channel.html' # Channel File
|
||||||
status: true # check login status
|
status: true # check login status
|
||||||
cookie: true # enable cookies to allow the server to access the session
|
cookie: true # enable cookies to allow the server to access the session
|
||||||
xfbml: true # parse XFBML
|
xfbml: true # parse XFBML
|
||||||
|
|
||||||
|
Backbone.Mediator.publish 'fbapi-loaded'
|
||||||
|
|
||||||
# This is fired for any auth related change, such as login, logout or session refresh.
|
# This is fired for any auth related change, such as login, logout or session refresh.
|
||||||
FB.Event.subscribe "auth.authResponseChange", (response) ->
|
FB.Event.subscribe 'auth.authResponseChange', (response) ->
|
||||||
|
|
||||||
# Here we specify what we do with the response anytime this event occurs.
|
# Here we specify what we do with the response anytime this event occurs.
|
||||||
if response.status is "connected"
|
if response.status is 'connected'
|
||||||
|
|
||||||
# They have logged in to the app.
|
# They have logged in to the app.
|
||||||
Backbone.Mediator.publish "facebook-logged-in",
|
Backbone.Mediator.publish 'facebook-logged-in',
|
||||||
response: response
|
response: response
|
||||||
|
|
||||||
else if response.status is "not_authorized"
|
else if response.status is 'not_authorized'
|
||||||
#
|
#
|
||||||
else
|
else
|
||||||
#
|
#
|
||||||
|
|
||||||
# Load the SDK asynchronously
|
# Load the SDK asynchronously
|
||||||
((d) ->
|
((d) ->
|
||||||
js = undefined
|
js = undefined
|
||||||
id = "facebook-jssdk"
|
id = 'facebook-jssdk'
|
||||||
ref = d.getElementsByTagName("script")[0]
|
ref = d.getElementsByTagName('script')[0]
|
||||||
return if d.getElementById(id)
|
return if d.getElementById(id)
|
||||||
js = d.createElement("script")
|
js = d.createElement('script')
|
||||||
js.id = id
|
js.id = id
|
||||||
js.async = true
|
js.async = true
|
||||||
js.src = "//connect.facebook.net/en_US/all.js"
|
js.src = '//connect.facebook.net/en_US/all.js'
|
||||||
|
|
||||||
#js.src = "//connect.facebook.net/en_US/all/debug.js";
|
#js.src = '//connect.facebook.net/en_US/all/debug.js'
|
||||||
ref.parentNode.insertBefore js, ref
|
ref.parentNode.insertBefore js, ref
|
||||||
return
|
return
|
||||||
) document
|
) document
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
module.exports = initializeFilepicker = ->
|
module.exports = initializeFilepicker = ->
|
||||||
((a) ->
|
((a) ->
|
||||||
return if window.filepicker
|
return if window.filepicker
|
||||||
b = a.createElement("script")
|
b = a.createElement('script')
|
||||||
b.type = "text/javascript"
|
b.type = 'text/javascript'
|
||||||
b.async = not 0
|
b.async = not 0
|
||||||
b.src = ((if "https:" is a.location.protocol then "https:" else "http:")) + "//api.filepicker.io/v1/filepicker.js"
|
b.src = ((if 'https:' is a.location.protocol then 'https:' else 'http:')) + '//api.filepicker.io/v1/filepicker.js'
|
||||||
c = a.getElementsByTagName("script")[0]
|
c = a.getElementsByTagName('script')[0]
|
||||||
c.parentNode.insertBefore b, c
|
c.parentNode.insertBefore b, c
|
||||||
d = {}
|
d = {}
|
||||||
d._queue = []
|
d._queue = []
|
||||||
e = "pick,pickMultiple,pickAndStore,read,write,writeUrl,export,convert,store,storeUrl,remove,stat,setKey,constructWidget,makeDropPane".split(",")
|
e = 'pick,pickMultiple,pickAndStore,read,write,writeUrl,export,convert,store,storeUrl,remove,stat,setKey,constructWidget,makeDropPane'.split(',')
|
||||||
f = (a, b) ->
|
f = (a, b) ->
|
||||||
->
|
->
|
||||||
b.push [
|
b.push [
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
module.exports = initializeGoogle = ->
|
module.exports = initializeGoogle = ->
|
||||||
window.onGPlusLoaded = ->
|
window.onGPlusLoaded = ->
|
||||||
Backbone.Mediator.publish "gapi-loaded"
|
Backbone.Mediator.publish 'gapi-loaded'
|
||||||
return
|
return
|
||||||
window.signinCallback = (authResult) ->
|
window.signinCallback = (authResult) ->
|
||||||
Backbone.Mediator.publish "gplus-logged-in", authResult if authResult["access_token"]
|
Backbone.Mediator.publish 'gplus-logged-in', authResult if authResult['access_token']
|
||||||
return
|
return
|
||||||
(->
|
(->
|
||||||
po = document.createElement("script")
|
po = document.createElement('script')
|
||||||
po.type = "text/javascript"
|
po.type = 'text/javascript'
|
||||||
po.async = true
|
po.async = true
|
||||||
po.src = "https://apis.google.com/js/client:plusone.js?onload=onGPlusLoaded"
|
po.src = 'https://apis.google.com/js/client:plusone.js?onload=onGPlusLoaded'
|
||||||
s = document.getElementsByTagName("script")[0]
|
s = document.getElementsByTagName('script')[0]
|
||||||
s.parentNode.insertBefore po, s
|
s.parentNode.insertBefore po, s
|
||||||
return
|
return
|
||||||
)()
|
)()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module.exports = initializeLinkedIn = ->
|
module.exports = initializeLinkedIn = ->
|
||||||
window.linkedInAsyncInit = ->
|
window.linkedInAsyncInit = ->
|
||||||
console.log "Linkedin async init success!"
|
console.log 'Linkedin async init success!'
|
||||||
Backbone.Mediator.publish 'linkedin-loaded'
|
Backbone.Mediator.publish 'linkedin-loaded'
|
||||||
|
|
||||||
linkedInSnippet =
|
linkedInSnippet =
|
||||||
|
|
|
@ -2,9 +2,9 @@ module.exports = initializeOlark = ->
|
||||||
window.olark or ((c) -> #<![CDATA[
|
window.olark or ((c) -> #<![CDATA[
|
||||||
f = window
|
f = window
|
||||||
d = document
|
d = document
|
||||||
l = (if f.location.protocol is "https:" then "https:" else "http:")
|
l = (if f.location.protocol is 'https:' then 'https:' else 'http:')
|
||||||
z = c.name
|
z = c.name
|
||||||
r = "load"
|
r = 'load'
|
||||||
nt = ->
|
nt = ->
|
||||||
s = ->
|
s = ->
|
||||||
a.P r
|
a.P r
|
||||||
|
@ -19,7 +19,7 @@ module.exports = initializeOlark = ->
|
||||||
while q--
|
while q--
|
||||||
((n) ->
|
((n) ->
|
||||||
f[z][n] = ->
|
f[z][n] = ->
|
||||||
f[z] "call", n, arguments
|
f[z] 'call', n, arguments
|
||||||
return
|
return
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -31,67 +31,67 @@ module.exports = initializeOlark = ->
|
||||||
a.p[u] = new Date - a.p[0]
|
a.p[u] = new Date - a.p[0]
|
||||||
return
|
return
|
||||||
|
|
||||||
(if f.addEventListener then f.addEventListener(r, s, false) else f.attachEvent("on" + r, s))
|
(if f.addEventListener then f.addEventListener(r, s, false) else f.attachEvent('on' + r, s))
|
||||||
ld = ->
|
ld = ->
|
||||||
p = (hd) ->
|
p = (hd) ->
|
||||||
hd = "head"
|
hd = 'head'
|
||||||
[
|
[
|
||||||
"<"
|
'<'
|
||||||
hd
|
hd
|
||||||
"></"
|
'></'
|
||||||
hd
|
hd
|
||||||
"><"
|
'><'
|
||||||
i
|
i
|
||||||
" onl" + "oad=\"var d="
|
' onl' + 'oad=\"var d='
|
||||||
g
|
g
|
||||||
";d.getElementsByTagName('head')[0]."
|
";d.getElementsByTagName('head')[0]."
|
||||||
j
|
j
|
||||||
"(d."
|
'(d.'
|
||||||
h
|
h
|
||||||
"('script'))."
|
"('script'))."
|
||||||
k
|
k
|
||||||
"='"
|
"='"
|
||||||
l
|
l
|
||||||
"//"
|
'//'
|
||||||
a.l
|
a.l
|
||||||
"'"
|
"'"
|
||||||
"\""
|
'\"'
|
||||||
"></"
|
'></'
|
||||||
i
|
i
|
||||||
">"
|
'>'
|
||||||
].join ""
|
].join ''
|
||||||
i = "body"
|
i = 'body'
|
||||||
m = d[i]
|
m = d[i]
|
||||||
return setTimeout(ld, 100) unless m
|
return setTimeout(ld, 100) unless m
|
||||||
a.P 1
|
a.P 1
|
||||||
j = "appendChild"
|
j = 'appendChild'
|
||||||
h = "createElement"
|
h = 'createElement'
|
||||||
k = "src"
|
k = 'src'
|
||||||
n = d[h]("div")
|
n = d[h]('div')
|
||||||
v = n[j](d[h](z))
|
v = n[j](d[h](z))
|
||||||
b = d[h]("iframe")
|
b = d[h]('iframe')
|
||||||
g = "document"
|
g = 'document'
|
||||||
e = "domain"
|
e = 'domain'
|
||||||
o = undefined
|
o = undefined
|
||||||
n.style.display = "none"
|
n.style.display = 'none'
|
||||||
m.insertBefore(n, m.firstChild).id = z
|
m.insertBefore(n, m.firstChild).id = z
|
||||||
b.frameBorder = "0"
|
b.frameBorder = '0'
|
||||||
b.id = z + "-loader"
|
b.id = z + '-loader'
|
||||||
b.src = "javascript:false" if /MSIE[ ]+6/.test(navigator.userAgent)
|
b.src = 'javascript:false' if /MSIE[ ]+6/.test(navigator.userAgent)
|
||||||
b.allowTransparency = "true"
|
b.allowTransparency = 'true'
|
||||||
v[j] b
|
v[j] b
|
||||||
try
|
try
|
||||||
b.contentWindow[g].open()
|
b.contentWindow[g].open()
|
||||||
catch w
|
catch w
|
||||||
c[e] = d[e]
|
c[e] = d[e]
|
||||||
o = "javascript:var d=" + g + ".open();d.domain='" + d.domain + "';"
|
o = 'javascript:var d=' + g + ".open();d.domain='" + d.domain + "';"
|
||||||
b[k] = o + "void(0);"
|
b[k] = o + 'void(0);'
|
||||||
try
|
try
|
||||||
t = b.contentWindow[g]
|
t = b.contentWindow[g]
|
||||||
t.write p()
|
t.write p()
|
||||||
t.close()
|
t.close()
|
||||||
catch x
|
catch x
|
||||||
b[k] = o + "d.write(\"" + p().replace(/"/g, String.fromCharCode(92) + "\"") + "\");d.close();"
|
b[k] = o + 'd.write(\"' + p().replace(/"/g, String.fromCharCode(92) + '\"') + '\");d.close();'
|
||||||
a.P 2
|
a.P 2
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -101,16 +101,15 @@ module.exports = initializeOlark = ->
|
||||||
nt()
|
nt()
|
||||||
return
|
return
|
||||||
)(
|
)(
|
||||||
loader: "static.olark.com/jsclient/loader0.js"
|
loader: 'static.olark.com/jsclient/loader0.js'
|
||||||
name: "olark"
|
name: 'olark'
|
||||||
methods: [
|
methods: [
|
||||||
"configure"
|
'configure'
|
||||||
"extend"
|
'extend'
|
||||||
"declare"
|
'declare'
|
||||||
"identify"
|
'identify'
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
# custom configuration goes here (www.olark.com/documentation)
|
# custom configuration goes here (www.olark.com/documentation)
|
||||||
olark.identify "1451-787-10-5544" #]]>
|
olark.identify '1451-787-10-5544' #]]>
|
||||||
|
|
||||||
|
|
|
@ -2,18 +2,18 @@ module.exports = initializeSegmentio = ->
|
||||||
analytics = analytics or []
|
analytics = analytics or []
|
||||||
(->
|
(->
|
||||||
e = [
|
e = [
|
||||||
"identify"
|
'identify'
|
||||||
"track"
|
'track'
|
||||||
"trackLink"
|
'trackLink'
|
||||||
"trackForm"
|
'trackForm'
|
||||||
"trackClick"
|
'trackClick'
|
||||||
"trackSubmit"
|
'trackSubmit'
|
||||||
"page"
|
'page'
|
||||||
"pageview"
|
'pageview'
|
||||||
"ab"
|
'ab'
|
||||||
"alias"
|
'alias'
|
||||||
"ready"
|
'ready'
|
||||||
"group"
|
'group'
|
||||||
]
|
]
|
||||||
t = (e) ->
|
t = (e) ->
|
||||||
->
|
->
|
||||||
|
@ -28,14 +28,13 @@ module.exports = initializeSegmentio = ->
|
||||||
return
|
return
|
||||||
)()
|
)()
|
||||||
analytics.load = (e) ->
|
analytics.load = (e) ->
|
||||||
t = document.createElement("script")
|
t = document.createElement('script')
|
||||||
t.type = "text/javascript"
|
t.type = 'text/javascript'
|
||||||
t.async = not 0
|
t.async = not 0
|
||||||
t.src = ((if "https:" is document.location.protocol then "https://" else "http://")) + "d2dq2ahtl5zl1z.cloudfront.net/analytics.js/v1/" + e + "/analytics.min.js"
|
t.src = ((if 'https:' is document.location.protocol then 'https://' else 'http://')) + 'd2dq2ahtl5zl1z.cloudfront.net/analytics.js/v1/' + e + '/analytics.min.js'
|
||||||
|
|
||||||
n = document.getElementsByTagName("script")[0]
|
n = document.getElementsByTagName('script')[0]
|
||||||
n.parentNode.insertBefore t, n
|
n.parentNode.insertBefore t, n
|
||||||
return
|
return
|
||||||
|
|
||||||
|
analytics.load 'jsjzx9n4d2'
|
||||||
analytics.load "jsjzx9n4d2"
|
|
||||||
|
|
|
@ -2,11 +2,11 @@ module.exports = initializeTwitter = ->
|
||||||
((d, s, id) ->
|
((d, s, id) ->
|
||||||
js = undefined
|
js = undefined
|
||||||
fjs = d.getElementsByTagName(s)[0]
|
fjs = d.getElementsByTagName(s)[0]
|
||||||
p = (if /^http:/.test(d.location) then "http" else "https")
|
p = (if /^http:/.test(d.location) then 'http' else 'https')
|
||||||
unless d.getElementById(id)
|
unless d.getElementById(id)
|
||||||
js = d.createElement(s)
|
js = d.createElement(s)
|
||||||
js.id = id
|
js.id = id
|
||||||
js.src = p + "://platform.twitter.com/widgets.js"
|
js.src = p + '://platform.twitter.com/widgets.js'
|
||||||
fjs.parentNode.insertBefore js, fjs
|
fjs.parentNode.insertBefore js, fjs
|
||||||
return
|
return
|
||||||
) document, "script", "twitter-wjs"
|
) document, 'script', 'twitter-wjs'
|
||||||
|
|
|
@ -8,7 +8,6 @@ Aether.addGlobal 'Vector', require 'lib/world/vector'
|
||||||
Aether.addGlobal '_', _
|
Aether.addGlobal '_', _
|
||||||
|
|
||||||
module.exports = class Simulator extends CocoClass
|
module.exports = class Simulator extends CocoClass
|
||||||
|
|
||||||
constructor: (@options) ->
|
constructor: (@options) ->
|
||||||
@options ?= {}
|
@options ?= {}
|
||||||
_.extend @, Backbone.Events
|
_.extend @, Backbone.Events
|
||||||
|
@ -27,12 +26,12 @@ module.exports = class Simulator extends CocoClass
|
||||||
fetchAndSimulateOneGame: (humanGameID, ogresGameID) =>
|
fetchAndSimulateOneGame: (humanGameID, ogresGameID) =>
|
||||||
return if @destroyed
|
return if @destroyed
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "/queue/scoring/getTwoGames"
|
url: '/queue/scoring/getTwoGames'
|
||||||
type: "POST"
|
type: 'POST'
|
||||||
parse: true
|
parse: true
|
||||||
data:
|
data:
|
||||||
"humansGameID": humanGameID
|
'humansGameID': humanGameID
|
||||||
"ogresGameID": ogresGameID
|
'ogresGameID': ogresGameID
|
||||||
error: (errorData) ->
|
error: (errorData) ->
|
||||||
console.warn "There was an error fetching two games! #{JSON.stringify errorData}"
|
console.warn "There was an error fetching two games! #{JSON.stringify errorData}"
|
||||||
success: (taskData) =>
|
success: (taskData) =>
|
||||||
|
@ -71,31 +70,31 @@ module.exports = class Simulator extends CocoClass
|
||||||
@god.createWorld @generateSpellsObject()
|
@god.createWorld @generateSpellsObject()
|
||||||
|
|
||||||
handleSingleSimulationError: (error) ->
|
handleSingleSimulationError: (error) ->
|
||||||
console.error "There was an error simulating a single game!", error
|
console.error 'There was an error simulating a single game!', error
|
||||||
if @options.headlessClient and @options.simulateOnlyOneGame
|
if @options.headlessClient and @options.simulateOnlyOneGame
|
||||||
console.log "GAMERESULT:tie"
|
console.log 'GAMERESULT:tie'
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
@cleanupAndSimulateAnotherTask()
|
@cleanupAndSimulateAnotherTask()
|
||||||
|
|
||||||
handleSingleSimulationInfiniteLoop: ->
|
handleSingleSimulationInfiniteLoop: ->
|
||||||
console.log "There was an infinite loop in the single game!"
|
console.log 'There was an infinite loop in the single game!'
|
||||||
if @options.headlessClient and @options.simulateOnlyOneGame
|
if @options.headlessClient and @options.simulateOnlyOneGame
|
||||||
console.log "GAMERESULT:tie"
|
console.log 'GAMERESULT:tie'
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
@cleanupAndSimulateAnotherTask()
|
@cleanupAndSimulateAnotherTask()
|
||||||
|
|
||||||
processSingleGameResults: (simulationResults) ->
|
processSingleGameResults: (simulationResults) ->
|
||||||
taskResults = @formTaskResultsObject simulationResults
|
taskResults = @formTaskResultsObject simulationResults
|
||||||
console.log "Processing results:", taskResults
|
console.log 'Processing results:', taskResults
|
||||||
humanSessionRank = taskResults.sessions[0].metrics.rank
|
humanSessionRank = taskResults.sessions[0].metrics.rank
|
||||||
ogreSessionRank = taskResults.sessions[1].metrics.rank
|
ogreSessionRank = taskResults.sessions[1].metrics.rank
|
||||||
if @options.headlessClient and @options.simulateOnlyOneGame
|
if @options.headlessClient and @options.simulateOnlyOneGame
|
||||||
if humanSessionRank is ogreSessionRank
|
if humanSessionRank is ogreSessionRank
|
||||||
console.log "GAMERESULT:tie"
|
console.log 'GAMERESULT:tie'
|
||||||
else if humanSessionRank < ogreSessionRank
|
else if humanSessionRank < ogreSessionRank
|
||||||
console.log "GAMERESULT:humans"
|
console.log 'GAMERESULT:humans'
|
||||||
else if ogreSessionRank < humanSessionRank
|
else if ogreSessionRank < humanSessionRank
|
||||||
console.log "GAMERESULT:ogres"
|
console.log 'GAMERESULT:ogres'
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
else
|
else
|
||||||
@sendSingleGameBackToServer(taskResults)
|
@sendSingleGameBackToServer(taskResults)
|
||||||
|
@ -104,32 +103,31 @@ module.exports = class Simulator extends CocoClass
|
||||||
@trigger 'statusUpdate', 'Simulation completed, sending results back to server!'
|
@trigger 'statusUpdate', 'Simulation completed, sending results back to server!'
|
||||||
|
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "/queue/scoring/recordTwoGames"
|
url: '/queue/scoring/recordTwoGames'
|
||||||
data: results
|
data: results
|
||||||
type: "PUT"
|
type: 'PUT'
|
||||||
parse: true
|
parse: true
|
||||||
success: @handleTaskResultsTransferSuccess
|
success: @handleTaskResultsTransferSuccess
|
||||||
error: @handleTaskResultsTransferError
|
error: @handleTaskResultsTransferError
|
||||||
complete: @cleanupAndSimulateAnotherTask
|
complete: @cleanupAndSimulateAnotherTask
|
||||||
|
|
||||||
|
|
||||||
fetchAndSimulateTask: =>
|
fetchAndSimulateTask: =>
|
||||||
return if @destroyed
|
return if @destroyed
|
||||||
|
|
||||||
if @options.headlessClient
|
if @options.headlessClient
|
||||||
if @dumpThisTime # The first heapdump would be useless to find leaks.
|
if @dumpThisTime # The first heapdump would be useless to find leaks.
|
||||||
console.log "Writing snapshot."
|
console.log 'Writing snapshot.'
|
||||||
@options.heapdump.writeSnapshot()
|
@options.heapdump.writeSnapshot()
|
||||||
@dumpThisTime = true if @options.heapdump
|
@dumpThisTime = true if @options.heapdump
|
||||||
|
|
||||||
if @options.testing
|
if @options.testing
|
||||||
_.delay @setupSimulationAndLoadLevel, 0, @options.testFile, "Testing...", status: 400
|
_.delay @setupSimulationAndLoadLevel, 0, @options.testFile, 'Testing...', status: 400
|
||||||
return
|
return
|
||||||
|
|
||||||
@trigger 'statusUpdate', 'Fetching simulation data!'
|
@trigger 'statusUpdate', 'Fetching simulation data!'
|
||||||
$.ajax
|
$.ajax
|
||||||
url: @taskURL
|
url: @taskURL
|
||||||
type: "GET"
|
type: 'GET'
|
||||||
parse: true
|
parse: true
|
||||||
error: @handleFetchTaskError
|
error: @handleFetchTaskError
|
||||||
success: @setupSimulationAndLoadLevel
|
success: @setupSimulationAndLoadLevel
|
||||||
|
@ -139,13 +137,12 @@ module.exports = class Simulator extends CocoClass
|
||||||
@trigger 'statusUpdate', 'There was an error fetching games to simulate. Retrying in 10 seconds.'
|
@trigger 'statusUpdate', 'There was an error fetching games to simulate. Retrying in 10 seconds.'
|
||||||
@simulateAnotherTaskAfterDelay()
|
@simulateAnotherTaskAfterDelay()
|
||||||
|
|
||||||
|
|
||||||
handleNoGamesResponse: ->
|
handleNoGamesResponse: ->
|
||||||
info = 'Finding game to simulate...'
|
info = 'Finding game to simulate...'
|
||||||
console.log info
|
console.log info
|
||||||
@trigger 'statusUpdate', info
|
@trigger 'statusUpdate', info
|
||||||
@fetchAndSimulateOneGame()
|
@fetchAndSimulateOneGame()
|
||||||
application.tracker?.trackEvent 'Simulator Result', label: "No Games", ['Google Analytics']
|
application.tracker?.trackEvent 'Simulator Result', label: 'No Games', ['Google Analytics']
|
||||||
|
|
||||||
simulateAnotherTaskAfterDelay: =>
|
simulateAnotherTaskAfterDelay: =>
|
||||||
console.log "Retrying in #{@retryDelayInSeconds}"
|
console.log "Retrying in #{@retryDelayInSeconds}"
|
||||||
|
@ -184,7 +181,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, "-- trying again in #{@retryDelayInSeconds} seconds"
|
||||||
@simulateAnotherTaskAfterDelay()
|
@simulateAnotherTaskAfterDelay()
|
||||||
|
|
||||||
assignWorldAndLevelFromLevelLoaderAndDestroyIt: ->
|
assignWorldAndLevelFromLevelLoaderAndDestroyIt: ->
|
||||||
|
@ -205,11 +202,11 @@ module.exports = class Simulator extends CocoClass
|
||||||
Backbone.Mediator.subscribeOnce 'god:goals-calculated', @processResults, @
|
Backbone.Mediator.subscribeOnce 'god:goals-calculated', @processResults, @
|
||||||
@god.createWorld @generateSpellsObject()
|
@god.createWorld @generateSpellsObject()
|
||||||
|
|
||||||
#Search for leaks, headless-client only.
|
# Search for leaks, headless-client only.
|
||||||
if @options.headlessClient and @options.leakTest and not @memwatch?
|
if @options.headlessClient and @options.leakTest and not @memwatch?
|
||||||
leakcount = 0
|
leakcount = 0
|
||||||
maxleakcount = 0
|
maxleakcount = 0
|
||||||
console.log "Setting leak callbacks."
|
console.log 'Setting leak callbacks.'
|
||||||
@memwatch = require 'memwatch'
|
@memwatch = require 'memwatch'
|
||||||
|
|
||||||
@memwatch.on 'leak', (info) =>
|
@memwatch.on 'leak', (info) =>
|
||||||
|
@ -220,17 +217,17 @@ module.exports = class Simulator extends CocoClass
|
||||||
@hd = new @memwatch.HeapDiff()
|
@hd = new @memwatch.HeapDiff()
|
||||||
|
|
||||||
@memwatch.on 'stats', (stats) =>
|
@memwatch.on 'stats', (stats) =>
|
||||||
console.warn "stats callback: " + stats
|
console.warn 'stats callback: ' + stats
|
||||||
diff = @hd.end()
|
diff = @hd.end()
|
||||||
console.warn "HeapDiff:\n" + JSON.stringify(diff)
|
console.warn "HeapDiff:\n" + JSON.stringify(diff)
|
||||||
|
|
||||||
if @options.exitOnLeak
|
if @options.exitOnLeak
|
||||||
console.warn "Exiting because of Leak."
|
console.warn 'Exiting because of Leak.'
|
||||||
process.exit()
|
process.exit()
|
||||||
@hd = new @memwatch.HeapDiff()
|
@hd = new @memwatch.HeapDiff()
|
||||||
|
|
||||||
onInfiniteLoop: ->
|
onInfiniteLoop: ->
|
||||||
console.warn "Skipping infinitely looping game."
|
console.warn 'Skipping infinitely looping game.'
|
||||||
@trigger 'statusUpdate', "Infinite loop detected; grabbing a new game in #{@retryDelayInSeconds} seconds."
|
@trigger 'statusUpdate', "Infinite loop detected; grabbing a new game in #{@retryDelayInSeconds} seconds."
|
||||||
_.delay @cleanupAndSimulateAnotherTask, @retryDelayInSeconds * 1000
|
_.delay @cleanupAndSimulateAnotherTask, @retryDelayInSeconds * 1000
|
||||||
|
|
||||||
|
@ -244,16 +241,16 @@ module.exports = class Simulator extends CocoClass
|
||||||
|
|
||||||
sendResultsBackToServer: (results) ->
|
sendResultsBackToServer: (results) ->
|
||||||
@trigger 'statusUpdate', 'Simulation completed, sending results back to server!'
|
@trigger 'statusUpdate', 'Simulation completed, sending results back to server!'
|
||||||
console.log "Sending result back to server:"
|
console.log 'Sending result back to server:'
|
||||||
console.log JSON.stringify results
|
console.log JSON.stringify results
|
||||||
|
|
||||||
if @options.headlessClient and @options.testing
|
if @options.headlessClient and @options.testing
|
||||||
return @fetchAndSimulateTask()
|
return @fetchAndSimulateTask()
|
||||||
|
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "/queue/scoring"
|
url: '/queue/scoring'
|
||||||
data: results
|
data: results
|
||||||
type: "PUT"
|
type: 'PUT'
|
||||||
parse: true
|
parse: true
|
||||||
success: @handleTaskResultsTransferSuccess
|
success: @handleTaskResultsTransferSuccess
|
||||||
error: @handleTaskResultsTransferError
|
error: @handleTaskResultsTransferError
|
||||||
|
@ -263,12 +260,12 @@ module.exports = class Simulator extends CocoClass
|
||||||
return if @destroyed
|
return if @destroyed
|
||||||
console.log "Task registration result: #{JSON.stringify result}"
|
console.log "Task registration result: #{JSON.stringify result}"
|
||||||
@trigger 'statusUpdate', 'Results were successfully sent back to server!'
|
@trigger 'statusUpdate', 'Results were successfully sent back to server!'
|
||||||
console.log "Simulated by you:", @simulatedByYou
|
console.log 'Simulated by you:', @simulatedByYou
|
||||||
@simulatedByYou++
|
@simulatedByYou++
|
||||||
unless @options.headlessClient
|
unless @options.headlessClient
|
||||||
simulatedBy = parseInt($('#simulated-by-you').text(), 10) + 1
|
simulatedBy = parseInt($('#simulated-by-you').text(), 10) + 1
|
||||||
$('#simulated-by-you').text(simulatedBy)
|
$('#simulated-by-you').text(simulatedBy)
|
||||||
application.tracker?.trackEvent 'Simulator Result', label: "Success", ['Google Analytics']
|
application.tracker?.trackEvent 'Simulator Result', label: 'Success', ['Google Analytics']
|
||||||
|
|
||||||
handleTaskResultsTransferError: (error) =>
|
handleTaskResultsTransferError: (error) =>
|
||||||
return if @destroyed
|
return if @destroyed
|
||||||
|
@ -316,11 +313,11 @@ module.exports = class Simulator extends CocoClass
|
||||||
humansWon = _.all humanGoals, {status: 'success'}
|
humansWon = _.all humanGoals, {status: 'success'}
|
||||||
if ogresWon is humansWon
|
if ogresWon is humansWon
|
||||||
return 0
|
return 0
|
||||||
else if ogresWon and teamSessionMap["ogres"] is sessionID
|
else if ogresWon and teamSessionMap['ogres'] is sessionID
|
||||||
return 0
|
return 0
|
||||||
else if ogresWon and teamSessionMap["ogres"] isnt sessionID
|
else if ogresWon and teamSessionMap['ogres'] isnt sessionID
|
||||||
return 1
|
return 1
|
||||||
else if humansWon and teamSessionMap["humans"] is sessionID
|
else if humansWon and teamSessionMap['humans'] is sessionID
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
return 1
|
return 1
|
||||||
|
@ -376,14 +373,13 @@ module.exports = class Simulator extends CocoClass
|
||||||
else
|
else
|
||||||
spellSession = _.filter(@task.getSessions(), {team: spellTeam})[0]
|
spellSession = _.filter(@task.getSessions(), {team: spellTeam})[0]
|
||||||
unless codeLanguage = spellSession?.submittedCodeLanguage
|
unless codeLanguage = spellSession?.submittedCodeLanguage
|
||||||
console.warn "Session", spellSession.creatorName, spellSession.team, "didn't have submittedCodeLanguage, just:", spellSession
|
console.warn 'Session', spellSession.creatorName, spellSession.team, 'didn\'t have submittedCodeLanguage, just:', spellSession
|
||||||
@spells[spellKey].thangs[thang.id].aether = @createAether @spells[spellKey].name, method, useProtectAPI, codeLanguage ? 'javascript'
|
@spells[spellKey].thangs[thang.id].aether = @createAether @spells[spellKey].name, method, useProtectAPI, codeLanguage ? 'javascript'
|
||||||
|
|
||||||
|
|
||||||
transpileSpell: (thang, spellKey, methodName) ->
|
transpileSpell: (thang, spellKey, methodName) ->
|
||||||
slugifiedThangID = _.string.slugify thang.id
|
slugifiedThangID = _.string.slugify thang.id
|
||||||
generatedSpellKey = [slugifiedThangID,methodName].join '/'
|
generatedSpellKey = [slugifiedThangID,methodName].join '/'
|
||||||
source = @currentUserCodeMap[generatedSpellKey] ? ""
|
source = @currentUserCodeMap[generatedSpellKey] ? ''
|
||||||
aether = @spells[spellKey].thangs[thang.id].aether
|
aether = @spells[spellKey].thangs[thang.id].aether
|
||||||
unless _.contains(@task.spellKeysToTranspile, generatedSpellKey)
|
unless _.contains(@task.spellKeysToTranspile, generatedSpellKey)
|
||||||
aether.pure = source
|
aether.pure = source
|
||||||
|
@ -399,22 +395,21 @@ module.exports = class Simulator extends CocoClass
|
||||||
functionName: methodName
|
functionName: methodName
|
||||||
protectAPI: useProtectAPI
|
protectAPI: useProtectAPI
|
||||||
includeFlow: false
|
includeFlow: false
|
||||||
yieldConditionally: methodName is "plan"
|
yieldConditionally: methodName is 'plan'
|
||||||
globals: ['Vector', '_']
|
globals: ['Vector', '_']
|
||||||
problems:
|
problems:
|
||||||
jshint_W040: {level: "ignore"}
|
jshint_W040: {level: 'ignore'}
|
||||||
jshint_W030: {level: "ignore"} # aether_NoEffect instead
|
jshint_W030: {level: 'ignore'} # aether_NoEffect instead
|
||||||
aether_MissingThis: {level: 'error'}
|
aether_MissingThis: {level: 'error'}
|
||||||
#functionParameters: # TODOOOOO
|
#functionParameters: # TODOOOOO
|
||||||
executionLimit: 1 * 1000 * 1000
|
executionLimit: 1 * 1000 * 1000
|
||||||
language: codeLanguage
|
language: codeLanguage
|
||||||
if methodName is 'hear' then aetherOptions.functionParameters = ['speaker', 'message', 'data']
|
if methodName is 'hear' then aetherOptions.functionParameters = ['speaker', 'message', 'data']
|
||||||
if methodName is 'makeBid' then aetherOptions.functionParameters = ['tileGroupLetter']
|
if methodName is 'makeBid' then aetherOptions.functionParameters = ['tileGroupLetter']
|
||||||
if methodName is "findCentroids" then aetherOptions.functionParameters = ["centroids"]
|
if methodName is 'findCentroids' then aetherOptions.functionParameters = ['centroids']
|
||||||
#console.log "creating aether with options", aetherOptions
|
#console.log 'creating aether with options', aetherOptions
|
||||||
return new Aether aetherOptions
|
return new Aether aetherOptions
|
||||||
|
|
||||||
|
|
||||||
class SimulationTask
|
class SimulationTask
|
||||||
constructor: (@rawData) ->
|
constructor: (@rawData) ->
|
||||||
@spellKeyToTeamMap = {}
|
@spellKeyToTeamMap = {}
|
||||||
|
@ -423,12 +418,12 @@ class SimulationTask
|
||||||
getLevelName: ->
|
getLevelName: ->
|
||||||
levelName = @rawData.sessions?[0]?.levelID
|
levelName = @rawData.sessions?[0]?.levelID
|
||||||
return levelName if levelName?
|
return levelName if levelName?
|
||||||
@throwMalformedTaskError "The level name couldn't be deduced from the task."
|
@throwMalformedTaskError 'The level name couldn\'t be deduced from the task.'
|
||||||
|
|
||||||
generateTeamToSessionMap: ->
|
generateTeamToSessionMap: ->
|
||||||
teamSessionMap = {}
|
teamSessionMap = {}
|
||||||
for session in @rawData.sessions
|
for session in @rawData.sessions
|
||||||
@throwMalformedTaskError "Two players share the same team" if teamSessionMap[session.team]?
|
@throwMalformedTaskError 'Two players share the same team' if teamSessionMap[session.team]?
|
||||||
teamSessionMap[session.team] = session.sessionID
|
teamSessionMap[session.team] = session.sessionID
|
||||||
|
|
||||||
teamSessionMap
|
teamSessionMap
|
||||||
|
@ -450,7 +445,6 @@ class SimulationTask
|
||||||
|
|
||||||
setWorld: (@world) ->
|
setWorld: (@world) ->
|
||||||
|
|
||||||
|
|
||||||
generateSpellKeyToSourceMap: ->
|
generateSpellKeyToSourceMap: ->
|
||||||
playerTeams = _.pluck @rawData.sessions, 'team'
|
playerTeams = _.pluck @rawData.sessions, 'team'
|
||||||
spellKeyToSourceMap = {}
|
spellKeyToSourceMap = {}
|
||||||
|
@ -469,7 +463,7 @@ class SimulationTask
|
||||||
|
|
||||||
for thangName, thangSpells of session.transpiledCode
|
for thangName, thangSpells of session.transpiledCode
|
||||||
for spellName, spell of thangSpells
|
for spellName, spell of thangSpells
|
||||||
fullSpellName = [thangName,spellName].join '/'
|
fullSpellName = [thangName, spellName].join '/'
|
||||||
if _.contains(teamSpells, fullSpellName)
|
if _.contains(teamSpells, fullSpellName)
|
||||||
teamCode[fullSpellName]=spell
|
teamCode[fullSpellName]=spell
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ module.exports = class SpriteBuilder
|
||||||
buildMovieClip: (animationName, movieClipArgs...) ->
|
buildMovieClip: (animationName, movieClipArgs...) ->
|
||||||
animData = @animationStore[animationName]
|
animData = @animationStore[animationName]
|
||||||
unless animData
|
unless animData
|
||||||
console.error "couldn't find animData from", @animationStore, "for", animationName
|
console.error 'couldn\'t find animData from', @animationStore, 'for', animationName
|
||||||
return null
|
return null
|
||||||
locals = {}
|
locals = {}
|
||||||
_.extend locals, @buildMovieClipShapes(animData.shapes)
|
_.extend locals, @buildMovieClipShapes(animData.shapes)
|
||||||
|
@ -111,7 +111,7 @@ module.exports = class SpriteBuilder
|
||||||
shape
|
shape
|
||||||
|
|
||||||
buildContainerFromStore: (containerKey) ->
|
buildContainerFromStore: (containerKey) ->
|
||||||
console.error "Yo we don't have no", containerKey unless containerKey
|
console.error 'Yo we don\'t have no', containerKey unless containerKey
|
||||||
contData = @containerStore[containerKey]
|
contData = @containerStore[containerKey]
|
||||||
cont = new createjs.Container()
|
cont = new createjs.Container()
|
||||||
cont.initialize()
|
cont.initialize()
|
||||||
|
@ -182,5 +182,4 @@ module.exports = class SpriteBuilder
|
||||||
continue if (not shape.fc?) or not(colors[shape.fc])
|
continue if (not shape.fc?) or not(colors[shape.fc])
|
||||||
@colorMap[shapeKey] = hslToHex(colors[shape.fc])
|
@colorMap[shapeKey] = hslToHex(colors[shape.fc])
|
||||||
|
|
||||||
|
|
||||||
sum = (nums) -> _.reduce(nums, (s, num) -> s + num)
|
sum = (nums) -> _.reduce(nums, (s, num) -> s + num)
|
||||||
|
|
|
@ -29,8 +29,8 @@ module.exports = class SpriteParser
|
||||||
parse: (source) ->
|
parse: (source) ->
|
||||||
# Grab the library properties' width/height so we can subtract half of each from frame bounds
|
# Grab the library properties' width/height so we can subtract half of each from frame bounds
|
||||||
properties = source.match(/.*lib\.properties = \{\n.*?width: (\d+),\n.*?height: (\d+)/im)
|
properties = source.match(/.*lib\.properties = \{\n.*?width: (\d+),\n.*?height: (\d+)/im)
|
||||||
@width = parseInt(properties?[1] ? "0", 10)
|
@width = parseInt(properties?[1] ? '0', 10)
|
||||||
@height = parseInt(properties?[2] ? "0", 10)
|
@height = parseInt(properties?[2] ? '0', 10)
|
||||||
|
|
||||||
options = {loc: false, range: true}
|
options = {loc: false, range: true}
|
||||||
ast = esprima.parse source, options
|
ast = esprima.parse source, options
|
||||||
|
@ -60,7 +60,7 @@ module.exports = class SpriteParser
|
||||||
continue if gotIt
|
continue if gotIt
|
||||||
for c in localContainers
|
for c in localContainers
|
||||||
if c.bn is bn
|
if c.bn is bn
|
||||||
instructions.push { t: c.t, gn: c.gn }
|
instructions.push {t: c.t, gn: c.gn}
|
||||||
break
|
break
|
||||||
@addContainer {c: instructions, b: container.bounds}, container.name
|
@addContainer {c: instructions, b: container.bounds}, container.name
|
||||||
for movieClip in movieClips
|
for movieClip in movieClips
|
||||||
|
@ -101,7 +101,7 @@ module.exports = class SpriteParser
|
||||||
if not shortKey?
|
if not shortKey?
|
||||||
shortKey = name
|
shortKey = name
|
||||||
if @thangType.containers[shortKey]?
|
if @thangType.containers[shortKey]?
|
||||||
shortKey = @animationName + ":" + name
|
shortKey = @animationName + ':' + name
|
||||||
@thangType.containers[shortKey] = container
|
@thangType.containers[shortKey] = container
|
||||||
@containerLongKeys[longKey] = shortKey
|
@containerLongKeys[longKey] = shortKey
|
||||||
@containerRenamings[name] = shortKey
|
@containerRenamings[name] = shortKey
|
||||||
|
@ -115,7 +115,7 @@ module.exports = class SpriteParser
|
||||||
else
|
else
|
||||||
shortKey = name
|
shortKey = name
|
||||||
if @thangType.animations[shortKey]?
|
if @thangType.animations[shortKey]?
|
||||||
shortKey = @animationName + ":" + name
|
shortKey = @animationName + ':' + name
|
||||||
@thangType.animations[shortKey] = animation
|
@thangType.animations[shortKey] = animation
|
||||||
@animationLongKeys[longKey] = shortKey
|
@animationLongKeys[longKey] = shortKey
|
||||||
@animationRenamings[name] = shortKey
|
@animationRenamings[name] = shortKey
|
||||||
|
@ -173,7 +173,7 @@ module.exports = class SpriteParser
|
||||||
frameBoundsRange = frameBoundsStatement.expression.right.range
|
frameBoundsRange = frameBoundsStatement.expression.right.range
|
||||||
frameBoundsSource = @subSourceFromRange frameBoundsRange, source
|
frameBoundsSource = @subSourceFromRange frameBoundsRange, source
|
||||||
if frameBoundsSource.search(/\[rect/) is -1 # some other statement; we don't have multiframe bounds
|
if frameBoundsSource.search(/\[rect/) is -1 # some other statement; we don't have multiframe bounds
|
||||||
console.log "Didn't have multiframe bounds for this movie clip."
|
console.log 'Didn\'t have multiframe bounds for this movie clip.'
|
||||||
frameBounds = [nominalBounds]
|
frameBounds = [nominalBounds]
|
||||||
else
|
else
|
||||||
lastRect = nominalBounds
|
lastRect = nominalBounds
|
||||||
|
@ -204,10 +204,10 @@ module.exports = class SpriteParser
|
||||||
functionExpressions
|
functionExpressions
|
||||||
|
|
||||||
###
|
###
|
||||||
this.shape_1.graphics.f("#605E4A").s().p("AAOD/IgOgaIAEhkIgmgdIgMgBIgPgFIgVgJQA1h9g8jXQAQAHAOASQAQAUAKAeQARAuAJBJQAHA/gBA5IAAADIACAfIAFARIACAGIAEAHIAHAHQAVAXAQAUQAUAaANAUIABACIgsgdIgggXIAAAnIABAwIgBgBg");
|
this.shape_1.graphics.f('#605E4A').s().p('AAOD/IgOgaIAEhkIgmgdIgMgBIgPgFIgVgJQA1h9g8jXQAQAHAOASQAQAUAKAeQARAuAJBJQAHA/gBA5IAAADIACAfIAFARIACAGIAEAHIAHAHQAVAXAQAUQAUAaANAUIABACIgsgdIgggXIAAAnIABAwIgBgBg');
|
||||||
this.shape_1.sett(23.2,30.1);
|
this.shape_1.sett(23.2,30.1);
|
||||||
|
|
||||||
this.shape.graphics.f().s("#000000").ss(0.1,1,1).p("AAAAAQAAAAAAAA");
|
this.shape.graphics.f().s('#000000').ss(0.1,1,1).p('AAAAAQAAAAAAAA');
|
||||||
this.shape.sett(3.8,22.4);
|
this.shape.sett(3.8,22.4);
|
||||||
###
|
###
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ module.exports = class SpriteParser
|
||||||
return unless node.type is 'NewExpression' and node.callee.property.name is 'Graphics'
|
return unless node.type is 'NewExpression' and node.callee.property.name is 'Graphics'
|
||||||
blockName = node.parent.parent.parent.id.name
|
blockName = node.parent.parent.parent.id.name
|
||||||
graphicsString = node.parent.parent.arguments[0].value
|
graphicsString = node.parent.parent.arguments[0].value
|
||||||
localGraphics.push({p:graphicsString, bn:blockName})
|
localGraphics.push {p:graphicsString, bn:blockName}
|
||||||
|
|
||||||
@walk block, null, gatherShapeDefinitions
|
@walk block, null, gatherShapeDefinitions
|
||||||
return localGraphics
|
return localGraphics
|
||||||
|
@ -233,7 +233,7 @@ module.exports = class SpriteParser
|
||||||
if not name
|
if not name
|
||||||
name = node.parent?.parent?.id?.name
|
name = node.parent?.parent?.id?.name
|
||||||
return unless name and name.indexOf('mask') is 0 and node.property?.name is 'Shape'
|
return unless name and name.indexOf('mask') is 0 and node.property?.name is 'Shape'
|
||||||
shape = { bn: name, im: true }
|
shape = {bn: name, im: true}
|
||||||
localShapes.push shape
|
localShapes.push shape
|
||||||
return
|
return
|
||||||
return unless name.search('shape') is 0 and node.object.property?.name is 'graphics'
|
return unless name.search('shape') is 0 and node.object.property?.name is 'graphics'
|
||||||
|
@ -243,14 +243,14 @@ module.exports = class SpriteParser
|
||||||
linearGradientFill = @grabFunctionArguments linearGradientFillSource.replace(/.*?lf\(/, 'lf('), true
|
linearGradientFill = @grabFunctionArguments linearGradientFillSource.replace(/.*?lf\(/, 'lf('), true
|
||||||
else
|
else
|
||||||
fillColor = fillCall.arguments[0]?.value ? null
|
fillColor = fillCall.arguments[0]?.value ? null
|
||||||
console.error "What is this?! Not a fill!" unless fillCall.callee.property.name is 'f'
|
console.error 'What is this?! Not a fill!' unless fillCall.callee.property.name is 'f'
|
||||||
strokeCall = node.parent.parent.parent.parent
|
strokeCall = node.parent.parent.parent.parent
|
||||||
if strokeCall.object.callee.property.name is 'ls'
|
if strokeCall.object.callee.property.name is 'ls'
|
||||||
linearGradientStrokeSource = @subSourceFromRange strokeCall.parent.range, source
|
linearGradientStrokeSource = @subSourceFromRange strokeCall.parent.range, source
|
||||||
linearGradientStroke = @grabFunctionArguments linearGradientStrokeSource.replace(/.*?ls\(/, 'ls(').replace(/\).ss\(.*/, ')'), true
|
linearGradientStroke = @grabFunctionArguments linearGradientStrokeSource.replace(/.*?ls\(/, 'ls(').replace(/\).ss\(.*/, ')'), true
|
||||||
else
|
else
|
||||||
strokeColor = strokeCall.object.arguments?[0]?.value ? null
|
strokeColor = strokeCall.object.arguments?[0]?.value ? null
|
||||||
console.error "What is this?! Not a stroke!" unless strokeCall.object.callee.property.name is 's'
|
console.error 'What is this?! Not a stroke!' unless strokeCall.object.callee.property.name is 's'
|
||||||
strokeStyle = null
|
strokeStyle = null
|
||||||
graphicsStatement = strokeCall.parent
|
graphicsStatement = strokeCall.parent
|
||||||
if strokeColor or linearGradientStroke
|
if strokeColor or linearGradientStroke
|
||||||
|
@ -264,7 +264,7 @@ module.exports = class SpriteParser
|
||||||
drawEllipse = @grabFunctionArguments drawEllipseSource.replace(/.*?de\(/, 'de('), true
|
drawEllipse = @grabFunctionArguments drawEllipseSource.replace(/.*?de\(/, 'de('), true
|
||||||
else
|
else
|
||||||
path = graphicsStatement.arguments?[0]?.value ? null
|
path = graphicsStatement.arguments?[0]?.value ? null
|
||||||
console.error "What is this?! Not a path!" unless graphicsStatement.callee.property.name is 'p'
|
console.error 'What is this?! Not a path!' unless graphicsStatement.callee.property.name is 'p'
|
||||||
body = graphicsStatement.parent.parent.body
|
body = graphicsStatement.parent.parent.body
|
||||||
graphicsStatementIndex = _.indexOf body, graphicsStatement.parent
|
graphicsStatementIndex = _.indexOf body, graphicsStatement.parent
|
||||||
t = body[graphicsStatementIndex + 1].expression
|
t = body[graphicsStatementIndex + 1].expression
|
||||||
|
@ -295,8 +295,8 @@ module.exports = class SpriteParser
|
||||||
shape.fc = fillColor if fillColor
|
shape.fc = fillColor if fillColor
|
||||||
shape.lf = linearGradientFill if linearGradientFill
|
shape.lf = linearGradientFill if linearGradientFill
|
||||||
shape.ls = linearGradientStroke if linearGradientStroke
|
shape.ls = linearGradientStroke if linearGradientStroke
|
||||||
if name.search('shape') isnt -1 and shape.fc is "rgba(0,0,0,0.451)" and not shape.ss and not shape.sc
|
if name.search('shape') isnt -1 and shape.fc is 'rgba(0,0,0,0.451)' and not shape.ss and not shape.sc
|
||||||
console.log "Skipping a shadow", name, shape, "because we're doing shadows separately now."
|
console.log 'Skipping a shadow', name, shape, 'because we\'re doing shadows separately now.'
|
||||||
return
|
return
|
||||||
shapeKeys.push shapeKey = @addShape shape
|
shapeKeys.push shapeKey = @addShape shape
|
||||||
localShape = {bn: name, gn: shapeKey}
|
localShape = {bn: name, gn: shapeKey}
|
||||||
|
@ -372,17 +372,17 @@ module.exports = class SpriteParser
|
||||||
return if name is 'get' and callExpressions.length # avoid Ease calls in the tweens
|
return if name is 'get' and callExpressions.length # avoid Ease calls in the tweens
|
||||||
flattenedRanges = _.flatten [a.range for a in node.arguments]
|
flattenedRanges = _.flatten [a.range for a in node.arguments]
|
||||||
range = [_.min(flattenedRanges), _.max(flattenedRanges)]
|
range = [_.min(flattenedRanges), _.max(flattenedRanges)]
|
||||||
# Replace "this.<local>" references with just the "name"
|
# Replace 'this.<local>' references with just the 'name'
|
||||||
argsSource = @subSourceFromRange(range, source)
|
argsSource = @subSourceFromRange(range, source)
|
||||||
argsSource = argsSource.replace(/mask/g, 'this.mask') # so the mask thing will be handled correctly as a blockName in the next line
|
argsSource = argsSource.replace(/mask/g, 'this.mask') # so the mask thing will be handled correctly as a blockName in the next line
|
||||||
argsSource = argsSource.replace(/this\.([a-z_0-9]+)/ig, '"$1"') # turns this.shape literal to "shape" string
|
argsSource = argsSource.replace(/this\.([a-z_0-9]+)/ig, '"$1"') # turns this.shape literal to 'shape' string
|
||||||
argsSource = argsSource.replace(/cjs(.+)\)/, '"createjs$1)"') # turns cjs.Ease.get(0.5)
|
argsSource = argsSource.replace(/cjs(.+)\)/, '"createjs$1)"') # turns cjs.Ease.get(0.5)
|
||||||
|
|
||||||
args = eval "[#{argsSource}]"
|
args = eval "[#{argsSource}]"
|
||||||
shadowTween = args[0]?.search?('shape') is 0 and not _.find(localShapes, bn: args[0])
|
shadowTween = args[0]?.search?('shape') is 0 and not _.find(localShapes, bn: args[0])
|
||||||
shadowTween = shadowTween or args[0]?.state?[0]?.t?.search?("shape") is 0 and not _.find(localShapes, bn: args[0].state[0].t)
|
shadowTween = shadowTween or args[0]?.state?[0]?.t?.search?('shape') is 0 and not _.find(localShapes, bn: args[0].state[0].t)
|
||||||
if shadowTween
|
if shadowTween
|
||||||
console.log "Skipping tween", name, argsSource, args, "from localShapes", localShapes, "presumably because it's a shadow we skipped."
|
console.log 'Skipping tween', name, argsSource, args, 'from localShapes', localShapes, 'presumably because it\'s a shadow we skipped.'
|
||||||
return
|
return
|
||||||
callExpressions.push {n: name, a: args}
|
callExpressions.push {n: name, a: args}
|
||||||
@walk node.parent.parent, null, gatherCallExpressions
|
@walk node.parent.parent, null, gatherCallExpressions
|
||||||
|
@ -395,7 +395,7 @@ module.exports = class SpriteParser
|
||||||
block = block.expression.object.right.body
|
block = block.expression.object.right.body
|
||||||
localArgs = []
|
localArgs = []
|
||||||
gatherAddChildCalls = (node) =>
|
gatherAddChildCalls = (node) =>
|
||||||
return unless node.type is "Identifier" and node.name is "addChild"
|
return unless node.type is 'Identifier' and node.name is 'addChild'
|
||||||
args = node.parent.parent.arguments
|
args = node.parent.parent.arguments
|
||||||
args = (arg.property.name for arg in args)
|
args = (arg.property.name for arg in args)
|
||||||
localArgs.push arg for arg in args
|
localArgs.push arg for arg in args
|
||||||
|
@ -427,18 +427,18 @@ var p; // shortcut to reference prototypes
|
||||||
|
|
||||||
// Layer 7
|
// Layer 7
|
||||||
this.shape = new cjs.Shape();
|
this.shape = new cjs.Shape();
|
||||||
this.shape.graphics.f("#4F6877").s().p("AgsAxQgSgVgB");
|
this.shape.graphics.f('#4F6877').s().p('AgsAxQgSgVgB');
|
||||||
this.shape.setTransform(283.1,146.1);
|
this.shape.setTransform(283.1,146.1);
|
||||||
|
|
||||||
// Layer 7 2
|
// Layer 7 2
|
||||||
this.shape_1 = new cjs.Shape();
|
this.shape_1 = new cjs.Shape();
|
||||||
this.shape_1.graphics.f("rgba(255,255,255,0.4)").s().p("ArTs0QSMB7EbVGQhsBhiGBHQjg1IvVkhg");
|
this.shape_1.graphics.f('rgba(255,255,255,0.4)').s().p('ArTs0QSMB7EbVGQhsBhiGBHQjg1IvVkhg');
|
||||||
this.shape_1.setTransform(400.2,185.5);
|
this.shape_1.setTransform(400.2,185.5);
|
||||||
|
|
||||||
this.timeline.addTween(cjs.Tween.get({}).to({state:[]}).to({state:[{t:this.shape}]},7).to({state:[]},2).wait(6));
|
this.timeline.addTween(cjs.Tween.get({}).to({state:[]}).to({state:[{t:this.shape}]},7).to({state:[]},2).wait(6));
|
||||||
|
|
||||||
// Wing
|
// Wing
|
||||||
this.instance_9 = new lib.Wing_Animation("synched",0);
|
this.instance_9 = new lib.Wing_Animation('synched',0);
|
||||||
this.instance_9.setTransform(313.9,145.6,1,1,0,0,0,49,-83.5);
|
this.instance_9.setTransform(313.9,145.6,1,1,0,0,0,49,-83.5);
|
||||||
|
|
||||||
this.timeline.addTween(cjs.Tween.get(this.instance_9).to({y:128,startPosition:7},7).wait(1));
|
this.timeline.addTween(cjs.Tween.get(this.instance_9).to({y:128,startPosition:7},7).wait(1));
|
||||||
|
@ -455,11 +455,11 @@ p.nominalBounds = new cjs.Rectangle(7.1,48.9,528.7,431.1);
|
||||||
|
|
||||||
// Isolation Mode
|
// Isolation Mode
|
||||||
this.shape = new cjs.Shape();
|
this.shape = new cjs.Shape();
|
||||||
this.shape.graphics.f("#1D2226").s().p("AgVAwQgUgdgN");
|
this.shape.graphics.f('#1D2226').s().p('AgVAwQgUgdgN');
|
||||||
this.shape.setTransform(75,25.8);
|
this.shape.setTransform(75,25.8);
|
||||||
|
|
||||||
this.shape_1 = new cjs.Shape();
|
this.shape_1 = new cjs.Shape();
|
||||||
this.shape_1.graphics.f("#1D2226").s().p("AgnBXQACABAF");
|
this.shape_1.graphics.f('#1D2226').s().p('AgnBXQACABAF');
|
||||||
this.shape_1.setTransform(80.8,22);
|
this.shape_1.setTransform(80.8,22);
|
||||||
|
|
||||||
this.addChild(this.shape_1,this.shape);
|
this.addChild(this.shape_1,this.shape);
|
||||||
|
@ -471,15 +471,15 @@ p.nominalBounds = new cjs.Rectangle(5.8,0,87.9,85);
|
||||||
|
|
||||||
// Layer 1
|
// Layer 1
|
||||||
this.shape = new cjs.Shape();
|
this.shape = new cjs.Shape();
|
||||||
this.shape.graphics.f("#DBDDBC").s().p("Ag3BeQgCgRA");
|
this.shape.graphics.f('#DBDDBC').s().p('Ag3BeQgCgRA');
|
||||||
this.shape.setTransform(10.6,19.7,1.081,1.081);
|
this.shape.setTransform(10.6,19.7,1.081,1.081);
|
||||||
|
|
||||||
this.shape_1 = new cjs.Shape();
|
this.shape_1 = new cjs.Shape();
|
||||||
this.shape_1.graphics.f("#1D2226").s().p("AB4CDQgGg");
|
this.shape_1.graphics.f('#1D2226').s().p('AB4CDQgGg');
|
||||||
this.shape_1.setTransform(19.9,17.6,1.081,1.081);
|
this.shape_1.setTransform(19.9,17.6,1.081,1.081);
|
||||||
|
|
||||||
this.shape_2 = new cjs.Shape();
|
this.shape_2 = new cjs.Shape();
|
||||||
this.shape_2.graphics.f("#605E4A").s().p("AiECbQgRg");
|
this.shape_2.graphics.f('#605E4A').s().p('AiECbQgRg');
|
||||||
this.shape_2.setTransform(19.5,18.4,1.081,1.081);
|
this.shape_2.setTransform(19.5,18.4,1.081,1.081);
|
||||||
|
|
||||||
this.addChild(this.shape_2,this.shape_1,this.shape);
|
this.addChild(this.shape_2,this.shape_1,this.shape);
|
||||||
|
|
|
@ -8,7 +8,7 @@ d2r = (degrees) -> degrees / 180 * Math.PI
|
||||||
MAX_ZOOM = 8
|
MAX_ZOOM = 8
|
||||||
MIN_ZOOM = 0.1
|
MIN_ZOOM = 0.1
|
||||||
DEFAULT_ZOOM = 2.0
|
DEFAULT_ZOOM = 2.0
|
||||||
DEFAULT_TARGET = {x:0, y:0}
|
DEFAULT_TARGET = {x: 0, y: 0}
|
||||||
DEFAULT_TIME = 1000
|
DEFAULT_TIME = 1000
|
||||||
STANDARD_ZOOM_WIDTH = 924
|
STANDARD_ZOOM_WIDTH = 924
|
||||||
STANDARD_ZOOM_HEIGHT = 589
|
STANDARD_ZOOM_HEIGHT = 589
|
||||||
|
@ -78,7 +78,7 @@ module.exports = class Camera extends CocoClass
|
||||||
console.log "Restricted given horizontal field of view to #{r2d(hFOV)} to #{r2d(@hFOV)}."
|
console.log "Restricted given horizontal field of view to #{r2d(hFOV)} to #{r2d(@hFOV)}."
|
||||||
@vFOV = 2 * Math.atan(Math.tan(@hFOV / 2) * @canvasHeight / @canvasWidth)
|
@vFOV = 2 * Math.atan(Math.tan(@hFOV / 2) * @canvasHeight / @canvasWidth)
|
||||||
if @vFOV > Math.PI
|
if @vFOV > Math.PI
|
||||||
console.log "Vertical field of view problem: expected canvas not to be taller than it is wide with high field of view."
|
console.log 'Vertical field of view problem: expected canvas not to be taller than it is wide with high field of view.'
|
||||||
@vFOV = Math.PI - epsilon
|
@vFOV = Math.PI - epsilon
|
||||||
|
|
||||||
calculateAxisConversionFactors: ->
|
calculateAxisConversionFactors: ->
|
||||||
|
@ -210,9 +210,9 @@ module.exports = class Camera extends CocoClass
|
||||||
right = Math.max(worldBounds[0].x, worldBounds[1].x)
|
right = Math.max(worldBounds[0].x, worldBounds[1].x)
|
||||||
bottom -= 1 if top is bottom
|
bottom -= 1 if top is bottom
|
||||||
right += 1 if left is right
|
right += 1 if left is right
|
||||||
p1 = @worldToSurface({x:left, y:top})
|
p1 = @worldToSurface({x: left, y: top})
|
||||||
p2 = @worldToSurface({x:right, y:bottom})
|
p2 = @worldToSurface({x: right, y: bottom})
|
||||||
{x:p1.x, y:p1.y, width:p2.x-p1.x, height:p2.y-p1.y}
|
{x: p1.x, y: p1.y, width: p2.x-p1.x, height: p2.y-p1.y}
|
||||||
|
|
||||||
calculateMinMaxZoom: ->
|
calculateMinMaxZoom: ->
|
||||||
# Zoom targets are always done in Surface coordinates.
|
# Zoom targets are always done in Surface coordinates.
|
||||||
|
@ -314,6 +314,7 @@ module.exports = class Camera extends CocoClass
|
||||||
lock: ->
|
lock: ->
|
||||||
@target = @currentTarget
|
@target = @currentTarget
|
||||||
@locked = true
|
@locked = true
|
||||||
|
|
||||||
unlock: ->
|
unlock: ->
|
||||||
@locked = false
|
@locked = false
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,6 @@ module.exports = class CameraBorder extends createjs.Container
|
||||||
i = width
|
i = width
|
||||||
while i
|
while i
|
||||||
opacity = 3 * (1 - (i/width)) / width
|
opacity = 3 * (1 - (i/width)) / width
|
||||||
@border.graphics.setStrokeStyle(i,"round").beginStroke("rgba(0,0,0,#{opacity})").drawRect(bounds.x, bounds.y, bounds.width, bounds.height)
|
@border.graphics.setStrokeStyle(i, 'round').beginStroke("rgba(0,0,0,#{opacity})").drawRect(bounds.x, bounds.y, bounds.width, bounds.height)
|
||||||
i -= 1
|
i -= 1
|
||||||
@border.cache bounds.x, bounds.y, bounds.width, bounds.height
|
@border.cache bounds.x, bounds.y, bounds.width, bounds.height
|
||||||
|
|
|
@ -11,21 +11,21 @@ module.exports = class CastingScreen extends CocoClass
|
||||||
options ?= {}
|
options ?= {}
|
||||||
@camera = options.camera
|
@camera = options.camera
|
||||||
@layer = options.layer
|
@layer = options.layer
|
||||||
console.error @toString(), "needs a camera." unless @camera
|
console.error @toString(), 'needs a camera.' unless @camera
|
||||||
console.error @toString(), "needs a layer." unless @layer
|
console.error @toString(), 'needs a layer.' unless @layer
|
||||||
@build()
|
@build()
|
||||||
|
|
||||||
onCastingBegins: (e) -> @show() unless e.preload
|
onCastingBegins: (e) -> @show() unless e.preload
|
||||||
onCastingEnds: (e) -> @hide()
|
onCastingEnds: (e) -> @hide()
|
||||||
|
|
||||||
toString: -> "<CastingScreen>"
|
toString: -> '<CastingScreen>'
|
||||||
|
|
||||||
build: ->
|
build: ->
|
||||||
@dimLayer = new createjs.Container()
|
@dimLayer = new createjs.Container()
|
||||||
@dimLayer.mouseEnabled = @dimLayer.mouseChildren = false
|
@dimLayer.mouseEnabled = @dimLayer.mouseChildren = false
|
||||||
@dimLayer.layerIndex = -11
|
@dimLayer.layerIndex = -11
|
||||||
@dimLayer.addChild @dimScreen = new createjs.Shape()
|
@dimLayer.addChild @dimScreen = new createjs.Shape()
|
||||||
@dimScreen.graphics.beginFill("rgba(0,0,0,0.5)").rect 0, 0, @camera.canvasWidth, @camera.canvasHeight
|
@dimScreen.graphics.beginFill('rgba(0,0,0,0.5)').rect 0, 0, @camera.canvasWidth, @camera.canvasHeight
|
||||||
@dimLayer.alpha = 0
|
@dimLayer.alpha = 0
|
||||||
@layer.addChild @dimLayer
|
@layer.addChild @dimLayer
|
||||||
@dimLayer.addChild @makeProgressBar()
|
@dimLayer.addChild @makeProgressBar()
|
||||||
|
@ -34,7 +34,7 @@ module.exports = class CastingScreen extends CocoClass
|
||||||
onWorldLoadProgressChanged: (e) ->
|
onWorldLoadProgressChanged: (e) ->
|
||||||
if new Date().getTime() - @t0 > 500
|
if new Date().getTime() - @t0 > 500
|
||||||
createjs.Tween.removeTweens @progressBar
|
createjs.Tween.removeTweens @progressBar
|
||||||
createjs.Tween.get(@progressBar).to({scaleX:e.progress}, 200)
|
createjs.Tween.get(@progressBar).to({scaleX: e.progress}, 200)
|
||||||
|
|
||||||
makeProgressBar: ->
|
makeProgressBar: ->
|
||||||
BAR_PIXEL_HEIGHT = 3
|
BAR_PIXEL_HEIGHT = 3
|
||||||
|
@ -44,8 +44,8 @@ module.exports = class CastingScreen extends CocoClass
|
||||||
barY = 3 * (@camera.canvasHeight / 5)
|
barY = 3 * (@camera.canvasHeight / 5)
|
||||||
|
|
||||||
g = new createjs.Graphics()
|
g = new createjs.Graphics()
|
||||||
g.beginFill(createjs.Graphics.getRGB(255,255, 255))
|
g.beginFill(createjs.Graphics.getRGB(255, 255, 255))
|
||||||
g.drawRoundRect(0,0,pixelWidth, BAR_PIXEL_HEIGHT, 3)
|
g.drawRoundRect(0, 0, pixelWidth, BAR_PIXEL_HEIGHT, 3)
|
||||||
@progressBar = new createjs.Shape(g)
|
@progressBar = new createjs.Shape(g)
|
||||||
@progressBar.x = pixelMargin
|
@progressBar.x = pixelMargin
|
||||||
@progressBar.y = barY
|
@progressBar.y = barY
|
||||||
|
@ -54,7 +54,7 @@ module.exports = class CastingScreen extends CocoClass
|
||||||
|
|
||||||
makeCastingText: ->
|
makeCastingText: ->
|
||||||
size = @camera.canvasHeight / 15
|
size = @camera.canvasHeight / 15
|
||||||
text = new createjs.Text("Casting", "#{size}px cursive", "#aaaaaa")
|
text = new createjs.Text('Casting', "#{size}px cursive", '#aaaaaa')
|
||||||
text.regX = text.getMeasuredWidth() / 2
|
text.regX = text.getMeasuredWidth() / 2
|
||||||
text.regY = text.getMeasuredHeight() / 2
|
text.regY = text.getMeasuredHeight() / 2
|
||||||
text.x = @camera.canvasWidth / 2
|
text.x = @camera.canvasWidth / 2
|
||||||
|
@ -70,7 +70,7 @@ module.exports = class CastingScreen extends CocoClass
|
||||||
@progressBar.scaleX = 0
|
@progressBar.scaleX = 0
|
||||||
@dimLayer.alpha = 0
|
@dimLayer.alpha = 0
|
||||||
createjs.Tween.removeTweens @dimLayer
|
createjs.Tween.removeTweens @dimLayer
|
||||||
createjs.Tween.get(@dimLayer).to({alpha:1}, 500)
|
createjs.Tween.get(@dimLayer).to({alpha: 1}, 500)
|
||||||
|
|
||||||
hide: ->
|
hide: ->
|
||||||
return unless @showing
|
return unless @showing
|
||||||
|
@ -78,4 +78,4 @@ module.exports = class CastingScreen extends CocoClass
|
||||||
|
|
||||||
createjs.Tween.removeTweens @progressBar
|
createjs.Tween.removeTweens @progressBar
|
||||||
createjs.Tween.removeTweens @dimLayer
|
createjs.Tween.removeTweens @dimLayer
|
||||||
createjs.Tween.get(@dimLayer).to({alpha:0}, 500)
|
createjs.Tween.get(@dimLayer).to({alpha: 0}, 500)
|
||||||
|
|
|
@ -65,7 +65,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
super()
|
super()
|
||||||
@options = _.extend($.extend(true, {}, @options), options)
|
@options = _.extend($.extend(true, {}, @options), options)
|
||||||
@setThang @options.thang
|
@setThang @options.thang
|
||||||
console.error @toString(), "has no ThangType!" unless @thangType
|
console.error @toString(), 'has no ThangType!' unless @thangType
|
||||||
|
|
||||||
# this is a stub, use @setImageObject to swap it out for something else later
|
# this is a stub, use @setImageObject to swap it out for something else later
|
||||||
@imageObject = new createjs.Container
|
@imageObject = new createjs.Container
|
||||||
|
@ -94,7 +94,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
else
|
else
|
||||||
result = @buildSpriteSheet()
|
result = @buildSpriteSheet()
|
||||||
if _.isString result # async build
|
if _.isString result # async build
|
||||||
@listenToOnce @thangType, 'build-complete', @setupSprite
|
@listenToOnce @thangType, 'build-complete', @setupSprite
|
||||||
else
|
else
|
||||||
@stillLoading = false
|
@stillLoading = false
|
||||||
@actions = @thangType.getActions()
|
@actions = @thangType.getActions()
|
||||||
|
@ -171,7 +171,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
onSurfaceTicked: (e) -> @age += e.dt
|
onSurfaceTicked: (e) -> @age += e.dt
|
||||||
|
|
||||||
playNextAction: =>
|
playNextAction: =>
|
||||||
@playAction(@actionQueue.splice(0,1)[0]) if @actionQueue.length
|
@playAction(@actionQueue.splice(0, 1)[0]) if @actionQueue.length
|
||||||
|
|
||||||
playAction: (action) ->
|
playAction: (action) ->
|
||||||
return if @isRaster
|
return if @isRaster
|
||||||
|
@ -180,7 +180,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
@show()
|
@show()
|
||||||
@updateBaseScale()
|
@updateBaseScale()
|
||||||
return @updateActionDirection() unless action.animation or action.container
|
return @updateActionDirection() unless action.animation or action.container
|
||||||
m = if action.container then "gotoAndStop" else "gotoAndPlay"
|
m = if action.container then 'gotoAndStop' else 'gotoAndPlay'
|
||||||
@imageObject.framerate = action.framerate or 20
|
@imageObject.framerate = action.framerate or 20
|
||||||
@imageObject[m] action.name
|
@imageObject[m] action.name
|
||||||
reg = @getOffset 'registration'
|
reg = @getOffset 'registration'
|
||||||
|
@ -235,7 +235,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
|
|
||||||
@handledDisplayEvents[event] = true
|
@handledDisplayEvents[event] = true
|
||||||
args = JSON.parse(event[4...])
|
args = JSON.parse(event[4...])
|
||||||
pos = @options.camera.worldToSurface {x:args[0], y:args[1]}
|
pos = @options.camera.worldToSurface {x: args[0], y: args[1]}
|
||||||
circle = new createjs.Shape()
|
circle = new createjs.Shape()
|
||||||
circle.graphics.beginFill(args[3]).drawCircle(0, 0, args[2]*Camera.PPM)
|
circle.graphics.beginFill(args[3]).drawCircle(0, 0, args[2]*Camera.PPM)
|
||||||
circle.x = pos.x
|
circle.x = pos.x
|
||||||
|
@ -270,18 +270,17 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
window.labels.push label
|
window.labels.push label
|
||||||
label.alpha = 0
|
label.alpha = 0
|
||||||
createjs.Tween.get(label)
|
createjs.Tween.get(label)
|
||||||
.to({y:label.y-2, alpha:1}, 200, createjs.Ease.linear)
|
.to({y: label.y-2, alpha: 1}, 200, createjs.Ease.linear)
|
||||||
.to({y:label.y-12}, 1000, createjs.Ease.linear)
|
.to({y: label.y-12}, 1000, createjs.Ease.linear)
|
||||||
.to({y:label.y-22, alpha:0}, 1000, createjs.Ease.linear)
|
.to({y: label.y-22, alpha: 0}, 1000, createjs.Ease.linear)
|
||||||
.call =>
|
.call =>
|
||||||
return if @destroyed
|
return if @destroyed
|
||||||
@options.floatingLayer.removeChild label
|
@options.floatingLayer.removeChild label
|
||||||
|
|
||||||
|
|
||||||
cache: ->
|
cache: ->
|
||||||
bounds = @imageObject.getBounds()
|
bounds = @imageObject.getBounds()
|
||||||
@imageObject.cache 0, 0, bounds.width, bounds.height
|
@imageObject.cache 0, 0, bounds.width, bounds.height
|
||||||
#console.log "just cached", @thang.id, "which was at", @imageObject.x, @imageObject.y, bounds.width, bounds.height, "with scale", Math.max(@imageObject.scaleX, @imageObject.scaleY)
|
#console.log 'just cached', @thang.id, 'which was at', @imageObject.x, @imageObject.y, bounds.width, bounds.height, 'with scale', Math.max(@imageObject.scaleX, @imageObject.scaleY)
|
||||||
|
|
||||||
getBobOffset: ->
|
getBobOffset: ->
|
||||||
return 0 unless @thang.bobHeight
|
return 0 unless @thang.bobHeight
|
||||||
|
@ -351,14 +350,14 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
angle = 180 - angle if angle > 90
|
angle = 180 - angle if angle > 90
|
||||||
scaleX = 0.5 + 0.5 * (90 - angle) / 90
|
scaleX = 0.5 + 0.5 * (90 - angle) / 90
|
||||||
|
|
||||||
# console.error "No thang for", @ unless @thang
|
# console.error 'No thang for', @ unless @thang
|
||||||
# TODO: support using scaleFactorX/Y from the thang object
|
# TODO: support using scaleFactorX/Y from the thang object
|
||||||
@imageObject.scaleX = @baseScaleX * @scaleFactor * scaleX
|
@imageObject.scaleX = @baseScaleX * @scaleFactor * scaleX
|
||||||
@imageObject.scaleY = @baseScaleY * @scaleFactor * scaleY
|
@imageObject.scaleY = @baseScaleY * @scaleFactor * scaleY
|
||||||
|
|
||||||
if @thang and (@thang.scaleFactor or 1) isnt @targetScaleFactor
|
if @thang and (@thang.scaleFactor or 1) isnt @targetScaleFactor
|
||||||
createjs.Tween.removeTweens(@)
|
createjs.Tween.removeTweens(@)
|
||||||
createjs.Tween.get(@).to({scaleFactor:@thang.scaleFactor or 1}, 2000, createjs.Ease.elasticOut)
|
createjs.Tween.get(@).to({scaleFactor: @thang.scaleFactor or 1}, 2000, createjs.Ease.elasticOut)
|
||||||
@targetScaleFactor = @thang.scaleFactor or 1
|
@targetScaleFactor = @thang.scaleFactor or 1
|
||||||
|
|
||||||
updateAlpha: ->
|
updateAlpha: ->
|
||||||
|
@ -410,7 +409,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
action = @determineAction()
|
action = @determineAction()
|
||||||
isDifferent = action isnt @currentRootAction or action is null
|
isDifferent = action isnt @currentRootAction or action is null
|
||||||
if not action and @thang?.actionActivated and not @stopLogging
|
if not action and @thang?.actionActivated and not @stopLogging
|
||||||
console.error "action is", action, "for", @thang?.id, "from", @currentRootAction, @thang.action, @thang.getActionName?()
|
console.error 'action is', action, 'for', @thang?.id, 'from', @currentRootAction, @thang.action, @thang.getActionName?()
|
||||||
@stopLogging = true
|
@stopLogging = true
|
||||||
@queueAction(action) if action and (isDifferent or (@thang?.actionActivated and action.name isnt 'move'))
|
@queueAction(action) if action and (isDifferent or (@thang?.actionActivated and action.name isnt 'move'))
|
||||||
@updateActionDirection()
|
@updateActionDirection()
|
||||||
|
@ -439,7 +438,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
rootAction ?= @currentRootAction
|
rootAction ?= @currentRootAction
|
||||||
return null unless relatedActions = rootAction?.relatedActions ? {}
|
return null unless relatedActions = rootAction?.relatedActions ? {}
|
||||||
rotation = @getRotation()
|
rotation = @getRotation()
|
||||||
if relatedActions["111111111111"] # has grid-surrounding-wall-based actions
|
if relatedActions['111111111111'] # has grid-surrounding-wall-based actions
|
||||||
if @wallGrid
|
if @wallGrid
|
||||||
action = ''
|
action = ''
|
||||||
tileSize = 4
|
tileSize = 4
|
||||||
|
@ -452,25 +451,25 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
wallThangs = ['outside of the map yo']
|
wallThangs = ['outside of the map yo']
|
||||||
if wallThangs.length is 0
|
if wallThangs.length is 0
|
||||||
if y is gy and x is gx
|
if y is gy and x is gx
|
||||||
action += "1" # the center wall we're placing
|
action += '1' # the center wall we're placing
|
||||||
else
|
else
|
||||||
action += "0"
|
action += '0'
|
||||||
else if wallThangs.length is 1
|
else if wallThangs.length is 1
|
||||||
action += "1"
|
action += '1'
|
||||||
else
|
else
|
||||||
console.error "Overlapping walls at", x, y, "...", wallThangs
|
console.error 'Overlapping walls at', x, y, '...', wallThangs
|
||||||
action += "1"
|
action += '1'
|
||||||
matchedAction = '111111111111'
|
matchedAction = '111111111111'
|
||||||
for relatedAction of relatedActions
|
for relatedAction of relatedActions
|
||||||
if action.match(relatedAction.replace(/\?/g, '.'))
|
if action.match(relatedAction.replace(/\?/g, '.'))
|
||||||
matchedAction = relatedAction
|
matchedAction = relatedAction
|
||||||
break
|
break
|
||||||
#console.log "returning", matchedAction, "for", @thang.id, "at", gx, gy
|
#console.log 'returning', matchedAction, 'for', @thang.id, 'at', gx, gy
|
||||||
return relatedActions[matchedAction]
|
return relatedActions[matchedAction]
|
||||||
else
|
else
|
||||||
keys = _.keys relatedActions
|
keys = _.keys relatedActions
|
||||||
index = Math.max 0, Math.floor((179 + rotation) / 360 * keys.length)
|
index = Math.max 0, Math.floor((179 + rotation) / 360 * keys.length)
|
||||||
#console.log "Showing", relatedActions[keys[index]]
|
#console.log 'Showing', relatedActions[keys[index]]
|
||||||
return relatedActions[keys[index]]
|
return relatedActions[keys[index]]
|
||||||
value = Math.abs(rotation)
|
value = Math.abs(rotation)
|
||||||
direction = null
|
direction = null
|
||||||
|
@ -510,8 +509,8 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
Backbone.Mediator.publish ourEventName, newEvent
|
Backbone.Mediator.publish ourEventName, newEvent
|
||||||
|
|
||||||
addHealthBar: ->
|
addHealthBar: ->
|
||||||
return unless @thang?.health? and "health" in (@thang?.hudProperties ? []) and @options.floatingLayer
|
return unless @thang?.health? and 'health' in (@thang?.hudProperties ? []) and @options.floatingLayer
|
||||||
healthColor = healthColors[@thang?.team] ? healthColors["neutral"]
|
healthColor = healthColors[@thang?.team] ? healthColors['neutral']
|
||||||
healthOffset = @getOffset 'aboveHead'
|
healthOffset = @getOffset 'aboveHead'
|
||||||
bar = @healthBar = createProgressBar(healthColor, healthOffset)
|
bar = @healthBar = createProgressBar(healthColor, healthOffset)
|
||||||
bar.name = 'health bar'
|
bar.name = 'health bar'
|
||||||
|
@ -660,7 +659,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
sound = e.sound ? AudioPlayer.soundForDialogue e.message, @thangType.get 'soundTriggers'
|
sound = e.sound ? AudioPlayer.soundForDialogue e.message, @thangType.get 'soundTriggers'
|
||||||
@instance?.stop()
|
@instance?.stop()
|
||||||
if @instance = @playSound sound, false
|
if @instance = @playSound sound, false
|
||||||
@instance.addEventListener "complete", -> Backbone.Mediator.publish 'dialogue-sound-completed'
|
@instance.addEventListener 'complete', -> Backbone.Mediator.publish 'dialogue-sound-completed'
|
||||||
@notifySpeechUpdated e
|
@notifySpeechUpdated e
|
||||||
|
|
||||||
onClearDialogue: (e) ->
|
onClearDialogue: (e) ->
|
||||||
|
@ -714,7 +713,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
delay = if withDelay and sound.delay then 1000 * sound.delay / createjs.Ticker.getFPS() else 0
|
delay = if withDelay and sound.delay then 1000 * sound.delay / createjs.Ticker.getFPS() else 0
|
||||||
name = AudioPlayer.nameForSoundReference sound
|
name = AudioPlayer.nameForSoundReference sound
|
||||||
instance = AudioPlayer.playSound name, volume, delay, @getWorldPosition()
|
instance = AudioPlayer.playSound name, volume, delay, @getWorldPosition()
|
||||||
#console.log @thang?.id, "played sound", name, "with delay", delay, "volume", volume, "and got sound instance", instance
|
#console.log @thang?.id, 'played sound', name, 'with delay', delay, 'volume', volume, 'and got sound instance', instance
|
||||||
instance
|
instance
|
||||||
|
|
||||||
onMove: (e) ->
|
onMove: (e) ->
|
||||||
|
@ -723,7 +722,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
if _.isArray pos
|
if _.isArray pos
|
||||||
pos = new Vector pos...
|
pos = new Vector pos...
|
||||||
else if _.isString pos
|
else if _.isString pos
|
||||||
return console.warn "Couldn't find target sprite", pos, "from", @options.sprites unless pos of @options.sprites
|
return console.warn 'Couldn\'t find target sprite', pos, 'from', @options.sprites unless pos of @options.sprites
|
||||||
target = @options.sprites[pos].thang
|
target = @options.sprites[pos].thang
|
||||||
heading = Vector.subtract(target.pos, @thang.pos).normalize()
|
heading = Vector.subtract(target.pos, @thang.pos).normalize()
|
||||||
distance = @thang.pos.distance target.pos
|
distance = @thang.pos.distance target.pos
|
||||||
|
@ -766,7 +765,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
|
|
||||||
@lastTween = createjs.Tween
|
@lastTween = createjs.Tween
|
||||||
.get(@shadow.pos)
|
.get(@shadow.pos)
|
||||||
.to({x:pos.x, y:pos.y}, duration, ease)
|
.to({x: pos.x, y: pos.y}, duration, ease)
|
||||||
.call(endFunc)
|
.call(endFunc)
|
||||||
|
|
||||||
pointToward: (pos) ->
|
pointToward: (pos) ->
|
||||||
|
|
|
@ -11,7 +11,7 @@ module.exports = class CoordinateDisplay extends createjs.Container
|
||||||
super()
|
super()
|
||||||
@initialize()
|
@initialize()
|
||||||
@camera = options.camera
|
@camera = options.camera
|
||||||
console.error "CoordinateDisplay needs camera." unless @camera
|
console.error 'CoordinateDisplay needs camera.' unless @camera
|
||||||
@build()
|
@build()
|
||||||
@show = _.debounce @show, 125
|
@show = _.debounce @show, 125
|
||||||
Backbone.Mediator.subscribe(channel, @[func], @) for channel, func of @subscriptions
|
Backbone.Mediator.subscribe(channel, @[func], @) for channel, func of @subscriptions
|
||||||
|
@ -24,10 +24,10 @@ module.exports = class CoordinateDisplay extends createjs.Container
|
||||||
build: ->
|
build: ->
|
||||||
@mouseEnabled = @mouseChildren = false
|
@mouseEnabled = @mouseChildren = false
|
||||||
@addChild @background = new createjs.Shape()
|
@addChild @background = new createjs.Shape()
|
||||||
@addChild @label = new createjs.Text("", "bold 16px Arial", "#FFFFFF")
|
@addChild @label = new createjs.Text('', 'bold 16px Arial', '#FFFFFF')
|
||||||
@label.name = 'Coordinate Display Text'
|
@label.name = 'Coordinate Display Text'
|
||||||
@label.shadow = new createjs.Shadow("#000000", 1, 1, 0)
|
@label.shadow = new createjs.Shadow('#000000', 1, 1, 0)
|
||||||
@background.name = "Coordinate Display Background"
|
@background.name = 'Coordinate Display Background'
|
||||||
|
|
||||||
onMouseOver: (e) -> @mouseInBounds = true
|
onMouseOver: (e) -> @mouseInBounds = true
|
||||||
onMouseOut: (e) -> @mouseInBounds = false
|
onMouseOut: (e) -> @mouseInBounds = false
|
||||||
|
@ -71,8 +71,8 @@ module.exports = class CoordinateDisplay extends createjs.Container
|
||||||
@label.regY = @background.regY = height / 2 - margin
|
@label.regY = @background.regY = height / 2 - margin
|
||||||
@background.graphics
|
@background.graphics
|
||||||
.clear()
|
.clear()
|
||||||
.beginFill("rgba(0, 0, 0, 0.4)")
|
.beginFill('rgba(0,0,0,0.4)')
|
||||||
.beginStroke("rgba(0, 0, 0, 0.6)")
|
.beginStroke('rgba(0,0,0,0.6)')
|
||||||
.setStrokeStyle(1)
|
.setStrokeStyle(1)
|
||||||
.drawRoundRect(0, 0, width, height, radius)
|
.drawRoundRect(0, 0, width, height, radius)
|
||||||
.endFill()
|
.endFill()
|
||||||
|
|
|
@ -8,7 +8,7 @@ module.exports = class DebugDisplay extends createjs.Container
|
||||||
@initialize()
|
@initialize()
|
||||||
@canvasWidth = options.canvasWidth
|
@canvasWidth = options.canvasWidth
|
||||||
@canvasHeight = options.canvasHeight
|
@canvasHeight = options.canvasHeight
|
||||||
console.error "DebugDisplay needs canvasWidth/Height." unless @canvasWidth and @canvasHeight
|
console.error 'DebugDisplay needs canvasWidth/Height.' unless @canvasWidth and @canvasHeight
|
||||||
@build()
|
@build()
|
||||||
@onSetDebug debug: true
|
@onSetDebug debug: true
|
||||||
Backbone.Mediator.subscribe(channel, @[func], @) for channel, func of @subscriptions
|
Backbone.Mediator.subscribe(channel, @[func], @) for channel, func of @subscriptions
|
||||||
|
@ -25,7 +25,7 @@ module.exports = class DebugDisplay extends createjs.Container
|
||||||
|
|
||||||
build: ->
|
build: ->
|
||||||
@mouseEnabled = @mouseChildren = false
|
@mouseEnabled = @mouseChildren = false
|
||||||
@addChild @frameText = new createjs.Text "...", "20px Arial", "#FFF"
|
@addChild @frameText = new createjs.Text '...', '20px Arial', '#FFF'
|
||||||
@frameText.name = 'frame text'
|
@frameText.name = 'frame text'
|
||||||
@frameText.x = @canvasWidth - 50
|
@frameText.x = @canvasWidth - 50
|
||||||
@frameText.y = @canvasHeight - 25
|
@frameText.y = @canvasHeight - 25
|
||||||
|
@ -41,5 +41,5 @@ module.exports = class DebugDisplay extends createjs.Container
|
||||||
@lastFrameSecondStart = time
|
@lastFrameSecondStart = time
|
||||||
@framesRenderedThisSecond = 0
|
@framesRenderedThisSecond = 0
|
||||||
|
|
||||||
@frameText.text = Math.round(currentFrame) + (if @fps? then " - " + @fps + ' fps' else '')
|
@frameText.text = Math.round(currentFrame) + (if @fps? then ' - ' + @fps + ' fps' else '')
|
||||||
@frameText.x = @canvasWidth - @frameText.getMeasuredWidth() - 10
|
@frameText.x = @canvasWidth - @frameText.getMeasuredWidth() - 10
|
||||||
|
|
|
@ -14,14 +14,14 @@ module.exports = class Dimmer extends CocoClass
|
||||||
options ?= {}
|
options ?= {}
|
||||||
@camera = options.camera
|
@camera = options.camera
|
||||||
@layer = options.layer
|
@layer = options.layer
|
||||||
console.error @toString(), "needs a camera." unless @camera
|
console.error @toString(), 'needs a camera.' unless @camera
|
||||||
console.error @toString(), "needs a layer." unless @layer
|
console.error @toString(), 'needs a layer.' unless @layer
|
||||||
@build()
|
@build()
|
||||||
@updateDimMask = _.throttle @updateDimMask, 10
|
@updateDimMask = _.throttle @updateDimMask, 10
|
||||||
@highlightedThangIDs = []
|
@highlightedThangIDs = []
|
||||||
@sprites = {}
|
@sprites = {}
|
||||||
|
|
||||||
toString: -> "<Dimmer>"
|
toString: -> '<Dimmer>'
|
||||||
|
|
||||||
build: ->
|
build: ->
|
||||||
@dimLayer = new createjs.Container()
|
@dimLayer = new createjs.Container()
|
||||||
|
@ -29,7 +29,7 @@ module.exports = class Dimmer extends CocoClass
|
||||||
@dimLayer.layerIndex = -10
|
@dimLayer.layerIndex = -10
|
||||||
@dimLayer.addChild @dimScreen = new createjs.Shape()
|
@dimLayer.addChild @dimScreen = new createjs.Shape()
|
||||||
@dimLayer.addChild @dimMask = new createjs.Shape()
|
@dimLayer.addChild @dimMask = new createjs.Shape()
|
||||||
@dimScreen.graphics.beginFill("rgba(0,0,0,0.5)").rect 0, 0, @camera.canvasWidth, @camera.canvasHeight
|
@dimScreen.graphics.beginFill('rgba(0,0,0,0.5)').rect 0, 0, @camera.canvasWidth, @camera.canvasHeight
|
||||||
@dimMask.compositeOperation = 'destination-out'
|
@dimMask.compositeOperation = 'destination-out'
|
||||||
@dimLayer.cache 0, 0, @camera.canvasWidth, @camera.canvasHeight
|
@dimLayer.cache 0, 0, @camera.canvasWidth, @camera.canvasHeight
|
||||||
|
|
||||||
|
@ -70,6 +70,6 @@ module.exports = class Dimmer extends CocoClass
|
||||||
sup = x: sprite.imageObject.x, y: sprite.imageObject.y
|
sup = x: sprite.imageObject.x, y: sprite.imageObject.y
|
||||||
cap = @camera.surfaceToCanvas sup
|
cap = @camera.surfaceToCanvas sup
|
||||||
r = 50 * @camera.zoom # TODO: find better way to get the radius based on the sprite's size
|
r = 50 * @camera.zoom # TODO: find better way to get the radius based on the sprite's size
|
||||||
@dimMask.graphics.beginRadialGradientFill(["rgba(0,0,0,1)", "rgba(0,0,0,0)"], [0.5, 1], cap.x, cap.y, 0, cap.x, cap.y, r).drawCircle(cap.x, cap.y, r)
|
@dimMask.graphics.beginRadialGradientFill(['rgba(0,0,0,1)', 'rgba(0,0,0,0)'], [0.5, 1], cap.x, cap.y, 0, cap.x, cap.y, r).drawCircle(cap.x, cap.y, r)
|
||||||
|
|
||||||
@dimLayer.updateCache 0, 0, @camera.canvasWidth, @camera.canvasHeight
|
@dimLayer.updateCache 0, 0, @camera.canvasWidth, @camera.canvasHeight
|
||||||
|
|
|
@ -25,5 +25,4 @@ Dropper = class Dropper
|
||||||
drop: ->
|
drop: ->
|
||||||
return @drop_counter > 0
|
return @drop_counter > 0
|
||||||
|
|
||||||
|
|
||||||
module.exports = new Dropper()
|
module.exports = new Dropper()
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
CocoClass = require 'lib/CocoClass'
|
CocoClass = require 'lib/CocoClass'
|
||||||
|
|
||||||
module.exports = class Label extends CocoClass
|
module.exports = class Label extends CocoClass
|
||||||
@STYLE_DIALOGUE = "dialogue" # A speech bubble from a script
|
@STYLE_DIALOGUE = 'dialogue' # A speech bubble from a script
|
||||||
@STYLE_SAY = "say" # A piece of text generated from the world
|
@STYLE_SAY = 'say' # A piece of text generated from the world
|
||||||
@STYLE_NAME = "name" # A name like Scott set up for the Wizard
|
@STYLE_NAME = 'name' # A name like Scott set up for the Wizard
|
||||||
# We might want to combine 'say' and 'name'; they're very similar
|
# We might want to combine 'say' and 'name'; they're very similar
|
||||||
# Nick designed 'say' based off of Scott's 'name' back when they were using two systems
|
# Nick designed 'say' based off of Scott's 'name' back when they were using two systems
|
||||||
|
|
||||||
|
@ -16,9 +16,9 @@ module.exports = class Label extends CocoClass
|
||||||
@camera = options.camera
|
@camera = options.camera
|
||||||
@layer = options.layer
|
@layer = options.layer
|
||||||
@style = options.style ? Label.STYLE_SAY
|
@style = options.style ? Label.STYLE_SAY
|
||||||
console.error @toString(), "needs a sprite." unless @sprite
|
console.error @toString(), 'needs a sprite.' unless @sprite
|
||||||
console.error @toString(), "needs a camera." unless @camera
|
console.error @toString(), 'needs a camera.' unless @camera
|
||||||
console.error @toString(), "needs a layer." unless @layer
|
console.error @toString(), 'needs a layer.' unless @layer
|
||||||
@setText options.text if options.text
|
@setText options.text if options.text
|
||||||
|
|
||||||
destroy: ->
|
destroy: ->
|
||||||
|
@ -58,15 +58,15 @@ module.exports = class Label extends CocoClass
|
||||||
st = {dialogue: 'D', say: 'S', name: 'N'}[@style]
|
st = {dialogue: 'D', say: 'S', name: 'N'}[@style]
|
||||||
o.marginX = {D: 5, S: 6, N: 3}[st]
|
o.marginX = {D: 5, S: 6, N: 3}[st]
|
||||||
o.marginY = {D: 6, S: 4, N: 3}[st]
|
o.marginY = {D: 6, S: 4, N: 3}[st]
|
||||||
o.fontWeight = {D: "bold", S: "bold", N: "bold"}[st]
|
o.fontWeight = {D: 'bold', S: 'bold', N: 'bold'}[st]
|
||||||
o.shadow = {D: false, S: true, N: true}[st]
|
o.shadow = {D: false, S: true, N: true}[st]
|
||||||
o.shadowColor = {D: "#FFF", S: "#000", N: "#FFF"}[st]
|
o.shadowColor = {D: '#FFF', S: '#000', N: '#FFF'}[st]
|
||||||
o.fontSize = {D: 25, S: 12, N: 12}[st]
|
o.fontSize = {D: 25, S: 12, N: 12}[st]
|
||||||
fontFamily = {D: "Arial", S: "Arial", N: "Arial"}[st]
|
fontFamily = {D: 'Arial', S: 'Arial', N: 'Arial'}[st]
|
||||||
o.fontDescriptor = "#{o.fontWeight} #{o.fontSize}px #{fontFamily}"
|
o.fontDescriptor = "#{o.fontWeight} #{o.fontSize}px #{fontFamily}"
|
||||||
o.fontColor = {D: "#000", S: "#FFF", N: "#00a"}[st]
|
o.fontColor = {D: '#000', S: '#FFF', N: '#00a'}[st]
|
||||||
o.backgroundFillColor = {D: "white", S: "rgba(0, 0, 0, 0.4)", N: "rgba(255, 255, 255, 0.5)"}[st]
|
o.backgroundFillColor = {D: 'white', S: 'rgba(0,0,0,0.4)', N: 'rgba(255,255,255,0.5)'}[st]
|
||||||
o.backgroundStrokeColor = {D: "black", S: "rgba(0, 0, 0, .6)", N: "rgba(0, 0, 0, 0.0)"}[st]
|
o.backgroundStrokeColor = {D: 'black', S: 'rgba(0,0,0,0.6)', N: 'rgba(0,0,0,0)'}[st]
|
||||||
o.backgroundStrokeStyle = {D: 2, S: 1, N: 1}[st]
|
o.backgroundStrokeStyle = {D: 2, S: 1, N: 1}[st]
|
||||||
o.backgroundBorderRadius = {D: 10, S: 3, N: 3}[st]
|
o.backgroundBorderRadius = {D: 10, S: 3, N: 3}[st]
|
||||||
o.layerPriority = {D: 10, S: 5, N: 5}[st]
|
o.layerPriority = {D: 10, S: 5, N: 5}[st]
|
||||||
|
@ -169,7 +169,7 @@ module.exports = class Label extends CocoClass
|
||||||
textWidth = 0
|
textWidth = 0
|
||||||
for word in words
|
for word in words
|
||||||
row.push(word)
|
row.push(word)
|
||||||
text = new createjs.Text(_.string.join(' ', row...), fontDescriptor, "#000")
|
text = new createjs.Text(_.string.join(' ', row...), fontDescriptor, '#000')
|
||||||
width = text.getMeasuredWidth()
|
width = text.getMeasuredWidth()
|
||||||
if width > maxWidth
|
if width > maxWidth
|
||||||
if row.length is 1 # one long word, truncate it
|
if row.length is 1 # one long word, truncate it
|
||||||
|
@ -186,5 +186,5 @@ module.exports = class Label extends CocoClass
|
||||||
textWidth = Math.max(textWidth, width)
|
textWidth = Math.max(textWidth, width)
|
||||||
rows.push(row) if row.length
|
rows.push(row) if row.length
|
||||||
for row, i in rows
|
for row, i in rows
|
||||||
rows[i] = _.string.join(" ", row...)
|
rows[i] = _.string.join(' ', row...)
|
||||||
text: _.string.join("\n", rows...), textWidth: textWidth
|
text: _.string.join("\n", rows...), textWidth: textWidth
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
###
|
###
|
||||||
|
|
||||||
module.exports = class Layer extends createjs.Container
|
module.exports = class Layer extends createjs.Container
|
||||||
@TRANSFORM_CHILD = "child" # Layer transform is managed by its parents
|
@TRANSFORM_CHILD = 'child' # Layer transform is managed by its parents
|
||||||
@TRANSFORM_SURFACE = "surface" # Layer moves/scales/zooms with the Surface of the World
|
@TRANSFORM_SURFACE = 'surface' # Layer moves/scales/zooms with the Surface of the World
|
||||||
@TRANSFORM_SURFACE_TEXT = "surface_text" # Layer moves with the Surface but is size-independent
|
@TRANSFORM_SURFACE_TEXT = 'surface_text' # Layer moves with the Surface but is size-independent
|
||||||
@TRANSFORM_SCREEN = "screen" # Layer stays fixed to the screen (different from child?)
|
@TRANSFORM_SCREEN = 'screen' # Layer stays fixed to the screen (different from child?)
|
||||||
|
|
||||||
subscriptions:
|
subscriptions:
|
||||||
'camera:zoom-updated': 'onZoomUpdated'
|
'camera:zoom-updated': 'onZoomUpdated'
|
||||||
|
@ -30,11 +30,11 @@ module.exports = class Layer extends createjs.Container
|
||||||
super()
|
super()
|
||||||
@initialize()
|
@initialize()
|
||||||
options ?= {}
|
options ?= {}
|
||||||
@name = options.name ? "Unnamed"
|
@name = options.name ? 'Unnamed'
|
||||||
@layerPriority = options.layerPriority ? 0
|
@layerPriority = options.layerPriority ? 0
|
||||||
@transformStyle = options.transform ? Layer.TRANSFORM_CHILD
|
@transformStyle = options.transform ? Layer.TRANSFORM_CHILD
|
||||||
@camera = options.camera
|
@camera = options.camera
|
||||||
console.error @toString(), "needs a camera." unless @camera
|
console.error @toString(), 'needs a camera.' unless @camera
|
||||||
@updateLayerOrder = _.throttle @updateLayerOrder, 1000 / 30 # Don't call multiple times in one frame; 30 FPS is probably good enough
|
@updateLayerOrder = _.throttle @updateLayerOrder, 1000 / 30 # Don't call multiple times in one frame; 30 FPS is probably good enough
|
||||||
Backbone.Mediator.subscribe(channel, @[func], @) for channel, func of @subscriptions
|
Backbone.Mediator.subscribe(channel, @[func], @) for channel, func of @subscriptions
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ module.exports = class Layer extends createjs.Container
|
||||||
child.scaleY *= @scaleY
|
child.scaleY *= @scaleY
|
||||||
|
|
||||||
updateLayerOrder: =>
|
updateLayerOrder: =>
|
||||||
#console.log @, @toString(), "sorting children", _.clone @children if @name is 'Default'
|
#console.log @, @toString(), 'sorting children', _.clone @children if @name is 'Default'
|
||||||
@sortChildren @layerOrderComparator
|
@sortChildren @layerOrderComparator
|
||||||
|
|
||||||
layerOrderComparator: (a, b) ->
|
layerOrderComparator: (a, b) ->
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
module.exports = class Letterbox extends createjs.Container
|
module.exports = class Letterbox extends createjs.Container
|
||||||
|
|
||||||
subscriptions:
|
subscriptions:
|
||||||
'level-set-letterbox': 'onSetLetterbox'
|
'level-set-letterbox': 'onSetLetterbox'
|
||||||
|
|
||||||
|
@ -8,7 +7,7 @@ module.exports = class Letterbox extends createjs.Container
|
||||||
@initialize()
|
@initialize()
|
||||||
@canvasWidth = options.canvasWidth
|
@canvasWidth = options.canvasWidth
|
||||||
@canvasHeight = options.canvasHeight
|
@canvasHeight = options.canvasHeight
|
||||||
console.error "Letterbox needs canvasWidth/Height." unless @canvasWidth and @canvasHeight
|
console.error 'Letterbox needs canvasWidth/Height.' unless @canvasWidth and @canvasHeight
|
||||||
@build()
|
@build()
|
||||||
Backbone.Mediator.subscribe(channel, @[func], @) for channel, func of @subscriptions
|
Backbone.Mediator.subscribe(channel, @[func], @) for channel, func of @subscriptions
|
||||||
|
|
||||||
|
@ -16,7 +15,7 @@ module.exports = class Letterbox extends createjs.Container
|
||||||
@mouseEnabled = @mouseChildren = false
|
@mouseEnabled = @mouseChildren = false
|
||||||
@matteHeight = 0.10 * @canvasHeight
|
@matteHeight = 0.10 * @canvasHeight
|
||||||
@upperMatte = new createjs.Shape()
|
@upperMatte = new createjs.Shape()
|
||||||
@upperMatte.graphics.beginFill("black").rect(0, 0, @canvasWidth, @matteHeight)
|
@upperMatte.graphics.beginFill('black').rect(0, 0, @canvasWidth, @matteHeight)
|
||||||
@lowerMatte = @upperMatte.clone()
|
@lowerMatte = @upperMatte.clone()
|
||||||
@upperMatte.x = @lowerMatte.x = 0
|
@upperMatte.x = @lowerMatte.x = 0
|
||||||
@upperMatte.y = -@matteHeight
|
@upperMatte.y = -@matteHeight
|
||||||
|
|
|
@ -15,9 +15,9 @@ module.exports = class Mark extends CocoClass
|
||||||
@camera = options.camera
|
@camera = options.camera
|
||||||
@layer = options.layer
|
@layer = options.layer
|
||||||
@thangType = options.thangType
|
@thangType = options.thangType
|
||||||
console.error @toString(), "needs a name." unless @name
|
console.error @toString(), 'needs a name.' unless @name
|
||||||
console.error @toString(), "needs a camera." unless @camera
|
console.error @toString(), 'needs a camera.' unless @camera
|
||||||
console.error @toString(), "needs a layer." unless @layer
|
console.error @toString(), 'needs a layer.' unless @layer
|
||||||
@build()
|
@build()
|
||||||
|
|
||||||
destroy: ->
|
destroy: ->
|
||||||
|
@ -58,7 +58,7 @@ module.exports = class Mark extends CocoClass
|
||||||
else if @name is 'debug' then @buildDebug()
|
else if @name is 'debug' then @buildDebug()
|
||||||
else if @name.match(/.+(Range|Distance|Radius)$/) then @buildRadius(@name)
|
else if @name.match(/.+(Range|Distance|Radius)$/) then @buildRadius(@name)
|
||||||
else if @thangType then @buildSprite()
|
else if @thangType then @buildSprite()
|
||||||
else console.error "Don't know how to build mark for", @name
|
else console.error 'Don\'t know how to build mark for', @name
|
||||||
@mark?.mouseEnabled = false
|
@mark?.mouseEnabled = false
|
||||||
@
|
@
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ module.exports = class Mark extends CocoClass
|
||||||
shape.graphics.setStrokeStyle 5
|
shape.graphics.setStrokeStyle 5
|
||||||
shape.graphics.beginStroke color
|
shape.graphics.beginStroke color
|
||||||
shape.graphics.beginFill color.replace('0.5', '0.25')
|
shape.graphics.beginFill color.replace('0.5', '0.25')
|
||||||
if @sprite.thang.shape in ["ellipsoid", "disc"]
|
if @sprite.thang.shape in ['ellipsoid', 'disc']
|
||||||
shape.drawEllipse 0, 0, w, h
|
shape.drawEllipse 0, 0, w, h
|
||||||
else
|
else
|
||||||
shape.graphics.drawRect -w / 2, -h / 2, w, h
|
shape.graphics.drawRect -w / 2, -h / 2, w, h
|
||||||
|
@ -86,20 +86,20 @@ module.exports = class Mark extends CocoClass
|
||||||
@mark.addChild shape
|
@mark.addChild shape
|
||||||
|
|
||||||
if @sprite.thang.drawsBoundsStyle is 'border-text'
|
if @sprite.thang.drawsBoundsStyle is 'border-text'
|
||||||
text = new createjs.Text "" + @drawsBoundsIndex, "20px Arial", color.replace('0.5', '1')
|
text = new createjs.Text '' + @drawsBoundsIndex, '20px Arial', color.replace('0.5', '1')
|
||||||
text.regX = text.getMeasuredWidth() / 2
|
text.regX = text.getMeasuredWidth() / 2
|
||||||
text.regY = text.getMeasuredHeight() / 2
|
text.regY = text.getMeasuredHeight() / 2
|
||||||
text.shadow = new createjs.Shadow("#000000", 1, 1, 0)
|
text.shadow = new createjs.Shadow('#000000', 1, 1, 0)
|
||||||
@mark.addChild text
|
@mark.addChild text
|
||||||
else if @sprite.thang.drawsBoundsStyle is 'corner-text'
|
else if @sprite.thang.drawsBoundsStyle is 'corner-text'
|
||||||
return if @sprite.thang.world.age is 0
|
return if @sprite.thang.world.age is 0
|
||||||
letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[@drawsBoundsIndex % 26]
|
letter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[@drawsBoundsIndex % 26]
|
||||||
text = new createjs.Text letter, "14px Arial", "#333333" # color.replace('0.5', '1')
|
text = new createjs.Text letter, '14px Arial', '#333333' # color.replace('0.5', '1')
|
||||||
text.x = -w / 2 + 2
|
text.x = -w / 2 + 2
|
||||||
text.y = -h / 2 + 2
|
text.y = -h / 2 + 2
|
||||||
@mark.addChild text
|
@mark.addChild text
|
||||||
else
|
else
|
||||||
console.warn @sprite.thang.id, "didn't know how to draw bounds style:", @sprite.thang.drawsBoundsStyle
|
console.warn @sprite.thang.id, 'didn\'t know how to draw bounds style:', @sprite.thang.drawsBoundsStyle
|
||||||
|
|
||||||
if w > 0 and h > 0
|
if w > 0 and h > 0
|
||||||
@mark.cache -w / 2, -h / 2, w, h, 2
|
@mark.cache -w / 2, -h / 2, w, h, 2
|
||||||
|
@ -118,7 +118,7 @@ module.exports = class Mark extends CocoClass
|
||||||
height *= Camera.PPM * @camera.y2x # TODO: doesn't work with rotation
|
height *= Camera.PPM * @camera.y2x # TODO: doesn't work with rotation
|
||||||
@mark = new createjs.Shape()
|
@mark = new createjs.Shape()
|
||||||
@mark.mouseEnabled = false
|
@mark.mouseEnabled = false
|
||||||
@mark.graphics.beginFill "rgba(0, 0, 0, #{alpha})"
|
@mark.graphics.beginFill "rgba(0,0,0,#{alpha})"
|
||||||
if @sprite.thang.shape in ['ellipsoid', 'disc']
|
if @sprite.thang.shape in ['ellipsoid', 'disc']
|
||||||
@mark.graphics.drawEllipse 0, 0, width, height
|
@mark.graphics.drawEllipse 0, 0, width, height
|
||||||
else
|
else
|
||||||
|
@ -132,16 +132,16 @@ module.exports = class Mark extends CocoClass
|
||||||
buildRadius: (range) ->
|
buildRadius: (range) ->
|
||||||
alpha = 0.15
|
alpha = 0.15
|
||||||
colors =
|
colors =
|
||||||
voiceRange: "rgba(0, 145, 0, #{alpha})"
|
voiceRange: "rgba(0,145,0,#{alpha})"
|
||||||
visualRange: "rgba(0, 0, 145, #{alpha})"
|
visualRange: "rgba(0,0,145,#{alpha})"
|
||||||
attackRange: "rgba(145, 0, 0, #{alpha})"
|
attackRange: "rgba(145,0,0,#{alpha})"
|
||||||
|
|
||||||
# Fallback colors which work on both dungeon and grass tiles
|
# Fallback colors which work on both dungeon and grass tiles
|
||||||
extraColors = [
|
extraColors = [
|
||||||
"rgba(145, 0, 145, #{alpha})"
|
"rgba(145,0,145,#{alpha})"
|
||||||
"rgba(0, 145, 145, #{alpha})"
|
"rgba(0,145,145,#{alpha})"
|
||||||
"rgba(145, 105, 0, #{alpha})"
|
"rgba(145,105,0,#{alpha})"
|
||||||
"rgba(225, 125, 0, #{alpha})"
|
"rgba(225,125,0,#{alpha})"
|
||||||
]
|
]
|
||||||
|
|
||||||
# Find the index of this range, to find the next-smallest radius
|
# Find the index of this range, to find the next-smallest radius
|
||||||
|
@ -179,7 +179,7 @@ module.exports = class Mark extends CocoClass
|
||||||
[w, h] = [Math.max(PX, @sprite.thang.width * Camera.PPM), Math.max(PX, @sprite.thang.height * Camera.PPM) * @camera.y2x]
|
[w, h] = [Math.max(PX, @sprite.thang.width * Camera.PPM), Math.max(PX, @sprite.thang.height * Camera.PPM) * @camera.y2x]
|
||||||
@mark.alpha = 0.5
|
@mark.alpha = 0.5
|
||||||
@mark.graphics.beginFill '#abcdef'
|
@mark.graphics.beginFill '#abcdef'
|
||||||
if @sprite.thang.shape in ["ellipsoid", "disc"]
|
if @sprite.thang.shape in ['ellipsoid', 'disc']
|
||||||
[w, h] = [Math.max(PX, w, h), Math.max(PX, w, h)]
|
[w, h] = [Math.max(PX, w, h), Math.max(PX, w, h)]
|
||||||
@mark.graphics.drawCircle 0, 0, w / 2
|
@mark.graphics.drawCircle 0, 0, w / 2
|
||||||
else
|
else
|
||||||
|
@ -248,11 +248,11 @@ module.exports = class Mark extends CocoClass
|
||||||
if @name is 'shadow'
|
if @name is 'shadow'
|
||||||
worldZ = @sprite.thang.pos.z - @sprite.thang.depth / 2 + @sprite.getBobOffset()
|
worldZ = @sprite.thang.pos.z - @sprite.thang.depth / 2 + @sprite.getBobOffset()
|
||||||
@mark.alpha = @alpha * 0.451 / Math.sqrt(worldZ / 2 + 1)
|
@mark.alpha = @alpha * 0.451 / Math.sqrt(worldZ / 2 + 1)
|
||||||
else if @name isnt "bounds"
|
else if @name isnt 'bounds'
|
||||||
@mark.alpha = @alpha
|
@mark.alpha = @alpha
|
||||||
|
|
||||||
updateRotation: ->
|
updateRotation: ->
|
||||||
if @name is 'debug' or (@name is 'shadow' and @sprite.thang?.shape in ["rectangle", "box"])
|
if @name is 'debug' or (@name is 'shadow' and @sprite.thang?.shape in ['rectangle', 'box'])
|
||||||
@mark.rotation = @sprite.thang.rotation * 180 / Math.PI
|
@mark.rotation = @sprite.thang.rotation * 180 / Math.PI
|
||||||
|
|
||||||
updateScale: ->
|
updateScale: ->
|
||||||
|
@ -271,7 +271,7 @@ module.exports = class Mark extends CocoClass
|
||||||
@mark.scaleX = thang.scaleFactor ? thang.scaleFactorX ? 1
|
@mark.scaleX = thang.scaleFactor ? thang.scaleFactorX ? 1
|
||||||
@mark.scaleY = thang.scaleFactor ? thang.scaleFactorY ? 1
|
@mark.scaleY = thang.scaleFactor ? thang.scaleFactorY ? 1
|
||||||
|
|
||||||
return unless @name in ["selection", "target", "repair", "highlight"]
|
return unless @name in ['selection', 'target', 'repair', 'highlight']
|
||||||
|
|
||||||
# scale these marks to 10m (100px). Adjust based on sprite size.
|
# scale these marks to 10m (100px). Adjust based on sprite size.
|
||||||
factor = 0.3 # default size: 3m width, most commonly for target when pointing to a location
|
factor = 0.3 # default size: 3m width, most commonly for target when pointing to a location
|
||||||
|
|
|
@ -25,7 +25,7 @@ module.exports = class MusicPlayer extends CocoClass
|
||||||
if (not e.file) or src is @currentMusic?.src
|
if (not e.file) or src is @currentMusic?.src
|
||||||
if e.play then @restartCurrentMusic() else @fadeOutCurrentMusic()
|
if e.play then @restartCurrentMusic() else @fadeOutCurrentMusic()
|
||||||
return
|
return
|
||||||
|
|
||||||
media = AudioPlayer.getStatus(src)
|
media = AudioPlayer.getStatus(src)
|
||||||
if not media?.loaded
|
if not media?.loaded
|
||||||
AudioPlayer.preloadSound(src)
|
AudioPlayer.preloadSound(src)
|
||||||
|
@ -35,23 +35,23 @@ module.exports = class MusicPlayer extends CocoClass
|
||||||
@standingBy = null
|
@standingBy = null
|
||||||
@fadeOutCurrentMusic()
|
@fadeOutCurrentMusic()
|
||||||
@startNewMusic(src) if e.play
|
@startNewMusic(src) if e.play
|
||||||
|
|
||||||
restartCurrentMusic: ->
|
restartCurrentMusic: ->
|
||||||
return unless @currentMusic
|
return unless @currentMusic
|
||||||
@currentMusic.play('none', 0, 0, -1, 0.3)
|
@currentMusic.play('none', 0, 0, -1, 0.3)
|
||||||
@updateMusicVolume()
|
@updateMusicVolume()
|
||||||
|
|
||||||
fadeOutCurrentMusic: ->
|
fadeOutCurrentMusic: ->
|
||||||
return unless @currentMusic
|
return unless @currentMusic
|
||||||
f = -> @stop()
|
f = -> @stop()
|
||||||
createjs.Tween.get(@currentMusic).to({volume:0.0}, CROSSFADE_LENGTH).call(f)
|
createjs.Tween.get(@currentMusic).to({volume: 0.0}, CROSSFADE_LENGTH).call(f)
|
||||||
|
|
||||||
startNewMusic: (src) ->
|
startNewMusic: (src) ->
|
||||||
@currentMusic = createjs.Sound.play(src, 'none', 0, 0, -1, 0.3) if src
|
@currentMusic = createjs.Sound.play(src, 'none', 0, 0, -1, 0.3) if src
|
||||||
return unless @currentMusic
|
return unless @currentMusic
|
||||||
@currentMusic.volume = 0.0
|
@currentMusic.volume = 0.0
|
||||||
if me.get('music')
|
if me.get('music')
|
||||||
createjs.Tween.get(@currentMusic).to({volume:1.0}, CROSSFADE_LENGTH)
|
createjs.Tween.get(@currentMusic).to({volume: 1.0}, CROSSFADE_LENGTH)
|
||||||
|
|
||||||
onMusicSettingChanged: ->
|
onMusicSettingChanged: ->
|
||||||
@updateMusicVolume()
|
@updateMusicVolume()
|
||||||
|
@ -64,4 +64,3 @@ module.exports = class MusicPlayer extends CocoClass
|
||||||
destroy: ->
|
destroy: ->
|
||||||
me.off 'change:music', @onMusicSettingChanged, @
|
me.off 'change:music', @onMusicSettingChanged, @
|
||||||
super()
|
super()
|
||||||
|
|
|
@ -6,18 +6,18 @@ module.exports = class PlaybackOverScreen extends CocoClass
|
||||||
options ?= {}
|
options ?= {}
|
||||||
@camera = options.camera
|
@camera = options.camera
|
||||||
@layer = options.layer
|
@layer = options.layer
|
||||||
console.error @toString(), "needs a camera." unless @camera
|
console.error @toString(), 'needs a camera.' unless @camera
|
||||||
console.error @toString(), "needs a layer." unless @layer
|
console.error @toString(), 'needs a layer.' unless @layer
|
||||||
@build()
|
@build()
|
||||||
|
|
||||||
toString: -> "<PlaybackOverScreen>"
|
toString: -> '<PlaybackOverScreen>'
|
||||||
|
|
||||||
build: ->
|
build: ->
|
||||||
@dimLayer = new createjs.Container()
|
@dimLayer = new createjs.Container()
|
||||||
@dimLayer.mouseEnabled = @dimLayer.mouseChildren = false
|
@dimLayer.mouseEnabled = @dimLayer.mouseChildren = false
|
||||||
@dimLayer.layerIndex = -12
|
@dimLayer.layerIndex = -12
|
||||||
@dimLayer.addChild @dimScreen = new createjs.Shape()
|
@dimLayer.addChild @dimScreen = new createjs.Shape()
|
||||||
@dimScreen.graphics.beginFill("rgba(0,0,0,0.4)").rect 0, 0, @camera.canvasWidth, @camera.canvasHeight
|
@dimScreen.graphics.beginFill('rgba(0,0,0,0.4)').rect 0, 0, @camera.canvasWidth, @camera.canvasHeight
|
||||||
@dimLayer.cache 0, 0, @camera.canvasWidth, @camera.canvasHeight
|
@dimLayer.cache 0, 0, @camera.canvasWidth, @camera.canvasHeight
|
||||||
@dimLayer.alpha = 0
|
@dimLayer.alpha = 0
|
||||||
@layer.addChild @dimLayer
|
@layer.addChild @dimLayer
|
||||||
|
@ -28,11 +28,11 @@ module.exports = class PlaybackOverScreen extends CocoClass
|
||||||
|
|
||||||
@dimLayer.alpha = 0
|
@dimLayer.alpha = 0
|
||||||
createjs.Tween.removeTweens @dimLayer
|
createjs.Tween.removeTweens @dimLayer
|
||||||
createjs.Tween.get(@dimLayer).to({alpha:1}, 500)
|
createjs.Tween.get(@dimLayer).to({alpha: 1}, 500)
|
||||||
|
|
||||||
hide: ->
|
hide: ->
|
||||||
return unless @showing
|
return unless @showing
|
||||||
@showing = false
|
@showing = false
|
||||||
|
|
||||||
createjs.Tween.removeTweens @dimLayer
|
createjs.Tween.removeTweens @dimLayer
|
||||||
createjs.Tween.get(@dimLayer).to({alpha:0}, 500)
|
createjs.Tween.get(@dimLayer).to({alpha: 0}, 500)
|
||||||
|
|
|
@ -19,12 +19,12 @@ module.exports = class PointChooser extends CocoClass
|
||||||
@shape = new createjs.Shape()
|
@shape = new createjs.Shape()
|
||||||
@shape.alpha = 0.9
|
@shape.alpha = 0.9
|
||||||
@shape.mouseEnabled = false
|
@shape.mouseEnabled = false
|
||||||
@shape.graphics.setStrokeStyle(1, "round").beginStroke("#000000").beginFill('#fedcba')
|
@shape.graphics.setStrokeStyle(1, 'round').beginStroke('#000000').beginFill('#fedcba')
|
||||||
@shape.graphics.drawCircle(0, 0, 4).endFill()
|
@shape.graphics.drawCircle(0, 0, 4).endFill()
|
||||||
@shape.layerIndex = 100
|
@shape.layerIndex = 100
|
||||||
|
|
||||||
onMouseDown: (e) =>
|
onMouseDown: (e) =>
|
||||||
console.log "got stagemousedown", e, key.shift
|
console.log 'got stagemousedown', e, key.shift
|
||||||
return unless key.shift
|
return unless key.shift
|
||||||
@setPoint @options.camera.screenToWorld {x: e.stageX, y: e.stageY}
|
@setPoint @options.camera.screenToWorld {x: e.stageX, y: e.stageY}
|
||||||
Backbone.Mediator.publish 'choose-point', point: @point
|
Backbone.Mediator.publish 'choose-point', point: @point
|
||||||
|
|
|
@ -51,12 +51,12 @@ module.exports = class SpriteBoss extends CocoClass
|
||||||
createLayers: ->
|
createLayers: ->
|
||||||
@spriteLayers = {}
|
@spriteLayers = {}
|
||||||
for [name, priority] in [
|
for [name, priority] in [
|
||||||
["Land", -40]
|
['Land', -40]
|
||||||
["Ground", -30]
|
['Ground', -30]
|
||||||
["Obstacle", -20]
|
['Obstacle', -20]
|
||||||
["Path", -10]
|
['Path', -10]
|
||||||
["Default", 0]
|
['Default', 0]
|
||||||
["Floating", 10]
|
['Floating', 10]
|
||||||
]
|
]
|
||||||
@spriteLayers[name] = new Layer name: name, layerPriority: priority, transform: Layer.TRANSFORM_CHILD, camera: @camera
|
@spriteLayers[name] = new Layer name: name, layerPriority: priority, transform: Layer.TRANSFORM_CHILD, camera: @camera
|
||||||
@surfaceLayer.addChild _.values(@spriteLayers)...
|
@surfaceLayer.addChild _.values(@spriteLayers)...
|
||||||
|
@ -66,36 +66,36 @@ module.exports = class SpriteBoss extends CocoClass
|
||||||
# TODO: make better system
|
# TODO: make better system
|
||||||
child.layerPriority = 0 if sprite?.thang?.isSelectable
|
child.layerPriority = 0 if sprite?.thang?.isSelectable
|
||||||
child.layerPriority = -40 if sprite?.thang?.isLand
|
child.layerPriority = -40 if sprite?.thang?.isLand
|
||||||
return @spriteLayers["Default"] unless child.layerPriority
|
return @spriteLayers['Default'] unless child.layerPriority
|
||||||
layer = _.findLast @spriteLayers, (layer, name) ->
|
layer = _.findLast @spriteLayers, (layer, name) ->
|
||||||
layer.layerPriority <= child.layerPriority
|
layer.layerPriority <= child.layerPriority
|
||||||
#console.log "layer for", child, "is", (layer ? @spriteLayers["Default"])
|
#console.log 'layer for', child, 'is', (layer ? @spriteLayers['Default'])
|
||||||
layer ? @spriteLayers["Default"]
|
layer ? @spriteLayers['Default']
|
||||||
|
|
||||||
addSprite: (sprite, id=null, layer=null) ->
|
addSprite: (sprite, id=null, layer=null) ->
|
||||||
id ?= sprite.thang.id
|
id ?= sprite.thang.id
|
||||||
console.error "Sprite collision! Already have:", id if @sprites[id]
|
console.error 'Sprite collision! Already have:', id if @sprites[id]
|
||||||
@sprites[id] = sprite
|
@sprites[id] = sprite
|
||||||
@spriteArray.push sprite
|
@spriteArray.push sprite
|
||||||
layer ?= @spriteLayers["Obstacle"] if sprite.thang?.spriteName.search(/(dungeon|indoor).wall/i) isnt -1
|
layer ?= @spriteLayers['Obstacle'] if sprite.thang?.spriteName.search(/(dungeon|indoor).wall/i) isnt -1
|
||||||
layer ?= @layerForChild sprite.imageObject, sprite
|
layer ?= @layerForChild sprite.imageObject, sprite
|
||||||
layer.addChild sprite.imageObject
|
layer.addChild sprite.imageObject
|
||||||
layer.updateLayerOrder()
|
layer.updateLayerOrder()
|
||||||
sprite
|
sprite
|
||||||
|
|
||||||
createMarks: ->
|
createMarks: ->
|
||||||
@targetMark = new Mark name: 'target', camera: @camera, layer: @spriteLayers["Ground"], thangType: 'target'
|
@targetMark = new Mark name: 'target', camera: @camera, layer: @spriteLayers['Ground'], thangType: 'target'
|
||||||
@selectionMark = new Mark name: 'selection', camera: @camera, layer: @spriteLayers["Ground"], thangType: 'selection'
|
@selectionMark = new Mark name: 'selection', camera: @camera, layer: @spriteLayers['Ground'], thangType: 'selection'
|
||||||
|
|
||||||
createSpriteOptions: (options) ->
|
createSpriteOptions: (options) ->
|
||||||
_.extend options, camera: @camera, resolutionFactor: 4, groundLayer: @spriteLayers["Ground"], textLayer: @surfaceTextLayer, floatingLayer: @spriteLayers["Floating"], spriteSheetCache: @spriteSheetCache, showInvisible: @options.showInvisible
|
_.extend options, camera: @camera, resolutionFactor: 4, groundLayer: @spriteLayers['Ground'], textLayer: @surfaceTextLayer, floatingLayer: @spriteLayers['Floating'], spriteSheetCache: @spriteSheetCache, showInvisible: @options.showInvisible
|
||||||
|
|
||||||
createIndieSprites: (indieSprites, withWizards) ->
|
createIndieSprites: (indieSprites, withWizards) ->
|
||||||
unless @indieSprites
|
unless @indieSprites
|
||||||
@indieSprites = []
|
@indieSprites = []
|
||||||
@indieSprites = (@createIndieSprite indieSprite for indieSprite in indieSprites) if indieSprites
|
@indieSprites = (@createIndieSprite indieSprite for indieSprite in indieSprites) if indieSprites
|
||||||
if withWizards and not @selfWizardSprite
|
if withWizards and not @selfWizardSprite
|
||||||
@selfWizardSprite = @createWizardSprite thangID: "My Wizard", isSelf: true, sprites: @sprites
|
@selfWizardSprite = @createWizardSprite thangID: 'My Wizard', isSelf: true, sprites: @sprites
|
||||||
|
|
||||||
createIndieSprite: (indieSprite) ->
|
createIndieSprite: (indieSprite) ->
|
||||||
unless thangType = @thangTypeFor indieSprite.thangType
|
unless thangType = @thangTypeFor indieSprite.thangType
|
||||||
|
@ -107,16 +107,16 @@ module.exports = class SpriteBoss extends CocoClass
|
||||||
createOpponentWizard: (opponent) ->
|
createOpponentWizard: (opponent) ->
|
||||||
# TODO: colorize name and cloud by team, colorize wizard by user's color config, level-specific wizard spawn points
|
# TODO: colorize name and cloud by team, colorize wizard by user's color config, level-specific wizard spawn points
|
||||||
sprite = @createWizardSprite thangID: opponent.id, name: opponent.name
|
sprite = @createWizardSprite thangID: opponent.id, name: opponent.name
|
||||||
if not opponent.levelSlug or opponent.levelSlug is "brawlwood"
|
if not opponent.levelSlug or opponent.levelSlug is 'brawlwood'
|
||||||
sprite.targetPos = if opponent.team is 'ogres' then {x: 52, y: 52} else {x: 28, y: 28}
|
sprite.targetPos = if opponent.team is 'ogres' then {x: 52, y: 52} else {x: 28, y: 28}
|
||||||
else if opponent.levelSlug is "dungeon-arena"
|
else if opponent.levelSlug is 'dungeon-arena'
|
||||||
sprite.targetPos = if opponent.team is 'ogres' then {x:72, y: 39} else {x: 9, y:39}
|
sprite.targetPos = if opponent.team is 'ogres' then {x: 72, y: 39} else {x: 9, y: 39}
|
||||||
else
|
else
|
||||||
sprite.targetPos = if opponent.team is 'ogres' then {x:52, y: 28} else {x: 20, y:28}
|
sprite.targetPos = if opponent.team is 'ogres' then {x: 52, y: 28} else {x: 20, y: 28}
|
||||||
|
|
||||||
createWizardSprite: (options) ->
|
createWizardSprite: (options) ->
|
||||||
sprite = new WizardSprite @thangTypeFor("Wizard"), @createSpriteOptions(options)
|
sprite = new WizardSprite @thangTypeFor('Wizard'), @createSpriteOptions(options)
|
||||||
@addSprite sprite, sprite.thang.id, @spriteLayers["Floating"]
|
@addSprite sprite, sprite.thang.id, @spriteLayers['Floating']
|
||||||
|
|
||||||
onPlayerJoined: (e) ->
|
onPlayerJoined: (e) ->
|
||||||
# Create another WizardSprite, unless this player is just me
|
# Create another WizardSprite, unless this player is just me
|
||||||
|
@ -172,7 +172,7 @@ module.exports = class SpriteBoss extends CocoClass
|
||||||
@adjustSpriteExistence() if frameChanged
|
@adjustSpriteExistence() if frameChanged
|
||||||
sprite.update frameChanged for sprite in @spriteArray
|
sprite.update frameChanged for sprite in @spriteArray
|
||||||
@updateSelection()
|
@updateSelection()
|
||||||
@spriteLayers["Default"].updateLayerOrder()
|
@spriteLayers['Default'].updateLayerOrder()
|
||||||
@cache()
|
@cache()
|
||||||
|
|
||||||
adjustSpriteExistence: ->
|
adjustSpriteExistence: ->
|
||||||
|
@ -184,11 +184,11 @@ module.exports = class SpriteBoss extends CocoClass
|
||||||
else
|
else
|
||||||
sprite = @addThangToSprites(thang)
|
sprite = @addThangToSprites(thang)
|
||||||
Backbone.Mediator.publish 'surface:new-thang-added', thang:thang, sprite:sprite
|
Backbone.Mediator.publish 'surface:new-thang-added', thang:thang, sprite:sprite
|
||||||
updateCache = updateCache or sprite.imageObject.parent is @spriteLayers["Obstacle"]
|
updateCache = updateCache or sprite.imageObject.parent is @spriteLayers['Obstacle']
|
||||||
sprite.playSounds()
|
sprite.playSounds()
|
||||||
for thangID, sprite of @sprites
|
for thangID, sprite of @sprites
|
||||||
missing = not (sprite.notOfThisWorld or @world.thangMap[thangID]?.exists)
|
missing = not (sprite.notOfThisWorld or @world.thangMap[thangID]?.exists)
|
||||||
isObstacle = sprite.imageObject.parent is @spriteLayers["Obstacle"]
|
isObstacle = sprite.imageObject.parent is @spriteLayers['Obstacle']
|
||||||
updateCache = updateCache or (isObstacle and (missing or sprite.hasMoved))
|
updateCache = updateCache or (isObstacle and (missing or sprite.hasMoved))
|
||||||
sprite.hasMoved = false
|
sprite.hasMoved = false
|
||||||
@removeSprite sprite if missing
|
@removeSprite sprite if missing
|
||||||
|
@ -210,11 +210,11 @@ module.exports = class SpriteBoss extends CocoClass
|
||||||
wallSprite.updateScale()
|
wallSprite.updateScale()
|
||||||
wallSprite.updatePosition()
|
wallSprite.updatePosition()
|
||||||
#console.log @wallGrid.toString()
|
#console.log @wallGrid.toString()
|
||||||
@spriteLayers["Obstacle"].uncache() if @spriteLayers["Obstacle"].cacheID # might have changed sizes
|
@spriteLayers['Obstacle'].uncache() if @spriteLayers['Obstacle'].cacheID # might have changed sizes
|
||||||
@spriteLayers["Obstacle"].cache()
|
@spriteLayers['Obstacle'].cache()
|
||||||
# test performance of doing land layer, too, to see if it's faster
|
# test performance of doing land layer, too, to see if it's faster
|
||||||
# @spriteLayers["Land"].uncache() if @spriteLayers["Land"].cacheID # might have changed sizes
|
# @spriteLayers['Land'].uncache() if @spriteLayers['Land'].cacheID # might have changed sizes
|
||||||
# @spriteLayers["Land"].cache()
|
# @spriteLayers['Land'].cache()
|
||||||
# I don't notice much difference - Scott
|
# I don't notice much difference - Scott
|
||||||
@cached = true
|
@cached = true
|
||||||
|
|
||||||
|
@ -291,7 +291,6 @@ module.exports = class SpriteBoss extends CocoClass
|
||||||
instance.addEventListener 'complete', ->
|
instance.addEventListener 'complete', ->
|
||||||
Backbone.Mediator.publish 'thang-finished-talking', thang: sprite?.thang
|
Backbone.Mediator.publish 'thang-finished-talking', thang: sprite?.thang
|
||||||
|
|
||||||
|
|
||||||
# Marks
|
# Marks
|
||||||
|
|
||||||
updateSelection: ->
|
updateSelection: ->
|
||||||
|
|
|
@ -90,7 +90,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
destroy: ->
|
destroy: ->
|
||||||
@dead = true
|
@dead = true
|
||||||
@camera?.destroy()
|
@camera?.destroy()
|
||||||
createjs.Ticker.removeEventListener("tick", @tick)
|
createjs.Ticker.removeEventListener('tick', @tick)
|
||||||
createjs.Sound.stop()
|
createjs.Sound.stop()
|
||||||
layer.destroy() for layer in @layers
|
layer.destroy() for layer in @layers
|
||||||
@spriteBoss.destroy()
|
@spriteBoss.destroy()
|
||||||
|
@ -160,12 +160,12 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
addMeshRectanglesToContainer: (mesh, container) ->
|
addMeshRectanglesToContainer: (mesh, container) ->
|
||||||
for rect in mesh
|
for rect in mesh
|
||||||
shape = new createjs.Shape()
|
shape = new createjs.Shape()
|
||||||
pos = @camera.worldToSurface {x:rect.x, y:rect.y}
|
pos = @camera.worldToSurface {x: rect.x, y: rect.y}
|
||||||
dim = @camera.worldToSurface {x:rect.width, y:rect.height}
|
dim = @camera.worldToSurface {x: rect.width, y: rect.height}
|
||||||
shape.graphics
|
shape.graphics
|
||||||
.setStrokeStyle(3)
|
.setStrokeStyle(3)
|
||||||
.beginFill('rgba(0, 0, 128, 0.3)')
|
.beginFill('rgba(0,0,128,0.3)')
|
||||||
.beginStroke('rgba(0, 0, 128, 0.7)')
|
.beginStroke('rgba(0,0,128,0.7)')
|
||||||
.drawRect(pos.x - dim.x/2, pos.y - dim.y/2, dim.x, dim.y)
|
.drawRect(pos.x - dim.x/2, pos.y - dim.y/2, dim.x, dim.y)
|
||||||
container.addChild shape
|
container.addChild shape
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
shape.graphics
|
shape.graphics
|
||||||
.setStrokeStyle(1)
|
.setStrokeStyle(1)
|
||||||
.moveTo(v1.x, v1.y)
|
.moveTo(v1.x, v1.y)
|
||||||
.beginStroke('rgba(128, 0, 0, 0.4)')
|
.beginStroke('rgba(128,0,0,0.4)')
|
||||||
.lineTo(v2.x, v2.y)
|
.lineTo(v2.x, v2.y)
|
||||||
.endStroke()
|
.endStroke()
|
||||||
container.addChild shape
|
container.addChild shape
|
||||||
|
@ -206,7 +206,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
if scrubDuration
|
if scrubDuration
|
||||||
t = createjs.Tween
|
t = createjs.Tween
|
||||||
.get(@)
|
.get(@)
|
||||||
.to({currentFrame:@scrubbingTo}, scrubDuration, createjs.Ease.sineInOut)
|
.to({currentFrame: @scrubbingTo}, scrubDuration, createjs.Ease.sineInOut)
|
||||||
.call(onTweenEnd)
|
.call(onTweenEnd)
|
||||||
t.addEventListener('change', @onFramesScrubbed)
|
t.addEventListener('change', @onFramesScrubbed)
|
||||||
else
|
else
|
||||||
|
@ -309,7 +309,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
return if @currentFrame is @lastFrame and not force
|
return if @currentFrame is @lastFrame and not force
|
||||||
progress = @getProgress()
|
progress = @getProgress()
|
||||||
Backbone.Mediator.publish('surface:frame-changed',
|
Backbone.Mediator.publish('surface:frame-changed',
|
||||||
type: "frame-changed"
|
type: 'frame-changed'
|
||||||
selectedThang: @spriteBoss.selectedSprite?.thang
|
selectedThang: @spriteBoss.selectedSprite?.thang
|
||||||
progress: progress
|
progress: progress
|
||||||
frame: @currentFrame
|
frame: @currentFrame
|
||||||
|
@ -353,7 +353,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
@setPaused false if @ended
|
@setPaused false if @ended
|
||||||
@casting = true
|
@casting = true
|
||||||
@wasPlayingWhenCastingBegan = @playing
|
@wasPlayingWhenCastingBegan = @playing
|
||||||
Backbone.Mediator.publish 'level-set-playing', { playing: false }
|
Backbone.Mediator.publish 'level-set-playing', {playing: false}
|
||||||
@setPlayingCalled = false # don't overwrite playing settings if they changed by, say, scripts
|
@setPlayingCalled = false # don't overwrite playing settings if they changed by, say, scripts
|
||||||
|
|
||||||
if @coordinateDisplay?
|
if @coordinateDisplay?
|
||||||
|
@ -361,7 +361,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
@coordinateDisplay.destroy()
|
@coordinateDisplay.destroy()
|
||||||
|
|
||||||
createjs.Tween.removeTweens(@surfaceLayer)
|
createjs.Tween.removeTweens(@surfaceLayer)
|
||||||
createjs.Tween.get(@surfaceLayer).to({alpha:0.9}, 1000, createjs.Ease.getPowOut(4.0))
|
createjs.Tween.get(@surfaceLayer).to({alpha: 0.9}, 1000, createjs.Ease.getPowOut(4.0))
|
||||||
|
|
||||||
onNewWorld: (event) ->
|
onNewWorld: (event) ->
|
||||||
return unless event.world.name is @world.name
|
return unless event.world.name is @world.name
|
||||||
|
@ -373,7 +373,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
|
|
||||||
# This has a tendency to break scripts that are waiting for playback to change when the level is loaded
|
# This has a tendency to break scripts that are waiting for playback to change when the level is loaded
|
||||||
# so only run it after the first world is created.
|
# so only run it after the first world is created.
|
||||||
Backbone.Mediator.publish 'level-set-playing', { playing: @wasPlayingWhenCastingBegan } unless event.firstWorld or @setPlayingCalled
|
Backbone.Mediator.publish 'level-set-playing', {playing: @wasPlayingWhenCastingBegan} unless event.firstWorld or @setPlayingCalled
|
||||||
|
|
||||||
fastForwardTo = null
|
fastForwardTo = null
|
||||||
if @playing
|
if @playing
|
||||||
|
@ -391,9 +391,9 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
@setProgress fastForwardToRatio, 1000 * fastForwardToTime / fastForwardSpeed
|
@setProgress fastForwardToRatio, 1000 * fastForwardToTime / fastForwardSpeed
|
||||||
@fastForwarding = true
|
@fastForwarding = true
|
||||||
createjs.Tween.get(@surfaceLayer)
|
createjs.Tween.get(@surfaceLayer)
|
||||||
.to({alpha:0.0}, 50)
|
.to({alpha: 0.0}, 50)
|
||||||
.call(f)
|
.call(f)
|
||||||
.to({alpha:1.0}, 2000, createjs.Ease.getPowOut(2.0))
|
.to({alpha: 1.0}, 2000, createjs.Ease.getPowOut(2.0))
|
||||||
|
|
||||||
# initialization
|
# initialization
|
||||||
|
|
||||||
|
@ -405,9 +405,9 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
@camera?.destroy()
|
@camera?.destroy()
|
||||||
@camera = new Camera @canvas
|
@camera = new Camera @canvas
|
||||||
AudioPlayer.camera = @camera
|
AudioPlayer.camera = @camera
|
||||||
@layers.push @surfaceLayer = new Layer name: "Surface", layerPriority: 0, transform: Layer.TRANSFORM_SURFACE, camera: @camera
|
@layers.push @surfaceLayer = new Layer name: 'Surface', layerPriority: 0, transform: Layer.TRANSFORM_SURFACE, camera: @camera
|
||||||
@layers.push @surfaceTextLayer = new Layer name: "Surface Text", layerPriority: 1, transform: Layer.TRANSFORM_SURFACE_TEXT, camera: @camera
|
@layers.push @surfaceTextLayer = new Layer name: 'Surface Text', layerPriority: 1, transform: Layer.TRANSFORM_SURFACE_TEXT, camera: @camera
|
||||||
@layers.push @screenLayer = new Layer name: "Screen", layerPriority: 2, transform: Layer.TRANSFORM_SCREEN, camera: @camera
|
@layers.push @screenLayer = new Layer name: 'Screen', layerPriority: 2, transform: Layer.TRANSFORM_SCREEN, camera: @camera
|
||||||
@stage.addChild @layers...
|
@stage.addChild @layers...
|
||||||
@surfaceLayer.addChild @cameraBorder = new CameraBorder bounds: @camera.bounds
|
@surfaceLayer.addChild @cameraBorder = new CameraBorder bounds: @camera.bounds
|
||||||
@screenLayer.addChild new Letterbox canvasWidth: canvasWidth, canvasHeight: canvasHeight
|
@screenLayer.addChild new Letterbox canvasWidth: canvasWidth, canvasHeight: canvasHeight
|
||||||
|
@ -449,7 +449,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
@updateState true
|
@updateState true
|
||||||
@drawCurrentFrame()
|
@drawCurrentFrame()
|
||||||
@showGrid() if @options.grid # TODO: pay attention to world grid setting (which we only know when world simulates)
|
@showGrid() if @options.grid # TODO: pay attention to world grid setting (which we only know when world simulates)
|
||||||
createjs.Ticker.addEventListener "tick", @tick
|
createjs.Ticker.addEventListener 'tick', @tick
|
||||||
Backbone.Mediator.publish 'level:started'
|
Backbone.Mediator.publish 'level:started'
|
||||||
|
|
||||||
createOpponentWizard: (opponent) ->
|
createOpponentWizard: (opponent) ->
|
||||||
|
@ -469,10 +469,10 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
@gridLayer.z = 90019001
|
@gridLayer.z = 90019001
|
||||||
@gridLayer.mouseEnabled = false
|
@gridLayer.mouseEnabled = false
|
||||||
@gridShape.alpha = 0.125
|
@gridShape.alpha = 0.125
|
||||||
@gridShape.graphics.beginStroke "blue"
|
@gridShape.graphics.beginStroke 'blue'
|
||||||
gridSize = Math.round(@world.size()[0] / 20)
|
gridSize = Math.round(@world.size()[0] / 20)
|
||||||
unless gridSize > 0.1
|
unless gridSize > 0.1
|
||||||
return console.error "Grid size is", gridSize, "so we can't draw a grid."
|
return console.error 'Grid size is', gridSize, 'so we can\'t draw a grid.'
|
||||||
wopStart = x: 0, y: 0
|
wopStart = x: 0, y: 0
|
||||||
wopEnd = x: @world.size()[0], y: @world.size()[1]
|
wopEnd = x: @world.size()[0], y: @world.size()[1]
|
||||||
supStart = @camera.worldToSurface wopStart
|
supStart = @camera.worldToSurface wopStart
|
||||||
|
@ -481,7 +481,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
while wop.x < wopEnd.x
|
while wop.x < wopEnd.x
|
||||||
sup = @camera.worldToSurface wop
|
sup = @camera.worldToSurface wop
|
||||||
@gridShape.graphics.mt(sup.x, supStart.y).lt(sup.x, supEnd.y)
|
@gridShape.graphics.mt(sup.x, supStart.y).lt(sup.x, supEnd.y)
|
||||||
t = new createjs.Text(wop.x.toFixed(0), "16px Arial", "blue")
|
t = new createjs.Text(wop.x.toFixed(0), '16px Arial', 'blue')
|
||||||
t.x = sup.x - t.getMeasuredWidth() / 2
|
t.x = sup.x - t.getMeasuredWidth() / 2
|
||||||
t.y = supStart.y - 10 - t.getMeasuredHeight() / 2
|
t.y = supStart.y - 10 - t.getMeasuredHeight() / 2
|
||||||
t.alpha = 0.75
|
t.alpha = 0.75
|
||||||
|
@ -490,7 +490,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
while wop.y < wopEnd.y
|
while wop.y < wopEnd.y
|
||||||
sup = @camera.worldToSurface wop
|
sup = @camera.worldToSurface wop
|
||||||
@gridShape.graphics.mt(supStart.x, sup.y).lt(supEnd.x, sup.y)
|
@gridShape.graphics.mt(supStart.x, sup.y).lt(supEnd.x, sup.y)
|
||||||
t = new createjs.Text(wop.y.toFixed(0), "16px Arial", "blue")
|
t = new createjs.Text(wop.y.toFixed(0), '16px Arial', 'blue')
|
||||||
t.x = 10 - t.getMeasuredWidth() / 2
|
t.x = 10 - t.getMeasuredWidth() / 2
|
||||||
t.y = sup.y - t.getMeasuredHeight() / 2
|
t.y = sup.y - t.getMeasuredHeight() / 2
|
||||||
t.alpha = 0.75
|
t.alpha = 0.75
|
||||||
|
@ -596,7 +596,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
Backbone.Mediator.publish('surface:ticked', {dt: 1 / @options.frameRate})
|
Backbone.Mediator.publish('surface:ticked', {dt: 1 / @options.frameRate})
|
||||||
mib = @stage.mouseInBounds
|
mib = @stage.mouseInBounds
|
||||||
if @mouseInBounds isnt mib
|
if @mouseInBounds isnt mib
|
||||||
Backbone.Mediator.publish('surface:mouse-' + (if mib then "over" else "out"), {})
|
Backbone.Mediator.publish('surface:mouse-' + (if mib then 'over' else 'out'), {})
|
||||||
@mouseInBounds = mib
|
@mouseInBounds = mib
|
||||||
|
|
||||||
restoreWorldState: ->
|
restoreWorldState: ->
|
||||||
|
@ -631,10 +631,10 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
return if @world.showPaths is 'paused' and @playing
|
return if @world.showPaths is 'paused' and @playing
|
||||||
return if @world.showPaths is 'selected' and not selectedThang
|
return if @world.showPaths is 'selected' and not selectedThang
|
||||||
@trailmaster ?= new path.Trailmaster @camera
|
@trailmaster ?= new path.Trailmaster @camera
|
||||||
selectedOnly = @playing and @world.showPaths is "selected"
|
selectedOnly = @playing and @world.showPaths is 'selected'
|
||||||
@paths = @trailmaster.generatePaths @world, @getCurrentFrame(), selectedThang, @spriteBoss.sprites, selectedOnly
|
@paths = @trailmaster.generatePaths @world, @getCurrentFrame(), selectedThang, @spriteBoss.sprites, selectedOnly
|
||||||
@paths.name = 'paths'
|
@paths.name = 'paths'
|
||||||
@spriteBoss.spriteLayers["Path"].addChild @paths
|
@spriteBoss.spriteLayers['Path'].addChild @paths
|
||||||
|
|
||||||
hidePaths: ->
|
hidePaths: ->
|
||||||
return if not @paths
|
return if not @paths
|
||||||
|
@ -647,8 +647,8 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
margin = (1 - 1 / zoom) / 2
|
margin = (1 - 1 / zoom) / 2
|
||||||
@stage.cache margin * w, margin * h, w / zoom, h / zoom, scale * zoom
|
@stage.cache margin * w, margin * h, w / zoom, h / zoom, scale * zoom
|
||||||
imageData = @stage.cacheCanvas.toDataURL(format, quality)
|
imageData = @stage.cacheCanvas.toDataURL(format, quality)
|
||||||
#console.log "Screenshot with scale", scale, "format", format, "quality", quality, "was", Math.floor(imageData.length / 1024), "kB"
|
#console.log 'Screenshot with scale', scale, 'format', format, 'quality', quality, 'was', Math.floor(imageData.length / 1024), 'kB'
|
||||||
screenshot = document.createElement("img")
|
screenshot = document.createElement('img')
|
||||||
screenshot.src = imageData
|
screenshot.src = imageData
|
||||||
@stage.uncache()
|
@stage.uncache()
|
||||||
imageData
|
imageData
|
||||||
|
|
|
@ -63,7 +63,7 @@ module.exports = class WizardSprite extends IndieSprite
|
||||||
continue unless state.wizard?
|
continue unless state.wizard?
|
||||||
@setColorHue state.wizard.wizardColor1
|
@setColorHue state.wizard.wizardColor1
|
||||||
if targetID = state.wizard.targetSprite
|
if targetID = state.wizard.targetSprite
|
||||||
return console.warn "Wizard Sprite couldn't find target sprite", targetID unless targetID of @options.sprites
|
return console.warn 'Wizard Sprite couldn\'t find target sprite', targetID unless targetID of @options.sprites
|
||||||
@setTarget @options.sprites[targetID]
|
@setTarget @options.sprites[targetID]
|
||||||
else
|
else
|
||||||
@setTarget state.wizard.targetPos
|
@setTarget state.wizard.targetPos
|
||||||
|
@ -129,7 +129,7 @@ module.exports = class WizardSprite extends IndieSprite
|
||||||
@targetPos = @boundWizard targetPos
|
@targetPos = @boundWizard targetPos
|
||||||
@beginMoveTween(duration, isLinear)
|
@beginMoveTween(duration, isLinear)
|
||||||
@shoveOtherWizards()
|
@shoveOtherWizards()
|
||||||
Backbone.Mediator.publish('self-wizard:target-changed', {sender:@}) if @isSelf
|
Backbone.Mediator.publish('self-wizard:target-changed', {sender: @}) if @isSelf
|
||||||
|
|
||||||
boundWizard: (target) ->
|
boundWizard: (target) ->
|
||||||
# Passed an {x, y} in world coordinates, returns {x, y} within world bounds
|
# Passed an {x, y} in world coordinates, returns {x, y} within world bounds
|
||||||
|
@ -168,7 +168,7 @@ module.exports = class WizardSprite extends IndieSprite
|
||||||
|
|
||||||
createjs.Tween
|
createjs.Tween
|
||||||
.get(@)
|
.get(@)
|
||||||
.to({tweenPercentage:0.0}, duration, ease)
|
.to({tweenPercentage: 0.0}, duration, ease)
|
||||||
.call(@endMoveTween)
|
.call(@endMoveTween)
|
||||||
@reachedTarget = false
|
@reachedTarget = false
|
||||||
@update true
|
@update true
|
||||||
|
@ -176,7 +176,7 @@ module.exports = class WizardSprite extends IndieSprite
|
||||||
shoveOtherWizards: (removeMe) ->
|
shoveOtherWizards: (removeMe) ->
|
||||||
return unless @targetSprite
|
return unless @targetSprite
|
||||||
allWizards = []
|
allWizards = []
|
||||||
Backbone.Mediator.publish('echo-all-wizard-sprites', {payload:allWizards})
|
Backbone.Mediator.publish('echo-all-wizard-sprites', {payload: allWizards})
|
||||||
allOfUs = (wizard for wizard in allWizards when wizard.targetSprite is @targetSprite)
|
allOfUs = (wizard for wizard in allWizards when wizard.targetSprite is @targetSprite)
|
||||||
allOfUs = (wizard for wizard in allOfUs when wizard isnt @) if removeMe
|
allOfUs = (wizard for wizard in allOfUs when wizard isnt @) if removeMe
|
||||||
|
|
||||||
|
|
|
@ -121,12 +121,12 @@ module.exports.Trailmaster = class Trailmaster
|
||||||
return unless thang.allTargets
|
return unless thang.allTargets
|
||||||
g = new createjs.Graphics()
|
g = new createjs.Graphics()
|
||||||
g.setStrokeStyle(0.5)
|
g.setStrokeStyle(0.5)
|
||||||
g.beginStroke(createjs.Graphics.getRGB(0,0,0))
|
g.beginStroke(createjs.Graphics.getRGB(0, 0, 0))
|
||||||
color = colorForThang(thang.team)
|
color = colorForThang(thang.team)
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
while i < thang.allTargets.length
|
while i < thang.allTargets.length
|
||||||
g.beginStroke(createjs.Graphics.getRGB(0,0,0))
|
g.beginStroke(createjs.Graphics.getRGB(0, 0, 0))
|
||||||
g.beginFill(createjs.Graphics.getRGB(color...))
|
g.beginFill(createjs.Graphics.getRGB(color...))
|
||||||
sup = @camera.worldToSurface x: thang.allTargets[i], y: thang.allTargets[i + 1]
|
sup = @camera.worldToSurface x: thang.allTargets[i], y: thang.allTargets[i + 1]
|
||||||
g.drawEllipse(sup.x - 5, sup.y - 3, 10, 6)
|
g.drawEllipse(sup.x - 5, sup.y - 3, 10, 6)
|
||||||
|
@ -168,7 +168,7 @@ module.exports.Trailmaster = class Trailmaster
|
||||||
clone.scaleY *= CLONE_SCALE
|
clone.scaleY *= CLONE_SCALE
|
||||||
if sprite.expandActions # old Sprite
|
if sprite.expandActions # old Sprite
|
||||||
sprite.updateRotation(clone, sprite.data)
|
sprite.updateRotation(clone, sprite.data)
|
||||||
animActions = sprite.expandActions(if thang.acts then thang.getActionName() else "idle")
|
animActions = sprite.expandActions(if thang.acts then thang.getActionName() else 'idle')
|
||||||
sprite.applyActionsToSprites(animActions, [clone], true)
|
sprite.applyActionsToSprites(animActions, [clone], true)
|
||||||
animation = clone.spriteSheet.getAnimation(clone.currentAnimation)
|
animation = clone.spriteSheet.getAnimation(clone.currentAnimation)
|
||||||
clone.currentAnimationFrame = Math.min(@clock % (animation.frames.length * 3), animation.frames.length - 1)
|
clone.currentAnimationFrame = Math.min(@clock % (animation.frames.length * 3), animation.frames.length - 1)
|
||||||
|
@ -186,9 +186,6 @@ module.exports.Trailmaster = class Trailmaster
|
||||||
@world.frames[@currentFrame].restoreStateForThang(thang)
|
@world.frames[@currentFrame].restoreStateForThang(thang)
|
||||||
sprites
|
sprites
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
createPath = (points, options={}, g=null) ->
|
createPath = (points, options={}, g=null) ->
|
||||||
options = options or {}
|
options = options or {}
|
||||||
tailColor = options.tailColor ? options.headColor
|
tailColor = options.tailColor ? options.headColor
|
||||||
|
@ -290,5 +287,3 @@ colorForThang = (team, brightness=100, alpha=1.0) =>
|
||||||
return color
|
return color
|
||||||
|
|
||||||
module.exports.createPath = createPath
|
module.exports.createPath = createPath
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
module.exports.clone = (obj) ->
|
module.exports.clone = (obj) ->
|
||||||
return obj if obj is null or typeof (obj) isnt "object"
|
return obj if obj is null or typeof (obj) isnt 'object'
|
||||||
temp = obj.constructor()
|
temp = obj.constructor()
|
||||||
for key of obj
|
for key of obj
|
||||||
temp[key] = module.exports.clone(obj[key])
|
temp[key] = module.exports.clone(obj[key])
|
||||||
|
@ -25,7 +25,7 @@ module.exports.normalizeFunc = (func_thing, object) ->
|
||||||
if _.isString(func_thing)
|
if _.isString(func_thing)
|
||||||
func = object[func_thing]
|
func = object[func_thing]
|
||||||
if not func
|
if not func
|
||||||
console.error("Could not find method", func_thing, 'in object', @)
|
console.error "Could not find method #{func_thing} in object #{@}"
|
||||||
return => null # always return a func, or Mediator will go boom
|
return => null # always return a func, or Mediator will go boom
|
||||||
func_thing = func
|
func_thing = func
|
||||||
return func_thing
|
return func_thing
|
||||||
|
@ -36,7 +36,7 @@ module.exports.hexToHSL = (hex) ->
|
||||||
hexToR = (h) -> parseInt (cutHex(h)).substring(0, 2), 16
|
hexToR = (h) -> parseInt (cutHex(h)).substring(0, 2), 16
|
||||||
hexToG = (h) -> parseInt (cutHex(h)).substring(2, 4), 16
|
hexToG = (h) -> parseInt (cutHex(h)).substring(2, 4), 16
|
||||||
hexToB = (h) -> parseInt (cutHex(h)).substring(4, 6), 16
|
hexToB = (h) -> parseInt (cutHex(h)).substring(4, 6), 16
|
||||||
cutHex = (h) -> (if (h.charAt(0) is "#") then h.substring(1, 7) else h)
|
cutHex = (h) -> (if (h.charAt(0) is '#') then h.substring(1, 7) else h)
|
||||||
|
|
||||||
module.exports.hslToHex = (hsl) ->
|
module.exports.hslToHex = (hsl) ->
|
||||||
'#' + (toHex(n) for n in hslToRgb(hsl...)).join('')
|
'#' + (toHex(n) for n in hslToRgb(hsl...)).join('')
|
||||||
|
@ -57,10 +57,10 @@ module.exports.i18n = (say, target, language=me.lang(), fallback='en') ->
|
||||||
if target of locale
|
if target of locale
|
||||||
result = locale[target]
|
result = locale[target]
|
||||||
else continue
|
else continue
|
||||||
return result if localeName == language
|
return result if localeName is language
|
||||||
generalResult = result if localeName == generalName
|
generalResult = result if localeName is generalName
|
||||||
fallbackResult = result if localeName == fallback
|
fallbackResult = result if localeName is fallback
|
||||||
fallforwardResult = result if localeName.indexOf(language) == 0 and not fallforwardResult?
|
fallforwardResult = result if localeName.indexOf(language) is 0 and not fallforwardResult?
|
||||||
|
|
||||||
return generalResult if generalResult?
|
return generalResult if generalResult?
|
||||||
return fallforwardResult if fallforwardResult?
|
return fallforwardResult if fallforwardResult?
|
||||||
|
|
|
@ -14,7 +14,7 @@ module.exports = class GoalManager extends CocoClass
|
||||||
# If you want weird goals or hybrid goals, make a custom goal.
|
# If you want weird goals or hybrid goals, make a custom goal.
|
||||||
|
|
||||||
nextGoalID: 0
|
nextGoalID: 0
|
||||||
nicks: ["GoalManager"]
|
nicks: ['GoalManager']
|
||||||
|
|
||||||
constructor: (@world, @initialGoals, @team) ->
|
constructor: (@world, @initialGoals, @team) ->
|
||||||
super()
|
super()
|
||||||
|
@ -134,9 +134,9 @@ module.exports = class GoalManager extends CocoClass
|
||||||
}
|
}
|
||||||
@initGoalState(state, [goal.killThangs, goal.saveThangs], 'killed')
|
@initGoalState(state, [goal.killThangs, goal.saveThangs], 'killed')
|
||||||
for getTo in goal.getAllToLocations ? []
|
for getTo in goal.getAllToLocations ? []
|
||||||
@initGoalState(state,[ getTo.getToLocation?.who , [] ], 'arrived')
|
@initGoalState(state, [getTo.getToLocation?.who, []], 'arrived')
|
||||||
for keepFrom in goal.keepAllFromLocations ? []
|
for keepFrom in goal.keepAllFromLocations ? []
|
||||||
@initGoalState(state,[ [] , keepFrom.keepFromLocation?.who], 'arrived')
|
@initGoalState(state, [[], keepFrom.keepFromLocation?.who], 'arrived')
|
||||||
@initGoalState(state, [goal.getToLocations?.who, goal.keepFromLocations?.who], 'arrived')
|
@initGoalState(state, [goal.getToLocations?.who, goal.keepFromLocations?.who], 'arrived')
|
||||||
@initGoalState(state, [goal.leaveOffSides?.who, goal.keepFromLeavingOffSides?.who], 'left')
|
@initGoalState(state, [goal.leaveOffSides?.who, goal.keepFromLeavingOffSides?.who], 'left')
|
||||||
@initGoalState(state, [goal.collectThangs?.who, goal.keepFromCollectingThangs?.who], 'collected')
|
@initGoalState(state, [goal.collectThangs?.who, goal.keepFromCollectingThangs?.who], 'collected')
|
||||||
|
@ -229,8 +229,8 @@ module.exports = class GoalManager extends CocoClass
|
||||||
if overallStatus = @checkOverallStatus true
|
if overallStatus = @checkOverallStatus true
|
||||||
matchedGoals = (_.find(@goals, {id: goalID}) for goalID, goalState of @goalStates when goalState.status is overallStatus)
|
matchedGoals = (_.find(@goals, {id: goalID}) for goalID, goalState of @goalStates when goalState.status is overallStatus)
|
||||||
mostEagerGoal = _.min matchedGoals, 'worldEndsAfter'
|
mostEagerGoal = _.min matchedGoals, 'worldEndsAfter'
|
||||||
victory = overallStatus is "success"
|
victory = overallStatus is 'success'
|
||||||
tentative = overallStatus is "success"
|
tentative = overallStatus is 'success'
|
||||||
@world.endWorld victory, mostEagerGoal.worldEndsAfter, tentative if mostEagerGoal isnt Infinity
|
@world.endWorld victory, mostEagerGoal.worldEndsAfter, tentative if mostEagerGoal isnt Infinity
|
||||||
|
|
||||||
updateGoalState: (goalID, thangID, progressObjectName, frameNumber) ->
|
updateGoalState: (goalID, thangID, progressObjectName, frameNumber) ->
|
||||||
|
@ -244,20 +244,20 @@ module.exports = class GoalManager extends CocoClass
|
||||||
if success
|
if success
|
||||||
numNeeded = goal.howMany ? Math.max(1, _.size stateThangs)
|
numNeeded = goal.howMany ? Math.max(1, _.size stateThangs)
|
||||||
else
|
else
|
||||||
# saveThangs: by default we would want to save all the Thangs, which means that we would want none of them to be "done"
|
# saveThangs: by default we would want to save all the Thangs, which means that we would want none of them to be 'done'
|
||||||
numNeeded = _.size(stateThangs) - Math.max((goal.howMany ? 1), _.size stateThangs) + 1
|
numNeeded = _.size(stateThangs) - Math.max((goal.howMany ? 1), _.size stateThangs) + 1
|
||||||
numDone = _.filter(stateThangs).length
|
numDone = _.filter(stateThangs).length
|
||||||
#console.log "needed", numNeeded, "done", numDone, "of total", _.size(stateThangs), "with how many", goal.howMany, "and stateThangs", stateThangs
|
#console.log 'needed', numNeeded, 'done', numDone, 'of total', _.size(stateThangs), 'with how many', goal.howMany, 'and stateThangs', stateThangs
|
||||||
return unless numDone >= numNeeded
|
return unless numDone >= numNeeded
|
||||||
return if state.status and not success # already failed it; don't wipe keyframe
|
return if state.status and not success # already failed it; don't wipe keyframe
|
||||||
state.status = if success then "success" else "failure"
|
state.status = if success then 'success' else 'failure'
|
||||||
state.keyFrame = frameNumber
|
state.keyFrame = frameNumber
|
||||||
#console.log goalID, "became", success, "on frame", frameNumber, "with overallStatus", @checkOverallStatus true
|
#console.log goalID, 'became', success, 'on frame', frameNumber, 'with overallStatus', @checkOverallStatus true
|
||||||
if overallStatus = @checkOverallStatus true
|
if overallStatus = @checkOverallStatus true
|
||||||
matchedGoals = (_.find(@goals, {id: goalID}) for goalID, goalState of @goalStates when goalState.status is overallStatus)
|
matchedGoals = (_.find(@goals, {id: goalID}) for goalID, goalState of @goalStates when goalState.status is overallStatus)
|
||||||
mostEagerGoal = _.min matchedGoals, 'worldEndsAfter'
|
mostEagerGoal = _.min matchedGoals, 'worldEndsAfter'
|
||||||
victory = overallStatus is "success"
|
victory = overallStatus is 'success'
|
||||||
tentative = overallStatus is "success"
|
tentative = overallStatus is 'success'
|
||||||
@world.endWorld victory, mostEagerGoal.worldEndsAfter, tentative if mostEagerGoal isnt Infinity
|
@world.endWorld victory, mostEagerGoal.worldEndsAfter, tentative if mostEagerGoal isnt Infinity
|
||||||
|
|
||||||
goalIsPositive: (goalID) ->
|
goalIsPositive: (goalID) ->
|
||||||
|
|
|
@ -31,7 +31,7 @@ module.exports = class Grid
|
||||||
for y in @columns gy - height / 2, gy + height / 2
|
for y in @columns gy - height / 2, gy + height / 2
|
||||||
for x in @rows gx - width / 2, gx + width / 2
|
for x in @rows gx - width / 2, gx + width / 2
|
||||||
for thang in @grid[y][x]
|
for thang in @grid[y][x]
|
||||||
thangs.push thang if thang.collides and not (thang in thangs) and thang.id isnt "Add Thang Phantom"
|
thangs.push thang if thang.collides and not (thang in thangs) and thang.id isnt 'Add Thang Phantom'
|
||||||
thangs
|
thangs
|
||||||
|
|
||||||
clampColumn: (y) ->
|
clampColumn: (y) ->
|
||||||
|
@ -51,4 +51,4 @@ module.exports = class Grid
|
||||||
toString: ->
|
toString: ->
|
||||||
upsideDown = _.clone @grid
|
upsideDown = _.clone @grid
|
||||||
upsideDown.reverse()
|
upsideDown.reverse()
|
||||||
(((if thangs.length then ("" + thangs.length) else " ") for thangs in row).join(" ") for row in upsideDown).join("\n")
|
(((if thangs.length then ('' + thangs.length) else ' ') for thangs in row).join(' ') for row in upsideDown).join("\n")
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
componentKeywords = ['attach', 'constructor', 'validateArguments', 'toString', 'isComponent'] # Array is faster than object
|
componentKeywords = ['attach', 'constructor', 'validateArguments', 'toString', 'isComponent'] # Array is faster than object
|
||||||
|
|
||||||
module.exports = class Component
|
module.exports = class Component
|
||||||
@className: "Component"
|
@className: 'Component'
|
||||||
isComponent: true
|
isComponent: true
|
||||||
constructor: (config) ->
|
constructor: (config) ->
|
||||||
for key, value of config
|
for key, value of config
|
||||||
|
@ -9,7 +9,7 @@ module.exports = class Component
|
||||||
|
|
||||||
attach: (thang) ->
|
attach: (thang) ->
|
||||||
# Optimize; this is much of the World constructor time
|
# Optimize; this is much of the World constructor time
|
||||||
for key, value of @ when key not in componentKeywords and key[0] isnt "_"
|
for key, value of @ when key not in componentKeywords and key[0] isnt '_'
|
||||||
oldValue = thang[key]
|
oldValue = thang[key]
|
||||||
if typeof oldValue is 'function'
|
if typeof oldValue is 'function'
|
||||||
thang.appendMethod key, value
|
thang.appendMethod key, value
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
Vector = require './vector'
|
Vector = require './vector'
|
||||||
|
|
||||||
module.exports.ArgumentError = class ArgumentError extends Error
|
module.exports.ArgumentError = class ArgumentError extends Error
|
||||||
@className: "ArgumentError"
|
@className: 'ArgumentError'
|
||||||
constructor: (@message, @functionName, @argumentName, @intendedType, @actualValue, @numArguments) ->
|
constructor: (@message, @functionName, @argumentName, @intendedType, @actualValue, @numArguments) ->
|
||||||
super message
|
super message
|
||||||
@name = "ArgumentError"
|
@name = 'ArgumentError'
|
||||||
if Error.captureStackTrace?
|
if Error.captureStackTrace?
|
||||||
Error.captureStackTrace @, @constructor
|
Error.captureStackTrace @, @constructor
|
||||||
|
|
||||||
toString: ->
|
toString: ->
|
||||||
s = "#{@functionName}"
|
s = "#{@functionName}"
|
||||||
if @argumentName is "return"
|
if @argumentName is 'return'
|
||||||
s += "'s return value"
|
s += "'s return value"
|
||||||
else if @argumentName is "_excess"
|
else if @argumentName is '_excess'
|
||||||
s += " takes only #{@numArguments} argument#{if @numArguments > 1 then 's' else ''}."
|
s += " takes only #{@numArguments} argument#{if @numArguments > 1 then 's' else ''}."
|
||||||
else if @argumentName
|
else if @argumentName
|
||||||
s += "'s argument #{@argumentName}"
|
s += "'s argument #{@argumentName}"
|
||||||
else
|
else
|
||||||
s += " takes no arguments."
|
s += ' takes no arguments.'
|
||||||
|
|
||||||
actualType = typeof @actualValue
|
actualType = typeof @actualValue
|
||||||
if not @actualValue?
|
if not @actualValue?
|
||||||
|
@ -26,12 +26,12 @@ module.exports.ArgumentError = class ArgumentError extends Error
|
||||||
actualType = 'array'
|
actualType = 'array'
|
||||||
typeMismatch = @intendedType and not @intendedType.match actualType
|
typeMismatch = @intendedType and not @intendedType.match actualType
|
||||||
if typeMismatch
|
if typeMismatch
|
||||||
v = ""
|
v = ''
|
||||||
if actualType is 'string'
|
if actualType is 'string'
|
||||||
v = "\"#{@actualValue}\""
|
v = "\"#{@actualValue}\""
|
||||||
else if actualType is "number"
|
else if actualType is 'number'
|
||||||
if Math.round(@actualValue) is @actualValue then @actualValue else @actualValue.toFixed(2)
|
if Math.round(@actualValue) is @actualValue then @actualValue else @actualValue.toFixed(2)
|
||||||
else if actualType is "boolean"
|
else if actualType is 'boolean'
|
||||||
v = "#{@actualValue}"
|
v = "#{@actualValue}"
|
||||||
else if (@actualValue? and @actualValue.id and @actualValue.trackedPropertiesKeys)
|
else if (@actualValue? and @actualValue.id and @actualValue.trackedPropertiesKeys)
|
||||||
# (Don't import Thang, but determine whether it is Thang.)
|
# (Don't import Thang, but determine whether it is Thang.)
|
||||||
|
@ -40,7 +40,7 @@ module.exports.ArgumentError = class ArgumentError extends Error
|
||||||
v = @actualValue.toString()
|
v = @actualValue.toString()
|
||||||
showValue = showValue or @actualValue instanceof Vector
|
showValue = showValue or @actualValue instanceof Vector
|
||||||
s += " should have type #{@intendedType}, but got #{actualType}#{if v then ': ' + v else ''}."
|
s += " should have type #{@intendedType}, but got #{actualType}#{if v then ': ' + v else ''}."
|
||||||
else if @argumentName and @argumentName isnt "_excess"
|
else if @argumentName and @argumentName isnt '_excess'
|
||||||
s += " has a problem."
|
s += ' has a problem.'
|
||||||
s += '\n' + @message if @message
|
s += '\n' + @message if @message
|
||||||
s
|
s
|
||||||
|
|
|
@ -1,375 +1,375 @@
|
||||||
module.exports.thangNames = thangNames =
|
module.exports.thangNames = thangNames =
|
||||||
"Soldier M": [
|
'Soldier M': [
|
||||||
"Duke"
|
'Duke'
|
||||||
"William"
|
'William'
|
||||||
"Lucas"
|
'Lucas'
|
||||||
"Marcus"
|
'Marcus'
|
||||||
"Robert"
|
'Robert'
|
||||||
"Gordon"
|
'Gordon'
|
||||||
"Kirin"
|
'Kirin'
|
||||||
"Theo"
|
'Theo'
|
||||||
"Roger"
|
'Roger'
|
||||||
"Roderick"
|
'Roderick'
|
||||||
"Samson"
|
'Samson'
|
||||||
"Silas"
|
'Silas'
|
||||||
"Richard"
|
'Richard'
|
||||||
"Max"
|
'Max'
|
||||||
"Jax"
|
'Jax'
|
||||||
"Dax"
|
'Dax'
|
||||||
"Mischa"
|
'Mischa'
|
||||||
"Ronald"
|
'Ronald'
|
||||||
"Tyrone"
|
'Tyrone'
|
||||||
"Thelonious"
|
'Thelonious'
|
||||||
"Miles"
|
'Miles'
|
||||||
"Bill"
|
'Bill'
|
||||||
"Kumar"
|
'Kumar'
|
||||||
"Ricardo"
|
'Ricardo'
|
||||||
"Maxwell"
|
'Maxwell'
|
||||||
"Jonah"
|
'Jonah'
|
||||||
"Leopold"
|
'Leopold'
|
||||||
"Phineas"
|
'Phineas'
|
||||||
"Ferb"
|
'Ferb'
|
||||||
"Felix"
|
'Felix'
|
||||||
"Ezra"
|
'Ezra'
|
||||||
"Lucian"
|
'Lucian'
|
||||||
"Augustus"
|
'Augustus'
|
||||||
"Ronan"
|
'Ronan'
|
||||||
"Pierce"
|
'Pierce'
|
||||||
"Harry"
|
'Harry'
|
||||||
"Hirium"
|
'Hirium'
|
||||||
"Hugo"
|
'Hugo'
|
||||||
"Cecil"
|
'Cecil'
|
||||||
"Barron"
|
'Barron'
|
||||||
"Huburt"
|
'Huburt'
|
||||||
"Sterling"
|
'Sterling'
|
||||||
"Alistair"
|
'Alistair'
|
||||||
"Cid"
|
'Cid'
|
||||||
"Remy"
|
'Remy'
|
||||||
"Stormy"
|
'Stormy'
|
||||||
"Halle"
|
'Halle'
|
||||||
"Sage"
|
'Sage'
|
||||||
"Ryan"
|
'Ryan'
|
||||||
"Bond"
|
'Bond'
|
||||||
]
|
]
|
||||||
"Soldier F": [
|
'Soldier F': [
|
||||||
"Sarah"
|
'Sarah'
|
||||||
"Alexandra"
|
'Alexandra'
|
||||||
"Holly"
|
'Holly'
|
||||||
"Trinity"
|
'Trinity'
|
||||||
"Nikita"
|
'Nikita'
|
||||||
"Alana"
|
'Alana'
|
||||||
"Lana"
|
'Lana'
|
||||||
"Joan"
|
'Joan'
|
||||||
"Helga"
|
'Helga'
|
||||||
"Annie"
|
'Annie'
|
||||||
"Lukaz"
|
'Lukaz'
|
||||||
"Gorgin"
|
'Gorgin'
|
||||||
"Coco"
|
'Coco'
|
||||||
"Buffy"
|
'Buffy'
|
||||||
"Allankrita"
|
'Allankrita'
|
||||||
"Kay"
|
'Kay'
|
||||||
]
|
]
|
||||||
"Peasant M": [
|
'Peasant M': [
|
||||||
"Yorik"
|
'Yorik'
|
||||||
"Hector"
|
'Hector'
|
||||||
"Thad"
|
'Thad'
|
||||||
"Victor"
|
'Victor'
|
||||||
"Lyle"
|
'Lyle'
|
||||||
"Charles"
|
'Charles'
|
||||||
"Yusef"
|
'Yusef'
|
||||||
"Hingle"
|
'Hingle'
|
||||||
"Azgot"
|
'Azgot'
|
||||||
"Piers"
|
'Piers'
|
||||||
"Carlton"
|
'Carlton'
|
||||||
"Hershell"
|
'Hershell'
|
||||||
"Gawain"
|
'Gawain'
|
||||||
"Durfkor"
|
'Durfkor'
|
||||||
"Paps"
|
'Paps'
|
||||||
"Hodor"
|
'Hodor'
|
||||||
]
|
]
|
||||||
"Peasant F": [
|
'Peasant F': [
|
||||||
"Hilda"
|
'Hilda'
|
||||||
"Icey"
|
'Icey'
|
||||||
"Matilda"
|
'Matilda'
|
||||||
"Mertia"
|
'Mertia'
|
||||||
"Mary"
|
'Mary'
|
||||||
"Brandy"
|
'Brandy'
|
||||||
"Gwendolin"
|
'Gwendolin'
|
||||||
"Tabitha"
|
'Tabitha'
|
||||||
"Regan"
|
'Regan'
|
||||||
"Giselle"
|
'Giselle'
|
||||||
"Bernadette"
|
'Bernadette'
|
||||||
]
|
]
|
||||||
"Archer F": [
|
'Archer F': [
|
||||||
"Phoebe"
|
'Phoebe'
|
||||||
"Mira"
|
'Mira'
|
||||||
"Agapi"
|
'Agapi'
|
||||||
"Cecily"
|
'Cecily'
|
||||||
"Tansy"
|
'Tansy'
|
||||||
"Ivy"
|
'Ivy'
|
||||||
"Gemma"
|
'Gemma'
|
||||||
"Keturah"
|
'Keturah'
|
||||||
"Korra"
|
'Korra'
|
||||||
"Kim"
|
'Kim'
|
||||||
"Odette"
|
'Odette'
|
||||||
"Orly"
|
'Orly'
|
||||||
"Mercedes"
|
'Mercedes'
|
||||||
"Rosaline"
|
'Rosaline'
|
||||||
"Vesper"
|
'Vesper'
|
||||||
"Beverly"
|
'Beverly'
|
||||||
"Natalie"
|
'Natalie'
|
||||||
"Clare"
|
'Clare'
|
||||||
"Rowan"
|
'Rowan'
|
||||||
"Omar"
|
'Omar'
|
||||||
"Alden"
|
'Alden'
|
||||||
"Cairn"
|
'Cairn'
|
||||||
"Jensen"
|
'Jensen'
|
||||||
"Yilitha"
|
'Yilitha'
|
||||||
"Mirana"
|
'Mirana'
|
||||||
"Lina"
|
'Lina'
|
||||||
"Luna"
|
'Luna'
|
||||||
"Alleria"
|
'Alleria'
|
||||||
"Vereesa"
|
'Vereesa'
|
||||||
"Beatrice"
|
'Beatrice'
|
||||||
]
|
]
|
||||||
"Archer M": [
|
'Archer M': [
|
||||||
"Brian"
|
'Brian'
|
||||||
"Cole"
|
'Cole'
|
||||||
"Roman"
|
'Roman'
|
||||||
"Hunter"
|
'Hunter'
|
||||||
"Simon"
|
'Simon'
|
||||||
"Robin"
|
'Robin'
|
||||||
"Quinn"
|
'Quinn'
|
||||||
"Arty"
|
'Arty'
|
||||||
"Gimsley"
|
'Gimsley'
|
||||||
"Fidsdale"
|
'Fidsdale'
|
||||||
"Slyvos"
|
'Slyvos'
|
||||||
"Logos"
|
'Logos'
|
||||||
"Denin"
|
'Denin'
|
||||||
"Lycan"
|
'Lycan'
|
||||||
"Loco"
|
'Loco'
|
||||||
"Vican"
|
'Vican'
|
||||||
"Mars"
|
'Mars'
|
||||||
"Dev"
|
'Dev'
|
||||||
"Oliver"
|
'Oliver'
|
||||||
]
|
]
|
||||||
"Ogre Munchkin M": [
|
'Ogre Munchkin M': [
|
||||||
"Brack"
|
'Brack'
|
||||||
"Gort"
|
'Gort'
|
||||||
"Weeb"
|
'Weeb'
|
||||||
"Nerph"
|
'Nerph'
|
||||||
"Kratt"
|
'Kratt'
|
||||||
"Smerk"
|
'Smerk'
|
||||||
"Raack"
|
'Raack'
|
||||||
"Dobo"
|
'Dobo'
|
||||||
"Draff"
|
'Draff'
|
||||||
"Zozo"
|
'Zozo'
|
||||||
"Kogpole"
|
'Kogpole'
|
||||||
"Leerer"
|
'Leerer'
|
||||||
"Skoggen"
|
'Skoggen'
|
||||||
"Treg"
|
'Treg'
|
||||||
"Goreball"
|
'Goreball'
|
||||||
"Gert"
|
'Gert'
|
||||||
"Thabt"
|
'Thabt'
|
||||||
"Snortt"
|
'Snortt'
|
||||||
"Kog"
|
'Kog'
|
||||||
"Ursa"
|
'Ursa'
|
||||||
"Ragtime"
|
'Ragtime'
|
||||||
]
|
]
|
||||||
"Ogre Munchkin F": [
|
'Ogre Munchkin F': [
|
||||||
"Iyert"
|
'Iyert'
|
||||||
"Palt"
|
'Palt'
|
||||||
"Shmeal"
|
'Shmeal'
|
||||||
"Gurzunn"
|
'Gurzunn'
|
||||||
"Yugark"
|
'Yugark'
|
||||||
"Dosha"
|
'Dosha'
|
||||||
"Inski"
|
'Inski'
|
||||||
"Lacos"
|
'Lacos'
|
||||||
"Upfish"
|
'Upfish'
|
||||||
]
|
]
|
||||||
"Ogre Peon M": [
|
'Ogre Peon M': [
|
||||||
"Durbo"
|
'Durbo'
|
||||||
"Kurger"
|
'Kurger'
|
||||||
"Mudwich"
|
'Mudwich'
|
||||||
"Ba Bo"
|
'Ba Bo'
|
||||||
"Zugger"
|
'Zugger'
|
||||||
"Toe Pod"
|
'Toe Pod'
|
||||||
]
|
]
|
||||||
"Ogre Peon F": [
|
'Ogre Peon F': [
|
||||||
"Iblet"
|
'Iblet'
|
||||||
"Lorba"
|
'Lorba'
|
||||||
"Zzoya"
|
'Zzoya'
|
||||||
"Yamra"
|
'Yamra'
|
||||||
"Greeke"
|
'Greeke'
|
||||||
"Vapa"
|
'Vapa'
|
||||||
]
|
]
|
||||||
"Ogre M": [
|
'Ogre M': [
|
||||||
"Krogg"
|
'Krogg'
|
||||||
"Dronck"
|
'Dronck'
|
||||||
"Trogdor"
|
'Trogdor'
|
||||||
"Kulgor"
|
'Kulgor'
|
||||||
"Skrungt"
|
'Skrungt'
|
||||||
"Mak Fod"
|
'Mak Fod'
|
||||||
"Trung"
|
'Trung'
|
||||||
"Axe Ox"
|
'Axe Ox'
|
||||||
"Vargutt"
|
'Vargutt'
|
||||||
"Grumus"
|
'Grumus'
|
||||||
"Gug"
|
'Gug'
|
||||||
"Tarlok"
|
'Tarlok'
|
||||||
"Gurulax"
|
'Gurulax'
|
||||||
"Mokrul"
|
'Mokrul'
|
||||||
"Polifemo"
|
'Polifemo'
|
||||||
"Muthyala"
|
'Muthyala'
|
||||||
"Saltporker"
|
'Saltporker'
|
||||||
]
|
]
|
||||||
"Ogre F": [
|
'Ogre F': [
|
||||||
"Nareng"
|
'Nareng'
|
||||||
"Morthrug"
|
'Morthrug'
|
||||||
"Glonc"
|
'Glonc'
|
||||||
"Marghurk"
|
'Marghurk'
|
||||||
"Martha"
|
'Martha'
|
||||||
"Holkam"
|
'Holkam'
|
||||||
"Alkaz"
|
'Alkaz'
|
||||||
"Gar'ah"
|
'Gar\'ah'
|
||||||
"Mak'rah"
|
'Mak\'rah'
|
||||||
"Marnag"
|
'Marnag'
|
||||||
]
|
]
|
||||||
"Ogre Brawler": [
|
'Ogre Brawler': [
|
||||||
"Grul'thock"
|
'Grul\'thock'
|
||||||
"Boz"
|
'Boz'
|
||||||
"Trod"
|
'Trod'
|
||||||
"Muul"
|
'Muul'
|
||||||
"Grumoll"
|
'Grumoll'
|
||||||
"Burobb"
|
'Burobb'
|
||||||
"Arelt"
|
'Arelt'
|
||||||
"Zagurk"
|
'Zagurk'
|
||||||
"Zeredd"
|
'Zeredd'
|
||||||
"Borgag"
|
'Borgag'
|
||||||
"Grognar"
|
'Grognar'
|
||||||
"Ironjaw"
|
'Ironjaw'
|
||||||
"Tuguro"
|
'Tuguro'
|
||||||
"York"
|
'York'
|
||||||
"Ork'han"
|
'Ork\'han'
|
||||||
"Roast Beefy"
|
'Roast Beefy'
|
||||||
"Haggar"
|
'Haggar'
|
||||||
]
|
]
|
||||||
"Ogre Fangrider": [
|
'Ogre Fangrider': [
|
||||||
"Dreek"
|
'Dreek'
|
||||||
"Flarsho"
|
'Flarsho'
|
||||||
"Mizzy"
|
'Mizzy'
|
||||||
"Secka"
|
'Secka'
|
||||||
"Arizard"
|
'Arizard'
|
||||||
"Secka"
|
'Secka'
|
||||||
"Arizard"
|
'Arizard'
|
||||||
"Morzgret"
|
'Morzgret'
|
||||||
"Doralt"
|
'Doralt'
|
||||||
"Geggret"
|
'Geggret'
|
||||||
"Gurzthrot"
|
'Gurzthrot'
|
||||||
"Murgark"
|
'Murgark'
|
||||||
"Muttin"
|
'Muttin'
|
||||||
"Bortrok"
|
'Bortrok'
|
||||||
]
|
]
|
||||||
"Ogre Shaman": [
|
'Ogre Shaman': [
|
||||||
"Sham'uk"
|
'Sham\'uk'
|
||||||
"Il'Du'duka"
|
'Il\'Du\'duka'
|
||||||
"Ahst'durante"
|
'Ahst\'durante'
|
||||||
"Poult"
|
'Poult'
|
||||||
"Aolian'Tak"
|
'Aolian\'Tak'
|
||||||
"Tuzell"
|
'Tuzell'
|
||||||
"Yamizeb"
|
'Yamizeb'
|
||||||
"Yerong"
|
'Yerong'
|
||||||
"Tuzang"
|
'Tuzang'
|
||||||
"Varreth"
|
'Varreth'
|
||||||
"Yugargen"
|
'Yugargen'
|
||||||
"Turann"
|
'Turann'
|
||||||
"Ugoki"
|
'Ugoki'
|
||||||
"Zulabar"
|
'Zulabar'
|
||||||
"Zo'Goroth"
|
'Zo\'Goroth'
|
||||||
"Mogadishu"
|
'Mogadishu'
|
||||||
"Nazgareth"
|
'Nazgareth'
|
||||||
"Gror"
|
'Gror'
|
||||||
"Grek"
|
'Grek'
|
||||||
"Gom"
|
'Gom'
|
||||||
"Gogg"
|
'Gogg'
|
||||||
"Ghuk"
|
'Ghuk'
|
||||||
"Makas"
|
'Makas'
|
||||||
"Drun"
|
'Drun'
|
||||||
]
|
]
|
||||||
"Ogre Thrower": [
|
'Ogre Thrower': [
|
||||||
"Kyrgg"
|
'Kyrgg'
|
||||||
"Durnath"
|
'Durnath'
|
||||||
"Kraggan"
|
'Kraggan'
|
||||||
"Rasha"
|
'Rasha'
|
||||||
"Moza"
|
'Moza'
|
||||||
"Vujii"
|
'Vujii'
|
||||||
"Esha"
|
'Esha'
|
||||||
"Zara"
|
'Zara'
|
||||||
"Hamedi"
|
'Hamedi'
|
||||||
"Jinjin"
|
'Jinjin'
|
||||||
"Yetu"
|
'Yetu'
|
||||||
"Makas"
|
'Makas'
|
||||||
"Rakash"
|
'Rakash'
|
||||||
"Drumbaa"
|
'Drumbaa'
|
||||||
"Pinakin"
|
'Pinakin'
|
||||||
]
|
]
|
||||||
"Burl": [
|
'Burl': [
|
||||||
"Borlit"
|
'Borlit'
|
||||||
"Burlosh"
|
'Burlosh'
|
||||||
"Dorf"
|
'Dorf'
|
||||||
]
|
]
|
||||||
"Griffin Rider": [
|
'Griffin Rider': [
|
||||||
"Aeoldan"
|
'Aeoldan'
|
||||||
"Bestarius"
|
'Bestarius'
|
||||||
|
|
||||||
]
|
]
|
||||||
"Potion Master": [
|
'Potion Master': [
|
||||||
"Snake"
|
'Snake'
|
||||||
"Amaranth"
|
'Amaranth'
|
||||||
"Zander"
|
'Zander'
|
||||||
"Arora"
|
'Arora'
|
||||||
"Curie"
|
'Curie'
|
||||||
"Clause"
|
'Clause'
|
||||||
"Vanders"
|
'Vanders'
|
||||||
]
|
]
|
||||||
"Librarian": [
|
'Librarian': [
|
||||||
"Hushbaum"
|
'Hushbaum'
|
||||||
"Matilda"
|
'Matilda'
|
||||||
"Agnes"
|
'Agnes'
|
||||||
"Agathe"
|
'Agathe'
|
||||||
"Satish"
|
'Satish'
|
||||||
]
|
]
|
||||||
"Equestrian": [
|
'Equestrian': [
|
||||||
"Reynaldo"
|
'Reynaldo'
|
||||||
"Ryder"
|
'Ryder'
|
||||||
"Thoron"
|
'Thoron'
|
||||||
"Mirial"
|
'Mirial'
|
||||||
"Neely"
|
'Neely'
|
||||||
]
|
]
|
||||||
"Knight": [
|
'Knight': [
|
||||||
"Tharin"
|
'Tharin'
|
||||||
"Arthur"
|
'Arthur'
|
||||||
"Galahad"
|
'Galahad'
|
||||||
"Mace"
|
'Mace'
|
||||||
"Drake"
|
'Drake'
|
||||||
"Duran"
|
'Duran'
|
||||||
"Almeric"
|
'Almeric'
|
||||||
"Hunfray"
|
'Hunfray'
|
||||||
"Hank"
|
'Hank'
|
||||||
"Jeph"
|
'Jeph'
|
||||||
"Neville"
|
'Neville'
|
||||||
"Alphonse"
|
'Alphonse'
|
||||||
"Edward"
|
'Edward'
|
||||||
]
|
]
|
||||||
"Captain": [
|
'Captain': [
|
||||||
"Anya"
|
'Anya'
|
||||||
"Brigette"
|
'Brigette'
|
||||||
"Sarre"
|
'Sarre'
|
||||||
"Katana"
|
'Katana'
|
||||||
"Lily"
|
'Lily'
|
||||||
"Isa"
|
'Isa'
|
||||||
"Dimia"
|
'Dimia'
|
||||||
"Jane"
|
'Jane'
|
||||||
"Lia"
|
'Lia'
|
||||||
"Hardcastle"
|
'Hardcastle'
|
||||||
"Leona"
|
'Leona'
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# http://coffeescriptcookbook.com/chapters/math/generating-predictable-random-numbers
|
# http://coffeescriptcookbook.com/chapters/math/generating-predictable-random-numbers
|
||||||
class Rand
|
class Rand
|
||||||
@className: "Rand"
|
@className: 'Rand'
|
||||||
# If created without a seed, uses current time as seed.
|
# If created without a seed, uses current time as seed.
|
||||||
constructor: (@seed) ->
|
constructor: (@seed) ->
|
||||||
# Knuth and Lewis' improvements to Park and Miller's LCPRNG
|
# Knuth and Lewis' improvements to Park and Miller's LCPRNG
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
Vector = require './vector'
|
Vector = require './vector'
|
||||||
|
|
||||||
class Rectangle
|
class Rectangle
|
||||||
@className: "Rectangle"
|
@className: 'Rectangle'
|
||||||
# Class methods for nondestructively operating
|
# Class methods for nondestructively operating
|
||||||
for name in ['add', 'subtract', 'multiply', 'divide']
|
for name in ['add', 'subtract', 'multiply', 'divide']
|
||||||
do (name) ->
|
do (name) ->
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# Other Systems might be things like Attraction, EdgeBounce, EdgeWrap, and non-physics ones, too, like Rendering, Animation, ...
|
# Other Systems might be things like Attraction, EdgeBounce, EdgeWrap, and non-physics ones, too, like Rendering, Animation, ...
|
||||||
|
|
||||||
module.exports = class System
|
module.exports = class System
|
||||||
@className: "System"
|
@className: 'System'
|
||||||
constructor: (@world, config) ->
|
constructor: (@world, config) ->
|
||||||
# Unlike with Component, we don't automatically copy all our properties onto the World.
|
# Unlike with Component, we don't automatically copy all our properties onto the World.
|
||||||
# Subclasses can copy select properties here if they like.
|
# Subclasses can copy select properties here if they like.
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
# http://codingowl.com/readblog.php?blogid=124
|
# http://codingowl.com/readblog.php?blogid=124
|
||||||
module.exports.CollisionCategory = class CollisionCategory
|
module.exports.CollisionCategory = class CollisionCategory
|
||||||
@className: "CollisionCategory"
|
@className: 'CollisionCategory'
|
||||||
constructor: (name, @superteamIndex=null, @collisionSystem) ->
|
constructor: (name, @superteamIndex=null, @collisionSystem) ->
|
||||||
# @superteamIndex is null for "none", "obstacles", and "dead".
|
# @superteamIndex is null for 'none', 'obstacles', and 'dead'.
|
||||||
# It's 0 for "ground", "air", and "ground_and_air" units with no superteams.
|
# It's 0 for 'ground', 'air', and 'ground_and_air' units with no superteams.
|
||||||
# It's 1, 2, or 3 for the superteams it gets after that. We can only have 16 collision categories.
|
# It's 1, 2, or 3 for the superteams it gets after that. We can only have 16 collision categories.
|
||||||
@ground = name.search("ground") isnt -1
|
@ground = name.search('ground') isnt -1
|
||||||
@air = name.search("air") isnt -1
|
@air = name.search('air') isnt -1
|
||||||
@name = CollisionCategory.nameFor name, @superteamIndex
|
@name = CollisionCategory.nameFor name, @superteamIndex
|
||||||
@superteamIndex ?= 0 if @ground or @air
|
@superteamIndex ?= 0 if @ground or @air
|
||||||
@number = 1 << @collisionSystem.totalCategories++
|
@number = 1 << @collisionSystem.totalCategories++
|
||||||
if @collisionSystem.totalCategories > 16 then console.log "There should only be 16 collision categories!"
|
if @collisionSystem.totalCategories > 16 then console.log 'There should only be 16 collision categories!'
|
||||||
@mask = 0
|
@mask = 0
|
||||||
@collisionSystem.allCategories[@name] = @
|
@collisionSystem.allCategories[@name] = @
|
||||||
for otherCatName, otherCat of @collisionSystem.allCategories
|
for otherCatName, otherCat of @collisionSystem.allCategories
|
||||||
|
@ -19,32 +19,32 @@ module.exports.CollisionCategory = class CollisionCategory
|
||||||
otherCat.mask = otherCat.mask | @number
|
otherCat.mask = otherCat.mask | @number
|
||||||
|
|
||||||
collidesWith: (cat) ->
|
collidesWith: (cat) ->
|
||||||
# "none" collides with nothing
|
# 'none' collides with nothing
|
||||||
return false if @name is "none" or cat.name is "none"
|
return false if @name is 'none' or cat.name is 'none'
|
||||||
|
|
||||||
# "obstacles" collides with everything; could also try letting air units (but not ground_and_air) fly over these
|
# 'obstacles' collides with everything; could also try letting air units (but not ground_and_air) fly over these
|
||||||
return true if cat.name is "obstacles" or @name is "obstacles"
|
return true if cat.name is 'obstacles' or @name is 'obstacles'
|
||||||
|
|
||||||
# "dead" collides only with obstacles
|
# 'dead' collides only with obstacles
|
||||||
return cat.name is "obstacles" if @name is "dead"
|
return cat.name is 'obstacles' if @name is 'dead'
|
||||||
return @name is "obstacles" if cat.name is "dead"
|
return @name is 'obstacles' if cat.name is 'dead'
|
||||||
|
|
||||||
# "ground_and_air_<team>" units don't hit ground or air units on their team (so missiles don't hit same team)
|
# 'ground_and_air_<team>' units don't hit ground or air units on their team (so missiles don't hit same team)
|
||||||
sameTeam = @superteamIndex and cat.superteamIndex is @superteamIndex
|
sameTeam = @superteamIndex and cat.superteamIndex is @superteamIndex
|
||||||
return false if sameTeam and @ground and @air
|
return false if sameTeam and @ground and @air
|
||||||
|
|
||||||
# actually, "ground_and_air<team>" units don't hit any ground_and_air units (temp missile collision fix)
|
# actually, 'ground_and_air<team>' units don't hit any ground_and_air units (temp missile collision fix)
|
||||||
return false if @ground and @air and cat.ground and cat.air
|
return false if @ground and @air and cat.ground and cat.air
|
||||||
|
|
||||||
# "ground" collides with "ground"
|
# 'ground' collides with 'ground'
|
||||||
return true if cat.ground and @ground
|
return true if cat.ground and @ground
|
||||||
|
|
||||||
# "air" collides with "air"
|
# 'air' collides with 'air'
|
||||||
return true if cat.air and @air
|
return true if cat.air and @air
|
||||||
|
|
||||||
# doesn't collide (probably "ground" and "air")
|
# doesn't collide (probably 'ground' and 'air')
|
||||||
false
|
false
|
||||||
|
|
||||||
@nameFor: (name, superteamIndex=null) ->
|
@nameFor: (name, superteamIndex=null) ->
|
||||||
return name unless name.match("ground") or name.match("air")
|
return name unless name.match('ground') or name.match('air')
|
||||||
name + "_" + (superteamIndex or 0)
|
name + '_' + (superteamIndex or 0)
|
||||||
|
|
|
@ -131,7 +131,7 @@ module.exports = class Thang
|
||||||
source.original = chain.original.toString()
|
source.original = chain.original.toString()
|
||||||
source.user = chain.user?.toString()
|
source.user = chain.user?.toString()
|
||||||
else
|
else
|
||||||
source.original = @[methodName]?.toString() ? ""
|
source.original = @[methodName]?.toString() ? ''
|
||||||
source.original = Aether.getFunctionBody source.original
|
source.original = Aether.getFunctionBody source.original
|
||||||
source
|
source
|
||||||
|
|
||||||
|
|
|
@ -8,15 +8,15 @@ else
|
||||||
bytesPerFloat = 4
|
bytesPerFloat = 4
|
||||||
|
|
||||||
module.exports = class ThangState
|
module.exports = class ThangState
|
||||||
@className: "ThangState"
|
@className: 'ThangState'
|
||||||
@trackedPropertyTypes: [
|
@trackedPropertyTypes: [
|
||||||
"boolean"
|
'boolean'
|
||||||
"number"
|
'number'
|
||||||
"string"
|
'string'
|
||||||
"array" # will turn everything into strings
|
'array' # will turn everything into strings
|
||||||
"object" # grrr
|
'object' # grrr
|
||||||
"Vector"
|
'Vector'
|
||||||
"Thang" # serialized as ids, like strings
|
'Thang' # serialized as ids, like strings
|
||||||
]
|
]
|
||||||
|
|
||||||
hasRestored: false
|
hasRestored: false
|
||||||
|
@ -40,7 +40,7 @@ module.exports = class ThangState
|
||||||
unless type
|
unless type
|
||||||
type = @trackedPropertyTypes[propIndex]
|
type = @trackedPropertyTypes[propIndex]
|
||||||
storage = @trackedPropertyValues[propIndex]
|
storage = @trackedPropertyValues[propIndex]
|
||||||
if type is "Vector"
|
if type is 'Vector'
|
||||||
value = new Vector storage[3 * @frameIndex], storage[3 * @frameIndex + 1], storage[3 * @frameIndex + 2]
|
value = new Vector storage[3 * @frameIndex], storage[3 * @frameIndex + 1], storage[3 * @frameIndex + 2]
|
||||||
else if type is 'string'
|
else if type is 'string'
|
||||||
specialKey = storage[@frameIndex]
|
specialKey = storage[@frameIndex]
|
||||||
|
@ -78,7 +78,7 @@ module.exports = class ThangState
|
||||||
type = @trackedPropertyTypes[propIndex]
|
type = @trackedPropertyTypes[propIndex]
|
||||||
storage = @trackedPropertyValues[propIndex]
|
storage = @trackedPropertyValues[propIndex]
|
||||||
props.push(@thang[prop] = @getStoredProp propIndex, type, storage)
|
props.push(@thang[prop] = @getStoredProp propIndex, type, storage)
|
||||||
#console.log @frameIndex, @thang.id, prop, propIndex, type, storage, "got", @thang[prop]
|
#console.log @frameIndex, @thang.id, prop, propIndex, type, storage, 'got', @thang[prop]
|
||||||
@props = props
|
@props = props
|
||||||
@trackedPropertyTypes = @trackedPropertyValues = @specialKeysToValues = null # leave @trackedPropertyKeys for indexing
|
@trackedPropertyTypes = @trackedPropertyValues = @specialKeysToValues = null # leave @trackedPropertyKeys for indexing
|
||||||
@hasRestored = true
|
@hasRestored = true
|
||||||
|
@ -90,14 +90,14 @@ module.exports = class ThangState
|
||||||
|
|
||||||
restorePartial: (ratio) ->
|
restorePartial: (ratio) ->
|
||||||
inverse = 1 - ratio
|
inverse = 1 - ratio
|
||||||
for prop, propIndex in @trackedPropertyKeys when prop is "pos" or prop is "rotation"
|
for prop, propIndex in @trackedPropertyKeys when prop is 'pos' or prop is 'rotation'
|
||||||
if @hasRestored
|
if @hasRestored
|
||||||
value = @props[propIndex]
|
value = @props[propIndex]
|
||||||
else
|
else
|
||||||
type = @trackedPropertyTypes[propIndex]
|
type = @trackedPropertyTypes[propIndex]
|
||||||
storage = @trackedPropertyValues[propIndex]
|
storage = @trackedPropertyValues[propIndex]
|
||||||
value = @getStoredProp propIndex, type, storage
|
value = @getStoredProp propIndex, type, storage
|
||||||
if prop is "pos"
|
if prop is 'pos'
|
||||||
if @thang.teleport and @thang.pos.distanceSquared(value) > 900
|
if @thang.teleport and @thang.pos.distanceSquared(value) > 900
|
||||||
# Don't interpolate; it was probably a teleport. https://github.com/codecombat/codecombat/issues/738
|
# Don't interpolate; it was probably a teleport. https://github.com/codecombat/codecombat/issues/738
|
||||||
@thang.pos = value
|
@thang.pos = value
|
||||||
|
@ -106,7 +106,7 @@ module.exports = class ThangState
|
||||||
@thang.pos.x = inverse * @thang.pos.x + ratio * value.x
|
@thang.pos.x = inverse * @thang.pos.x + ratio * value.x
|
||||||
@thang.pos.y = inverse * @thang.pos.y + ratio * value.y
|
@thang.pos.y = inverse * @thang.pos.y + ratio * value.y
|
||||||
@thang.pos.z = inverse * @thang.pos.z + ratio * value.z
|
@thang.pos.z = inverse * @thang.pos.z + ratio * value.z
|
||||||
else if prop is "rotation"
|
else if prop is 'rotation'
|
||||||
@thang.rotation = inverse * @thang.rotation + ratio * value
|
@thang.rotation = inverse * @thang.rotation + ratio * value
|
||||||
@thang.partialState = true
|
@thang.partialState = true
|
||||||
@
|
@
|
||||||
|
@ -119,7 +119,7 @@ module.exports = class ThangState
|
||||||
value = @props[originalPropIndex]
|
value = @props[originalPropIndex]
|
||||||
if value
|
if value
|
||||||
# undefined, null, false, 0 won't trigger in this serialization code scheme anyway, so we can't differentiate between them when deserializing
|
# undefined, null, false, 0 won't trigger in this serialization code scheme anyway, so we can't differentiate between them when deserializing
|
||||||
if type is "Vector"
|
if type is 'Vector'
|
||||||
storage[3 * frameIndex] = value.x
|
storage[3 * frameIndex] = value.x
|
||||||
storage[3 * frameIndex + 1] = value.y
|
storage[3 * frameIndex + 1] = value.y
|
||||||
storage[3 * frameIndex + 2] = value.z
|
storage[3 * frameIndex + 2] = value.z
|
||||||
|
@ -157,7 +157,7 @@ module.exports = class ThangState
|
||||||
storage[frameIndex] = specialKey
|
storage[frameIndex] = specialKey
|
||||||
else
|
else
|
||||||
storage[frameIndex] = value
|
storage[frameIndex] = value
|
||||||
#console.log @thang.id, "assigned prop", originalPropIndex, newPropIndex, value, type, "at", frameIndex, "to", storage[frameIndex]
|
#console.log @thang.id, 'assigned prop', originalPropIndex, newPropIndex, value, type, 'at', frameIndex, 'to', storage[frameIndex]
|
||||||
null
|
null
|
||||||
|
|
||||||
@deserialize: (world, frameIndex, thang, trackedPropertyKeys, trackedPropertyTypes, trackedPropertyValues, specialKeysToValues) ->
|
@deserialize: (world, frameIndex, thang, trackedPropertyKeys, trackedPropertyTypes, trackedPropertyValues, specialKeysToValues) ->
|
||||||
|
@ -173,12 +173,12 @@ module.exports = class ThangState
|
||||||
|
|
||||||
@transferableBytesNeededForType: (type, nFrames) ->
|
@transferableBytesNeededForType: (type, nFrames) ->
|
||||||
bytes = switch type
|
bytes = switch type
|
||||||
when "boolean" then 1
|
when 'boolean' then 1
|
||||||
when "number" then bytesPerFloat
|
when 'number' then bytesPerFloat
|
||||||
when "Vector" then bytesPerFloat * 3
|
when 'Vector' then bytesPerFloat * 3
|
||||||
when "string" then 4
|
when 'string' then 4
|
||||||
when "Thang" then 4 # turn them into strings of their ids
|
when 'Thang' then 4 # turn them into strings of their ids
|
||||||
when "array" then 4 # turn them into strings and hope it doesn't explode?
|
when 'array' then 4 # turn them into strings and hope it doesn't explode?
|
||||||
else 0
|
else 0
|
||||||
# We need to be a multiple of bytesPerFloat otherwise bigger-byte array (Float64Array, etc.) offsets won't work
|
# We need to be a multiple of bytesPerFloat otherwise bigger-byte array (Float64Array, etc.) offsets won't work
|
||||||
# http://www.kirupa.com/forum/showthread.php?378737-Typed-Arrays-Y-U-No-offset-at-values-other-than-multiples-of-element-size
|
# http://www.kirupa.com/forum/showthread.php?378737-Typed-Arrays-Y-U-No-offset-at-values-other-than-multiples-of-element-size
|
||||||
|
@ -187,17 +187,17 @@ module.exports = class ThangState
|
||||||
@createArrayForType: (type, nFrames, buffer, offset) ->
|
@createArrayForType: (type, nFrames, buffer, offset) ->
|
||||||
bytes = @transferableBytesNeededForType type, nFrames
|
bytes = @transferableBytesNeededForType type, nFrames
|
||||||
storage = switch type
|
storage = switch type
|
||||||
when "boolean"
|
when 'boolean'
|
||||||
new Uint8Array(buffer, offset, nFrames)
|
new Uint8Array(buffer, offset, nFrames)
|
||||||
when "number"
|
when 'number'
|
||||||
new FloatArrayType(buffer, offset, nFrames)
|
new FloatArrayType(buffer, offset, nFrames)
|
||||||
when "Vector"
|
when 'Vector'
|
||||||
new FloatArrayType(buffer, offset, nFrames * 3)
|
new FloatArrayType(buffer, offset, nFrames * 3)
|
||||||
when "string"
|
when 'string'
|
||||||
new Uint32Array(buffer, offset, nFrames)
|
new Uint32Array(buffer, offset, nFrames)
|
||||||
when "Thang"
|
when 'Thang'
|
||||||
new Uint32Array(buffer, offset, nFrames)
|
new Uint32Array(buffer, offset, nFrames)
|
||||||
when "array"
|
when 'array'
|
||||||
new Uint32Array(buffer, offset, nFrames)
|
new Uint32Array(buffer, offset, nFrames)
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# https://github.com/hornairs/blog/blob/master/assets/coffeescripts/flocking/vector.coffee
|
# https://github.com/hornairs/blog/blob/master/assets/coffeescripts/flocking/vector.coffee
|
||||||
class Vector
|
class Vector
|
||||||
@className: "Vector"
|
@className: 'Vector'
|
||||||
# Class methods for nondestructively operating
|
# Class methods for nondestructively operating
|
||||||
for name in ['add', 'subtract', 'multiply', 'divide', 'limit', 'normalize']
|
for name in ['add', 'subtract', 'multiply', 'divide', 'limit', 'normalize']
|
||||||
do (name) ->
|
do (name) ->
|
||||||
|
|
|
@ -12,7 +12,7 @@ PROGRESS_UPDATE_INTERVAL = 200
|
||||||
DESERIALIZATION_INTERVAL = 20
|
DESERIALIZATION_INTERVAL = 20
|
||||||
|
|
||||||
module.exports = class World
|
module.exports = class World
|
||||||
@className: "World"
|
@className: 'World'
|
||||||
age: 0
|
age: 0
|
||||||
ended: false
|
ended: false
|
||||||
preloading: false # Whether we are just preloading a world in case we soon cast it
|
preloading: false # Whether we are just preloading a world in case we soon cast it
|
||||||
|
@ -63,12 +63,12 @@ module.exports = class World
|
||||||
@thangMap[thang.id] = thang
|
@thangMap[thang.id] = thang
|
||||||
|
|
||||||
thangDialogueSounds: ->
|
thangDialogueSounds: ->
|
||||||
if @frames.length < @totalFrames then throw new Error("World should be over before grabbing dialogue")
|
if @frames.length < @totalFrames then throw new Error('World should be over before grabbing dialogue')
|
||||||
[sounds, seen] = [[], {}]
|
[sounds, seen] = [[], {}]
|
||||||
for frame in @frames
|
for frame in @frames
|
||||||
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
|
||||||
unless seen[soundKey]
|
unless seen[soundKey]
|
||||||
sounds.push [state.thang.spriteName, sayMessage]
|
sounds.push [state.thang.spriteName, sayMessage]
|
||||||
seen[soundKey] = true
|
seen[soundKey] = true
|
||||||
|
@ -83,7 +83,7 @@ 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
|
unless @thangs.length
|
||||||
console.log "Warning: loadFrames called on empty World (no thangs)."
|
console.log 'Warning: loadFrames called on empty World (no thangs).'
|
||||||
t1 = now()
|
t1 = now()
|
||||||
@t0 ?= t1
|
@t0 ?= t1
|
||||||
if loadUntilFrame
|
if loadUntilFrame
|
||||||
|
@ -113,7 +113,7 @@ module.exports = class World
|
||||||
loadProgressCallback? i / @totalFrames unless @preloading
|
loadProgressCallback? i / @totalFrames unless @preloading
|
||||||
t1 = t2
|
t1 = t2
|
||||||
if t2 - @t0 > 1000
|
if t2 - @t0 > 1000
|
||||||
console.log(' Loaded', i, 'of', @totalFrames, "(+" + (t2 - @t0).toFixed(0) + "ms)")
|
console.log ' Loaded', i, 'of', @totalFrames, '(+' + (t2 - @t0).toFixed(0) + 'ms)'
|
||||||
@t0 = t2
|
@t0 = t2
|
||||||
continueFn = =>
|
continueFn = =>
|
||||||
return if @destroyed
|
return if @destroyed
|
||||||
|
@ -155,7 +155,7 @@ module.exports = class World
|
||||||
for levelSystem in level.systems
|
for levelSystem in level.systems
|
||||||
systemModel = levelSystem.model
|
systemModel = levelSystem.model
|
||||||
config = levelSystem.config
|
config = levelSystem.config
|
||||||
systemClass = @loadClassFromCode systemModel.js, systemModel.name, "system"
|
systemClass = @loadClassFromCode systemModel.js, systemModel.name, 'system'
|
||||||
#console.log "using db system class ---\n", systemClass, "\n--- from code ---n", systemModel.js, "\n---"
|
#console.log "using db system class ---\n", systemClass, "\n--- from code ---n", systemModel.js, "\n---"
|
||||||
system = new systemClass @, config
|
system = new systemClass @, config
|
||||||
@addSystems system
|
@addSystems system
|
||||||
|
@ -169,15 +169,15 @@ module.exports = class World
|
||||||
# Load new Thangs
|
# Load new Thangs
|
||||||
toAdd = []
|
toAdd = []
|
||||||
for d in level.thangs
|
for d in level.thangs
|
||||||
continue if d.thangType is "Interface" # ignore old Interface Thangs until we've migrated away
|
continue if d.thangType is 'Interface' # ignore old Interface Thangs until we've migrated away
|
||||||
components = []
|
components = []
|
||||||
for component in d.components
|
for component in d.components
|
||||||
componentModel = _.find level.levelComponents, (c) -> c.original is component.original and c.version.major is (component.majorVersion ? 0)
|
componentModel = _.find level.levelComponents, (c) -> c.original is component.original and c.version.major is (component.majorVersion ? 0)
|
||||||
#console.log "found model", componentModel, "from", component, "for", d.id, "from existing components", level.levelComponents
|
#console.log 'found model', componentModel, 'from', component, 'for', d.id, 'from existing components', level.levelComponents
|
||||||
componentClass = @loadClassFromCode componentModel.js, componentModel.name, "component"
|
componentClass = @loadClassFromCode componentModel.js, componentModel.name, 'component'
|
||||||
components.push [componentClass, component.config]
|
components.push [componentClass, component.config]
|
||||||
#console.log "---", d.id, "using db component class ---\n", componentClass, "\n--- from code ---\n", componentModel.js, '\n---'
|
#console.log '---', d.id, "using db component class ---\n", componentClass, "\n--- from code ---\n", componentModel.js, '\n---'
|
||||||
#console.log "(found", componentModel, "for id", component.original, "from", level.levelComponents, ")"
|
#console.log '(found', componentModel, 'for id', component.original, 'from', level.levelComponents, ')'
|
||||||
thangType = d.thangType
|
thangType = d.thangType
|
||||||
thangTypeModel = _.find level.thangTypes, (t) -> t.original is thangType
|
thangTypeModel = _.find level.thangTypes, (t) -> t.original is thangType
|
||||||
thangType = thangTypeModel.name if thangTypeModel
|
thangType = thangTypeModel.name if thangTypeModel
|
||||||
|
@ -185,7 +185,7 @@ module.exports = class World
|
||||||
try
|
try
|
||||||
thang.addComponents components...
|
thang.addComponents components...
|
||||||
catch e
|
catch e
|
||||||
console.error "couldn't load components for", d.thangType, d.id, "because", e, e.stack, e.stackTrace
|
console.error 'couldn\'t load components for', d.thangType, d.id, 'because', e, e.stack, e.stackTrace
|
||||||
toAdd.push thang
|
toAdd.push thang
|
||||||
@extraneousThangs = consolidateThangs toAdd if willSimulate # combine walls, for example; serialize the leftovers later
|
@extraneousThangs = consolidateThangs toAdd if willSimulate # combine walls, for example; serialize the leftovers later
|
||||||
for thang in toAdd
|
for thang in toAdd
|
||||||
|
@ -200,11 +200,11 @@ module.exports = class World
|
||||||
@scripts = []
|
@scripts = []
|
||||||
@addScripts level.scripts...
|
@addScripts level.scripts...
|
||||||
|
|
||||||
loadClassFromCode: (js, name, kind="component") ->
|
loadClassFromCode: (js, name, kind='component') ->
|
||||||
# Cache them based on source code so we don't have to worry about extra compilations
|
# Cache them based on source code so we don't have to worry about extra compilations
|
||||||
@componentCodeClassMap ?= {}
|
@componentCodeClassMap ?= {}
|
||||||
@systemCodeClassMap ?= {}
|
@systemCodeClassMap ?= {}
|
||||||
map = if kind is "component" then @componentCodeClassMap else @systemCodeClassMap
|
map = if kind is 'component' then @componentCodeClassMap else @systemCodeClassMap
|
||||||
c = map[js]
|
c = map[js]
|
||||||
return c if c
|
return c if c
|
||||||
c = map[js] = eval js
|
c = map[js] = eval js
|
||||||
|
@ -285,7 +285,7 @@ module.exports = class World
|
||||||
|
|
||||||
serialize: ->
|
serialize: ->
|
||||||
# Code hotspot; optimize it
|
# Code hotspot; optimize it
|
||||||
if @frames.length < @totalFrames then throw new Error("World Should Be Over Before Serialization")
|
if @frames.length < @totalFrames then throw new Error('World Should Be Over Before Serialization')
|
||||||
[transferableObjects, nontransferableObjects] = [0, 0]
|
[transferableObjects, nontransferableObjects] = [0, 0]
|
||||||
o = {totalFrames: @totalFrames, maxTotalFrames: @maxTotalFrames, frameRate: @frameRate, dt: @dt, victory: @victory, userCodeMap: {}, trackedProperties: {}}
|
o = {totalFrames: @totalFrames, maxTotalFrames: @maxTotalFrames, frameRate: @frameRate, dt: @dt, victory: @victory, userCodeMap: {}, trackedProperties: {}}
|
||||||
o.trackedProperties[prop] = @[prop] for prop in @trackedProperties or []
|
o.trackedProperties[prop] = @[prop] for prop in @trackedProperties or []
|
||||||
|
@ -364,20 +364,20 @@ module.exports = class World
|
||||||
flattened.push value
|
flattened.push value
|
||||||
o.storageBuffer = flattened
|
o.storageBuffer = flattened
|
||||||
|
|
||||||
#console.log "Allocating memory:", (t1 - t0).toFixed(0), "ms; assigning values:", (t2 - t1).toFixed(0), "ms, so", ((t2 - t1) / @frames.length).toFixed(3), "ms per frame"
|
#console.log 'Allocating memory:', (t1 - t0).toFixed(0), 'ms; assigning values:', (t2 - t1).toFixed(0), 'ms, so', ((t2 - t1) / @frames.length).toFixed(3), 'ms per frame'
|
||||||
#console.log "Got", transferableObjects, "transferable objects and", nontransferableObjects, "nontransferable; stored", transferableStorageBytesNeeded, "bytes transferably"
|
#console.log 'Got', transferableObjects, 'transferable objects and', nontransferableObjects, 'nontransferable; stored', transferableStorageBytesNeeded, 'bytes transferably'
|
||||||
|
|
||||||
o.thangs = (t.serialize() for t in @thangs.concat(@extraneousThangs ? []))
|
o.thangs = (t.serialize() for t in @thangs.concat(@extraneousThangs ? []))
|
||||||
o.scriptNotes = (sn.serialize() for sn in @scriptNotes)
|
o.scriptNotes = (sn.serialize() for sn in @scriptNotes)
|
||||||
if o.scriptNotes.length > 200
|
if o.scriptNotes.length > 200
|
||||||
console.log "Whoa, serializing a lot of WorldScriptNotes here:", o.scriptNotes.length
|
console.log 'Whoa, serializing a lot of WorldScriptNotes here:', o.scriptNotes.length
|
||||||
{serializedWorld: o, transferableObjects: [o.storageBuffer]}
|
{serializedWorld: o, transferableObjects: [o.storageBuffer]}
|
||||||
|
|
||||||
@deserialize: (o, classMap, oldSerializedWorldFrames, finishedWorldCallback) ->
|
@deserialize: (o, classMap, oldSerializedWorldFrames, finishedWorldCallback) ->
|
||||||
# Code hotspot; optimize it
|
# Code hotspot; optimize it
|
||||||
#console.log "Deserializing", o, "length", JSON.stringify(o).length
|
#console.log 'Deserializing', o, 'length', JSON.stringify(o).length
|
||||||
#console.log JSON.stringify(o)
|
#console.log JSON.stringify(o)
|
||||||
#console.log "Got special keys and values:", o.specialValuesToKeys, o.specialKeysToValues
|
#console.log 'Got special keys and values:', o.specialValuesToKeys, o.specialKeysToValues
|
||||||
perf = {}
|
perf = {}
|
||||||
perf.t0 = now()
|
perf.t0 = now()
|
||||||
w = new World o.userCodeMap, classMap
|
w = new World o.userCodeMap, classMap
|
||||||
|
@ -424,13 +424,13 @@ module.exports = class World
|
||||||
w.ended = true
|
w.ended = true
|
||||||
w.getFrame(w.totalFrames - 1).restoreState()
|
w.getFrame(w.totalFrames - 1).restoreState()
|
||||||
perf.t5 = now()
|
perf.t5 = now()
|
||||||
console.log "Deserialization:", (perf.t5 - perf.t0).toFixed(0) + "ms (" + ((perf.t5 - perf.t0) / w.frames.length).toFixed(3) + "ms per frame).", perf.batches, "batches."
|
console.log 'Deserialization:', (perf.t5 - perf.t0).toFixed(0) + 'ms (' + ((perf.t5 - perf.t0) / w.frames.length).toFixed(3) + 'ms per frame).', perf.batches, 'batches.'
|
||||||
if false
|
if false
|
||||||
console.log " Deserializing--constructing new World:", (perf.t1 - perf.t0).toFixed(2) + "ms"
|
console.log ' Deserializing--constructing new World:', (perf.t1 - perf.t0).toFixed(2) + 'ms'
|
||||||
console.log " Deserializing--Thangs and ScriptNotes:", (perf.t2 - perf.t1).toFixed(2) + "ms"
|
console.log ' Deserializing--Thangs and ScriptNotes:', (perf.t2 - perf.t1).toFixed(2) + 'ms'
|
||||||
console.log " Deserializing--reallocating memory:", (perf.t3 - perf.t2).toFixed(2) + "ms"
|
console.log ' Deserializing--reallocating memory:', (perf.t3 - perf.t2).toFixed(2) + 'ms'
|
||||||
console.log " Deserializing--WorldFrames:", (perf.t4 - perf.t3).toFixed(2) + "ms"
|
console.log ' Deserializing--WorldFrames:', (perf.t4 - perf.t3).toFixed(2) + 'ms'
|
||||||
console.log " Deserializing--restoring last WorldFrame:", (perf.t5 - perf.t4).toFixed(2) + "ms"
|
console.log ' Deserializing--restoring last WorldFrame:', (perf.t5 - perf.t4).toFixed(2) + 'ms'
|
||||||
finishedWorldCallback w
|
finishedWorldCallback w
|
||||||
|
|
||||||
findFirstChangedFrame: (oldWorld) ->
|
findFirstChangedFrame: (oldWorld) ->
|
||||||
|
@ -440,9 +440,9 @@ module.exports = class World
|
||||||
break unless oldFrame and newFrame.hash is oldFrame.hash
|
break unless oldFrame and newFrame.hash is oldFrame.hash
|
||||||
@firstChangedFrame = i
|
@firstChangedFrame = i
|
||||||
if @frames[i]
|
if @frames[i]
|
||||||
console.log "First changed frame is", @firstChangedFrame, "with hash", @frames[i].hash, "compared to", oldWorld.frames[i]?.hash
|
console.log 'First changed frame is', @firstChangedFrame, 'with hash', @frames[i].hash, 'compared to', oldWorld.frames[i]?.hash
|
||||||
else
|
else
|
||||||
console.log "No frames were changed out of all", @frames.length
|
console.log 'No frames were changed out of all', @frames.length
|
||||||
@firstChangedFrame
|
@firstChangedFrame
|
||||||
|
|
||||||
pointsForThang: (thangID, frameStart=0, frameEnd=null, camera=null, resolution=4) ->
|
pointsForThang: (thangID, frameStart=0, frameEnd=null, camera=null, resolution=4) ->
|
||||||
|
@ -478,7 +478,7 @@ module.exports = class World
|
||||||
actionsForThang: (thangID, keepIdle=false) ->
|
actionsForThang: (thangID, keepIdle=false) ->
|
||||||
# Optimized
|
# Optimized
|
||||||
@actionsForThangCache ?= {}
|
@actionsForThangCache ?= {}
|
||||||
cacheKey = thangID + "_" + Boolean(keepIdle)
|
cacheKey = thangID + '_' + Boolean(keepIdle)
|
||||||
cached = @actionsForThangCache[cacheKey]
|
cached = @actionsForThangCache[cacheKey]
|
||||||
return cached if cached
|
return cached if cached
|
||||||
states = (frame.thangStateMap[thangID] for frame in @frames)
|
states = (frame.thangStateMap[thangID] for frame in @frames)
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
ThangState = require './thang_state'
|
ThangState = require './thang_state'
|
||||||
|
|
||||||
module.exports = class WorldFrame
|
module.exports = class WorldFrame
|
||||||
@className: "WorldFrame"
|
@className: 'WorldFrame'
|
||||||
|
|
||||||
constructor: (@world, @time=0) ->
|
constructor: (@world, @time=0) ->
|
||||||
@thangStateMap = {}
|
@thangStateMap = {}
|
||||||
@setState() if @world
|
@setState() if @world
|
||||||
|
|
||||||
getNextFrame: ->
|
getNextFrame: ->
|
||||||
# Optimized. Must be called while thangs are current at this frame.
|
# Optimized. Must be called while thangs are current at this frame.
|
||||||
nextTime = @time + @world.dt
|
nextTime = @time + @world.dt
|
||||||
|
@ -22,7 +24,7 @@ module.exports = class WorldFrame
|
||||||
thangState.restore() for thangID, thangState of @thangStateMap
|
thangState.restore() for thangID, thangState of @thangStateMap
|
||||||
for thang in @world.thangs
|
for thang in @world.thangs
|
||||||
if not @thangStateMap[thang.id] and not thang.stateless
|
if not @thangStateMap[thang.id] and not thang.stateless
|
||||||
#console.log "Frame", @time, "restoring state for", thang.id, "and saying it don't exist"
|
#console.log 'Frame', @time, 'restoring state for', thang.id, 'and saying it don\'t exist'
|
||||||
thang.exists = false
|
thang.exists = false
|
||||||
|
|
||||||
restorePartialState: (ratio) ->
|
restorePartialState: (ratio) ->
|
||||||
|
@ -33,22 +35,22 @@ module.exports = class WorldFrame
|
||||||
if not thangState
|
if not thangState
|
||||||
if not thang.stateless
|
if not thang.stateless
|
||||||
thang.exists = false
|
thang.exists = false
|
||||||
#console.log "Frame", @time, "restoring state for", thang.id, "in particular and saying it don't exist"
|
#console.log 'Frame', @time, 'restoring state for', thang.id, 'in particular and saying it don\'t exist'
|
||||||
return
|
return
|
||||||
thangState.restore()
|
thangState.restore()
|
||||||
|
|
||||||
clearEvents: -> thang.currentEvents = [] for thang in @world.thangs
|
clearEvents: -> thang.currentEvents = [] for thang in @world.thangs
|
||||||
|
|
||||||
toString: ->
|
toString: ->
|
||||||
map = ((' ' for x in [0 .. @world.width]) \
|
map = ((' ' for x in [0 .. @world.width]) \
|
||||||
for y in [0 .. @world.height])
|
for y in [0 .. @world.height])
|
||||||
symbols = ".ox@dfga[]/D"
|
symbols = '.ox@dfga[]/D'
|
||||||
for thang, i in @world.thangs when thang.rectangle
|
for thang, i in @world.thangs when thang.rectangle
|
||||||
rect = thang.rectangle().axisAlignedBoundingBox()
|
rect = thang.rectangle().axisAlignedBoundingBox()
|
||||||
for y in [Math.floor(rect.y - rect.height / 2) ... Math.ceil(rect.y + rect.height / 2)]
|
for y in [Math.floor(rect.y - rect.height / 2) ... Math.ceil(rect.y + rect.height / 2)]
|
||||||
for x in [Math.floor(rect.x - rect.width / 2) ... Math.ceil(rect.x + rect.width / 2)]
|
for x in [Math.floor(rect.x - rect.width / 2) ... Math.ceil(rect.x + rect.width / 2)]
|
||||||
map[y][x] = symbols[i % symbols.length] if 0 <= y < @world.height and 0 <= x < @world.width
|
map[y][x] = symbols[i % symbols.length] if 0 <= y < @world.height and 0 <= x < @world.width
|
||||||
@time + "\n" + (xs.join(' ') for xs in map).join('\n') + '\n'
|
@time + '\n' + (xs.join(' ') for xs in map).join('\n') + '\n'
|
||||||
|
|
||||||
serialize: (frameIndex, trackedPropertiesThangIDs, trackedPropertiesPerThangIndices, trackedPropertiesPerThangTypes, trackedPropertiesPerThangValues, specialValuesToKeys, specialKeysToValues) ->
|
serialize: (frameIndex, trackedPropertiesThangIDs, trackedPropertiesPerThangIndices, trackedPropertiesPerThangTypes, trackedPropertiesPerThangValues, specialValuesToKeys, specialKeysToValues) ->
|
||||||
# Optimize
|
# Optimize
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
{scriptMatchesEventPrereqs} = require './script_event_prereqs'
|
{scriptMatchesEventPrereqs} = require './script_event_prereqs'
|
||||||
|
|
||||||
module.exports = class WorldScriptNote
|
module.exports = class WorldScriptNote
|
||||||
@className: "WorldScriptNote"
|
@className: 'WorldScriptNote'
|
||||||
constructor: (script, @event, world) ->
|
constructor: (script, @event, world) ->
|
||||||
return unless script?
|
return unless script?
|
||||||
@invalid = true
|
@invalid = true
|
||||||
|
|
|
@ -78,17 +78,17 @@ module.exports.consolidateThangs = consolidateThangs = (thangs) ->
|
||||||
topmost = _.max structural, (t) -> t.pos.y + t.height / 2
|
topmost = _.max structural, (t) -> t.pos.y + t.height / 2
|
||||||
leftmost = _.min structural, (t) -> t.pos.x - t.width / 2
|
leftmost = _.min structural, (t) -> t.pos.x - t.width / 2
|
||||||
bottommost = _.min structural, (t) -> t.pos.y - t.height / 2
|
bottommost = _.min structural, (t) -> t.pos.y - t.height / 2
|
||||||
console.log "got rightmost", rightmost.id, "topmost", topmost.id, "lefmostmost", leftmost.id, "bottommost", bottommost.id, "out of", structural.length, "structural thangs" if debug
|
console.log 'got rightmost', rightmost.id, 'topmost', topmost.id, 'lefmostmost', leftmost.id, 'bottommost', bottommost.id, 'out of', structural.length, 'structural thangs' if debug
|
||||||
left = Math.min 0, leftmost.pos.x - leftmost.width / 2
|
left = Math.min 0, leftmost.pos.x - leftmost.width / 2
|
||||||
bottom = Math.min 0, bottommost.pos.y - bottommost.height / 2
|
bottom = Math.min 0, bottommost.pos.y - bottommost.height / 2
|
||||||
if (left < 0) or (bottom < 0)
|
if (left < 0) or (bottom < 0)
|
||||||
console.error "Negative structural Thangs aren't supported, sorry!" # TODO: largestRectangle, AI System, and anything else that accesses grid directly need updating to finish this
|
console.error 'Negative structural Thangs aren\'t supported, sorry!' # TODO: largestRectangle, AI System, and anything else that accesses grid directly need updating to finish this
|
||||||
left = 0
|
left = 0
|
||||||
bottom = 0
|
bottom = 0
|
||||||
width = rightmost.pos.x + rightmost.width / 2 - left
|
width = rightmost.pos.x + rightmost.width / 2 - left
|
||||||
height = topmost.pos.y + topmost.height / 2 - bottom
|
height = topmost.pos.y + topmost.height / 2 - bottom
|
||||||
padding = 0
|
padding = 0
|
||||||
console.log "got max width", width, "height", height, "left", left, "bottom", bottom, "of thangs", thangs.length, "structural", structural.length if debug
|
console.log 'got max width', width, 'height', height, 'left', left, 'bottom', bottom, 'of thangs', thangs.length, 'structural', structural.length if debug
|
||||||
grid = new Grid structural, width, height, padding, left, bottom
|
grid = new Grid structural, width, height, padding, left, bottom
|
||||||
console.log grid.toString() if debug
|
console.log grid.toString() if debug
|
||||||
|
|
||||||
|
@ -107,14 +107,14 @@ module.exports.consolidateThangs = consolidateThangs = (thangs) ->
|
||||||
grid.grid[y2][x2] = []
|
grid.grid[y2][x2] = []
|
||||||
console.log grid.toString() if debug
|
console.log grid.toString() if debug
|
||||||
thang = structural[dissection.length] # grab one we already know is configured properly
|
thang = structural[dissection.length] # grab one we already know is configured properly
|
||||||
console.error "Hmm, our dissection has more Thangs than the original structural Thangs?", dissection.length unless thang
|
console.error 'Hmm, our dissection has more Thangs than the original structural Thangs?', dissection.length unless thang
|
||||||
thang.width = rect.width
|
thang.width = rect.width
|
||||||
thang.height = rect.height
|
thang.height = rect.height
|
||||||
thang.pos.x = rect.x
|
thang.pos.x = rect.x
|
||||||
thang.pos.y = rect.y
|
thang.pos.y = rect.y
|
||||||
thang.createBodyDef()
|
thang.createBodyDef()
|
||||||
dissection.push thang
|
dissection.push thang
|
||||||
console.log "Turned", structural.length, "structural Thangs into", dissection.length, "dissecting Thangs."
|
console.log 'Turned', structural.length, 'structural Thangs into', dissection.length, 'dissecting Thangs.'
|
||||||
thangs.push dissection...
|
thangs.push dissection...
|
||||||
structural[dissection.length ... structural.length]
|
structural[dissection.length ... structural.length]
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ module.exports.largestRectangle = largestRectangle = (grid, bottomY, leftX, want
|
||||||
break unless coveredRow
|
break unless coveredRow
|
||||||
coveredRows.push coveredRow
|
coveredRows.push coveredRow
|
||||||
shortestCoveredRow = Math.min(shortestCoveredRow, coveredRow)
|
shortestCoveredRow = Math.min(shortestCoveredRow, coveredRow)
|
||||||
console.log "largestRectangle() for", bottomY, leftX, "got coveredRows", coveredRows if debug
|
console.log 'largestRectangle() for', bottomY, leftX, 'got coveredRows', coveredRows if debug
|
||||||
[maxArea, maxAreaRows, maxAreaRowLength, shortestRow] = [0, 0, 0, 0]
|
[maxArea, maxAreaRows, maxAreaRowLength, shortestRow] = [0, 0, 0, 0]
|
||||||
for rowLength, rowIndex in coveredRows
|
for rowLength, rowIndex in coveredRows
|
||||||
shortestRow ||= rowLength
|
shortestRow ||= rowLength
|
||||||
|
@ -143,7 +143,7 @@ module.exports.largestRectangle = largestRectangle = (grid, bottomY, leftX, want
|
||||||
maxAreaRowLength = shortestRow
|
maxAreaRowLength = shortestRow
|
||||||
maxArea = area
|
maxArea = area
|
||||||
shortestRow = Math.min(rowLength, shortestRow)
|
shortestRow = Math.min(rowLength, shortestRow)
|
||||||
console.log "So largest rect has area", maxArea, "with", maxAreaRows, "rows of length", maxAreaRowLength if debug
|
console.log 'So largest rect has area', maxArea, 'with', maxAreaRows, 'rows of length', maxAreaRowLength if debug
|
||||||
rect = new Rectangle leftX + maxAreaRowLength / 2, bottomY + maxAreaRows / 2, maxAreaRowLength, maxAreaRows
|
rect = new Rectangle leftX + maxAreaRowLength / 2, bottomY + maxAreaRows / 2, maxAreaRowLength, maxAreaRows
|
||||||
console.log "That corresponds to a rectangle", rect.toString() if debug
|
console.log 'That corresponds to a rectangle', rect.toString() if debug
|
||||||
rect
|
rect
|
||||||
|
|
|
@ -101,40 +101,40 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
||||||
multiplayer: "Multiplayer"
|
multiplayer: "Multiplayer"
|
||||||
for_developers: "Für Entwickler"
|
for_developers: "Für Entwickler"
|
||||||
|
|
||||||
# play:
|
play:
|
||||||
# choose_your_level: "Choose Your Level"
|
choose_your_level: "Wähl dis Level us"
|
||||||
# adventurer_prefix: "You can jump to any level below, or discuss the levels on "
|
adventurer_prefix: "Du chasch zu de untere Level zrugg goh oder die kommende Level diskutiere "
|
||||||
# adventurer_forum: "the Adventurer forum"
|
adventurer_forum: "s Abentürer-Forum"
|
||||||
# adventurer_suffix: "."
|
# adventurer_suffix: "."
|
||||||
# campaign_beginner: "Beginner Campaign"
|
campaign_beginner: "Afängerkampagne"
|
||||||
# campaign_beginner_description: "... in which you learn the wizardry of programming."
|
campaign_beginner_description: "... i dere du d Zauberkunst vom Programmiere lernsch."
|
||||||
# campaign_dev: "Random Harder Levels"
|
campaign_dev: "Zuefälligi schwierigeri Level"
|
||||||
# campaign_dev_description: "... in which you learn the interface while doing something a little harder."
|
campaign_dev_description: "... i dene du s Interface kenne lernsch, während du öppis chli Schwierigers machsch."
|
||||||
# campaign_multiplayer: "Multiplayer Arenas"
|
campaign_multiplayer: "Multiplayer Arenas"
|
||||||
# campaign_multiplayer_description: "... in which you code head-to-head against other players."
|
campaign_multiplayer_description: "... i dene du Chopf a Chopf geg anderi Spieler spielsch."
|
||||||
# campaign_player_created: "Player-Created"
|
# campaign_player_created: "Player-Created"
|
||||||
# campaign_player_created_description: "... in which you battle against the creativity of your fellow <a href=\"/contribute#artisan\">Artisan Wizards</a>."
|
# campaign_player_created_description: "... in which you battle against the creativity of your fellow <a href=\"/contribute#artisan\">Artisan Wizards</a>."
|
||||||
# level_difficulty: "Difficulty: "
|
level_difficulty: "Schwierigkeit: "
|
||||||
# play_as: "Play As"
|
play_as: "Spiel als"
|
||||||
# spectate: "Spectate"
|
spectate: "Zueluege"
|
||||||
|
|
||||||
# contact:
|
contact:
|
||||||
# contact_us: "Contact CodeCombat"
|
contact_us: "CodeCombat kontaktiere"
|
||||||
# welcome: "Good to hear from you! Use this form to send us email. "
|
welcome: "Mir ghöred gern vo dir! Benutz das Formular zum üs e E-Mail schicke."
|
||||||
# contribute_prefix: "If you're interested in contributing, check out our "
|
contribute_prefix: "Wenn du dra interessiert bisch, mitzhelfe denn lueg doch mol verbii uf üsere"
|
||||||
# contribute_page: "contribute page"
|
contribute_page: "Contribute Page"
|
||||||
# contribute_suffix: "!"
|
# contribute_suffix: "!"
|
||||||
# forum_prefix: "For anything public, please try "
|
forum_prefix: "Für öffentlichi Sache versuechs mol bi"
|
||||||
# forum_page: "our forum"
|
forum_page: "üsem Forum"
|
||||||
# forum_suffix: " instead."
|
forum_suffix: " stattdesse."
|
||||||
# send: "Send Feedback"
|
send: "Feedback schicke"
|
||||||
# contact_candidate: "Contact Candidate"
|
# contact_candidate: "Contact Candidate"
|
||||||
# recruitment_reminder: "Use this form to reach out to candidates you are interested in interviewing. Remember that CodeCombat charges 15% of first-year salary. The fee is due upon hiring the employee and is refundable for 90 days if the employee does not remain employed. Part time, remote, and contract employees are free, as are interns."
|
# recruitment_reminder: "Use this form to reach out to candidates you are interested in interviewing. Remember that CodeCombat charges 15% of first-year salary. The fee is due upon hiring the employee and is refundable for 90 days if the employee does not remain employed. Part time, remote, and contract employees are free, as are interns."
|
||||||
|
|
||||||
diplomat_suggestion:
|
diplomat_suggestion:
|
||||||
title: "Hilf, CodeCombat z übersetze!"
|
title: "Hilf, CodeCombat z übersetze!"
|
||||||
sub_heading: "Mir bruuched dini Sprochfähigkeite."
|
sub_heading: "Mir bruuched dini Sprochfähigkeite."
|
||||||
pitch_body: "We develop CodeCombat in English, but we already have players all over the world. Many of them want to play in Swiss German but don't speak English, so if you can speak both, please consider signing up to be a Diplomat and help translate both the CodeCombat website and all the levels into Swiss German."
|
pitch_body: "Mir entwickled CodeCombat in Englisch, aber mir hend scho Spieler uf de ganze Welt. Vieli devo würed gern uf Schwiizerdütsch spiele, aber chönd kei Englisch. Wenn du beides chasch, denk doch mol drüber noh, dich bi üs als Diplomat izträge und z helfe, d CodeCombat Websiite und alli Level uf Schwiizerdütsch z übersetze."
|
||||||
missing_translations: "Until we can translate everything into Swiss German, you'll see generic German or English when Swiss German isn't available."
|
missing_translations: "Until we can translate everything into Swiss German, you'll see generic German or English when Swiss German isn't available."
|
||||||
learn_more: "Lern meh drüber, en Diplomat zsii"
|
learn_more: "Lern meh drüber, en Diplomat zsii"
|
||||||
subscribe_as_diplomat: "Abonnier als en Diplomat"
|
subscribe_as_diplomat: "Abonnier als en Diplomat"
|
||||||
|
@ -142,18 +142,18 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
||||||
wizard_settings:
|
wizard_settings:
|
||||||
title: "Zaubereristellige"
|
title: "Zaubereristellige"
|
||||||
customize_avatar: "Pass din Avatar ah"
|
customize_avatar: "Pass din Avatar ah"
|
||||||
# active: "Active"
|
active: "Aktiv"
|
||||||
color: "Farb"
|
color: "Farb"
|
||||||
group: "Gruppe"
|
group: "Gruppe"
|
||||||
clothes: "Chleider"
|
clothes: "Chleider"
|
||||||
# trim: "Trim"
|
trim: "Zueschniide"
|
||||||
cloud: "Wolke"
|
cloud: "Wolke"
|
||||||
team: "Team"
|
team: "Team"
|
||||||
spell: "Zauberspruch"
|
spell: "Zauberspruch"
|
||||||
boots: "Stiefel"
|
boots: "Stiefel"
|
||||||
# hue: "Hue"
|
hue: "Färbig"
|
||||||
saturation: "Sättigung"
|
saturation: "Sättigung"
|
||||||
# lightness: "Lightness"
|
lightness: "Helligkeit"
|
||||||
|
|
||||||
account_settings:
|
account_settings:
|
||||||
title: "Account Istellige"
|
title: "Account Istellige"
|
||||||
|
@ -166,16 +166,16 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
||||||
password_tab: "Passwort"
|
password_tab: "Passwort"
|
||||||
emails_tab: "E-Mails"
|
emails_tab: "E-Mails"
|
||||||
admin: "Admin"
|
admin: "Admin"
|
||||||
# wizard_color: "Wizard Clothes Color"
|
wizard_color: "Zaubererchleid Farb"
|
||||||
new_password: "Neus Passwort"
|
new_password: "Neus Passwort"
|
||||||
new_password_verify: "Bestätige"
|
new_password_verify: "Bestätige"
|
||||||
email_subscriptions: "E-Mail Abos"
|
email_subscriptions: "E-Mail Abos"
|
||||||
email_announcements: "Akündigunge"
|
email_announcements: "Akündigunge"
|
||||||
email_announcements_description: "Bechum Mails mit Neuigkeite und de neuste Entwicklige bi CodeCombat."
|
email_announcements_description: "Bechum Mails mit Neuigkeite und de neuste Entwicklige bi CodeCombat."
|
||||||
email_notifications: "Benachrichtigunge"
|
email_notifications: "Benachrichtigunge"
|
||||||
# email_notifications_summary: "Controls for personalized, automatic email notifications related to your CodeCombat activity."
|
email_notifications_summary: "Istellige für personalisierti, automatischi E-Mail Notifikatione im Zemehang mit dine CodeCombat Aktivitäte"
|
||||||
# email_any_notes: "Any Notifications"
|
email_any_notes: "Alli Notifikatione"
|
||||||
# email_any_notes_description: "Disable to stop all activity notification emails."
|
email_any_notes_description: "Deaktiviere zum kei Aktivitäts-Notifikatione meh per E-Mail becho."
|
||||||
# email_recruit_notes: "Job Opportunities"
|
# email_recruit_notes: "Job Opportunities"
|
||||||
# email_recruit_notes_description: "If you play really well, we may contact you about getting you a (better) job."
|
# email_recruit_notes_description: "If you play really well, we may contact you about getting you a (better) job."
|
||||||
# contributor_emails: "Contributor Class Emails"
|
# contributor_emails: "Contributor Class Emails"
|
||||||
|
@ -192,36 +192,35 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
||||||
# sample_profile: "See a sample profile"
|
# sample_profile: "See a sample profile"
|
||||||
# view_profile: "View Your Profile"
|
# view_profile: "View Your Profile"
|
||||||
|
|
||||||
# account_profile:
|
account_profile:
|
||||||
# settings: "Settings"
|
settings: "Istellige"
|
||||||
# edit_profile: "Edit Profile"
|
edit_profile: "Profil bearbeite"
|
||||||
# done_editing: "Done Editing"
|
done_editing: "Fertig mit bearbeite"
|
||||||
# profile_for_prefix: "Profile for "
|
profile_for_prefix: "Profil für "
|
||||||
# profile_for_suffix: ""
|
# profile_for_suffix: ""
|
||||||
# featured: "Featured"
|
# featured: "Featured"
|
||||||
# not_featured: "Not Featured"
|
# not_featured: "Not Featured"
|
||||||
# looking_for: "Looking for:"
|
# looking_for: "Looking for:"
|
||||||
# last_updated: "Last updated:"
|
last_updated: "S letzte Update:"
|
||||||
# contact: "Contact"
|
contact: "Kontakt"
|
||||||
# active: "Looking for interview offers now"
|
# active: "Looking for interview offers now"
|
||||||
# inactive: "Not looking for offers right now"
|
# inactive: "Not looking for offers right now"
|
||||||
# complete: "complete"
|
complete: "komplett"
|
||||||
# next: "Next"
|
next: "Nögst"
|
||||||
# next_city: "city?"
|
next_city: "Stadt?"
|
||||||
# next_country: "pick your country."
|
next_country: "wähl dis Land."
|
||||||
# next_name: "name?"
|
next_name: "Name?"
|
||||||
# next_short_description: "write a short description."
|
next_short_description: "schriibe e churzi Beschriibig."
|
||||||
# next_long_description: "describe your desired position."
|
next_long_description: "beschriib dini Wunschstell."
|
||||||
# next_skills: "list at least five skills."
|
|
||||||
# next_work: "chronicle your work history."
|
# next_work: "chronicle your work history."
|
||||||
# next_education: "recount your educational ordeals."
|
# next_education: "recount your educational ordeals."
|
||||||
# next_projects: "show off up to three projects you've worked on."
|
next_projects: "Zeig üs bis zu drü Projekt a dene du scho gschaffet hesch."
|
||||||
# next_links: "add any personal or social links."
|
next_links: "füeg persönlichi oder Social Media Links ih."
|
||||||
# next_photo: "add an optional professional photo."
|
# next_photo: "add an optional professional photo."
|
||||||
# next_active: "mark yourself open to offers to show up in searches."
|
# next_active: "mark yourself open to offers to show up in searches."
|
||||||
# example_blog: "Blog"
|
example_blog: "Blog"
|
||||||
# example_personal_site: "Personal Site"
|
example_personal_site: "Eigeni Websiite"
|
||||||
# links_header: "Personal Links"
|
links_header: "Eigeni Links"
|
||||||
# links_blurb: "Link any other sites or profiles you want to highlight, like your GitHub, your LinkedIn, or your blog."
|
# links_blurb: "Link any other sites or profiles you want to highlight, like your GitHub, your LinkedIn, or your blog."
|
||||||
# links_name: "Link Name"
|
# links_name: "Link Name"
|
||||||
# links_name_help: "What are you linking to?"
|
# links_name_help: "What are you linking to?"
|
||||||
|
@ -324,39 +323,39 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
||||||
# other_developers: "Other Developers"
|
# other_developers: "Other Developers"
|
||||||
# inactive_developers: "Inactive Developers"
|
# inactive_developers: "Inactive Developers"
|
||||||
|
|
||||||
# play_level:
|
play_level:
|
||||||
# done: "Done"
|
done: "Fertig"
|
||||||
# grid: "Grid"
|
grid: "Gitter"
|
||||||
# customize_wizard: "Customize Wizard"
|
customize_wizard: "Zauberer apasse"
|
||||||
# home: "Home"
|
home: "Home"
|
||||||
# guide: "Guide"
|
guide: "Aleitig"
|
||||||
# multiplayer: "Multiplayer"
|
multiplayer: "Multiplayer"
|
||||||
# restart: "Restart"
|
restart: "Neu starte"
|
||||||
# goals: "Goals"
|
goals: "Ziel"
|
||||||
# success: "Success!"
|
success: "Erfolg!"
|
||||||
# incomplete: "Incomplete"
|
incomplete: "Unvollständig"
|
||||||
# timed_out: "Ran out of time"
|
timed_out: "Ziit abglaufe"
|
||||||
# failing: "Failing"
|
failing: "Fehler"
|
||||||
# action_timeline: "Action Timeline"
|
action_timeline: "Aktionsziitleiste"
|
||||||
# click_to_select: "Click on a unit to select it."
|
click_to_select: "Klick uf e Einheit zum sie uswähle."
|
||||||
# reload_title: "Reload All Code?"
|
reload_title: "De ganze Code neu lade?"
|
||||||
# reload_really: "Are you sure you want to reload this level back to the beginning?"
|
reload_really: "Bisch sicher du willsch level neu lade bis zrugg zum Afang?"
|
||||||
# reload_confirm: "Reload All"
|
reload_confirm: "Alles neu lade"
|
||||||
# victory_title_prefix: ""
|
# victory_title_prefix: ""
|
||||||
# victory_title_suffix: " Complete"
|
victory_title_suffix: " Vollständig"
|
||||||
# victory_sign_up: "Sign Up to Save Progress"
|
victory_sign_up: "Meld dich ah zum din Fortschritt speichere"
|
||||||
# victory_sign_up_poke: "Want to save your code? Create a free account!"
|
victory_sign_up_poke: "Wötsch din Code speichere? Erstell gratis en Account!"
|
||||||
# victory_rate_the_level: "Rate the level: "
|
victory_rate_the_level: "Bewerte das Level: "
|
||||||
# victory_return_to_ladder: "Return to Ladder"
|
victory_return_to_ladder: "Zrugg zum letzte Level"
|
||||||
# victory_play_next_level: "Play Next Level"
|
victory_play_next_level: "Spiel s nögste Level"
|
||||||
# victory_go_home: "Go Home"
|
# victory_go_home: "Go Home"
|
||||||
# victory_review: "Tell us more!"
|
victory_review: "Verzell üs meh!"
|
||||||
# victory_hour_of_code_done: "Are You Done?"
|
victory_hour_of_code_done: "Bisch fertig?"
|
||||||
# victory_hour_of_code_done_yes: "Yes, I'm finished with my Hour of Code™!"
|
victory_hour_of_code_done_yes: "Jo, ich bin fertig mit mim Hour of Code™!"
|
||||||
# multiplayer_title: "Multiplayer Settings"
|
multiplayer_title: "Multiplayer Istellige"
|
||||||
# multiplayer_link_description: "Give this link to anyone to have them join you."
|
multiplayer_link_description: "Gib de Link jedem, wo mit dir will spiele."
|
||||||
# multiplayer_hint_label: "Hint:"
|
multiplayer_hint_label: "Hiiwis:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
multiplayer_hint: " Klick uf de Link zum alles uswähle und druck ⌘-C or Ctrl-C zum de Link kopiere"
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
CocoModel = require('./CocoModel')
|
CocoModel = require './CocoModel'
|
||||||
|
|
||||||
module.exports = class Article extends CocoModel
|
module.exports = class Article extends CocoModel
|
||||||
@className: "Article"
|
@className: 'Article'
|
||||||
@schema: require 'schemas/models/article'
|
@schema: require 'schemas/models/article'
|
||||||
urlRoot: "/db/article"
|
urlRoot: '/db/article'
|
||||||
saveBackups: true
|
saveBackups: true
|
||||||
|
|
|
@ -4,7 +4,7 @@ deltasLib = require 'lib/deltas'
|
||||||
NewAchievementCollection = require '../collections/NewAchievementCollection'
|
NewAchievementCollection = require '../collections/NewAchievementCollection'
|
||||||
|
|
||||||
class CocoModel extends Backbone.Model
|
class CocoModel extends Backbone.Model
|
||||||
idAttribute: "_id"
|
idAttribute: '_id'
|
||||||
loaded: false
|
loaded: false
|
||||||
loading: false
|
loading: false
|
||||||
saveBackups: false
|
saveBackups: false
|
||||||
|
@ -55,10 +55,12 @@ class CocoModel extends Backbone.Model
|
||||||
return unless @saveBackups
|
return unless @saveBackups
|
||||||
existing = storage.load @id
|
existing = storage.load @id
|
||||||
if existing
|
if existing
|
||||||
@set(existing, {silent:true})
|
@set(existing, {silent: true})
|
||||||
CocoModel.backedUp[@id] = @
|
CocoModel.backedUp[@id] = @
|
||||||
|
|
||||||
saveBackup: ->
|
saveBackup: -> @saveBackupNow()
|
||||||
|
|
||||||
|
saveBackupNow: ->
|
||||||
storage.save(@id, @attributes)
|
storage.save(@id, @attributes)
|
||||||
CocoModel.backedUp[@id] = @
|
CocoModel.backedUp[@id] = @
|
||||||
|
|
||||||
|
@ -74,7 +76,7 @@ class CocoModel extends Backbone.Model
|
||||||
if errors?.length
|
if errors?.length
|
||||||
console.debug "Validation failed for #{@constructor.className}: '#{@get('name') or @}'."
|
console.debug "Validation failed for #{@constructor.className}: '#{@get('name') or @}'."
|
||||||
for error in errors
|
for error in errors
|
||||||
console.debug "\t", error.dataPath, ":", error.message
|
console.debug "\t", error.dataPath, ':', error.message
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
save: (attrs, options) ->
|
save: (attrs, options) ->
|
||||||
|
@ -84,7 +86,7 @@ class CocoModel extends Backbone.Model
|
||||||
success = options.success
|
success = options.success
|
||||||
error = options.error
|
error = options.error
|
||||||
options.success = (model, res) =>
|
options.success = (model, res) =>
|
||||||
@trigger "save:success", @
|
@trigger 'save:success', @
|
||||||
success(@, res) if success
|
success(@, res) if success
|
||||||
@markToRevert() if @_revertAttributes
|
@markToRevert() if @_revertAttributes
|
||||||
@clearBackup()
|
@clearBackup()
|
||||||
|
@ -95,7 +97,7 @@ class CocoModel extends Backbone.Model
|
||||||
errorMessage = "Error saving #{@get('name') ? @type()}"
|
errorMessage = "Error saving #{@get('name') ? @type()}"
|
||||||
console.error errorMessage, res.responseJSON
|
console.error errorMessage, res.responseJSON
|
||||||
noty text: "#{errorMessage}: #{res.status} #{res.statusText}", layout: 'topCenter', type: 'error', killer: false, timeout: 10000
|
noty text: "#{errorMessage}: #{res.status} #{res.statusText}", layout: 'topCenter', type: 'error', killer: false, timeout: 10000
|
||||||
@trigger "save", @
|
@trigger 'save', @
|
||||||
return super attrs, options
|
return super attrs, options
|
||||||
|
|
||||||
patch: (options) ->
|
patch: (options) ->
|
||||||
|
@ -137,7 +139,6 @@ class CocoModel extends Backbone.Model
|
||||||
|
|
||||||
cloneNewMinorVersion: ->
|
cloneNewMinorVersion: ->
|
||||||
newData = _.clone @attributes
|
newData = _.clone @attributes
|
||||||
|
|
||||||
clone = new @constructor(newData)
|
clone = new @constructor(newData)
|
||||||
clone
|
clone
|
||||||
|
|
||||||
|
@ -152,20 +153,20 @@ class CocoModel extends Backbone.Model
|
||||||
false
|
false
|
||||||
|
|
||||||
publish: ->
|
publish: ->
|
||||||
if @isPublished() then throw new Error("Can't publish what's already-published. Can't kill what's already dead.")
|
if @isPublished() then throw new Error('Can\'t publish what\'s already-published. Can\'t kill what\'s already dead.')
|
||||||
@set "permissions", (@get("permissions") or []).concat({access: 'read', target: 'public'})
|
@set 'permissions', (@get('permissions') or []).concat({access: 'read', target: 'public'})
|
||||||
|
|
||||||
addSchemaDefaults: ->
|
addSchemaDefaults: ->
|
||||||
return if @addedSchemaDefaults
|
return if @addedSchemaDefaults
|
||||||
@addedSchemaDefaults = true
|
@addedSchemaDefaults = true
|
||||||
for prop, defaultValue of @constructor.schema.default or {}
|
for prop, defaultValue of @constructor.schema.default or {}
|
||||||
continue if @get(prop)?
|
continue if @get(prop)?
|
||||||
#console.log "setting", prop, "to", defaultValue, "from attributes.default"
|
#console.log 'setting', prop, 'to', defaultValue, 'from attributes.default'
|
||||||
@set prop, defaultValue
|
@set prop, defaultValue
|
||||||
for prop, sch of @constructor.schema.properties or {}
|
for prop, sch of @constructor.schema.properties or {}
|
||||||
continue if @get(prop)?
|
continue if @get(prop)?
|
||||||
continue if prop is 'emails' # hack, defaults are handled through User.coffee's email-specific methods.
|
continue if prop is 'emails' # hack, defaults are handled through User.coffee's email-specific methods.
|
||||||
#console.log "setting", prop, "to", sch.default, "from sch.default" if sch.default?
|
#console.log 'setting', prop, 'to', sch.default, 'from sch.default' if sch.default?
|
||||||
@set prop, sch.default if sch.default?
|
@set prop, sch.default if sch.default?
|
||||||
if @loaded
|
if @loaded
|
||||||
@loadFromBackup()
|
@loadFromBackup()
|
||||||
|
@ -210,7 +211,7 @@ class CocoModel extends Backbone.Model
|
||||||
try
|
try
|
||||||
jsondiffpatch.patch newAttributes, delta
|
jsondiffpatch.patch newAttributes, delta
|
||||||
catch error
|
catch error
|
||||||
console.error "Error applying delta", delta, "to attributes", newAttributes, error
|
console.error 'Error applying delta\n', JSON.stringify(delta, null, '\t'), '\n\nto attributes\n\n', newAttributes
|
||||||
return false
|
return false
|
||||||
@set newAttributes
|
@set newAttributes
|
||||||
return true
|
return true
|
||||||
|
@ -224,7 +225,7 @@ class CocoModel extends Backbone.Model
|
||||||
deltasLib.expandDelta(delta, @attributes, @schema())
|
deltasLib.expandDelta(delta, @attributes, @schema())
|
||||||
|
|
||||||
watch: (doWatch=true) ->
|
watch: (doWatch=true) ->
|
||||||
$.ajax("#{@urlRoot}/#{@id}/watch", {type:'PUT', data:{on:doWatch}})
|
$.ajax("#{@urlRoot}/#{@id}/watch", {type: 'PUT', data: {on: doWatch}})
|
||||||
@watching = -> doWatch
|
@watching = -> doWatch
|
||||||
|
|
||||||
watching: ->
|
watching: ->
|
||||||
|
@ -254,9 +255,9 @@ class CocoModel extends Backbone.Model
|
||||||
|
|
||||||
@getReferencedModel: (data, schema) ->
|
@getReferencedModel: (data, schema) ->
|
||||||
return null unless schema.links?
|
return null unless schema.links?
|
||||||
linkObject = _.find schema.links, rel: "db"
|
linkObject = _.find schema.links, rel: 'db'
|
||||||
return null unless linkObject
|
return null unless linkObject
|
||||||
return null if linkObject.href.match("thang.type") and not @isObjectID(data) # Skip loading hardcoded Thang Types for now (TODO)
|
return null if linkObject.href.match('thang.type') and not @isObjectID(data) # Skip loading hardcoded Thang Types for now (TODO)
|
||||||
|
|
||||||
# not fully extensible, but we can worry about that later
|
# not fully extensible, but we can worry about that later
|
||||||
link = linkObject.href
|
link = linkObject.href
|
||||||
|
@ -296,7 +297,6 @@ class CocoModel extends Backbone.Model
|
||||||
me.fetch (success: -> Backbone.Mediator.publish('achievements:new', collection)) unless _.isEmpty(collection.models)
|
me.fetch (success: -> Backbone.Mediator.publish('achievements:new', collection)) unless _.isEmpty(collection.models)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
CocoModel.pollAchievements = _.debounce CocoModel.pollAchievements, 500
|
CocoModel.pollAchievements = _.debounce CocoModel.pollAchievements, 500
|
||||||
|
|
||||||
module.exports = CocoModel
|
module.exports = CocoModel
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
CocoModel = require('./CocoModel')
|
CocoModel = require './CocoModel'
|
||||||
|
|
||||||
module.exports = class File extends CocoModel
|
module.exports = class File extends CocoModel
|
||||||
@className: "File"
|
@className: 'File'
|
||||||
@schema: {}
|
@schema: {}
|
||||||
urlRoot: "/db/file"
|
urlRoot: '/db/file'
|
||||||
|
|
|
@ -4,10 +4,10 @@ LevelSystem = require './LevelSystem'
|
||||||
ThangType = require './ThangType'
|
ThangType = require './ThangType'
|
||||||
|
|
||||||
module.exports = class Level extends CocoModel
|
module.exports = class Level extends CocoModel
|
||||||
@className: "Level"
|
@className: 'Level'
|
||||||
@schema: require 'schemas/models/level'
|
@schema: require 'schemas/models/level'
|
||||||
urlRoot: "/db/level"
|
urlRoot: '/db/level'
|
||||||
|
|
||||||
serialize: (supermodel) ->
|
serialize: (supermodel) ->
|
||||||
# o = _.cloneDeep @attributes # slow in level editor when there are hundreds of Thangs
|
# o = _.cloneDeep @attributes # slow in level editor when there are hundreds of Thangs
|
||||||
o = $.extend true, {}, @attributes
|
o = $.extend true, {}, @attributes
|
||||||
|
@ -23,7 +23,6 @@ module.exports = class Level extends CocoModel
|
||||||
@fillInDefaultSystemConfiguration o.systems
|
@fillInDefaultSystemConfiguration o.systems
|
||||||
|
|
||||||
o.thangTypes = (original: tt.get('original'), name: tt.get('name') for tt in supermodel.getModels ThangType)
|
o.thangTypes = (original: tt.get('original'), name: tt.get('name') for tt in supermodel.getModels ThangType)
|
||||||
|
|
||||||
o
|
o
|
||||||
|
|
||||||
sortSystems: (levelSystems, systemModels) ->
|
sortSystems: (levelSystems, systemModels) ->
|
||||||
|
@ -31,11 +30,11 @@ module.exports = class Level extends CocoModel
|
||||||
visit = (system) ->
|
visit = (system) ->
|
||||||
return if system.original of originalsSeen
|
return if system.original of originalsSeen
|
||||||
systemModel = _.find systemModels, {original: system.original}
|
systemModel = _.find systemModels, {original: system.original}
|
||||||
console.error "Couldn't find model for original", system.original, "from", systemModels unless systemModel
|
console.error 'Couldn\'t find model for original', system.original, 'from', systemModels unless systemModel
|
||||||
for d in systemModel.dependencies or []
|
for d in systemModel.dependencies or []
|
||||||
system2 = _.find levelSystems, {original: d.original}
|
system2 = _.find levelSystems, {original: d.original}
|
||||||
visit system2
|
visit system2
|
||||||
#console.log "sorted systems adding", systemModel.name
|
#console.log 'sorted systems adding', systemModel.name
|
||||||
sorted.push {model: systemModel, config: _.cloneDeep system.config}
|
sorted.push {model: systemModel, config: _.cloneDeep system.config}
|
||||||
originalsSeen[system.original] = true
|
originalsSeen[system.original] = true
|
||||||
visit system for system in levelSystems
|
visit system for system in levelSystems
|
||||||
|
@ -54,21 +53,21 @@ module.exports = class Level extends CocoModel
|
||||||
visit = (c) ->
|
visit = (c) ->
|
||||||
return if c in sorted
|
return if c in sorted
|
||||||
lc = _.find levelComponents, {original: c.original}
|
lc = _.find levelComponents, {original: c.original}
|
||||||
console.error thang.id, "couldn't find lc for", c unless lc
|
console.error thang.id, 'couldn\'t find lc for', c unless lc
|
||||||
if lc.name is "Programmable"
|
if lc.name is 'Programmable'
|
||||||
# Programmable always comes last
|
# Programmable always comes last
|
||||||
visit c2 for c2 in _.without thang.components, c
|
visit c2 for c2 in _.without thang.components, c
|
||||||
else
|
else
|
||||||
for d in lc.dependencies or []
|
for d in lc.dependencies or []
|
||||||
c2 = _.find thang.components, {original: d.original}
|
c2 = _.find thang.components, {original: d.original}
|
||||||
console.error thang.id, "couldn't find dependent Component", d.original, "from", lc.name unless c2
|
console.error thang.id, 'couldn\'t find dependent Component', d.original, 'from', lc.name unless c2
|
||||||
visit c2
|
visit c2
|
||||||
if lc.name is "Collides"
|
if lc.name is 'Collides'
|
||||||
allied = _.find levelComponents, {name: "Allied"}
|
allied = _.find levelComponents, {name: 'Allied'}
|
||||||
if allied
|
if allied
|
||||||
collides = _.find(thang.components, {original: allied.original})
|
collides = _.find(thang.components, {original: allied.original})
|
||||||
visit collides if collides
|
visit collides if collides
|
||||||
#console.log thang.id, "sorted comps adding", lc.name
|
#console.log thang.id, 'sorted comps adding', lc.name
|
||||||
sorted.push c
|
sorted.push c
|
||||||
for comp in thang.components
|
for comp in thang.components
|
||||||
visit comp
|
visit comp
|
||||||
|
@ -90,7 +89,7 @@ module.exports = class Level extends CocoModel
|
||||||
return unless properties
|
return unless properties
|
||||||
for prop, schema of properties
|
for prop, schema of properties
|
||||||
if schema.default? and config[prop] is undefined
|
if schema.default? and config[prop] is undefined
|
||||||
#console.log "Setting default of", config, "for", prop, "to", schema.default
|
#console.log 'Setting default of', config, 'for', prop, 'to', schema.default
|
||||||
config[prop] = schema.default
|
config[prop] = schema.default
|
||||||
if schema.type is 'object' and config[prop]
|
if schema.type is 'object' and config[prop]
|
||||||
@walkDefaults config[prop], schema.properties
|
@walkDefaults config[prop], schema.properties
|
||||||
|
@ -107,4 +106,4 @@ module.exports = class Level extends CocoModel
|
||||||
continue unless c?
|
continue unless c?
|
||||||
width = c.width if c.width? and c.width > width
|
width = c.width if c.width? and c.width > width
|
||||||
height = c.height if c.height? and c.height > height
|
height = c.height if c.height? and c.height > height
|
||||||
return {width:width, height:height}
|
return {width: width, height: height}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
CocoModel = require('./CocoModel')
|
CocoModel = require './CocoModel'
|
||||||
|
|
||||||
module.exports = class LevelComponent extends CocoModel
|
module.exports = class LevelComponent extends CocoModel
|
||||||
@className: "LevelComponent"
|
@className: 'LevelComponent'
|
||||||
@schema: require 'schemas/models/level_component'
|
@schema: require 'schemas/models/level_component'
|
||||||
urlRoot: "/db/level.component"
|
urlRoot: '/db/level.component'
|
||||||
|
|
||||||
set: (key, val, options) ->
|
set: (key, val, options) ->
|
||||||
if _.isObject key
|
if _.isObject key
|
||||||
|
@ -20,11 +20,11 @@ module.exports = class LevelComponent extends CocoModel
|
||||||
|
|
||||||
compile: (code) ->
|
compile: (code) ->
|
||||||
if @get('codeLanguage') and @get('codeLanguage') isnt 'coffeescript'
|
if @get('codeLanguage') and @get('codeLanguage') isnt 'coffeescript'
|
||||||
return console.error("Can't compile", @get('codeLanguage'), "-- only CoffeeScript.", @)
|
return console.error('Can\'t compile', @get('codeLanguage'), '-- only CoffeeScript.', @)
|
||||||
try
|
try
|
||||||
js = CoffeeScript.compile(code, bare: true)
|
js = CoffeeScript.compile(code, bare: true)
|
||||||
catch e
|
catch e
|
||||||
#console.log "couldn't compile", code, "for", @get('name'), "because", e
|
#console.log 'couldn\'t compile', code, 'for', @get('name'), 'because', e
|
||||||
js = @get 'js'
|
js = @get 'js'
|
||||||
js
|
js
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
CocoModel = require('./CocoModel')
|
CocoModel = require './CocoModel'
|
||||||
|
|
||||||
module.exports = class LevelFeedback extends CocoModel
|
module.exports = class LevelFeedback extends CocoModel
|
||||||
@className: "LevelFeedback"
|
@className: 'LevelFeedback'
|
||||||
@schema: require 'schemas/models/level_feedback'
|
@schema: require 'schemas/models/level_feedback'
|
||||||
urlRoot: "/db/level.feedback"
|
urlRoot: '/db/level.feedback'
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
CocoModel = require('./CocoModel')
|
CocoModel = require './CocoModel'
|
||||||
|
|
||||||
module.exports = class LevelSession extends CocoModel
|
module.exports = class LevelSession extends CocoModel
|
||||||
@className: "LevelSession"
|
@className: 'LevelSession'
|
||||||
@schema: require 'schemas/models/level_session'
|
@schema: require 'schemas/models/level_session'
|
||||||
urlRoot: "/db/level.session"
|
urlRoot: '/db/level.session'
|
||||||
|
|
||||||
initialize: ->
|
initialize: ->
|
||||||
super()
|
super()
|
||||||
|
@ -16,7 +16,7 @@ module.exports = class LevelSession extends CocoModel
|
||||||
permissions = @get 'permissions'
|
permissions = @get 'permissions'
|
||||||
permissions = (p for p in permissions when p.target isnt 'public')
|
permissions = (p for p in permissions when p.target isnt 'public')
|
||||||
if @get('multiplayer')
|
if @get('multiplayer')
|
||||||
permissions.push {target:'public', access:'write'}
|
permissions.push {target: 'public', access: 'write'}
|
||||||
@set 'permissions', permissions
|
@set 'permissions', permissions
|
||||||
|
|
||||||
getSourceFor: (spellKey) ->
|
getSourceFor: (spellKey) ->
|
||||||
|
@ -30,7 +30,7 @@ module.exports = class LevelSession extends CocoModel
|
||||||
return false unless c1 = @get('code')
|
return false unless c1 = @get('code')
|
||||||
return false unless team = @get('team')
|
return false unless team = @get('team')
|
||||||
return true unless c2 = @get('submittedCode')
|
return true unless c2 = @get('submittedCode')
|
||||||
thangSpellArr = (s.split("/") for s in @get('teamSpells')[team])
|
thangSpellArr = (s.split('/') for s in @get('teamSpells')[team])
|
||||||
for item in thangSpellArr
|
for item in thangSpellArr
|
||||||
thang = item[0]
|
thang = item[0]
|
||||||
spell = item[1]
|
spell = item[1]
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
CocoModel = require('./CocoModel')
|
CocoModel = require './CocoModel'
|
||||||
SystemNameLoader = require('lib/SystemNameLoader')
|
SystemNameLoader = require 'lib/SystemNameLoader'
|
||||||
|
|
||||||
module.exports = class LevelSystem extends CocoModel
|
module.exports = class LevelSystem extends CocoModel
|
||||||
@className: "LevelSystem"
|
@className: 'LevelSystem'
|
||||||
@schema: require 'schemas/models/level_system'
|
@schema: require 'schemas/models/level_system'
|
||||||
urlRoot: "/db/level.system"
|
urlRoot: '/db/level.system'
|
||||||
|
|
||||||
set: (key, val, options) ->
|
set: (key, val, options) ->
|
||||||
if _.isObject key
|
if _.isObject key
|
||||||
|
@ -22,11 +22,11 @@ module.exports = class LevelSystem extends CocoModel
|
||||||
|
|
||||||
compile: (code) ->
|
compile: (code) ->
|
||||||
if @get('codeLanguage') and @get('codeLanguage') isnt 'coffeescript'
|
if @get('codeLanguage') and @get('codeLanguage') isnt 'coffeescript'
|
||||||
return console.error("Can't compile", @get('codeLanguage'), "-- only CoffeeScript.", @)
|
return console.error('Can\'t compile', @get('codeLanguage'), '-- only CoffeeScript.', @)
|
||||||
try
|
try
|
||||||
js = CoffeeScript.compile(code, bare: true)
|
js = CoffeeScript.compile(code, bare: true)
|
||||||
catch e
|
catch e
|
||||||
#console.log "couldn't compile", code, "for", @get('name'), "because", e
|
#console.log 'couldn\'t compile', code, 'for', @get('name'), 'because', e
|
||||||
js = @get 'js'
|
js = @get 'js'
|
||||||
js
|
js
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
CocoModel = require('./CocoModel')
|
CocoModel = require './CocoModel'
|
||||||
|
|
||||||
module.exports = class PatchModel extends CocoModel
|
module.exports = class PatchModel extends CocoModel
|
||||||
@className: "Patch"
|
@className: 'Patch'
|
||||||
@schema: require 'schemas/models/patch'
|
@schema: require 'schemas/models/patch'
|
||||||
urlRoot: "/db/patch"
|
urlRoot: '/db/patch'
|
||||||
|
|
||||||
setStatus: (status) ->
|
setStatus: (status) ->
|
||||||
PatchModel.setStatus @id, status
|
PatchModel.setStatus @id, status
|
||||||
|
|
||||||
@setStatus: (id, status) ->
|
@setStatus: (id, status) ->
|
||||||
$.ajax("/db/patch/#{id}/status", {type:"PUT", data: {status:status}})
|
$.ajax("/db/patch/#{id}/status", {type: 'PUT', data: {status: status}})
|
||||||
|
|
|
@ -19,11 +19,11 @@ module.exports = class SuperModel extends Backbone.Model
|
||||||
|
|
||||||
report: ->
|
report: ->
|
||||||
# Useful for debugging why a SuperModel never finishes loading.
|
# Useful for debugging why a SuperModel never finishes loading.
|
||||||
console.info "SuperModel report ------------------------"
|
console.info 'SuperModel report ------------------------'
|
||||||
console.info "#{_.values(@resources).length} resources."
|
console.info "#{_.values(@resources).length} resources."
|
||||||
unfinished = []
|
unfinished = []
|
||||||
for resource in _.values(@resources) when resource
|
for resource in _.values(@resources) when resource
|
||||||
console.info '\t', resource.name, "loaded", resource.isLoaded
|
console.info "\t", resource.name, 'loaded', resource.isLoaded
|
||||||
unfinished.push resource unless resource.isLoaded
|
unfinished.push resource unless resource.isLoaded
|
||||||
unfinished
|
unfinished
|
||||||
|
|
||||||
|
@ -38,7 +38,6 @@ module.exports = class SuperModel extends Backbone.Model
|
||||||
res = @addModelResource(cachedModel, name, fetchOptions, value)
|
res = @addModelResource(cachedModel, name, fetchOptions, value)
|
||||||
res.markLoading()
|
res.markLoading()
|
||||||
return res
|
return res
|
||||||
|
|
||||||
else
|
else
|
||||||
@registerModel(model)
|
@registerModel(model)
|
||||||
res = @addModelResource(model, name, fetchOptions, value)
|
res = @addModelResource(model, name, fetchOptions, value)
|
||||||
|
@ -57,7 +56,6 @@ module.exports = class SuperModel extends Backbone.Model
|
||||||
res = @addModelResource(cachedCollection, name, fetchOptions, value)
|
res = @addModelResource(cachedCollection, name, fetchOptions, value)
|
||||||
res.markLoading()
|
res.markLoading()
|
||||||
return res
|
return res
|
||||||
|
|
||||||
else
|
else
|
||||||
@addCollection collection
|
@addCollection collection
|
||||||
@listenToOnce collection, 'sync', (c) ->
|
@listenToOnce collection, 'sync', (c) ->
|
||||||
|
@ -196,8 +194,6 @@ module.exports = class SuperModel extends Backbone.Model
|
||||||
getResource: (rid) ->
|
getResource: (rid) ->
|
||||||
return @resources[rid]
|
return @resources[rid]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Resource extends Backbone.Model
|
class Resource extends Backbone.Model
|
||||||
constructor: (name, value=1) ->
|
constructor: (name, value=1) ->
|
||||||
@name = name
|
@name = name
|
||||||
|
@ -230,8 +226,6 @@ class Resource extends Backbone.Model
|
||||||
|
|
||||||
load: -> @
|
load: -> @
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ModelResource extends Resource
|
class ModelResource extends Resource
|
||||||
constructor: (modelOrCollection, name, fetchOptions, value)->
|
constructor: (modelOrCollection, name, fetchOptions, value)->
|
||||||
super(name, value)
|
super(name, value)
|
||||||
|
@ -253,7 +247,6 @@ class ModelResource extends Resource
|
||||||
@jqxhr = null
|
@jqxhr = null
|
||||||
@model.jqxhr = null
|
@model.jqxhr = null
|
||||||
|
|
||||||
|
|
||||||
class RequestResource extends Resource
|
class RequestResource extends Resource
|
||||||
constructor: (name, jqxhrOptions, value) ->
|
constructor: (name, jqxhrOptions, value) ->
|
||||||
super(name, value)
|
super(name, value)
|
||||||
|
@ -267,6 +260,4 @@ class RequestResource extends Resource
|
||||||
@jqxhr.fail => _.defer => @markFailed()
|
@jqxhr.fail => _.defer => @markFailed()
|
||||||
@
|
@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SomethingResource extends Resource
|
class SomethingResource extends Resource
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
CocoModel = require('./CocoModel')
|
CocoModel = require './CocoModel'
|
||||||
SpriteBuilder = require 'lib/sprites/SpriteBuilder'
|
SpriteBuilder = require 'lib/sprites/SpriteBuilder'
|
||||||
|
|
||||||
buildQueue = []
|
buildQueue = []
|
||||||
|
|
||||||
module.exports = class ThangType extends CocoModel
|
module.exports = class ThangType extends CocoModel
|
||||||
@className: "ThangType"
|
@className: 'ThangType'
|
||||||
@schema: require 'schemas/models/thang_type'
|
@schema: require 'schemas/models/thang_type'
|
||||||
urlRoot: "/db/thang.type"
|
urlRoot: '/db/thang.type'
|
||||||
building: {}
|
building: {}
|
||||||
|
|
||||||
initialize: ->
|
initialize: ->
|
||||||
|
@ -27,7 +27,7 @@ module.exports = class ThangType extends CocoModel
|
||||||
@resetRawData() unless @get('raw')
|
@resetRawData() unless @get('raw')
|
||||||
|
|
||||||
resetRawData: ->
|
resetRawData: ->
|
||||||
@set('raw', {shapes:{}, containers:{}, animations:{}})
|
@set('raw', {shapes: {}, containers: {}, animations: {}})
|
||||||
|
|
||||||
resetSpriteSheetCache: ->
|
resetSpriteSheetCache: ->
|
||||||
@buildActions()
|
@buildActions()
|
||||||
|
@ -48,7 +48,7 @@ module.exports = class ThangType extends CocoModel
|
||||||
for name, action of @actions
|
for name, action of @actions
|
||||||
action.name = name
|
action.name = name
|
||||||
for relatedName, relatedAction of action.relatedActions ? {}
|
for relatedName, relatedAction of action.relatedActions ? {}
|
||||||
relatedAction.name = action.name + "_" + relatedName
|
relatedAction.name = action.name + '_' + relatedName
|
||||||
@actions[relatedAction.name] = relatedAction
|
@actions[relatedAction.name] = relatedAction
|
||||||
@actions
|
@actions
|
||||||
|
|
||||||
|
@ -114,12 +114,12 @@ module.exports = class ThangType extends CocoModel
|
||||||
mc = @vectorParser.buildMovieClip name
|
mc = @vectorParser.buildMovieClip name
|
||||||
continue unless mc
|
continue unless mc
|
||||||
@builder.addMovieClip mc, null, animation.scale * @options.resolutionFactor
|
@builder.addMovieClip mc, null, animation.scale * @options.resolutionFactor
|
||||||
framesMap[animation.scale + "_" + name] = @builder._animations[name].frames
|
framesMap[animation.scale + '_' + name] = @builder._animations[name].frames
|
||||||
|
|
||||||
for name, action of @actions when action.animation
|
for name, action of @actions when action.animation
|
||||||
continue if name is 'portrait'
|
continue if name is 'portrait'
|
||||||
scale = action.scale ? @get('scale') ? 1
|
scale = action.scale ? @get('scale') ? 1
|
||||||
frames = framesMap[scale + "_" + action.animation]
|
frames = framesMap[scale + '_' + action.animation]
|
||||||
continue unless frames
|
continue unless frames
|
||||||
frames = @mapFrames(action.frames, frames[0]) if action.frames?
|
frames = @mapFrames(action.frames, frames[0]) if action.frames?
|
||||||
next = true
|
next = true
|
||||||
|
@ -179,7 +179,7 @@ module.exports = class ThangType extends CocoModel
|
||||||
buildQueue[0]?.buildAsync()
|
buildQueue[0]?.buildAsync()
|
||||||
@spriteSheets[key] = e.target.spriteSheet
|
@spriteSheets[key] = e.target.spriteSheet
|
||||||
@building[key] = false
|
@building[key] = false
|
||||||
@trigger 'build-complete', {key:key, thangType:@}
|
@trigger 'build-complete', {key: key, thangType: @}
|
||||||
@vectorParser = null
|
@vectorParser = null
|
||||||
|
|
||||||
logBuild: (startTime, async, portrait) ->
|
logBuild: (startTime, async, portrait) ->
|
||||||
|
@ -249,14 +249,14 @@ module.exports = class ThangType extends CocoModel
|
||||||
path: "db/thang.type/#{@get('original')}"
|
path: "db/thang.type/#{@get('original')}"
|
||||||
b64png: src
|
b64png: src
|
||||||
force: 'true'
|
force: 'true'
|
||||||
$.ajax('/file', { type: 'POST', data: body, success: callback or @onFileUploaded })
|
$.ajax('/file', {type: 'POST', data: body, success: callback or @onFileUploaded})
|
||||||
|
|
||||||
onFileUploaded: =>
|
onFileUploaded: =>
|
||||||
console.log 'Image uploaded'
|
console.log 'Image uploaded'
|
||||||
|
|
||||||
@loadUniversalWizard: ->
|
@loadUniversalWizard: ->
|
||||||
return @wizardType if @wizardType
|
return @wizardType if @wizardType
|
||||||
wizOriginal = "52a00d55cf1818f2be00000b"
|
wizOriginal = '52a00d55cf1818f2be00000b'
|
||||||
url = "/db/thang.type/#{wizOriginal}/version"
|
url = "/db/thang.type/#{wizOriginal}/version"
|
||||||
@wizardType = new module.exports()
|
@wizardType = new module.exports()
|
||||||
@wizardType.url = -> url
|
@wizardType.url = -> url
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
GRAVATAR_URL = 'https://www.gravatar.com/'
|
GRAVATAR_URL = 'https://www.gravatar.com/'
|
||||||
cache = {}
|
cache = {}
|
||||||
CocoModel = require('./CocoModel')
|
CocoModel = require './CocoModel'
|
||||||
|
|
||||||
module.exports = class User extends CocoModel
|
module.exports = class User extends CocoModel
|
||||||
@className: "User"
|
@className: 'User'
|
||||||
@schema: require 'schemas/models/user'
|
@schema: require 'schemas/models/user'
|
||||||
urlRoot: "/db/user"
|
urlRoot: '/db/user'
|
||||||
|
|
||||||
initialize: ->
|
initialize: ->
|
||||||
super()
|
super()
|
||||||
|
@ -16,24 +16,24 @@ module.exports = class User extends CocoModel
|
||||||
return 'admin' in permissions
|
return 'admin' in permissions
|
||||||
|
|
||||||
displayName: ->
|
displayName: ->
|
||||||
@get('name') or "Anoner"
|
@get('name') or 'Anoner'
|
||||||
|
|
||||||
lang: ->
|
lang: ->
|
||||||
@get('preferredLanguage') or "en-US"
|
@get('preferredLanguage') or 'en-US'
|
||||||
|
|
||||||
getPhotoURL: (size=80, useJobProfilePhoto=false) ->
|
getPhotoURL: (size=80, useJobProfilePhoto=false) ->
|
||||||
photoURL = if useJobProfilePhoto then @get('jobProfile')?.photoURL else null
|
photoURL = if useJobProfilePhoto then @get('jobProfile')?.photoURL else null
|
||||||
photoURL ||= @get('photoURL')
|
photoURL ||= @get('photoURL')
|
||||||
if photoURL
|
if photoURL
|
||||||
prefix = if photoURL.search(/\?/) is -1 then "?" else "&"
|
prefix = if photoURL.search(/\?/) is -1 then '?' else '&'
|
||||||
return "#{photoURL}#{prefix}s=#{size}" if photoURL.search('http') isnt -1 # legacy
|
return "#{photoURL}#{prefix}s=#{size}" if photoURL.search('http') isnt -1 # legacy
|
||||||
return "/file/#{photoURL}#{prefix}s=#{size}"
|
return "/file/#{photoURL}#{prefix}s=#{size}"
|
||||||
return "/db/user/#{@id}/avatar?s=#{size}"
|
return "/db/user/#{@id}/avatar?s=#{size}"
|
||||||
|
|
||||||
@getByID = (id, properties, force) ->
|
@getByID = (id, properties, force) ->
|
||||||
{me} = require('lib/auth')
|
{me} = require 'lib/auth'
|
||||||
return me if me.id is id
|
return me if me.id is id
|
||||||
user = cache[id] or new module.exports({_id:id})
|
user = cache[id] or new module.exports({_id: id})
|
||||||
if force or not cache[id]
|
if force or not cache[id]
|
||||||
user.loading = true
|
user.loading = true
|
||||||
user.fetch(
|
user.fetch(
|
||||||
|
@ -44,18 +44,18 @@ module.exports = class User extends CocoModel
|
||||||
)
|
)
|
||||||
cache[id] = user
|
cache[id] = user
|
||||||
user
|
user
|
||||||
|
|
||||||
getEnabledEmails: ->
|
getEnabledEmails: ->
|
||||||
@migrateEmails()
|
@migrateEmails()
|
||||||
emails = _.clone(@get('emails')) or {}
|
emails = _.clone(@get('emails')) or {}
|
||||||
emails = _.defaults emails, @schema().properties.emails.default
|
emails = _.defaults emails, @schema().properties.emails.default
|
||||||
(emailName for emailName, emailDoc of emails when emailDoc.enabled)
|
(emailName for emailName, emailDoc of emails when emailDoc.enabled)
|
||||||
|
|
||||||
setEmailSubscription: (name, enabled) ->
|
setEmailSubscription: (name, enabled) ->
|
||||||
newSubs = _.clone(@get('emails')) or {}
|
newSubs = _.clone(@get('emails')) or {}
|
||||||
(newSubs[name] ?= {}).enabled = enabled
|
(newSubs[name] ?= {}).enabled = enabled
|
||||||
@set 'emails', newSubs
|
@set 'emails', newSubs
|
||||||
|
|
||||||
emailMap:
|
emailMap:
|
||||||
announcement: 'generalNews'
|
announcement: 'generalNews'
|
||||||
developer: 'archmageNews'
|
developer: 'archmageNews'
|
||||||
|
@ -70,9 +70,9 @@ module.exports = class User extends CocoModel
|
||||||
return if @attributes.emails or not @attributes.emailSubscriptions
|
return if @attributes.emails or not @attributes.emailSubscriptions
|
||||||
oldSubs = @get('emailSubscriptions') or []
|
oldSubs = @get('emailSubscriptions') or []
|
||||||
newSubs = {}
|
newSubs = {}
|
||||||
newSubs[newSubName] = { enabled: oldSubName in oldSubs } for oldSubName, newSubName of @emailMap
|
newSubs[newSubName] = {enabled: oldSubName in oldSubs} for oldSubName, newSubName of @emailMap
|
||||||
@set('emails', newSubs)
|
@set('emails', newSubs)
|
||||||
|
|
||||||
isEmailSubscriptionEnabled: (name) -> (@get('emails') or {})[name]?.enabled
|
isEmailSubscriptionEnabled: (name) -> (@get('emails') or {})[name]?.enabled
|
||||||
|
|
||||||
a = 5
|
a = 5
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
CocoModel = require('./CocoModel')
|
CocoModel = require './CocoModel'
|
||||||
|
|
||||||
module.exports = class UserRemark extends CocoModel
|
module.exports = class UserRemark extends CocoModel
|
||||||
@className: "UserRemark"
|
@className: 'UserRemark'
|
||||||
@schema: require 'schemas/models/user_remark'
|
@schema: require 'schemas/models/user_remark'
|
||||||
urlRoot: "/db/user.remark"
|
urlRoot: '/db/user.remark'
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
module.exports =
|
module.exports =
|
||||||
bus:
|
bus:
|
||||||
title: "Bus"
|
title: 'Bus'
|
||||||
id: "bus"
|
id: 'bus'
|
||||||
$schema: "http://json-schema.org/draft-04/schema#"
|
$schema: 'http://json-schema.org/draft-04/schema#'
|
||||||
description: "Bus" # TODO
|
description: 'Bus' # TODO
|
||||||
type: "object"
|
type: 'object'
|
||||||
properties: # TODO
|
properties: # TODO
|
||||||
joined:
|
joined:
|
||||||
type: ["boolean", "null"]
|
type: ['boolean', 'null']
|
||||||
players:
|
players:
|
||||||
type: "object"
|
type: 'object'
|
||||||
required: ["joined", "players"]
|
required: ['joined', 'players']
|
||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
module.exports =
|
module.exports =
|
||||||
jQueryEvent:
|
jQueryEvent:
|
||||||
title: "jQuery Event"
|
title: 'jQuery Event'
|
||||||
id: "jQueryEvent"
|
id: 'jQueryEvent'
|
||||||
$schema: "http://json-schema.org/draft-04/schema#"
|
$schema: 'http://json-schema.org/draft-04/schema#'
|
||||||
description: "A standard jQuery Event"
|
description: 'A standard jQuery Event'
|
||||||
type: "object"
|
type: 'object'
|
||||||
properties: # TODO schema complete
|
properties: # TODO schema complete
|
||||||
altKey:
|
altKey:
|
||||||
type: "boolean"
|
type: 'boolean'
|
||||||
required: []
|
required: []
|
||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
|
|
|
@ -3,26 +3,24 @@ c = require './schemas'
|
||||||
|
|
||||||
languageCodeArrayRegex = c.generateLanguageCodeArrayRegex()
|
languageCodeArrayRegex = c.generateLanguageCodeArrayRegex()
|
||||||
|
|
||||||
|
|
||||||
ExampleSchema = {
|
ExampleSchema = {
|
||||||
title: "Example Schema",
|
title: 'Example Schema',
|
||||||
description:"An example schema",
|
description: 'An example schema',
|
||||||
type: "object",
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
text: {
|
text: {
|
||||||
title: "Text",
|
title: 'Text',
|
||||||
description: "A short message to display in the dialogue area. Markdown okay.",
|
description: 'A short message to display in the dialogue area. Markdown okay.',
|
||||||
type: "string",
|
type: 'string',
|
||||||
maxLength: 400
|
maxLength: 400
|
||||||
},
|
},
|
||||||
i18n: {"$ref": "#/definitions/i18n"}
|
i18n: {'$ref': '#/definitions/i18n'}
|
||||||
},
|
},
|
||||||
|
|
||||||
definitions: {
|
definitions: {
|
||||||
i18n: {
|
i18n: {
|
||||||
title: "i18n",
|
title: 'i18n',
|
||||||
description: "The internationalization object",
|
description: 'The internationalization object',
|
||||||
type: "object",
|
type: 'object',
|
||||||
patternProperties: {
|
patternProperties: {
|
||||||
languageCodeArrayRegex: {
|
languageCodeArrayRegex: {
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
|
@ -30,19 +28,18 @@ ExampleSchema = {
|
||||||
#put the translatable properties here
|
#put the translatable properties here
|
||||||
#if it is possible to not include i18n with a reference
|
#if it is possible to not include i18n with a reference
|
||||||
# to #/properties, you could just do
|
# to #/properties, you could just do
|
||||||
properties: {"$ref":"#/properties"}
|
properties: {'$ref': '#/properties'}
|
||||||
# text: {"$ref": "#/properties/text"}
|
# text: {'$ref': '#/properties/text'}
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
title: "LanguageCode",
|
title: 'LanguageCode',
|
||||||
description: "LanguageDescription"
|
description: 'LanguageDescription'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define a i18n object type for each schema, then have the i18n have it's oneOf check against
|
#define a i18n object type for each schema, then have the i18n have it's oneOf check against
|
||||||
#translatable schemas of that object
|
#translatable schemas of that object
|
||||||
|
|
|
@ -1,132 +1,132 @@
|
||||||
# The JSON Schema Core/Validation Meta-Schema, but with titles and descriptions added to make it easier to edit in Treema, and in CoffeeScript
|
# The JSON Schema Core/Validation Meta-Schema, but with titles and descriptions added to make it easier to edit in Treema, and in CoffeeScript
|
||||||
|
|
||||||
module.exports =
|
module.exports =
|
||||||
id: "metaschema"
|
id: 'metaschema'
|
||||||
displayProperty: "title"
|
displayProperty: 'title'
|
||||||
$schema: "http://json-schema.org/draft-04/schema#"
|
$schema: 'http://json-schema.org/draft-04/schema#'
|
||||||
title: "Schema"
|
title: 'Schema'
|
||||||
description: "Core schema meta-schema"
|
description: 'Core schema meta-schema'
|
||||||
definitions:
|
definitions:
|
||||||
schemaArray:
|
schemaArray:
|
||||||
type: "array"
|
type: 'array'
|
||||||
minItems: 1
|
minItems: 1
|
||||||
items: { $ref: "#" }
|
items: {$ref: '#'}
|
||||||
title: "Array of Schemas"
|
title: 'Array of Schemas'
|
||||||
"default": [{}]
|
'default': [{}]
|
||||||
positiveInteger:
|
positiveInteger:
|
||||||
type: "integer"
|
type: 'integer'
|
||||||
minimum: 0
|
minimum: 0
|
||||||
title: "Positive Integer"
|
title: 'Positive Integer'
|
||||||
positiveIntegerDefault0:
|
positiveIntegerDefault0:
|
||||||
allOf: [ { $ref: "#/definitions/positiveInteger" }, { "default": 0 } ]
|
allOf: [{$ref: '#/definitions/positiveInteger'}, {'default': 0}]
|
||||||
simpleTypes:
|
simpleTypes:
|
||||||
title: "Single Type"
|
title: 'Single Type'
|
||||||
"enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ]
|
'enum': ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string']
|
||||||
stringArray:
|
stringArray:
|
||||||
type: "array"
|
type: 'array'
|
||||||
items: { type: "string" }
|
items: {type: 'string'}
|
||||||
minItems: 1
|
minItems: 1
|
||||||
uniqueItems: true
|
uniqueItems: true
|
||||||
title: "String Array"
|
title: 'String Array'
|
||||||
"default": ['']
|
'default': ['']
|
||||||
type: "object"
|
type: 'object'
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
type: "string"
|
type: 'string'
|
||||||
format: "uri"
|
format: 'uri'
|
||||||
$schema:
|
$schema:
|
||||||
type: "string"
|
type: 'string'
|
||||||
format: "uri"
|
format: 'uri'
|
||||||
"default": "http://json-schema.org/draft-04/schema#"
|
'default': 'http://json-schema.org/draft-04/schema#'
|
||||||
title:
|
title:
|
||||||
type: "string"
|
type: 'string'
|
||||||
description:
|
description:
|
||||||
type: "string"
|
type: 'string'
|
||||||
"default": {}
|
'default': {}
|
||||||
multipleOf:
|
multipleOf:
|
||||||
type: "number"
|
type: 'number'
|
||||||
minimum: 0
|
minimum: 0
|
||||||
exclusiveMinimum: true
|
exclusiveMinimum: true
|
||||||
maximum:
|
maximum:
|
||||||
type: "number"
|
type: 'number'
|
||||||
exclusiveMaximum:
|
exclusiveMaximum:
|
||||||
type: "boolean"
|
type: 'boolean'
|
||||||
"default": false
|
'default': false
|
||||||
minimum:
|
minimum:
|
||||||
type: "number"
|
type: 'number'
|
||||||
exclusiveMinimum:
|
exclusiveMinimum:
|
||||||
type: "boolean"
|
type: 'boolean'
|
||||||
"default": false
|
'default': false
|
||||||
maxLength: { $ref: "#/definitions/positiveInteger" }
|
maxLength: {$ref: '#/definitions/positiveInteger'}
|
||||||
minLength: { $ref: "#/definitions/positiveIntegerDefault0" }
|
minLength: {$ref: '#/definitions/positiveIntegerDefault0'}
|
||||||
pattern:
|
pattern:
|
||||||
type: "string"
|
type: 'string'
|
||||||
format: "regex"
|
format: 'regex'
|
||||||
additionalItems:
|
additionalItems:
|
||||||
anyOf: [
|
anyOf: [
|
||||||
{ type: "boolean", "default": false }
|
{type: 'boolean', 'default': false}
|
||||||
{ $ref: "#" }
|
{$ref: '#'}
|
||||||
]
|
]
|
||||||
items:
|
items:
|
||||||
anyOf: [
|
anyOf: [
|
||||||
{ $ref: "#" }
|
{$ref: '#'}
|
||||||
{ $ref: "#/definitions/schemaArray" }
|
{$ref: '#/definitions/schemaArray'}
|
||||||
]
|
]
|
||||||
"default": {}
|
'default': {}
|
||||||
maxItems: { $ref: "#/definitions/positiveInteger" }
|
maxItems: {$ref: '#/definitions/positiveInteger'}
|
||||||
minItems: { $ref: "#/definitions/positiveIntegerDefault0" }
|
minItems: {$ref: '#/definitions/positiveIntegerDefault0'}
|
||||||
uniqueItems:
|
uniqueItems:
|
||||||
type: "boolean"
|
type: 'boolean'
|
||||||
"default": false
|
'default': false
|
||||||
maxProperties: { $ref: "#/definitions/positiveInteger" }
|
maxProperties: {$ref: '#/definitions/positiveInteger'}
|
||||||
minProperties: { $ref: "#/definitions/positiveIntegerDefault0" }
|
minProperties: {$ref: '#/definitions/positiveIntegerDefault0'}
|
||||||
required: { $ref: "#/definitions/stringArray" }
|
required: {$ref: '#/definitions/stringArray'}
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
anyOf: [
|
anyOf: [
|
||||||
{ type: "boolean", "default": true }
|
{type: 'boolean', 'default': true}
|
||||||
{ $ref: "#" }
|
{$ref: '#'}
|
||||||
]
|
]
|
||||||
"default": {}
|
'default': {}
|
||||||
definitions:
|
definitions:
|
||||||
type: "object"
|
type: 'object'
|
||||||
additionalProperties: { $ref: "#" }
|
additionalProperties: {$ref: '#'}
|
||||||
"default": {}
|
'default': {}
|
||||||
properties:
|
properties:
|
||||||
type: "object"
|
type: 'object'
|
||||||
additionalProperties: { $ref: "#" }
|
additionalProperties: {$ref: '#'}
|
||||||
"default": {}
|
'default': {}
|
||||||
patternProperties:
|
patternProperties:
|
||||||
type: "object"
|
type: 'object'
|
||||||
additionalProperties: { $ref: "#" }
|
additionalProperties: {$ref: '#'}
|
||||||
"default": {}
|
'default': {}
|
||||||
dependencies:
|
dependencies:
|
||||||
type: "object"
|
type: 'object'
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
anyOf: [
|
anyOf: [
|
||||||
{ $ref: "#" }
|
{$ref: '#'}
|
||||||
{ $ref: "#/definitions/stringArray" }
|
{$ref: '#/definitions/stringArray'}
|
||||||
]
|
]
|
||||||
"enum":
|
'enum':
|
||||||
type: "array"
|
type: 'array'
|
||||||
minItems: 1
|
minItems: 1
|
||||||
uniqueItems: true
|
uniqueItems: true
|
||||||
"default": ['']
|
'default': ['']
|
||||||
type:
|
type:
|
||||||
anyOf: [
|
anyOf: [
|
||||||
{ $ref: "#/definitions/simpleTypes" }
|
{$ref: '#/definitions/simpleTypes'}
|
||||||
{
|
{
|
||||||
type: "array"
|
type: 'array'
|
||||||
items: { $ref: "#/definitions/simpleTypes" }
|
items: {$ref: '#/definitions/simpleTypes'}
|
||||||
minItems: 1
|
minItems: 1
|
||||||
uniqueItems: true
|
uniqueItems: true
|
||||||
title: "Array of Types"
|
title: 'Array of Types'
|
||||||
"default": ['string']
|
'default': ['string']
|
||||||
}]
|
}]
|
||||||
allOf: { $ref: "#/definitions/schemaArray" }
|
allOf: {$ref: '#/definitions/schemaArray'}
|
||||||
anyOf: { $ref: "#/definitions/schemaArray" }
|
anyOf: {$ref: '#/definitions/schemaArray'}
|
||||||
oneOf: { $ref: "#/definitions/schemaArray" }
|
oneOf: {$ref: '#/definitions/schemaArray'}
|
||||||
not: { $ref: "#" }
|
not: {$ref: '#'}
|
||||||
dependencies:
|
dependencies:
|
||||||
exclusiveMaximum: [ "maximum" ]
|
exclusiveMaximum: ['maximum']
|
||||||
exclusiveMinimum: [ "minimum" ]
|
exclusiveMinimum: ['minimum']
|
||||||
"default": {}
|
'default': {}
|
||||||
|
|
|
@ -11,7 +11,7 @@ MongoQueryOperatorSchema =
|
||||||
'$in': type: 'array'
|
'$in': type: 'array'
|
||||||
'$lt': type: 'number'
|
'$lt': type: 'number'
|
||||||
'$lte': type: 'number'
|
'$lte': type: 'number'
|
||||||
'$ne': type: [ 'number', 'string' ]
|
'$ne': type: ['number', 'string']
|
||||||
'$nin': type: 'array'
|
'$nin': type: 'array'
|
||||||
additionalProperties: true # TODO set to false when the schema's done
|
additionalProperties: true # TODO set to false when the schema's done
|
||||||
|
|
||||||
|
@ -23,9 +23,9 @@ MongoFindQuerySchema =
|
||||||
#'^[-a-zA-Z0-9_]*$':
|
#'^[-a-zA-Z0-9_]*$':
|
||||||
'^[-a-zA-Z0-9\.]*$':
|
'^[-a-zA-Z0-9\.]*$':
|
||||||
oneOf: [
|
oneOf: [
|
||||||
#{ $ref: '#/definitions/' + MongoQueryOperatorSchema.id},
|
#{$ref: '#/definitions/' + MongoQueryOperatorSchema.id},
|
||||||
{ type: 'string' }
|
{type: 'string'},
|
||||||
{ type: 'object' }
|
{type: 'object'}
|
||||||
]
|
]
|
||||||
additionalProperties: true # TODO make Treema accept new pattern matched keys
|
additionalProperties: true # TODO make Treema accept new pattern matched keys
|
||||||
definitions: {}
|
definitions: {}
|
||||||
|
@ -41,12 +41,12 @@ _.extend(AchievementSchema.properties,
|
||||||
query:
|
query:
|
||||||
#type:'object'
|
#type:'object'
|
||||||
$ref: '#/definitions/' + MongoFindQuerySchema.id
|
$ref: '#/definitions/' + MongoFindQuerySchema.id
|
||||||
worth: { type: 'number' }
|
worth: {type: 'number'}
|
||||||
collection: { type: 'string' }
|
collection: {type: 'string'}
|
||||||
description: { type: 'string' }
|
description: {type: 'string'}
|
||||||
userField: { type: 'string' }
|
userField: {type: 'string'}
|
||||||
related: c.objectId(description: 'Related entity')
|
related: c.objectId(description: 'Related entity')
|
||||||
icon: { type: 'string', format: 'image-file', title: 'Icon' }
|
icon: {type: 'string', format: 'image-file', title: 'Icon'}
|
||||||
proportionalTo:
|
proportionalTo:
|
||||||
type: 'string'
|
type: 'string'
|
||||||
description: 'For repeatables only. Denotes the field a repeatable achievement needs for its calculations'
|
description: 'For repeatables only. Denotes the field a repeatable achievement needs for its calculations'
|
||||||
|
|
|
@ -3,8 +3,8 @@ c = require './../schemas'
|
||||||
ArticleSchema = c.object()
|
ArticleSchema = c.object()
|
||||||
c.extendNamedProperties ArticleSchema # name first
|
c.extendNamedProperties ArticleSchema # name first
|
||||||
|
|
||||||
ArticleSchema.properties.body = { type: 'string', title: 'Content', format: 'markdown' }
|
ArticleSchema.properties.body = {type: 'string', title: 'Content', format: 'markdown'}
|
||||||
ArticleSchema.properties.i18n = { type: 'object', title: 'i18n', format: 'i18n', props: ['name', 'body'] }
|
ArticleSchema.properties.i18n = {type: 'object', title: 'i18n', format: 'i18n', props: ['name', 'body']}
|
||||||
|
|
||||||
c.extendBasicProperties ArticleSchema, 'article'
|
c.extendBasicProperties ArticleSchema, 'article'
|
||||||
c.extendSearchableProperties ArticleSchema
|
c.extendSearchableProperties ArticleSchema
|
||||||
|
|
|
@ -9,7 +9,7 @@ module.exports =
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
rel: 'extra'
|
rel: 'extra'
|
||||||
href: "/db/user/{($)}"
|
href: '/db/user/{($)}'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
achievement: c.objectId
|
achievement: c.objectId
|
||||||
|
|
|
@ -3,242 +3,242 @@ ThangComponentSchema = require './thang_component'
|
||||||
|
|
||||||
SpecificArticleSchema = c.object()
|
SpecificArticleSchema = c.object()
|
||||||
c.extendNamedProperties SpecificArticleSchema # name first
|
c.extendNamedProperties SpecificArticleSchema # name first
|
||||||
SpecificArticleSchema.properties.body = { type: 'string', title: 'Content', description: "The body content of the article, in Markdown.", format: 'markdown' }
|
SpecificArticleSchema.properties.body = {type: 'string', title: 'Content', description: 'The body content of the article, in Markdown.', format: 'markdown'}
|
||||||
SpecificArticleSchema.properties.i18n = {type: "object", format: 'i18n', props: ['name', 'body'], description: "Help translate this article"}
|
SpecificArticleSchema.properties.i18n = {type: 'object', format: 'i18n', props: ['name', 'body'], description: 'Help translate this article'}
|
||||||
SpecificArticleSchema.displayProperty = 'name'
|
SpecificArticleSchema.displayProperty = 'name'
|
||||||
|
|
||||||
side = {title: "Side", description: "A side.", type: 'string', 'enum': ['left', 'right', 'top', 'bottom']}
|
side = {title: 'Side', description: 'A side.', type: 'string', 'enum': ['left', 'right', 'top', 'bottom']}
|
||||||
thang = {title: "Thang", description: "The name of a Thang.", type: 'string', maxLength: 30, format:'thang'}
|
thang = {title: 'Thang', description: 'The name of a Thang.', type: 'string', maxLength: 30, format: 'thang'}
|
||||||
|
|
||||||
eventPrereqValueTypes = ["boolean", "integer", "number", "null", "string"] # not "object" or "array"
|
eventPrereqValueTypes = ['boolean', 'integer', 'number', 'null', 'string'] # not 'object' or 'array'
|
||||||
EventPrereqSchema = c.object {title: "Event Prerequisite", format: 'event-prereq', description: "Script requires that the value of some property on the event triggering it to meet some prerequisite.", "default": {eventProps: []}, required: ["eventProps"]},
|
EventPrereqSchema = c.object {title: 'Event Prerequisite', format: 'event-prereq', description: 'Script requires that the value of some property on the event triggering it to meet some prerequisite.', 'default': {eventProps: []}, required: ['eventProps']},
|
||||||
eventProps: c.array {'default': ["thang"], format:'event-value-chain', maxItems: 10, title: "Event Property", description: 'A chain of keys in the event, like "thang.pos.x" to access event.thang.pos.x.'}, c.shortString(title: "Property", description: "A key in the event property key chain.")
|
eventProps: c.array {'default': ['thang'], format: 'event-value-chain', maxItems: 10, title: 'Event Property', description: 'A chain of keys in the event, like "thang.pos.x" to access event.thang.pos.x.'}, c.shortString(title: 'Property', description: 'A key in the event property key chain.')
|
||||||
equalTo: c.object {type: eventPrereqValueTypes, title: "==", description: "Script requires the event's property chain value to be equal to this value."}
|
equalTo: c.object {type: eventPrereqValueTypes, title: '==', description: 'Script requires the event\'s property chain value to be equal to this value.'}
|
||||||
notEqualTo: c.object {type: eventPrereqValueTypes, title: "!=", description: "Script requires the event's property chain value to *not* be equal to this value."}
|
notEqualTo: c.object {type: eventPrereqValueTypes, title: '!=', description: 'Script requires the event\'s property chain value to *not* be equal to this value.'}
|
||||||
greaterThan: {type: 'number', title: ">", description: "Script requires the event's property chain value to be greater than this value."}
|
greaterThan: {type: 'number', title: '>', description: 'Script requires the event\'s property chain value to be greater than this value.'}
|
||||||
greaterThanOrEqualTo: {type: 'number', title: ">=", description: "Script requires the event's property chain value to be greater or equal to this value."}
|
greaterThanOrEqualTo: {type: 'number', title: '>=', description: 'Script requires the event\'s property chain value to be greater or equal to this value.'}
|
||||||
lessThan: {type: 'number', title: "<", description: "Script requires the event's property chain value to be less than this value."}
|
lessThan: {type: 'number', title: '<', description: 'Script requires the event\'s property chain value to be less than this value.'}
|
||||||
lessThanOrEqualTo: {type: 'number', title: "<=", description: "Script requires the event's property chain value to be less than or equal to this value."}
|
lessThanOrEqualTo: {type: 'number', title: '<=', description: 'Script requires the event\'s property chain value to be less than or equal to this value.'}
|
||||||
containingString: c.shortString(title: "Contains", description: "Script requires the event's property chain value to be a string containing this string.")
|
containingString: c.shortString(title: 'Contains', description: 'Script requires the event\'s property chain value to be a string containing this string.')
|
||||||
notContainingString: c.shortString(title: "Does not contain", description: "Script requires the event's property chain value to *not* be a string containing this string.")
|
notContainingString: c.shortString(title: 'Does not contain', description: 'Script requires the event\'s property chain value to *not* be a string containing this string.')
|
||||||
containingRegexp: c.shortString(title: "Contains Regexp", description: "Script requires the event's property chain value to be a string containing this regular expression.")
|
containingRegexp: c.shortString(title: 'Contains Regexp', description: 'Script requires the event\'s property chain value to be a string containing this regular expression.')
|
||||||
notContainingRegexp: c.shortString(title: "Does not contain regexp", description: "Script requires the event's property chain value to *not* be a string containing this regular expression.")
|
notContainingRegexp: c.shortString(title: 'Does not contain regexp', description: 'Script requires the event\'s property chain value to *not* be a string containing this regular expression.')
|
||||||
|
|
||||||
GoalSchema = c.object {title: "Goal", description: "A goal that the player can accomplish.", required: ["name", "id"]},
|
GoalSchema = c.object {title: 'Goal', description: 'A goal that the player can accomplish.', required: ['name', 'id']},
|
||||||
name: c.shortString(title: "Name", description: "Name of the goal that the player will see, like \"Defeat eighteen dragons\".")
|
name: c.shortString(title: 'Name', description: 'Name of the goal that the player will see, like \"Defeat eighteen dragons\".')
|
||||||
i18n: {type: "object", format: 'i18n', props: ['name'], description: "Help translate this goal"}
|
i18n: {type: 'object', format: 'i18n', props: ['name'], description: 'Help translate this goal'}
|
||||||
id: c.shortString(title: "ID", description: "Unique identifier for this goal, like \"defeat-dragons\".") # unique somehow?
|
id: c.shortString(title: 'ID', description: 'Unique identifier for this goal, like \"defeat-dragons\".') # unique somehow?
|
||||||
worldEndsAfter: {title: 'World Ends After', description: "When included, ends the world this many seconds after this goal succeeds or fails.", type: 'number', minimum: 0, exclusiveMinimum: true, maximum: 300, default: 3}
|
worldEndsAfter: {title: 'World Ends After', description: 'When included, ends the world this many seconds after this goal succeeds or fails.', type: 'number', minimum: 0, exclusiveMinimum: true, maximum: 300, default: 3}
|
||||||
howMany: {title: "How Many", description: "When included, require only this many of the listed goal targets instead of all of them.", type: 'integer', minimum: 1}
|
howMany: {title: 'How Many', description: 'When included, require only this many of the listed goal targets instead of all of them.', type: 'integer', minimum: 1}
|
||||||
hiddenGoal: {title: "Hidden", description: "Hidden goals don't show up in the goals area for the player until they're failed. (Usually they're obvious, like 'don't die'.)", 'type': 'boolean', default: false}
|
hiddenGoal: {title: 'Hidden', description: 'Hidden goals don\'t show up in the goals area for the player until they\'re failed. (Usually they\'re obvious, like "don\'t die".)', 'type': 'boolean', default: false}
|
||||||
team: c.shortString(title: 'Team', description: 'Name of the team this goal is for, if it is not for all of the playable teams.')
|
team: c.shortString(title: 'Team', description: 'Name of the team this goal is for, if it is not for all of the playable teams.')
|
||||||
killThangs: c.array {title: "Kill Thangs", description: "A list of Thang IDs the player should kill, or team names.", uniqueItems: true, minItems: 1, "default": ["ogres"]}, thang
|
killThangs: c.array {title: 'Kill Thangs', description: 'A list of Thang IDs the player should kill, or team names.', uniqueItems: true, minItems: 1, 'default': ['ogres']}, thang
|
||||||
saveThangs: c.array {title: "Save Thangs", description: "A list of Thang IDs the player should save, or team names", uniqueItems: true, minItems: 1, "default": ["humans"]}, thang
|
saveThangs: c.array {title: 'Save Thangs', description: 'A list of Thang IDs the player should save, or team names', uniqueItems: true, minItems: 1, 'default': ['humans']}, thang
|
||||||
getToLocations: c.object {title: "Get To Locations", description: "Will be set off when any of the \"who\" touch any of the \"targets\" ", required: ["who", "targets"]},
|
getToLocations: c.object {title: 'Get To Locations', description: 'Will be set off when any of the \"who\" touch any of the \"targets\"', required: ['who', 'targets']},
|
||||||
who: c.array {title: "Who", description: "The Thangs who must get to the target locations.", minItems: 1}, thang
|
who: c.array {title: 'Who', description: 'The Thangs who must get to the target locations.', minItems: 1}, thang
|
||||||
targets: c.array {title: "Targets", description: "The target locations to which the Thangs must get.", minItems: 1}, thang
|
targets: c.array {title: 'Targets', description: 'The target locations to which the Thangs must get.', minItems: 1}, thang
|
||||||
getAllToLocations: c.array {title: "Get all to locations", description: "Similar to getToLocations but now a specific \"who\" can have a specific \"target\", also must be used with the HowMany property for desired effect",required: ["getToLocation"]},
|
getAllToLocations: c.array {title: 'Get all to locations', description: 'Similar to getToLocations but now a specific \"who\" can have a specific \"target\", also must be used with the HowMany property for desired effect', required: ['getToLocation']},
|
||||||
c.object {title: "", description: ""},
|
c.object {title: '', description: ''},
|
||||||
getToLocation: c.object {title: "Get To Locations", description: "TODO: explain", required: ["who", "targets"]},
|
getToLocation: c.object {title: 'Get To Locations', description: 'TODO: explain', required: ['who', 'targets']},
|
||||||
who: c.array {title: "Who", description: "The Thangs who must get to the target locations.", minItems: 1}, thang
|
who: c.array {title: 'Who', description: 'The Thangs who must get to the target locations.', minItems: 1}, thang
|
||||||
targets: c.array {title: "Targets", description: "The target locations to which the Thangs must get.", minItems: 1}, thang
|
targets: c.array {title: 'Targets', description: 'The target locations to which the Thangs must get.', minItems: 1}, thang
|
||||||
keepFromLocations: c.object {title: "Keep From Locations", description: "TODO: explain", required: ["who", "targets"]},
|
keepFromLocations: c.object {title: 'Keep From Locations', description: 'TODO: explain', required: ['who', 'targets']},
|
||||||
who: c.array {title: "Who", description: "The Thangs who must not get to the target locations.", minItems: 1}, thang
|
who: c.array {title: 'Who', description: 'The Thangs who must not get to the target locations.', minItems: 1}, thang
|
||||||
targets: c.array {title: "Targets", description: "The target locations to which the Thangs must not get.", minItems: 1}, thang
|
targets: c.array {title: 'Targets', description: 'The target locations to which the Thangs must not get.', minItems: 1}, thang
|
||||||
keepAllFromLocations: c.array {title: "Keep ALL From Locations", description: "Similar to keepFromLocations but now a specific \"who\" can have a specific \"target\", also must be used with the HowMany property for desired effect", required: ["keepFromLocation"]},
|
keepAllFromLocations: c.array {title: 'Keep ALL From Locations', description: 'Similar to keepFromLocations but now a specific \"who\" can have a specific \"target\", also must be used with the HowMany property for desired effect', required: ['keepFromLocation']},
|
||||||
c.object {title: "", description: ""},
|
c.object {title: '', description: ''},
|
||||||
keepFromLocation: c.object {title: "Keep From Locations", description: "TODO: explain", required: ["who", "targets"]},
|
keepFromLocation: c.object {title: 'Keep From Locations', description: 'TODO: explain', required: ['who', 'targets']},
|
||||||
who: c.array {title: "Who", description: "The Thangs who must not get to the target locations.", minItems: 1}, thang
|
who: c.array {title: 'Who', description: 'The Thangs who must not get to the target locations.', minItems: 1}, thang
|
||||||
targets: c.array {title: "Targets", description: "The target locations to which the Thangs must not get.", minItems: 1}, thang
|
targets: c.array {title: 'Targets', description: 'The target locations to which the Thangs must not get.', minItems: 1}, thang
|
||||||
leaveOffSides: c.object {title: "Leave Off Sides", description: "Sides of the level to get some Thangs to leave across.", required: ["who", "sides"]},
|
leaveOffSides: c.object {title: 'Leave Off Sides', description: 'Sides of the level to get some Thangs to leave across.', required: ['who', 'sides']},
|
||||||
who: c.array {title: "Who", description: "The Thangs which must leave off the sides of the level.", minItems: 1}, thang
|
who: c.array {title: 'Who', description: 'The Thangs which must leave off the sides of the level.', minItems: 1}, thang
|
||||||
sides: c.array {title: "Sides", description: "The sides off which the Thangs must leave.", minItems: 1}, side
|
sides: c.array {title: 'Sides', description: 'The sides off which the Thangs must leave.', minItems: 1}, side
|
||||||
keepFromLeavingOffSides: c.object {title: "Keep From Leaving Off Sides", description: "Sides of the level to keep some Thangs from leaving across.", required: ["who", "sides"]},
|
keepFromLeavingOffSides: c.object {title: 'Keep From Leaving Off Sides', description: 'Sides of the level to keep some Thangs from leaving across.', required: ['who', 'sides']},
|
||||||
who: c.array {title: "Who", description: "The Thangs which must not leave off the sides of the level.", minItems: 1}, thang
|
who: c.array {title: 'Who', description: 'The Thangs which must not leave off the sides of the level.', minItems: 1}, thang
|
||||||
sides: side, {title: "Sides", description: "The sides off which the Thangs must not leave.", minItems: 1}, side
|
sides: side, {title: 'Sides', description: 'The sides off which the Thangs must not leave.', minItems: 1}, side
|
||||||
collectThangs: c.object {title: "Collect", description: "Thangs that other Thangs must collect.", required: ["who", "targets"]},
|
collectThangs: c.object {title: 'Collect', description: 'Thangs that other Thangs must collect.', required: ['who', 'targets']},
|
||||||
who: c.array {title: "Who", description: "The Thangs which must collect the target items.", minItems: 1}, thang
|
who: c.array {title: 'Who', description: 'The Thangs which must collect the target items.', minItems: 1}, thang
|
||||||
targets: c.array {title: "Targets", description: "The target items which the Thangs must collect.", minItems: 1}, thang
|
targets: c.array {title: 'Targets', description: 'The target items which the Thangs must collect.', minItems: 1}, thang
|
||||||
keepFromCollectingThangs: c.object {title: "Keep From Collecting", description: "Thangs that the player must prevent other Thangs from collecting.", required: ["who", "targets"]},
|
keepFromCollectingThangs: c.object {title: 'Keep From Collecting', description: 'Thangs that the player must prevent other Thangs from collecting.', required: ['who', 'targets']},
|
||||||
who: c.array {title: "Who", description: "The Thangs which must not collect the target items.", minItems: 1}, thang
|
who: c.array {title: 'Who', description: 'The Thangs which must not collect the target items.', minItems: 1}, thang
|
||||||
targets: c.array {title: "Targets", description: "The target items which the Thangs must not collect.", minItems: 1}, thang
|
targets: c.array {title: 'Targets', description: 'The target items which the Thangs must not collect.', minItems: 1}, thang
|
||||||
|
|
||||||
ResponseSchema = c.object {title: "Dialogue Button", description: "A button to be shown to the user with the dialogue.", required: ["text"]},
|
ResponseSchema = c.object {title: 'Dialogue Button', description: 'A button to be shown to the user with the dialogue.', required: ['text']},
|
||||||
text: {title: "Title", description: "The text that will be on the button", "default": "Okay", type: 'string', maxLength: 30}
|
text: {title: 'Title', description: 'The text that will be on the button', 'default': 'Okay', type: 'string', maxLength: 30}
|
||||||
channel: c.shortString(title: "Channel", format: 'event-channel', description: 'Channel that this event will be broadcast over, like "level-set-playing".')
|
channel: c.shortString(title: 'Channel', format: 'event-channel', description: 'Channel that this event will be broadcast over, like "level-set-playing".')
|
||||||
event: {type: 'object', title: "Event", description: "Event that will be broadcast when this button is pressed, like {playing: true}."}
|
event: {type: 'object', title: 'Event', description: 'Event that will be broadcast when this button is pressed, like {playing: true}.'}
|
||||||
buttonClass: c.shortString(title: "Button Class", description: 'CSS class that will be added to the button, like "btn-primary".')
|
buttonClass: c.shortString(title: 'Button Class', description: 'CSS class that will be added to the button, like "btn-primary".')
|
||||||
i18n: {type: "object", format: 'i18n', props: ['text'], description: "Help translate this button"}
|
i18n: {type: 'object', format: 'i18n', props: ['text'], description: 'Help translate this button'}
|
||||||
|
|
||||||
PointSchema = c.object {title: "Point", description: "An {x, y} coordinate point.", format: "point2d", required: ["x", "y"]},
|
PointSchema = c.object {title: 'Point', description: 'An {x, y} coordinate point.', format: 'point2d', required: ['x', 'y']},
|
||||||
x: {title: "x", description: "The x coordinate.", type: "number", "default": 15}
|
x: {title: 'x', description: 'The x coordinate.', type: 'number', 'default': 15}
|
||||||
y: {title: "y", description: "The y coordinate.", type: "number", "default": 20}
|
y: {title: 'y', description: 'The y coordinate.', type: 'number', 'default': 20}
|
||||||
|
|
||||||
SpriteCommandSchema = c.object {title: "Thang Command", description: "Make a target Thang move or say something, or select/deselect it.", required: ["id"], default: {id: "Captain Anya"}},
|
SpriteCommandSchema = c.object {title: 'Thang Command', description: 'Make a target Thang move or say something, or select/deselect it.', required: ['id'], default: {id: 'Captain Anya'}},
|
||||||
id: thang
|
id: thang
|
||||||
select: {title: "Select", description: "Select or deselect this Thang.", type: 'boolean'}
|
select: {title: 'Select', description: 'Select or deselect this Thang.', type: 'boolean'}
|
||||||
say: c.object {title: "Say", description: "Make this Thang say a message.", required: ["text"]},
|
say: c.object {title: 'Say', description: 'Make this Thang say a message.', required: ['text']},
|
||||||
blurb: c.shortString(title: "Blurb", description: "A very short message to display above this Thang's head. Plain text.", maxLength: 50)
|
blurb: c.shortString(title: 'Blurb', description: 'A very short message to display above this Thang\'s head. Plain text.', maxLength: 50)
|
||||||
mood: c.shortString(title: "Mood", description: "The mood with which the Thang speaks.", "enum": ["explain", "debrief", "congrats", "attack", "joke", "tip", "alarm"], "default": "explain")
|
mood: c.shortString(title: 'Mood', description: 'The mood with which the Thang speaks.', 'enum': ['explain', 'debrief', 'congrats', 'attack', 'joke', 'tip', 'alarm'], 'default': 'explain')
|
||||||
text: {title: "Text", description: "A short message to display in the dialogue area. Markdown okay.", type: "string", maxLength: 400}
|
text: {title: 'Text', description: 'A short message to display in the dialogue area. Markdown okay.', type: 'string', maxLength: 400}
|
||||||
sound: c.object {title: "Sound", description: "A dialogue sound file to accompany the message.", required: ["mp3", "ogg"]},
|
sound: c.object {title: 'Sound', description: 'A dialogue sound file to accompany the message.', required: ['mp3', 'ogg']},
|
||||||
mp3: c.shortString(title: "MP3", format: 'sound-file')
|
mp3: c.shortString(title: 'MP3', format: 'sound-file')
|
||||||
ogg: c.shortString(title: "OGG", format: 'sound-file')
|
ogg: c.shortString(title: 'OGG', format: 'sound-file')
|
||||||
preload: {title: "Preload", description: "Whether to load this sound file before the level can begin (typically for the first dialogue of a level).", type: 'boolean', "default": false}
|
preload: {title: 'Preload', description: 'Whether to load this sound file before the level can begin (typically for the first dialogue of a level).', type: 'boolean', 'default': false}
|
||||||
responses: c.array {title: "Buttons", description: "An array of buttons to include with the dialogue, with which the user can respond."}, ResponseSchema
|
responses: c.array {title: 'Buttons', description: 'An array of buttons to include with the dialogue, with which the user can respond.'}, ResponseSchema
|
||||||
i18n: {type: "object", format: 'i18n', props: ['blurb', 'text'], description: "Help translate this message"}
|
i18n: {type: 'object', format: 'i18n', props: ['blurb', 'text'], description: 'Help translate this message'}
|
||||||
move: c.object {title: "Move", description: "Tell the Thang to move.", required: ['target'], default: {target: {x: 20, y: 20}, duration: 500}},
|
move: c.object {title: 'Move', description: 'Tell the Thang to move.', required: ['target'], default: {target: {x: 20, y: 20}, duration: 500}},
|
||||||
target: _.extend _.cloneDeep(PointSchema), {title: 'Target', description: 'Target point to which the Thang will move.'}
|
target: _.extend _.cloneDeep(PointSchema), {title: 'Target', description: 'Target point to which the Thang will move.'}
|
||||||
duration: {title: "Duration", description: "Number of milliseconds over which to move, or 0 for an instant move.", type: 'integer', minimum: 0, default: 500, format: 'milliseconds'}
|
duration: {title: 'Duration', description: 'Number of milliseconds over which to move, or 0 for an instant move.', type: 'integer', minimum: 0, default: 500, format: 'milliseconds'}
|
||||||
|
|
||||||
NoteGroupSchema = c.object {title: "Note Group", description: "A group of notes that should be sent out as a result of this script triggering.", displayProperty: "name"},
|
NoteGroupSchema = c.object {title: 'Note Group', description: 'A group of notes that should be sent out as a result of this script triggering.', displayProperty: 'name'},
|
||||||
name: {title: "Name", description: "Short name describing the script, like \"Anya greets the player\", for your convenience.", type: "string"}
|
name: {title: 'Name', description: 'Short name describing the script, like \"Anya greets the player\", for your convenience.', type: 'string'}
|
||||||
dom: c.object {title: "DOM", description: "Manipulate things in the play area DOM, outside of the level area canvas."},
|
dom: c.object {title: 'DOM', description: 'Manipulate things in the play area DOM, outside of the level area canvas.'},
|
||||||
focus: c.shortString(title: "Focus", description: "Set the window focus to this DOM selector string.")
|
focus: c.shortString(title: 'Focus', description: 'Set the window focus to this DOM selector string.')
|
||||||
showVictory: {
|
showVictory: {
|
||||||
title: "Show Victory",
|
title: 'Show Victory',
|
||||||
description: "Show the done button and maybe also the victory modal.",
|
description: 'Show the done button and maybe also the victory modal.',
|
||||||
enum: [true, 'Done Button', 'Done Button And Modal'] # deprecate true, same as 'done_button_and_modal'
|
enum: [true, 'Done Button', 'Done Button And Modal'] # deprecate true, same as 'done_button_and_modal'
|
||||||
}
|
}
|
||||||
highlight: c.object {title: "Highlight", description: "Highlight the target DOM selector string with a big arrow."},
|
highlight: c.object {title: 'Highlight', description: 'Highlight the target DOM selector string with a big arrow.'},
|
||||||
target: c.shortString(title: "Target", description: "Target highlight element DOM selector string.")
|
target: c.shortString(title: 'Target', description: 'Target highlight element DOM selector string.')
|
||||||
delay: {type: 'integer', minimum: 0, title: "Delay", description: "Show the highlight after this many milliseconds. Doesn't affect the dim shade cutout highlight method."}
|
delay: {type: 'integer', minimum: 0, title: 'Delay', description: 'Show the highlight after this many milliseconds. Doesn\'t affect the dim shade cutout highlight method.'}
|
||||||
offset: _.extend _.cloneDeep(PointSchema), {title: 'Offset', description: 'Pointing arrow tip offset in pixels from the default target.', format: null}
|
offset: _.extend _.cloneDeep(PointSchema), {title: 'Offset', description: 'Pointing arrow tip offset in pixels from the default target.', format: null}
|
||||||
rotation: {type: 'number', minimum: 0, title: "Rotation", description: "Rotation of the pointing arrow, in radians. PI / 2 points left, PI points up, etc."}
|
rotation: {type: 'number', minimum: 0, title: 'Rotation', description: 'Rotation of the pointing arrow, in radians. PI / 2 points left, PI points up, etc.'}
|
||||||
sides: c.array {title: "Sides", description: "Which sides of the target element to point at."}, {type: 'string', 'enum': ['left', 'right', 'top', 'bottom'], title: "Side", description: "A side of the target element to point at."}
|
sides: c.array {title: 'Sides', description: 'Which sides of the target element to point at.'}, {type: 'string', 'enum': ['left', 'right', 'top', 'bottom'], title: 'Side', description: 'A side of the target element to point at.'}
|
||||||
lock: {title: "Lock", description: "Whether the interface should be locked so that the player's focus is on the script, or specific areas to lock.", type: ['boolean', 'array'], items: {type: 'string', enum: ['surface', 'editor', 'palette', 'hud', 'playback', 'playback-hover', 'level']}}
|
lock: {title: 'Lock', description: 'Whether the interface should be locked so that the player\'s focus is on the script, or specific areas to lock.', type: ['boolean', 'array'], items: {type: 'string', enum: ['surface', 'editor', 'palette', 'hud', 'playback', 'playback-hover', 'level']}}
|
||||||
letterbox: {type: 'boolean', title: 'Letterbox', description:'Turn letterbox mode on or off. Disables surface and playback controls.'}
|
letterbox: {type: 'boolean', title: 'Letterbox', description: 'Turn letterbox mode on or off. Disables surface and playback controls.'}
|
||||||
|
|
||||||
goals: c.object {title: "Goals (Old)", description: "Deprecated. Goals added here have no effect. Add goals in the level settings instead."},
|
goals: c.object {title: 'Goals (Old)', description: 'Deprecated. Goals added here have no effect. Add goals in the level settings instead.'},
|
||||||
add: c.array {title: "Add", description: "Deprecated. Goals added here have no effect. Add goals in the level settings instead."}, GoalSchema
|
add: c.array {title: 'Add', description: 'Deprecated. Goals added here have no effect. Add goals in the level settings instead.'}, GoalSchema
|
||||||
remove: c.array {title: "Remove", description: "Deprecated. Goals removed here have no effect. Adjust goals in the level settings instead."}, GoalSchema
|
remove: c.array {title: 'Remove', description: 'Deprecated. Goals removed here have no effect. Adjust goals in the level settings instead.'}, GoalSchema
|
||||||
|
|
||||||
playback: c.object {title: "Playback", description: "Control the playback of the level."},
|
playback: c.object {title: 'Playback', description: 'Control the playback of the level.'},
|
||||||
playing: {type: 'boolean', title: "Set Playing", description: "Set whether playback is playing or paused."}
|
playing: {type: 'boolean', title: 'Set Playing', description: 'Set whether playback is playing or paused.'}
|
||||||
scrub: c.object {title: "Scrub", description: "Scrub the level playback time to a certain point.", default: {offset: 2, duration: 1000, toRatio: 0.5}},
|
scrub: c.object {title: 'Scrub', description: 'Scrub the level playback time to a certain point.', default: {offset: 2, duration: 1000, toRatio: 0.5}},
|
||||||
offset: {type: 'integer', title: "Offset", description: "Number of frames by which to adjust the scrub target time.", default: 2}
|
offset: {type: 'integer', title: 'Offset', description: 'Number of frames by which to adjust the scrub target time.', default: 2}
|
||||||
duration: {type: 'integer', title: "Duration", description: "Number of milliseconds over which to scrub time.", minimum: 0, format: 'milliseconds'}
|
duration: {type: 'integer', title: 'Duration', description: 'Number of milliseconds over which to scrub time.', minimum: 0, format: 'milliseconds'}
|
||||||
toRatio: {type: 'number', title: "To Progress Ratio", description: "Set playback time to a target playback progress ratio.", minimum: 0, maximum: 1}
|
toRatio: {type: 'number', title: 'To Progress Ratio', description: 'Set playback time to a target playback progress ratio.', minimum: 0, maximum: 1}
|
||||||
toTime: {type: 'number', title: "To Time", description: "Set playback time to a target playback point, in seconds.", minimum: 0}
|
toTime: {type: 'number', title: 'To Time', description: 'Set playback time to a target playback point, in seconds.', minimum: 0}
|
||||||
toGoal: c.shortString(title: "To Goal", description: "Set playback time to when this goal was achieved. (TODO: not implemented.)")
|
toGoal: c.shortString(title: 'To Goal', description: 'Set playback time to when this goal was achieved. (TODO: not implemented.)')
|
||||||
|
|
||||||
script: c.object {title: "Script", description: "Extra configuration for this action group."},
|
script: c.object {title: 'Script', description: 'Extra configuration for this action group.'},
|
||||||
duration: {type: 'integer', minimum: 0, title: "Duration", description: "How long this script should last in milliseconds. 0 for indefinite.", format: 'milliseconds'}
|
duration: {type: 'integer', minimum: 0, title: 'Duration', description: 'How long this script should last in milliseconds. 0 for indefinite.', format: 'milliseconds'}
|
||||||
skippable: {type: 'boolean', title: "Skippable", description: "Whether this script shouldn't bother firing when the player skips past all current scripts."}
|
skippable: {type: 'boolean', title: 'Skippable', description: 'Whether this script shouldn\'t bother firing when the player skips past all current scripts.'}
|
||||||
beforeLoad: {type: 'boolean', title: "Before Load", description: "Whether this script should fire before the level is finished loading."}
|
beforeLoad: {type: 'boolean', title: 'Before Load', description: 'Whether this script should fire before the level is finished loading.'}
|
||||||
|
|
||||||
sprites: c.array {title: "Sprites", description: "Commands to issue to Sprites on the Surface."}, SpriteCommandSchema
|
sprites: c.array {title: 'Sprites', description: 'Commands to issue to Sprites on the Surface.'}, SpriteCommandSchema
|
||||||
|
|
||||||
surface: c.object {title: "Surface", description: "Commands to issue to the Surface itself."},
|
surface: c.object {title: 'Surface', description: 'Commands to issue to the Surface itself.'},
|
||||||
focus: c.object {title: "Camera", description: "Focus the camera on a specific point on the Surface.", format:'viewport'},
|
focus: c.object {title: 'Camera', description: 'Focus the camera on a specific point on the Surface.', format: 'viewport'},
|
||||||
target: {anyOf: [PointSchema, thang, {type: 'null'}], title: "Target", description: "Where to center the camera view.", default: {x:0, y:0}}
|
target: {anyOf: [PointSchema, thang, {type: 'null'}], title: 'Target', description: 'Where to center the camera view.', default: {x: 0, y: 0}}
|
||||||
zoom: {type: 'number', minimum: 0, exclusiveMinimum: true, maximum: 64, title: "Zoom", description: "What zoom level to use."}
|
zoom: {type: 'number', minimum: 0, exclusiveMinimum: true, maximum: 64, title: 'Zoom', description: 'What zoom level to use.'}
|
||||||
duration: {type:'number', minimum: 0, title: "Duration", description: "in ms"}
|
duration: {type: 'number', minimum: 0, title: 'Duration', description: 'in ms'}
|
||||||
bounds: c.array {title:'Boundary', maxItems: 2, minItems: 2, default:[{x:0,y:0}, {x:46, y:39}], format: 'bounds'}, PointSchema
|
bounds: c.array {title: 'Boundary', maxItems: 2, minItems: 2, default: [{x: 0, y: 0}, {x: 46, y: 39}], format: 'bounds'}, PointSchema
|
||||||
isNewDefault: {type:'boolean', format: 'hidden', title: "New Default", description: 'Set this as new default zoom once scripts end.'} # deprecated
|
isNewDefault: {type: 'boolean', format: 'hidden', title: 'New Default', description: 'Set this as new default zoom once scripts end.'} # deprecated
|
||||||
highlight: c.object {title: "Highlight", description: "Highlight specific Sprites on the Surface."},
|
highlight: c.object {title: 'Highlight', description: 'Highlight specific Sprites on the Surface.'},
|
||||||
targets: c.array {title: "Targets", description: "Thang IDs of target Sprites to highlight."}, thang
|
targets: c.array {title: 'Targets', description: 'Thang IDs of target Sprites to highlight.'}, thang
|
||||||
delay: {type: 'integer', minimum: 0, title: "Delay", description: "Delay in milliseconds before the highlight appears."}
|
delay: {type: 'integer', minimum: 0, title: 'Delay', description: 'Delay in milliseconds before the highlight appears.'}
|
||||||
lockSelect: {type: 'boolean', title: "Lock Select", description: "Whether to lock Sprite selection so that the player can't select/deselect anything."}
|
lockSelect: {type: 'boolean', title: 'Lock Select', description: 'Whether to lock Sprite selection so that the player can\'t select/deselect anything.'}
|
||||||
|
|
||||||
sound: c.object {title: "Sound", description: "Commands to control sound playback."},
|
sound: c.object {title: 'Sound', description: 'Commands to control sound playback.'},
|
||||||
suppressSelectionSounds: {type: "boolean", title: "Suppress Selection Sounds", description: "Whether to suppress selection sounds made from clicking on Thangs."}
|
suppressSelectionSounds: {type: 'boolean', title: 'Suppress Selection Sounds', description: 'Whether to suppress selection sounds made from clicking on Thangs.'}
|
||||||
music: c.object { title: "Music", description: "Control music playing"},
|
music: c.object {title: 'Music', description: 'Control music playing'},
|
||||||
play: { title: "Play", type: "boolean" }
|
play: {title: 'Play', type: 'boolean'}
|
||||||
file: c.shortString(title: "File", enum:['/music/music_level_1','/music/music_level_2','/music/music_level_3','/music/music_level_4','/music/music_level_5'])
|
file: c.shortString(title: 'File', enum: ['/music/music_level_1', '/music/music_level_2', '/music/music_level_3', '/music/music_level_4', '/music/music_level_5'])
|
||||||
|
|
||||||
ScriptSchema = c.object {
|
ScriptSchema = c.object {
|
||||||
title: "Script"
|
title: 'Script'
|
||||||
description: 'A script fires off a chain of notes to interact with the game when a certain event triggers it.'
|
description: 'A script fires off a chain of notes to interact with the game when a certain event triggers it.'
|
||||||
required: ["channel"]
|
required: ['channel']
|
||||||
'default': {channel: "world:won", noteChain: []}
|
'default': {channel: 'world:won', noteChain: []}
|
||||||
},
|
},
|
||||||
id: c.shortString(title: "ID", description: "A unique ID that other scripts can rely on in their Happens After prereqs, for sequencing.") # uniqueness?
|
id: c.shortString(title: 'ID', description: 'A unique ID that other scripts can rely on in their Happens After prereqs, for sequencing.') # uniqueness?
|
||||||
channel: c.shortString(title: "Event", format: 'event-channel', description: 'Event channel this script might trigger for, like "world:won".')
|
channel: c.shortString(title: 'Event', format: 'event-channel', description: 'Event channel this script might trigger for, like "world:won".')
|
||||||
eventPrereqs: c.array {title: "Event Checks", description: "Logical checks on the event for this script to trigger.", format:'event-prereqs'}, EventPrereqSchema
|
eventPrereqs: c.array {title: 'Event Checks', description: 'Logical checks on the event for this script to trigger.', format: 'event-prereqs'}, EventPrereqSchema
|
||||||
repeats: {title: "Repeats", description: "Whether this script can trigger more than once during a level.", enum: [true, false, 'session'], "default": false}
|
repeats: {title: 'Repeats', description: 'Whether this script can trigger more than once during a level.', enum: [true, false, 'session'], 'default': false}
|
||||||
scriptPrereqs: c.array {title: "Happens After", description: "Scripts that need to fire first."},
|
scriptPrereqs: c.array {title: 'Happens After', description: 'Scripts that need to fire first.'},
|
||||||
c.shortString(title: "ID", description: "A unique ID of a script.")
|
c.shortString(title: 'ID', description: 'A unique ID of a script.')
|
||||||
notAfter: c.array {title: "Not After", description: "Do not run this script if any of these scripts have run."},
|
notAfter: c.array {title: 'Not After', description: 'Do not run this script if any of these scripts have run.'},
|
||||||
c.shortString(title: "ID", description: "A unique ID of a script.")
|
c.shortString(title: 'ID', description: 'A unique ID of a script.')
|
||||||
noteChain: c.array {title: "Actions", description: "A list of things that happen when this script triggers."}, NoteGroupSchema
|
noteChain: c.array {title: 'Actions', description: 'A list of things that happen when this script triggers.'}, NoteGroupSchema
|
||||||
|
|
||||||
LevelThangSchema = c.object {
|
LevelThangSchema = c.object {
|
||||||
title: "Thang",
|
title: 'Thang',
|
||||||
description: "Thangs are any units, doodads, or abstract things that you use to build the level. (\"Thing\" was too confusing to say.)",
|
description: 'Thangs are any units, doodads, or abstract things that you use to build the level. (\"Thing\" was too confusing to say.)',
|
||||||
format: "thang"
|
format: 'thang'
|
||||||
required: ["id", "thangType", "components"]
|
required: ['id', 'thangType', 'components']
|
||||||
'default':
|
'default':
|
||||||
id: "Boris"
|
id: 'Boris'
|
||||||
thangType: "Soldier"
|
thangType: 'Soldier'
|
||||||
components: []
|
components: []
|
||||||
},
|
},
|
||||||
id: thang # TODO: figure out if we can make this unique and how to set dynamic defaults
|
id: thang # TODO: figure out if we can make this unique and how to set dynamic defaults
|
||||||
# TODO: split thangType into "original" and "majorVersion" like the rest for consistency
|
# TODO: split thangType into 'original' and 'majorVersion' like the rest for consistency
|
||||||
thangType: c.objectId(links: [{rel: "db", href: "/db/thang.type/{($)}/version"}], title: "Thang Type", description: "A reference to the original Thang template being configured.", format: 'thang-type')
|
thangType: c.objectId(links: [{rel: 'db', href: '/db/thang.type/{($)}/version'}], title: 'Thang Type', description: 'A reference to the original Thang template being configured.', format: 'thang-type')
|
||||||
components: c.array {title: "Components", description: "Thangs are configured by changing the Components attached to them.", uniqueItems: true, format: 'thang-components-array'}, ThangComponentSchema # TODO: uniqueness should be based on "original", not whole thing
|
components: c.array {title: 'Components', description: 'Thangs are configured by changing the Components attached to them.', uniqueItems: true, format: 'thang-components-array'}, ThangComponentSchema # TODO: uniqueness should be based on 'original', not whole thing
|
||||||
|
|
||||||
LevelSystemSchema = c.object {
|
LevelSystemSchema = c.object {
|
||||||
title: "System"
|
title: 'System'
|
||||||
description: "Configuration for a System that this Level uses."
|
description: 'Configuration for a System that this Level uses.'
|
||||||
format: 'level-system'
|
format: 'level-system'
|
||||||
required: ['original', 'majorVersion']
|
required: ['original', 'majorVersion']
|
||||||
'default':
|
'default':
|
||||||
majorVersion: 0
|
majorVersion: 0
|
||||||
config: {}
|
config: {}
|
||||||
links: [{rel: "db", href: "/db/level.system/{(original)}/version/{(majorVersion)}"}]
|
links: [{rel: 'db', href: '/db/level.system/{(original)}/version/{(majorVersion)}'}]
|
||||||
},
|
},
|
||||||
original: c.objectId(title: "Original", description: "A reference to the original System being configured.", format: "hidden")
|
original: c.objectId(title: 'Original', description: 'A reference to the original System being configured.', format: 'hidden')
|
||||||
config: c.object {title: "Configuration", description: "System-specific configuration properties.", additionalProperties: true, format: 'level-system-configuration'}
|
config: c.object {title: 'Configuration', description: 'System-specific configuration properties.', additionalProperties: true, format: 'level-system-configuration'}
|
||||||
majorVersion: {title: "Major Version", description: "Which major version of the System is being used.", type: 'integer', minimum: 0, default: 0, format: "hidden"}
|
majorVersion: {title: 'Major Version', description: 'Which major version of the System is being used.', type: 'integer', minimum: 0, default: 0, format: 'hidden'}
|
||||||
|
|
||||||
GeneralArticleSchema = c.object {
|
GeneralArticleSchema = c.object {
|
||||||
title: "Article"
|
title: 'Article'
|
||||||
description: "Reference to a general documentation article."
|
description: 'Reference to a general documentation article.'
|
||||||
required: ['original']
|
required: ['original']
|
||||||
format: 'latest-version-reference'
|
format: 'latest-version-reference'
|
||||||
'default':
|
'default':
|
||||||
original: null
|
original: null
|
||||||
majorVersion: 0
|
majorVersion: 0
|
||||||
links: [{rel: "db", href: "/db/article/{(original)}/version/{(majorVersion)}"}]
|
links: [{rel: 'db', href: '/db/article/{(original)}/version/{(majorVersion)}'}]
|
||||||
},
|
},
|
||||||
original: c.objectId(title: "Original", description: "A reference to the original Article.")#, format: "hidden") # hidden?
|
original: c.objectId(title: 'Original', description: 'A reference to the original Article.')#, format: 'hidden') # hidden?
|
||||||
majorVersion: {title: "Major Version", description: "Which major version of the Article is being used.", type: 'integer', minimum: 0}#, format: "hidden"} # hidden?
|
majorVersion: {title: 'Major Version', description: 'Which major version of the Article is being used.', type: 'integer', minimum: 0}#, format: 'hidden'} # hidden?
|
||||||
|
|
||||||
LevelSchema = c.object {
|
LevelSchema = c.object {
|
||||||
title: "Level"
|
title: 'Level'
|
||||||
description: "A spectacular level which will delight and educate its stalwart players with the sorcery of coding."
|
description: 'A spectacular level which will delight and educate its stalwart players with the sorcery of coding.'
|
||||||
required: ["name", "description", "scripts", "thangs", "documentation"]
|
required: ['name', 'description', 'scripts', 'thangs', 'documentation']
|
||||||
'default':
|
'default':
|
||||||
name: "Ineffable Wizardry"
|
name: 'Ineffable Wizardry'
|
||||||
description: "This level is indescribably flarmy."
|
description: 'This level is indescribably flarmy.'
|
||||||
documentation: {specificArticles: [], generalArticles: []}
|
documentation: {specificArticles: [], generalArticles: []}
|
||||||
scripts: []
|
scripts: []
|
||||||
thangs: []
|
thangs: []
|
||||||
}
|
}
|
||||||
c.extendNamedProperties LevelSchema # let's have the name be the first property
|
c.extendNamedProperties LevelSchema # let's have the name be the first property
|
||||||
_.extend LevelSchema.properties,
|
_.extend LevelSchema.properties,
|
||||||
description: {title: "Description", description: "A short explanation of what this level is about.", type: "string", maxLength: 65536, "default": "This level is indescribably flarmy!", format: 'markdown'}
|
description: {title: 'Description', description: 'A short explanation of what this level is about.', type: 'string', maxLength: 65536, 'default': 'This level is indescribably flarmy!', format: 'markdown'}
|
||||||
documentation: c.object {title: "Documentation", description: "Documentation articles relating to this level.", required: ["specificArticles", "generalArticles"], 'default': {specificArticles: [], generalArticles: []}},
|
documentation: c.object {title: 'Documentation', description: 'Documentation articles relating to this level.', required: ['specificArticles', 'generalArticles'], 'default': {specificArticles: [], generalArticles: []}},
|
||||||
specificArticles: c.array {title: "Specific Articles", description: "Specific documentation articles that live only in this level.", uniqueItems: true, "default": []}, SpecificArticleSchema
|
specificArticles: c.array {title: 'Specific Articles', description: 'Specific documentation articles that live only in this level.', uniqueItems: true, 'default': []}, SpecificArticleSchema
|
||||||
generalArticles: c.array {title: "General Articles", description: "General documentation articles that can be linked from multiple levels.", uniqueItems: true, "default": []}, GeneralArticleSchema
|
generalArticles: c.array {title: 'General Articles', description: 'General documentation articles that can be linked from multiple levels.', uniqueItems: true, 'default': []}, GeneralArticleSchema
|
||||||
background: c.objectId({format: 'hidden'})
|
background: c.objectId({format: 'hidden'})
|
||||||
nextLevel: {
|
nextLevel: {
|
||||||
type:'object',
|
type: 'object',
|
||||||
links: [{rel: "extra", href: "/db/level/{($)}"}, {rel:'db', href: "/db/level/{(original)}/version/{(majorVersion)}"}],
|
links: [{rel: 'extra', href: '/db/level/{($)}'}, {rel: 'db', href: '/db/level/{(original)}/version/{(majorVersion)}'}],
|
||||||
format: 'latest-version-reference',
|
format: 'latest-version-reference',
|
||||||
title: "Next Level",
|
title: 'Next Level',
|
||||||
description: "Reference to the next level players will play after beating this one."
|
description: 'Reference to the next level players will play after beating this one.'
|
||||||
}
|
}
|
||||||
scripts: c.array {title: "Scripts", description: "An array of scripts that trigger based on what the player does and affect things outside of the core level simulation.", "default": []}, ScriptSchema
|
scripts: c.array {title: 'Scripts', description: 'An array of scripts that trigger based on what the player does and affect things outside of the core level simulation.', 'default': []}, ScriptSchema
|
||||||
thangs: c.array {title: "Thangs", description: "An array of Thangs that make up the level.", "default": []}, LevelThangSchema
|
thangs: c.array {title: 'Thangs', description: 'An array of Thangs that make up the level.', 'default': []}, LevelThangSchema
|
||||||
systems: c.array {title: "Systems", description: "Levels are configured by changing the Systems attached to them.", uniqueItems: true, default: []}, LevelSystemSchema # TODO: uniqueness should be based on "original", not whole thing
|
systems: c.array {title: 'Systems', description: 'Levels are configured by changing the Systems attached to them.', uniqueItems: true, default: []}, LevelSystemSchema # TODO: uniqueness should be based on 'original', not whole thing
|
||||||
victory: c.object {title: "Victory Screen", default: {}, properties: {'body': {type: 'string', format: 'markdown', title: 'Body Text', description: 'Inserted into the Victory Modal once this level is complete. Tell the player they did a good job and what they accomplished!'}, i18n: {type: "object", format: 'i18n', props: ['body'], description: "Help translate this victory message"}}}
|
victory: c.object {title: 'Victory Screen', default: {}, properties: {'body': {type: 'string', format: 'markdown', title: 'Body Text', description: 'Inserted into the Victory Modal once this level is complete. Tell the player they did a good job and what they accomplished!'}, i18n: {type: 'object', format: 'i18n', props: ['body'], description: 'Help translate this victory message'}}}
|
||||||
i18n: {type: "object", format: 'i18n', props: ['name', 'description'], description: "Help translate this level"}
|
i18n: {type: 'object', format: 'i18n', props: ['name', 'description'], description: 'Help translate this level'}
|
||||||
icon: { type: 'string', format: 'image-file', title: 'Icon' }
|
icon: {type: 'string', format: 'image-file', title: 'Icon'}
|
||||||
goals: c.array {title: 'Goals', description: 'An array of goals which are visible to the player and can trigger scripts.'}, GoalSchema
|
goals: c.array {title: 'Goals', description: 'An array of goals which are visible to the player and can trigger scripts.'}, GoalSchema
|
||||||
type: c.shortString(title: "Type", description: "What kind of level this is.", "enum": ['campaign', 'ladder', 'ladder-tutorial'])
|
type: c.shortString(title: 'Type', description: 'What kind of level this is.', 'enum': ['campaign', 'ladder', 'ladder-tutorial'])
|
||||||
showsGuide: c.shortString(title: "Shows Guide", description: "If the guide is shown at the beginning of the level.", "enum": ['first-time', 'always'])
|
showsGuide: c.shortString(title: 'Shows Guide', description: 'If the guide is shown at the beginning of the level.', 'enum': ['first-time', 'always'])
|
||||||
|
|
||||||
c.extendBasicProperties LevelSchema, 'level'
|
c.extendBasicProperties LevelSchema, 'level'
|
||||||
c.extendSearchableProperties LevelSchema
|
c.extendSearchableProperties LevelSchema
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue