mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-28 01:55:38 -05:00
Merge branch 'master' of https://github.com/codecombat/codecombat
This commit is contained in:
commit
50b4e79c7b
25 changed files with 329 additions and 82 deletions
|
@ -40,12 +40,17 @@ module.exports = class SpriteParser
|
||||||
if movieClips.length
|
if movieClips.length
|
||||||
# First movie clip is root, so do it last
|
# First movie clip is root, so do it last
|
||||||
movieClips = movieClips[1 ... movieClips.length].concat([movieClips[0]])
|
movieClips = movieClips[1 ... movieClips.length].concat([movieClips[0]])
|
||||||
else if containers.length
|
|
||||||
# First container is root, so do it last
|
# first container isn't necessarily root... actually the last one is root in blue-cart
|
||||||
containers = containers[1 ... containers.length].concat([containers[0]])
|
# else if containers.length
|
||||||
|
# # First container is root, so do it last
|
||||||
|
# containers = containers[1 ... containers.length].concat([containers[0]])
|
||||||
mainClip = _.last(movieClips) ? _.last(containers)
|
mainClip = _.last(movieClips) ? _.last(containers)
|
||||||
@animationName = mainClip.name
|
@animationName = mainClip.name
|
||||||
for container in containers
|
for container, index in containers
|
||||||
|
if index is containers.length - 1 and not movieClips.length and container.bounds?.length
|
||||||
|
container.bounds[0] -= @width / 2
|
||||||
|
container.bounds[1] -= @height / 2
|
||||||
[shapeKeys, localShapes] = @getShapesFromBlock container, source
|
[shapeKeys, localShapes] = @getShapesFromBlock container, source
|
||||||
localContainers = @getContainersFromMovieClip container, source
|
localContainers = @getContainersFromMovieClip container, source
|
||||||
addChildArgs = @getAddChildCallArguments container, source
|
addChildArgs = @getAddChildCallArguments container, source
|
||||||
|
@ -62,6 +67,7 @@ module.exports = class SpriteParser
|
||||||
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
|
||||||
|
continue unless container.bounds and instructions.length
|
||||||
@addContainer {c: instructions, b: container.bounds}, container.name
|
@addContainer {c: instructions, b: container.bounds}, container.name
|
||||||
for movieClip, index in movieClips
|
for movieClip, index in movieClips
|
||||||
if index is 0
|
if index is 0
|
||||||
|
|
|
@ -240,7 +240,6 @@ module.exports = class ThangType extends CocoModel
|
||||||
return if _.isString spriteSheet
|
return if _.isString spriteSheet
|
||||||
return unless spriteSheet
|
return unless spriteSheet
|
||||||
canvas = $("<canvas width='#{size}' height='#{size}'></canvas>")
|
canvas = $("<canvas width='#{size}' height='#{size}'></canvas>")
|
||||||
console.log 'made canvas', canvas, 'with size', size unless canvas[0]
|
|
||||||
stage = new createjs.Stage(canvas[0])
|
stage = new createjs.Stage(canvas[0])
|
||||||
sprite = new createjs.Sprite(spriteSheet)
|
sprite = new createjs.Sprite(spriteSheet)
|
||||||
pt = @actions.portrait?.positions?.registration
|
pt = @actions.portrait?.positions?.registration
|
||||||
|
@ -261,6 +260,29 @@ module.exports = class ThangType extends CocoModel
|
||||||
createjs.Ticker.removeEventListener 'tick', @tick
|
createjs.Ticker.removeEventListener 'tick', @tick
|
||||||
@tick = null
|
@tick = null
|
||||||
stage
|
stage
|
||||||
|
|
||||||
|
getVectorPortraitStage: (size=100) ->
|
||||||
|
return unless @actions
|
||||||
|
canvas = $("<canvas width='#{size}' height='#{size}'></canvas>")
|
||||||
|
stage = new createjs.Stage(canvas[0])
|
||||||
|
portrait = @actions.portrait
|
||||||
|
return unless portrait and (portrait.animation or portrait.container)
|
||||||
|
scale = portrait.scale or 1
|
||||||
|
|
||||||
|
vectorParser = new SpriteBuilder(@, {})
|
||||||
|
if portrait.animation
|
||||||
|
sprite = vectorParser.buildMovieClip portrait.animation
|
||||||
|
sprite.gotoAndStop(0)
|
||||||
|
else if portrait.container
|
||||||
|
sprite = vectorParser.buildContainerFromStore(portrait.container)
|
||||||
|
|
||||||
|
pt = portrait.positions?.registration
|
||||||
|
sprite.regX = pt?.x or 0
|
||||||
|
sprite.regY = pt?.y or 0
|
||||||
|
sprite.scaleX = sprite.scaleY = scale * size / 100
|
||||||
|
stage.addChild(sprite)
|
||||||
|
stage.update()
|
||||||
|
stage
|
||||||
|
|
||||||
uploadGenericPortrait: (callback, src) ->
|
uploadGenericPortrait: (callback, src) ->
|
||||||
src ?= @getPortraitSource()
|
src ?= @getPortraitSource()
|
||||||
|
@ -339,9 +361,10 @@ module.exports = class ThangType extends CocoModel
|
||||||
unless itemConfig = _.find(components, original: LevelComponent.ItemID)?.config
|
unless itemConfig = _.find(components, original: LevelComponent.ItemID)?.config
|
||||||
console.warn @get('name'), 'is not an item, but you are asking for its stats.'
|
console.warn @get('name'), 'is not an item, but you are asking for its stats.'
|
||||||
return props: [], stats: {}
|
return props: [], stats: {}
|
||||||
|
stats = {}
|
||||||
props = itemConfig.programmableProperties ? []
|
props = itemConfig.programmableProperties ? []
|
||||||
props = props.concat itemConfig.moreProgrammableProperties ? []
|
props = props.concat itemConfig.moreProgrammableProperties ? []
|
||||||
stats = {}
|
props = _.without props, 'canCast', 'spellNames', 'spells'
|
||||||
for stat, modifiers of itemConfig.stats ? {}
|
for stat, modifiers of itemConfig.stats ? {}
|
||||||
stats[stat] = @formatStatDisplay stat, modifiers
|
stats[stat] = @formatStatDisplay stat, modifiers
|
||||||
for stat in itemConfig.extraHUDProperties ? []
|
for stat in itemConfig.extraHUDProperties ? []
|
||||||
|
|
|
@ -224,6 +224,7 @@ LevelSchema = c.object {
|
||||||
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, format: 'markdown'}
|
description: {title: 'Description', description: 'A short explanation of what this level is about.', type: 'string', maxLength: 65536, format: 'markdown'}
|
||||||
|
loadingTip: { type: 'string', title: 'Loading Tip', description: 'What to show for this level while it\'s loading.' }
|
||||||
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 }, SpecificArticleSchema
|
specificArticles: c.array {title: 'Specific Articles', description: 'Specific documentation articles that live only in this level.', uniqueItems: true }, SpecificArticleSchema
|
||||||
generalArticles: c.array {title: 'General Articles', description: 'General documentation articles that can be linked from multiple levels.', uniqueItems: true}, GeneralArticleSchema
|
generalArticles: c.array {title: 'General Articles', description: 'General documentation articles that can be linked from multiple levels.', uniqueItems: true}, GeneralArticleSchema
|
||||||
|
@ -243,7 +244,7 @@ _.extend LevelSchema.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!'},
|
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: ['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', 'loadingTip'], description: 'Help translate this level'}
|
||||||
icon: {type: 'string', format: 'image-file', title: 'Icon'}
|
icon: {type: 'string', format: 'image-file', title: 'Icon'}
|
||||||
banner: {type: 'string', format: 'image-file', title: 'Banner'}
|
banner: {type: 'string', format: 'image-file', title: 'Banner'}
|
||||||
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
|
||||||
|
|
|
@ -130,6 +130,7 @@ _.extend ThangTypeSchema.properties,
|
||||||
positions: PositionsSchema
|
positions: PositionsSchema
|
||||||
raster: {type: 'string', format: 'image-file', title: 'Raster Image'}
|
raster: {type: 'string', format: 'image-file', title: 'Raster Image'}
|
||||||
rasterIcon: { type: 'string', format: 'image-file', title: 'Raster Image Icon' }
|
rasterIcon: { type: 'string', format: 'image-file', title: 'Raster Image Icon' }
|
||||||
|
containerIcon: { type: 'string' }
|
||||||
featureImage: { type: 'string', format: 'image-file', title: 'Feature Image' }
|
featureImage: { type: 'string', format: 'image-file', title: 'Feature Image' }
|
||||||
colorGroups: c.object
|
colorGroups: c.object
|
||||||
title: 'Color Groups'
|
title: 'Color Groups'
|
||||||
|
|
|
@ -4,9 +4,8 @@ module.exports =
|
||||||
'ipad:products': c.object {required: ['products']},
|
'ipad:products': c.object {required: ['products']},
|
||||||
products: c.array {},
|
products: c.array {},
|
||||||
c.object {},
|
c.object {},
|
||||||
gems: { type: 'integer' }
|
|
||||||
price: { type: 'string' }
|
price: { type: 'string' }
|
||||||
id: { type: 'string' }
|
id: { type: 'string' }
|
||||||
|
|
||||||
'ipad:iap-complete': c.object {},
|
'ipad:iap-complete': c.object {},
|
||||||
gems: { type: 'integer' }
|
productID: { type: 'string' }
|
||||||
|
|
9
app/styles/editor/thang/vector-icon-setup-modal.sass
Normal file
9
app/styles/editor/thang/vector-icon-setup-modal.sass
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#vector-icon-setup-modal
|
||||||
|
select
|
||||||
|
margin-bottom: 20px
|
||||||
|
|
||||||
|
canvas
|
||||||
|
background: lightblue
|
||||||
|
border: 3px solid black
|
||||||
|
margin: 20px auto
|
||||||
|
display: block
|
|
@ -194,6 +194,26 @@ $gameControlMargin: 30px
|
||||||
display: block
|
display: block
|
||||||
margin: 10px auto 0 auto
|
margin: 10px auto 0 auto
|
||||||
width: 200px
|
width: 200px
|
||||||
|
|
||||||
|
.campaign-switch
|
||||||
|
color: purple
|
||||||
|
position: absolute
|
||||||
|
z-index: 1
|
||||||
|
font-size: 2vw
|
||||||
|
text-shadow: 0 0 0.3vw white, 0 0 0.3vw white
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
text-decoration: none
|
||||||
|
|
||||||
|
&#forest-link
|
||||||
|
left: 94.5%
|
||||||
|
top: 7%
|
||||||
|
transform: rotate(-35deg)
|
||||||
|
|
||||||
|
&#dungeon-link
|
||||||
|
left: 26.6%
|
||||||
|
top: 43%
|
||||||
|
transform: rotate(180deg)
|
||||||
|
|
||||||
.game-controls
|
.game-controls
|
||||||
position: absolute
|
position: absolute
|
||||||
|
|
|
@ -81,12 +81,15 @@ block outer_content
|
||||||
div#settings-col.well
|
div#settings-col.well
|
||||||
img#portrait.img-thumbnail
|
img#portrait.img-thumbnail
|
||||||
div.file-controls
|
div.file-controls
|
||||||
button(disabled=authorized === true ? undefined : "true").btn.btn-small.btn-info#upload-button
|
button(disabled=authorized === true ? undefined : "true").btn.btn-sm.btn-info#upload-button
|
||||||
span.glyphicon.glyphicon-upload
|
span.glyphicon.glyphicon-upload
|
||||||
span.spl Upload Animation
|
span.spl Upload Animation
|
||||||
button(disabled=authorized === true ? undefined : "true").btn.btn-small.btn-danger#clear-button
|
button(disabled=authorized === true ? undefined : "true").btn.btn-sm.btn-danger#clear-button
|
||||||
span.glyphicon.glyphicon-remove
|
span.glyphicon.glyphicon-remove
|
||||||
span.spl Clear Data
|
span.spl Clear Data
|
||||||
|
button#set-vector-icon(disabled=authorized === true ? undefined : "true").btn.btn-sm
|
||||||
|
span.glyphicon.glyphicon-gbp
|
||||||
|
span.spl Vector Icon Setup
|
||||||
input#real-upload-button(type="file")
|
input#real-upload-button(type="file")
|
||||||
#thang-type-file-size= fileSizeString
|
#thang-type-file-size= fileSizeString
|
||||||
div#thang-type-treema
|
div#thang-type-treema
|
||||||
|
|
24
app/templates/editor/thang/vector-icon-setup-modal.jade
Normal file
24
app/templates/editor/thang/vector-icon-setup-modal.jade
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
extends /templates/modal/modal_base
|
||||||
|
|
||||||
|
block modal-header-content
|
||||||
|
h3 Choose Container for Vector Icon
|
||||||
|
|
||||||
|
block modal-body-content
|
||||||
|
if chosenContainer
|
||||||
|
form.form
|
||||||
|
.form-group
|
||||||
|
select#container-select.form-control
|
||||||
|
for container in containers
|
||||||
|
option(value=container, selected=container === chosenContainer)= container
|
||||||
|
|
||||||
|
canvas(width=demoSize height=demoSize)#resulting-icon
|
||||||
|
|
||||||
|
.alert.alert-info Arrow keys to move, Shift-Plus/Minus to scale.
|
||||||
|
else
|
||||||
|
div forgetting something?
|
||||||
|
|
||||||
|
block modal-footer-content
|
||||||
|
button.btn.pull-left.btn-info#center
|
||||||
|
span.glyphicon.glyphicon-cutlery
|
||||||
|
span.spl Center
|
||||||
|
button.btn.btn-primary#done-button Done
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
if props.length
|
if props.length
|
||||||
#skills
|
#skills
|
||||||
h3.big-font(data-i18n="play.skills-granted")
|
h3.big-font(data-i18n="play.skills_granted")
|
||||||
for prop in props
|
for prop in props
|
||||||
p
|
p
|
||||||
strong.big-font= prop.name
|
strong.big-font= prop.name
|
||||||
|
|
|
@ -35,12 +35,17 @@
|
||||||
.campaign-label(style="color: #{campaign.color}")= campaign.name
|
.campaign-label(style="color: #{campaign.color}")= campaign.name
|
||||||
if isIPadApp && !level.disabled && !level.locked
|
if isIPadApp && !level.disabled && !level.locked
|
||||||
button.btn.btn-success.btn-lg.start-level(data-i18n="common.play") Play
|
button.btn.btn-success.btn-lg.start-level(data-i18n="common.play") Play
|
||||||
|
if mapType === 'dungeon' && forestIsAvailable
|
||||||
|
a#forest-link.glyphicon.glyphicon-share-alt.campaign-switch(href="/play/forest", data-i18n="[title]play.campaign_forest")
|
||||||
|
if mapType === 'forest'
|
||||||
|
a#dungeon-link.glyphicon.glyphicon-share-alt.campaign-switch(href="/play/dungeon", data-i18n="[title]play.campaign_dungeon")
|
||||||
|
|
||||||
.game-controls.header-font
|
.game-controls.header-font
|
||||||
button.btn.items(data-toggle='coco-modal', data-target='play/modal/PlayItemsModal', data-i18n="[title]play.items")
|
button.btn.items(data-toggle='coco-modal', data-target='play/modal/PlayItemsModal', data-i18n="[title]play.items")
|
||||||
button.btn.heroes(data-toggle='coco-modal', data-target='play/modal/PlayHeroesModal', data-i18n="[title]play.heroes")
|
button.btn.heroes(data-toggle='coco-modal', data-target='play/modal/PlayHeroesModal', data-i18n="[title]play.heroes")
|
||||||
if me.isAdmin()
|
if me.isAdmin() || isIPadApp
|
||||||
button.btn.gems(data-toggle='coco-modal', data-target='play/modal/BuyGemsModal', data-i18n="[title]play.buy_gems")
|
button.btn.gems(data-toggle='coco-modal', data-target='play/modal/BuyGemsModal', data-i18n="[title]play.buy_gems")
|
||||||
|
if me.isAdmin()
|
||||||
button.btn.achievements(data-toggle='coco-modal', data-target='play/modal/PlayAchievementsModal', data-i18n="[title]play.achievements")
|
button.btn.achievements(data-toggle='coco-modal', data-target='play/modal/PlayAchievementsModal', data-i18n="[title]play.achievements")
|
||||||
button.btn.account(data-toggle='coco-modal', data-target='play/modal/PlayAccountModal', data-i18n="[title]play.account")
|
button.btn.account(data-toggle='coco-modal', data-target='play/modal/PlayAccountModal', data-i18n="[title]play.account")
|
||||||
button.btn.settings(data-toggle='coco-modal', data-target='play/modal/PlaySettingsModal', data-i18n="[title]play.settings")
|
button.btn.settings(data-toggle='coco-modal', data-target='play/modal/PlaySettingsModal', data-i18n="[title]play.settings")
|
||||||
|
@ -52,13 +57,6 @@
|
||||||
// a.btn.account(href="/user/#{me.getSlugOrID()}", data-i18n="[title]play.account")
|
// a.btn.account(href="/user/#{me.getSlugOrID()}", data-i18n="[title]play.account")
|
||||||
// a.btn.settings(href='/account', data-i18n="[title]play.settings")
|
// a.btn.settings(href='/account', data-i18n="[title]play.settings")
|
||||||
|
|
||||||
if mapType === 'forest'
|
|
||||||
a.btn.campaign-switch(href="/play/dungeon", data-i18n="[title]play.campaign_dungeon")
|
|
||||||
img(src="/images/pages/play/map_dungeon_icon.jpg").img-thumbnail
|
|
||||||
if mapType === 'dungeon'
|
|
||||||
a.btn.campaign-switch(href="/play/forest", data-i18n="[title]play.campaign_forest")
|
|
||||||
img(src="/images/pages/play/map_forest_icon.jpg").img-thumbnail
|
|
||||||
|
|
||||||
.old-levels
|
.old-levels
|
||||||
a(href="/play-old", data-i18n="play.older_campaigns").header-font Older Campaigns
|
a(href="/play-old", data-i18n="play.older_campaigns").header-font Older Campaigns
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ module.exports = class SettingsTabView extends CocoView
|
||||||
# not thangs or scripts or the backend stuff
|
# not thangs or scripts or the backend stuff
|
||||||
editableSettings: [
|
editableSettings: [
|
||||||
'name', 'description', 'documentation', 'nextLevel', 'background', 'victory', 'i18n', 'icon', 'goals',
|
'name', 'description', 'documentation', 'nextLevel', 'background', 'victory', 'i18n', 'icon', 'goals',
|
||||||
'type', 'terrain', 'showsGuide', 'banner', 'employerDescription'
|
'type', 'terrain', 'showsGuide', 'banner', 'employerDescription', 'loadingTip'
|
||||||
]
|
]
|
||||||
|
|
||||||
subscriptions:
|
subscriptions:
|
||||||
|
|
|
@ -12,6 +12,7 @@ ThangTypeVersionsModal = require './ThangTypeVersionsModal'
|
||||||
ThangTypeColorsTabView = require './ThangTypeColorsTabView'
|
ThangTypeColorsTabView = require './ThangTypeColorsTabView'
|
||||||
PatchesView = require 'views/editor/PatchesView'
|
PatchesView = require 'views/editor/PatchesView'
|
||||||
ForkModal = require 'views/editor/ForkModal'
|
ForkModal = require 'views/editor/ForkModal'
|
||||||
|
VectorIconSetupModal = require 'views/editor/thang/VectorIconSetupModal'
|
||||||
SaveVersionModal = require 'views/modal/SaveVersionModal'
|
SaveVersionModal = require 'views/modal/SaveVersionModal'
|
||||||
template = require 'templates/editor/thang/thang-type-edit-view'
|
template = require 'templates/editor/thang/thang-type-edit-view'
|
||||||
storage = require 'lib/storage'
|
storage = require 'lib/storage'
|
||||||
|
@ -33,6 +34,7 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
events:
|
events:
|
||||||
'click #clear-button': 'clearRawData'
|
'click #clear-button': 'clearRawData'
|
||||||
'click #upload-button': -> @$el.find('input#real-upload-button').click()
|
'click #upload-button': -> @$el.find('input#real-upload-button').click()
|
||||||
|
'click #set-vector-icon': 'onClickSetVectorIcon'
|
||||||
'change #real-upload-button': 'animationFileChosen'
|
'change #real-upload-button': 'animationFileChosen'
|
||||||
'change #animations-select': 'showAnimation'
|
'change #animations-select': 'showAnimation'
|
||||||
'click #marker-button': 'toggleDots'
|
'click #marker-button': 'toggleDots'
|
||||||
|
@ -47,6 +49,12 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
'keyup .play-with-level-input': 'onPlayLevelKeyUp'
|
'keyup .play-with-level-input': 'onPlayLevelKeyUp'
|
||||||
'click #pop-level-i18n-button': 'onPopulateLevelI18N'
|
'click #pop-level-i18n-button': 'onPopulateLevelI18N'
|
||||||
|
|
||||||
|
|
||||||
|
onClickSetVectorIcon: ->
|
||||||
|
modal = new VectorIconSetupModal({}, @thangType)
|
||||||
|
@openModalView modal
|
||||||
|
modal.once 'done', => @treema.set('/', @getThangData())
|
||||||
|
|
||||||
subscriptions:
|
subscriptions:
|
||||||
'editor:thang-type-color-groups-changed': 'onColorGroupsChanged'
|
'editor:thang-type-color-groups-changed': 'onColorGroupsChanged'
|
||||||
'editor:save-new-version': 'saveNewThangType'
|
'editor:save-new-version': 'saveNewThangType'
|
||||||
|
@ -234,7 +242,7 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
# animation select
|
# animation select
|
||||||
|
|
||||||
refreshAnimation: =>
|
refreshAnimation: =>
|
||||||
@thangType.buildActions()
|
@thangType.resetSpriteSheetCache()
|
||||||
return @showRasterImage() if @thangType.get('raster')
|
return @showRasterImage() if @thangType.get('raster')
|
||||||
options = @getLankOptions()
|
options = @getLankOptions()
|
||||||
console.log 'refresh animation....'
|
console.log 'refresh animation....'
|
||||||
|
|
115
app/views/editor/thang/VectorIconSetupModal.coffee
Normal file
115
app/views/editor/thang/VectorIconSetupModal.coffee
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
ModalView = require 'views/kinds/ModalView'
|
||||||
|
template = require 'templates/editor/thang/vector-icon-setup-modal'
|
||||||
|
|
||||||
|
module.exports = class VectorIconSetupModal extends ModalView
|
||||||
|
id: "vector-icon-setup-modal"
|
||||||
|
template: template
|
||||||
|
demoSize: 400
|
||||||
|
plain: true
|
||||||
|
|
||||||
|
events:
|
||||||
|
'change #container-select': 'onChangeContainer'
|
||||||
|
'click #center': 'onClickCenter'
|
||||||
|
'click #zero-bounds': 'onClickZeroBounds'
|
||||||
|
'click #done-button': 'onClickDone'
|
||||||
|
|
||||||
|
shortcuts:
|
||||||
|
'shift+-': -> @incrScale(-0.02)
|
||||||
|
'shift+=': -> @incrScale(0.02)
|
||||||
|
'up': -> @incrRegY(1)
|
||||||
|
'down': -> @incrRegY(-1)
|
||||||
|
'left': -> @incrRegX(1)
|
||||||
|
'right': -> @incrRegX(-1)
|
||||||
|
|
||||||
|
constructor: (options, @thangType) ->
|
||||||
|
portrait = @thangType.get('actions')?.portrait
|
||||||
|
@containers = _.keys(@thangType.get('raw')?.containers or {})
|
||||||
|
@container = portrait?.container or _.last @containers
|
||||||
|
@scale = portrait?.scale or 1
|
||||||
|
@regX = portrait?.positions?.registration?.x or 0
|
||||||
|
@regY = portrait?.positions?.registration?.y or 0
|
||||||
|
@saveChanges()
|
||||||
|
super(options)
|
||||||
|
|
||||||
|
saveChanges: ->
|
||||||
|
actions = _.cloneDeep (@thangType.get('actions') ? {})
|
||||||
|
actions.portrait ?= {}
|
||||||
|
actions.portrait.scale = @scale
|
||||||
|
actions.portrait.positions ?= {}
|
||||||
|
actions.portrait.positions.registration = { x: @regX, y: @regY }
|
||||||
|
actions.portrait.container = @container
|
||||||
|
@thangType.set('actions', actions)
|
||||||
|
@thangType.buildActions()
|
||||||
|
|
||||||
|
getRenderData: ->
|
||||||
|
c = super()
|
||||||
|
c.containers = @containers
|
||||||
|
c.chosenContainer = @container
|
||||||
|
c.demoSize = @demoSize
|
||||||
|
c
|
||||||
|
|
||||||
|
afterRender: ->
|
||||||
|
@initStage()
|
||||||
|
super()
|
||||||
|
|
||||||
|
initStage: ->
|
||||||
|
return unless @containers and @container
|
||||||
|
@stage = @thangType.getVectorPortraitStage(@demoSize)
|
||||||
|
@sprite = @stage.children[0]
|
||||||
|
canvas = $(@stage.canvas)
|
||||||
|
canvas.attr('id', 'resulting-icon')
|
||||||
|
@$el.find('#resulting-icon').replaceWith(canvas)
|
||||||
|
@updateSpriteProperties()
|
||||||
|
|
||||||
|
onChangeContainer: (e) ->
|
||||||
|
@container = $(e.target).val()
|
||||||
|
@saveChanges()
|
||||||
|
@initStage()
|
||||||
|
|
||||||
|
refreshSprite: ->
|
||||||
|
return unless @stage
|
||||||
|
stage = @thangType.getVectorPortraitStage(@demoSize)
|
||||||
|
@stage.removeAllChildren()
|
||||||
|
@stage.addChild(@sprite = stage.children[0])
|
||||||
|
@updateSpriteProperties()
|
||||||
|
@stage.update()
|
||||||
|
|
||||||
|
updateSpriteProperties: ->
|
||||||
|
@sprite.scaleX = @sprite.scaleY = @scale * @demoSize / 100
|
||||||
|
@sprite.regX = @regX
|
||||||
|
@sprite.regY = @regY
|
||||||
|
console.log 'set to', @scale, @regX, @regY
|
||||||
|
|
||||||
|
onClickCenter: ->
|
||||||
|
containerInfo = @thangType.get('raw').containers[@container]
|
||||||
|
b = containerInfo.b
|
||||||
|
@regX = b[0]
|
||||||
|
@regY = b[1]
|
||||||
|
maxDimension = Math.max(b[2], b[3])
|
||||||
|
@scale = 100 / maxDimension
|
||||||
|
if b[2] > b[3]
|
||||||
|
@regY += (b[3] - b[2]) / 2
|
||||||
|
else
|
||||||
|
@regX += (b[2] - b[3]) / 2
|
||||||
|
@updateSpriteProperties()
|
||||||
|
@stage.update()
|
||||||
|
|
||||||
|
incrScale: (amount) ->
|
||||||
|
@scale += amount
|
||||||
|
@updateSpriteProperties()
|
||||||
|
@stage.update()
|
||||||
|
|
||||||
|
incrRegX: (amount) ->
|
||||||
|
@regX += amount
|
||||||
|
@updateSpriteProperties()
|
||||||
|
@stage.update()
|
||||||
|
|
||||||
|
incrRegY: (amount) ->
|
||||||
|
@regY += amount
|
||||||
|
@updateSpriteProperties()
|
||||||
|
@stage.update()
|
||||||
|
|
||||||
|
onClickDone: ->
|
||||||
|
@saveChanges()
|
||||||
|
@trigger 'done'
|
||||||
|
@hide()
|
|
@ -15,6 +15,8 @@ module.exports = class I18NEditLevelView extends I18NEditModelView
|
||||||
@wrapRow "Level name", ['name'], name, i18n[lang]?.name, []
|
@wrapRow "Level name", ['name'], name, i18n[lang]?.name, []
|
||||||
if description = @model.get('description')
|
if description = @model.get('description')
|
||||||
@wrapRow "Level description", ['description'], description, i18n[lang]?.description, []
|
@wrapRow "Level description", ['description'], description, i18n[lang]?.description, []
|
||||||
|
if loadingTip = @model.get('loadingTip')
|
||||||
|
@wrapRow "Loading tip", ['loadingTip'], loadingTip, i18n[lang]?.loadingTip, []
|
||||||
|
|
||||||
# goals
|
# goals
|
||||||
for goal, index in @model.get('goals') ? []
|
for goal, index in @model.get('goals') ? []
|
||||||
|
|
|
@ -34,6 +34,7 @@ module.exports = class RootView extends CocoView
|
||||||
'achievements:new': 'handleNewAchievements'
|
'achievements:new': 'handleNewAchievements'
|
||||||
|
|
||||||
showNewAchievement: (achievement, earnedAchievement) ->
|
showNewAchievement: (achievement, earnedAchievement) ->
|
||||||
|
return if achievement.get('collection') is 'level.sessions'
|
||||||
popup = new AchievementPopup achievement: achievement, earnedAchievement: earnedAchievement
|
popup = new AchievementPopup achievement: achievement, earnedAchievement: earnedAchievement
|
||||||
|
|
||||||
handleNewAchievements: (e) ->
|
handleNewAchievements: (e) ->
|
||||||
|
|
|
@ -100,6 +100,7 @@ module.exports = class WorldMapView extends RootView
|
||||||
context.isIPadApp = application.isIPadApp
|
context.isIPadApp = application.isIPadApp
|
||||||
context.mapType = _.string.slugify @terrain
|
context.mapType = _.string.slugify @terrain
|
||||||
context.nextLevel = @nextLevel
|
context.nextLevel = @nextLevel
|
||||||
|
context.forestIsAvailable = '541b67f71ccc8eaae19f3c62' in (me.get('earned')?.levels or [])
|
||||||
context
|
context
|
||||||
|
|
||||||
afterRender: ->
|
afterRender: ->
|
||||||
|
@ -596,7 +597,7 @@ forest = [
|
||||||
description: 'Protect the peasants from the pursuing ogres.'
|
description: 'Protect the peasants from the pursuing ogres.'
|
||||||
nextLevels:
|
nextLevels:
|
||||||
continue: 'winding-trail'
|
continue: 'winding-trail'
|
||||||
x: 29.63
|
x: 32.63
|
||||||
y: 53.69
|
y: 53.69
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,7 +18,7 @@ module.exports = class LevelLoadingView extends CocoView
|
||||||
@$el.find('.tip.rare').remove() if _.random(1, 10) < 9
|
@$el.find('.tip.rare').remove() if _.random(1, 10) < 9
|
||||||
tips = @$el.find('.tip').addClass('to-remove')
|
tips = @$el.find('.tip').addClass('to-remove')
|
||||||
tip = _.sample(tips)
|
tip = _.sample(tips)
|
||||||
$(tip).removeClass('to-remove')
|
$(tip).removeClass('to-remove').addClass('secret')
|
||||||
@$el.find('.to-remove').remove()
|
@$el.find('.to-remove').remove()
|
||||||
@onLevelLoaded level: @options.level if @options.level?.get('goals') # If Level was already loaded.
|
@onLevelLoaded level: @options.level if @options.level?.get('goals') # If Level was already loaded.
|
||||||
|
|
||||||
|
@ -47,6 +47,11 @@ module.exports = class LevelLoadingView extends CocoView
|
||||||
goalContainer.removeClass('secret')
|
goalContainer.removeClass('secret')
|
||||||
if goalCount is 1
|
if goalCount is 1
|
||||||
goalContainer.find('.panel-heading').text $.i18n.t 'play_level.goal' # Not plural
|
goalContainer.find('.panel-heading').text $.i18n.t 'play_level.goal' # Not plural
|
||||||
|
tip = @$el.find('.tip')
|
||||||
|
if @level.get('loadingTip')
|
||||||
|
loadingTip = utils.i18n @level.attributes, 'loadingTip'
|
||||||
|
tip.text(loadingTip)
|
||||||
|
tip.removeClass('secret')
|
||||||
|
|
||||||
showReady: ->
|
showReady: ->
|
||||||
return if @shownReady
|
return if @shownReady
|
||||||
|
@ -59,8 +64,6 @@ module.exports = class LevelLoadingView extends CocoView
|
||||||
@startUnveiling()
|
@startUnveiling()
|
||||||
@unveil()
|
@unveil()
|
||||||
else
|
else
|
||||||
ready = $.i18n.t('play_level.loading_ready', defaultValue: 'Ready!')
|
|
||||||
@$el.find('#tip-wrapper .tip').addClass('ready').text ready
|
|
||||||
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'level_loaded', volume: 0.75 # old: loading_ready
|
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'level_loaded', volume: 0.75 # old: loading_ready
|
||||||
@$el.find('.progress').addClass 'active progress-striped'
|
@$el.find('.progress').addClass 'active progress-striped'
|
||||||
@$el.find('.start-level-button').removeClass 'secret'
|
@$el.find('.start-level-button').removeClass 'secret'
|
||||||
|
|
|
@ -427,6 +427,7 @@ module.exports = class PlayLevelView extends RootView
|
||||||
application.tracker?.trackTiming victoryTime, 'Level Victory Time', @levelID, @levelID, 100
|
application.tracker?.trackTiming victoryTime, 'Level Victory Time', @levelID, @levelID, 100
|
||||||
|
|
||||||
showVictory: ->
|
showVictory: ->
|
||||||
|
@endHighlight()
|
||||||
options = {level: @level, supermodel: @supermodel, session: @session}
|
options = {level: @level, supermodel: @supermodel, session: @session}
|
||||||
ModalClass = if @level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] then HeroVictoryModal else VictoryModal
|
ModalClass = if @level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] then HeroVictoryModal else VictoryModal
|
||||||
victoryModal = new ModalClass(options)
|
victoryModal = new ModalClass(options)
|
||||||
|
|
|
@ -129,6 +129,7 @@ module.exports = class SpellPaletteView extends CocoView
|
||||||
storages = [storages] if _.isString storages
|
storages = [storages] if _.isString storages
|
||||||
for storage in storages
|
for storage in storages
|
||||||
props = _.reject @thang[storage] ? [], (prop) -> prop[0] is '_' # no private properties
|
props = _.reject @thang[storage] ? [], (prop) -> prop[0] is '_' # no private properties
|
||||||
|
props = _.uniq props
|
||||||
added = _.sortBy(props).slice()
|
added = _.sortBy(props).slice()
|
||||||
propGroups[owner] = (propGroups[owner] ? []).concat added
|
propGroups[owner] = (propGroups[owner] ? []).concat added
|
||||||
count += added.length
|
count += added.length
|
||||||
|
@ -181,14 +182,18 @@ module.exports = class SpellPaletteView extends CocoView
|
||||||
propsByItem = {}
|
propsByItem = {}
|
||||||
propCount = 0
|
propCount = 0
|
||||||
itemsByProp = {}
|
itemsByProp = {}
|
||||||
for slot, thangTypeName of @thang.inventoryThangTypeNames ? {}
|
# Make sure that we get the spellbook first, then the primary hand, then anything else.
|
||||||
|
slots = _.sortBy _.keys(@thang.inventoryThangTypeNames ? {}), (slot) ->
|
||||||
|
if slot is 'left-hand' then 0 else if slot is 'right-hand' then 1 else 2
|
||||||
|
for slot in slots
|
||||||
|
thangTypeName = @thang.inventoryThangTypeNames[slot]
|
||||||
if item = itemThangTypes[thangTypeName]
|
if item = itemThangTypes[thangTypeName]
|
||||||
unless item.get('components')
|
unless item.get('components')
|
||||||
console.error 'Item', item, 'did not have any components when we went to assemble docs.'
|
console.error 'Item', item, 'did not have any components when we went to assemble docs.'
|
||||||
for component in item.get('components') ? [] when component.config
|
for component in item.get('components') ? [] when component.config
|
||||||
for owner, storages of propStorage
|
for owner, storages of propStorage
|
||||||
if props = component.config[storages]
|
if props = component.config[storages]
|
||||||
for prop in _.sortBy(props) when prop[0] isnt '_' # no private properties
|
for prop in _.sortBy(props) when prop[0] isnt '_' and not itemsByProp[prop] # no private properties
|
||||||
propsByItem[item.get('name')] ?= []
|
propsByItem[item.get('name')] ?= []
|
||||||
propsByItem[item.get('name')].push owner: owner, prop: prop, item: item
|
propsByItem[item.get('name')].push owner: owner, prop: prop, item: item
|
||||||
itemsByProp[prop] = item
|
itemsByProp[prop] = item
|
||||||
|
|
|
@ -31,7 +31,13 @@ module.exports = class BuyGemsModal extends ModalView
|
||||||
return c
|
return c
|
||||||
|
|
||||||
onIPadProducts: (e) ->
|
onIPadProducts: (e) ->
|
||||||
@products = e.products
|
newProducts = []
|
||||||
|
for iapProduct in e.products
|
||||||
|
localProduct = _.find @products, { id: iapProduct.id }
|
||||||
|
continue unless localProduct
|
||||||
|
localProduct.price = iapProduct.price
|
||||||
|
newProducts.push localProduct
|
||||||
|
@products = newProducts
|
||||||
@render()
|
@render()
|
||||||
|
|
||||||
onClickProductButton: (e) ->
|
onClickProductButton: (e) ->
|
||||||
|
@ -45,8 +51,10 @@ module.exports = class BuyGemsModal extends ModalView
|
||||||
@$el.find('.modal-body').append($('<div class="alert alert-danger">Not implemented</div>'))
|
@$el.find('.modal-body').append($('<div class="alert alert-danger">Not implemented</div>'))
|
||||||
|
|
||||||
onIAPComplete: (e) ->
|
onIAPComplete: (e) ->
|
||||||
|
product = _.find @products, { id: e.productID }
|
||||||
purchased = me.get('purchased') ? {}
|
purchased = me.get('purchased') ? {}
|
||||||
|
purchased = _.clone purchased
|
||||||
purchased.gems ?= 0
|
purchased.gems ?= 0
|
||||||
purchased.gems += e.gems
|
purchased.gems += product.gems
|
||||||
me.set('purchased', purchased)
|
me.set('purchased', purchased)
|
||||||
@hide()
|
@hide()
|
|
@ -12,41 +12,47 @@ module.exports = class ItemDetailsView extends CocoView
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super(arguments...)
|
super(arguments...)
|
||||||
@propDocs = {}
|
@propDocs = {}
|
||||||
|
@spellDocs = {}
|
||||||
|
|
||||||
setItem: (@item) ->
|
setItem: (@item) ->
|
||||||
if @item
|
if @item
|
||||||
|
@spellDocs = {}
|
||||||
@item.name = utils.i18n @item.attributes, 'name'
|
@item.name = utils.i18n @item.attributes, 'name'
|
||||||
@item.affordable = me.gems() >= @item.get('gems')
|
@item.affordable = me.gems() >= @item.get('gems')
|
||||||
@item.owned = me.ownsItem @item.get('original')
|
@item.owned = me.ownsItem @item.get('original')
|
||||||
@item.comingSoon = not @item.getFrontFacingStats().props.length and not _.size @item.getFrontFacingStats().stats # Temp: while there are placeholder items
|
@item.comingSoon = not @item.getFrontFacingStats().props.length and not _.size @item.getFrontFacingStats().stats # Temp: while there are placeholder items
|
||||||
|
|
||||||
stats = @item.getFrontFacingStats()
|
stats = @item.getFrontFacingStats()
|
||||||
props = (p for p in stats.props when not @propDocs[p])
|
props = (p for p in stats.props when not @propDocs[p])
|
||||||
if props.length > 0
|
if props.length > 0 or ('cast' in stats.props)
|
||||||
|
|
||||||
docs = new CocoCollection([], {
|
docs = new CocoCollection([], {
|
||||||
url: '/db/level.component?view=prop-doc-lookup'
|
url: '/db/level.component?view=prop-doc-lookup'
|
||||||
model: LevelComponent
|
model: LevelComponent
|
||||||
project: [
|
project: [
|
||||||
|
'name'
|
||||||
'propertyDocumentation.name'
|
'propertyDocumentation.name'
|
||||||
'propertyDocumentation.description'
|
'propertyDocumentation.description'
|
||||||
'propertyDocumentation.i18n'
|
'propertyDocumentation.i18n'
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
docs.fetch({ data: {
|
docs.fetch({ data: {
|
||||||
componentOriginals: [c.original for c in @item.get('components')].join(',')
|
componentOriginals: [c.original for c in @item.get('components')].join(',')
|
||||||
propertyNames: props.join(',')
|
propertyNames: props.join(',')
|
||||||
}})
|
}})
|
||||||
@listenToOnce docs, 'sync', @onDocsLoaded
|
@listenToOnce docs, 'sync', @onDocsLoaded
|
||||||
|
|
||||||
@render()
|
@render()
|
||||||
@$el.find('.nano:visible').nanoScroller()
|
@$el.find('.nano:visible').nanoScroller()
|
||||||
|
|
||||||
onDocsLoaded: (levelComponents) ->
|
onDocsLoaded: (levelComponents) ->
|
||||||
for component in levelComponents.models
|
for component in levelComponents.models
|
||||||
for propDoc in component.get('propertyDocumentation')
|
for propDoc in component.get('propertyDocumentation')
|
||||||
@propDocs[propDoc.name] = propDoc
|
if /^cast.+/.test propDoc.name
|
||||||
|
@spellDocs[propDoc.name] = propDoc
|
||||||
|
else
|
||||||
|
@propDocs[propDoc.name] = propDoc
|
||||||
@render()
|
@render()
|
||||||
|
|
||||||
getRenderData: ->
|
getRenderData: ->
|
||||||
|
@ -57,20 +63,27 @@ module.exports = class ItemDetailsView extends CocoView
|
||||||
c.stats = _.values(stats.stats)
|
c.stats = _.values(stats.stats)
|
||||||
_.last(c.stats).isLast = true if c.stats.length
|
_.last(c.stats).isLast = true if c.stats.length
|
||||||
c.props = []
|
c.props = []
|
||||||
progLang = (me.get('aceConfig') ? {}).language or 'python'
|
stats.props = stats.props.concat _.keys @spellDocs
|
||||||
|
codeLanguage = (me.get('aceConfig') ? {}).language or 'python'
|
||||||
for prop in stats.props
|
for prop in stats.props
|
||||||
description = utils.i18n @propDocs[prop] ? {}, 'description'
|
doc = @propDocs[prop] ? @spellDocs[prop] ? {}
|
||||||
|
description = utils.i18n doc, 'description'
|
||||||
|
|
||||||
if _.isObject description
|
if _.isObject description
|
||||||
description = description[progLang] or _.values(description)[0]
|
description = description[codeLanguage] or _.values(description)[0]
|
||||||
if _.isString description
|
if _.isString description
|
||||||
description = description.replace(/#{spriteName}/g, 'hero')
|
description = description.replace(/#{spriteName}/g, 'hero')
|
||||||
if fact = stats.stats.shieldDefenseFactor
|
if fact = stats.stats.shieldDefenseFactor
|
||||||
description = description.replace(/#{shieldDefensePercent}%/g, fact.display)
|
description = description.replace(/#{shieldDefensePercent}%/g, fact.display)
|
||||||
|
## We don't have the full components loaded here, so we can't really get most of these values.
|
||||||
|
#description = description.replace /#{([^.]+?)}/g, (match, keyChain) ->
|
||||||
|
# console.log 'gotta find', keyChain, 'from', match, 'and have', stats
|
||||||
|
# match
|
||||||
|
description = description.replace(/#{(.+?)}/g, '`$1`')
|
||||||
description = $(marked(description)).html()
|
description = $(marked(description)).html()
|
||||||
|
|
||||||
c.props.push {
|
c.props.push {
|
||||||
name: prop
|
name: _.string.humanize prop
|
||||||
description: description or '...'
|
description: description or '...'
|
||||||
}
|
}
|
||||||
c
|
c
|
||||||
|
|
|
@ -37,9 +37,12 @@ LevelComponentHandler = class LevelComponentHandler extends Handler
|
||||||
properties = req.query.propertyNames.split(',')
|
properties = req.query.propertyNames.split(',')
|
||||||
catch e
|
catch e
|
||||||
return @sendBadInputError(res, 'Could not parse componentOriginals or propertyNames.')
|
return @sendBadInputError(res, 'Could not parse componentOriginals or propertyNames.')
|
||||||
|
|
||||||
query['original'] = {$in: components}
|
query['original'] = {$in: components}
|
||||||
query['propertyDocumentation.name'] = {$in: properties}
|
query.$or = [
|
||||||
|
{'propertyDocumentation.name': {$in: properties}}
|
||||||
|
{'propertyDocumentation.name': {$regex: /^cast.+/}}
|
||||||
|
]
|
||||||
|
|
||||||
q = LevelComponent.find(query, projection)
|
q = LevelComponent.find(query, projection)
|
||||||
q.exec (err, documents) =>
|
q.exec (err, documents) =>
|
||||||
|
|
|
@ -29,6 +29,7 @@ LevelHandler = class LevelHandler extends Handler
|
||||||
'employerDescription'
|
'employerDescription'
|
||||||
'terrain'
|
'terrain'
|
||||||
'i18nCoverage'
|
'i18nCoverage'
|
||||||
|
'loadingTip'
|
||||||
]
|
]
|
||||||
|
|
||||||
postEditableProperties: ['name']
|
postEditableProperties: ['name']
|
||||||
|
|
|
@ -1,41 +1,43 @@
|
||||||
InventoryView = require 'views/game-menu/InventoryView'
|
# TODO: rework this spec for the InventoryModal
|
||||||
|
|
||||||
thangTypes = [
|
#InventoryView = require 'views/game-menu/InventoryView'
|
||||||
{"_id":"boots-id","name":"Boots","original":"boots","components":[{"original":"524b85837fc0f6d519000020","majorVersion":0},{"original":"524b7b857fc0f6d519000012","majorVersion":0},{"original":"524b4150ff92f1f4f8000024","majorVersion":0},{"original":"53e12043b82921000051cdf9","majorVersion":0,"config":{"slots":["feet"],"programmableProperties":["move","targetPos"],"moreProgrammableProperties":[],"extraHUDProperties":["maxSpeed"],"stats":{"maxSpeed":{"factor":1}}}},{"original":"524b7b8c7fc0f6d519000013","majorVersion":0,"config":{"locomotionType":"running","maxSpeed":5,"maxAcceleration":100}},{"original":"524b75ad7fc0f6d519000001","majorVersion":0,"config":{"pos":{"x":39.08,"y":20.72,"z":0.5},"width":1,"height":1,"depth":1,"shape":"ellipsoid"}},{"original":"524b7b7c7fc0f6d519000011","majorVersion":0}]},
|
#
|
||||||
{"_id":"boots-of-leaping-id","name":"Boots of Leaping","original":"boots-of-leaping","components":[{"original":"524b85837fc0f6d519000020","majorVersion":0},{"original":"524b7b857fc0f6d519000012","majorVersion":0},{"original":"524b4150ff92f1f4f8000024","majorVersion":0},{"original":"53e12043b82921000051cdf9","majorVersion":0,"config":{"ownerID":"Tharin","slots":["feet"],"programmableProperties":["move","targetPos","jumpTo"],"moreProgrammableProperties":["jump"],"extraHUDProperties":["maxSpeed"],"stats":{"maxSpeed":{"factor":1.2}}}},{"original":"524b7b8c7fc0f6d519000013","majorVersion":0,"config":{"locomotionType":"running","maxSpeed":6,"maxAcceleration":100}},{"original":"524b1f54d768d916b5000001","majorVersion":0,"config":{"jumpHeight":3}},{"original":"5275392d69abdcb12401441e","majorVersion":0,"config":{"jumpSpeedFactor":1.5}},{"original":"524b75ad7fc0f6d519000001","majorVersion":0,"config":{"pos":{"x":39.08,"y":20.72,"z":0.5},"width":1,"height":1,"depth":1,"shape":"ellipsoid"}},{"original":"524b7b7c7fc0f6d519000011","majorVersion":0}]},
|
#thangTypes = [
|
||||||
{"_id":"crossbow-id","name":"Crossbow","original":"crossbow","components":[{"original":"524b85837fc0f6d519000020","majorVersion":0},{"original":"524b517fff92f1f4f8000046","majorVersion":0},{"original":"524b7b747fc0f6d519000010","majorVersion":0,"config":{"team":"humans"}},{"original":"524b7bc67fc0f6d51900001a","majorVersion":0,"config":{"missileThangID":"Arrow"}},{"original":"524b7ba57fc0f6d519000016","majorVersion":0,"config":{"attackDamage":5,"attackRange":20,"cooldown":0.6,"chasesWhenAttackingOutOfRange":true}},{"original":"524b3e3fff92f1f4f800000d","majorVersion":0},{"original":"524cbdc03ea855e0ab0000bb","majorVersion":0},{"original":"524b4150ff92f1f4f8000024","majorVersion":0},{"original":"53e12043b82921000051cdf9","majorVersion":0,"config":{"slots":["right-hand"],"programmableProperties":["attack","target","attackRange"],"moreProgrammableProperties":["attackXY","targetPos"],"extraHUDProperties":["attackDamage","attackRange"]}},{"original":"524b75ad7fc0f6d519000001","majorVersion":0,"config":{"pos":{"x":41.105000000000004,"y":31.6,"z":0.125},"width":1.5,"height":0.75,"depth":0.25,"shape":"box"}},{"original":"524b7b7c7fc0f6d519000011","majorVersion":0},{"original":"524b457bff92f1f4f8000031","majorVersion":0}]},
|
# {"_id":"boots-id","name":"Boots","original":"boots","components":[{"original":"524b85837fc0f6d519000020","majorVersion":0},{"original":"524b7b857fc0f6d519000012","majorVersion":0},{"original":"524b4150ff92f1f4f8000024","majorVersion":0},{"original":"53e12043b82921000051cdf9","majorVersion":0,"config":{"slots":["feet"],"programmableProperties":["move","targetPos"],"moreProgrammableProperties":[],"extraHUDProperties":["maxSpeed"],"stats":{"maxSpeed":{"factor":1}}}},{"original":"524b7b8c7fc0f6d519000013","majorVersion":0,"config":{"locomotionType":"running","maxSpeed":5,"maxAcceleration":100}},{"original":"524b75ad7fc0f6d519000001","majorVersion":0,"config":{"pos":{"x":39.08,"y":20.72,"z":0.5},"width":1,"height":1,"depth":1,"shape":"ellipsoid"}},{"original":"524b7b7c7fc0f6d519000011","majorVersion":0}]},
|
||||||
{"_id":"crude-glasses-id","name":"Crude Glasses","original":"crude-glasses","components":[{"original":"524b7b747fc0f6d519000010","majorVersion":0,"config":{"team":"humans"}},{"original":"524b4150ff92f1f4f8000024","majorVersion":0},{"original":"53e12043b82921000051cdf9","majorVersion":0,"config":{"slots":["eyes"],"programmableProperties":["pos","getEnemies"],"moreProgrammableProperties":["getItems","getFriends"]}},{"original":"524b75ad7fc0f6d519000001","majorVersion":0,"config":{"pos":{"x":33.230000000000004,"y":20.75,"z":2},"width":1,"height":2,"depth":1,"shape":"ellipsoid"}},{"original":"524b457bff92f1f4f8000031","majorVersion":0,"config":{"visualRange":50}}]}
|
# {"_id":"boots-of-leaping-id","name":"Boots of Leaping","original":"boots-of-leaping","components":[{"original":"524b85837fc0f6d519000020","majorVersion":0},{"original":"524b7b857fc0f6d519000012","majorVersion":0},{"original":"524b4150ff92f1f4f8000024","majorVersion":0},{"original":"53e12043b82921000051cdf9","majorVersion":0,"config":{"ownerID":"Tharin","slots":["feet"],"programmableProperties":["move","targetPos","jumpTo"],"moreProgrammableProperties":["jump"],"extraHUDProperties":["maxSpeed"],"stats":{"maxSpeed":{"factor":1.2}}}},{"original":"524b7b8c7fc0f6d519000013","majorVersion":0,"config":{"locomotionType":"running","maxSpeed":6,"maxAcceleration":100}},{"original":"524b1f54d768d916b5000001","majorVersion":0,"config":{"jumpHeight":3}},{"original":"5275392d69abdcb12401441e","majorVersion":0,"config":{"jumpSpeedFactor":1.5}},{"original":"524b75ad7fc0f6d519000001","majorVersion":0,"config":{"pos":{"x":39.08,"y":20.72,"z":0.5},"width":1,"height":1,"depth":1,"shape":"ellipsoid"}},{"original":"524b7b7c7fc0f6d519000011","majorVersion":0}]},
|
||||||
]
|
# {"_id":"crossbow-id","name":"Crossbow","original":"crossbow","components":[{"original":"524b85837fc0f6d519000020","majorVersion":0},{"original":"524b517fff92f1f4f8000046","majorVersion":0},{"original":"524b7b747fc0f6d519000010","majorVersion":0,"config":{"team":"humans"}},{"original":"524b7bc67fc0f6d51900001a","majorVersion":0,"config":{"missileThangID":"Arrow"}},{"original":"524b7ba57fc0f6d519000016","majorVersion":0,"config":{"attackDamage":5,"attackRange":20,"cooldown":0.6,"chasesWhenAttackingOutOfRange":true}},{"original":"524b3e3fff92f1f4f800000d","majorVersion":0},{"original":"524cbdc03ea855e0ab0000bb","majorVersion":0},{"original":"524b4150ff92f1f4f8000024","majorVersion":0},{"original":"53e12043b82921000051cdf9","majorVersion":0,"config":{"slots":["right-hand"],"programmableProperties":["attack","target","attackRange"],"moreProgrammableProperties":["attackXY","targetPos"],"extraHUDProperties":["attackDamage","attackRange"]}},{"original":"524b75ad7fc0f6d519000001","majorVersion":0,"config":{"pos":{"x":41.105000000000004,"y":31.6,"z":0.125},"width":1.5,"height":0.75,"depth":0.25,"shape":"box"}},{"original":"524b7b7c7fc0f6d519000011","majorVersion":0},{"original":"524b457bff92f1f4f8000031","majorVersion":0}]},
|
||||||
|
# {"_id":"crude-glasses-id","name":"Crude Glasses","original":"crude-glasses","components":[{"original":"524b7b747fc0f6d519000010","majorVersion":0,"config":{"team":"humans"}},{"original":"524b4150ff92f1f4f8000024","majorVersion":0},{"original":"53e12043b82921000051cdf9","majorVersion":0,"config":{"slots":["eyes"],"programmableProperties":["pos","getEnemies"],"moreProgrammableProperties":["getItems","getFriends"]}},{"original":"524b75ad7fc0f6d519000001","majorVersion":0,"config":{"pos":{"x":33.230000000000004,"y":20.75,"z":2},"width":1,"height":2,"depth":1,"shape":"ellipsoid"}},{"original":"524b457bff92f1f4f8000031","majorVersion":0,"config":{"visualRange":50}}]}
|
||||||
describe 'InventoryView', ->
|
#]
|
||||||
inventoryView = null
|
#
|
||||||
|
#describe 'InventoryView', ->
|
||||||
beforeEach (done) ->
|
# inventoryView = null
|
||||||
equipment = { 'feet':'boots', 'eyes': 'crude-glasses' }
|
#
|
||||||
inventoryView = new InventoryView({ equipment: equipment })
|
# beforeEach (done) ->
|
||||||
responses =
|
# equipment = { 'feet':'boots', 'eyes': 'crude-glasses' }
|
||||||
'/db/thang.type?view=items': thangTypes
|
# inventoryView = new InventoryView({ equipment: equipment })
|
||||||
jasmine.Ajax.requests.sendResponses(responses)
|
# responses =
|
||||||
_.defer ->
|
# '/db/thang.type?view=items': thangTypes
|
||||||
inventoryView.render()
|
# jasmine.Ajax.requests.sendResponses(responses)
|
||||||
done()
|
# _.defer ->
|
||||||
|
# inventoryView.render()
|
||||||
it 'selects a slot when you click it', ->
|
# done()
|
||||||
inventoryView.getSlot('eyes').click()
|
#
|
||||||
expect(inventoryView.getSelectedSlot().data('slot')).toBe('eyes')
|
# it 'selects a slot when you click it', ->
|
||||||
|
# inventoryView.getSlot('eyes').click()
|
||||||
it 'unselects a selected slot when you click it', ->
|
# expect(inventoryView.getSelectedSlot().data('slot')).toBe('eyes')
|
||||||
inventoryView.getSlot('eyes').click().click()
|
#
|
||||||
expect(inventoryView.getSelectedSlot().data('slot')).toBeUndefined()
|
# it 'unselects a selected slot when you click it', ->
|
||||||
|
# inventoryView.getSlot('eyes').click().click()
|
||||||
it 'selects an available item when you click it', ->
|
# expect(inventoryView.getSelectedSlot().data('slot')).toBeUndefined()
|
||||||
inventoryView.getAvailableItemContainer('boots-of-leaping').click()
|
#
|
||||||
expect(inventoryView.getSelectedAvailableItemContainer().data('item-id')).toBe('boots-of-leaping')
|
# it 'selects an available item when you click it', ->
|
||||||
|
# inventoryView.getAvailableItemContainer('boots-of-leaping').click()
|
||||||
it 'equips an available item when you double click it', ->
|
# expect(inventoryView.getSelectedAvailableItemContainer().data('item-id')).toBe('boots-of-leaping')
|
||||||
inventoryView.getAvailableItemContainer('crossbow').click().dblclick()
|
#
|
||||||
expect(inventoryView.getCurrentEquipmentConfig()['right-hand']).toBeTruthy()
|
# it 'equips an available item when you double click it', ->
|
||||||
|
# inventoryView.getAvailableItemContainer('crossbow').click().dblclick()
|
||||||
it 'unequips an item when you double click it', ->
|
# expect(inventoryView.getCurrentEquipmentConfig()['right-hand']).toBeTruthy()
|
||||||
inventoryView.getSlot('eyes').find('.item-view').click().dblclick()
|
#
|
||||||
expect(inventoryView.getCurrentEquipmentConfig().eyes).toBeUndefined()
|
# it 'unequips an item when you double click it', ->
|
||||||
|
# inventoryView.getSlot('eyes').find('.item-view').click().dblclick()
|
||||||
|
# expect(inventoryView.getCurrentEquipmentConfig().eyes).toBeUndefined()
|
||||||
|
|
Loading…
Reference in a new issue