Merge branch 'master' into production

This commit is contained in:
Nick Winter 2014-11-10 22:08:12 -08:00
commit 40081fc853
11 changed files with 69 additions and 22 deletions

View file

@ -167,6 +167,7 @@
medium: "Medium"
hard: "Hard"
player: "Player"
player_level: "Level" # Like player level 5, not like level: Dungeons of Kithgard
units:
second: "second"

View file

@ -396,8 +396,16 @@ module.exports = class ThangType extends CocoModel
name: name, display: display
isSilhouettedItem: ->
# TODO: have items have actual levels instead of just going by their gem count
return console.error "Trying to determine whether #{@get('name')} should be a silhouetted item, but it has no gem cost." unless @get 'gems'
console.info "Add (or make sure you have fetched) a tier for #{@get('name')} to more accurately determine whether it is silhouetted." unless @get('tier')?
tier = @get 'tier'
if tier?
return @levelRequiredForItem() > me.level()
points = me.get('points')
expectedTotalGems = (points ? 0) * 1.5 # Not actually true, but roughly kinda close for tier 0, kinda tier 1
@get('gems') > (100 + expectedTotalGems) * 2
@get('gems') > (100 + expectedTotalGems) * 1.2
levelRequiredForItem: ->
return console.error "Trying to determine what level is required for #{@get('name')}, but it has no tier." unless @get('tier')?
tier = @get 'tier'
me.constructor.levelForTier(Math.pow(tier, 0.7))

View file

@ -63,9 +63,22 @@ module.exports = class User extends CocoModel
@expForLevel: (level) ->
if level > 1 then Math.ceil Math.exp((level - 1)/ a) * b - c else 0
@tierFromLevel: (level) ->
# TODO: math
# For now, just eyeball it.
tiersByLevel[Math.min(level, tiersByLevel.length - 1)]
@levelForTier: (tier) ->
# TODO: math
for tierThreshold, level in tiersByLevel
return level if tierThreshold >= tier
level: ->
User.levelFromExp(@get('points'))
tier: ->
User.tierFromLevel @level()
gems: ->
gemsEarned = @get('earned')?.gems ? 0
gemsPurchased = @get('purchased')?.gems ? 0
@ -146,3 +159,5 @@ module.exports = class User extends CocoModel
@kithmazeGroup = 'haunted-kithmaze' if me.isAdmin()
application.tracker.identify kithmazeGroup: @kithmazeGroup unless me.isAdmin()
@kithmazeGroup
tiersByLevel = [-1, 0, 0.05, 0.14, 0.18, 0.32, 0.41, 0.5, 0.64, 0.82, 0.91, 1.04, 1.22, 1.35, 1.48, 1.65, 1.78, 1.96, 2.1, 2.24, 2.38, 2.55, 2.69, 2.86, 3.03, 3.16, 3.29, 3.42, 3.58, 3.74, 3.89, 4.04, 4.19, 4.32, 4.47, 4.64, 4.79, 4.96]

View file

@ -109,6 +109,7 @@ _.extend ThangTypeSchema.properties,
terrains: c.array {title: 'Terrains', description: 'If specified, limits this ThangType to levels with matching terrains.', uniqueItems: true}, c.terrainString
gems: {type: 'integer', minimum: 0, title: 'Gem Cost', description: 'How many gems this item or hero costs.'}
heroClass: {type: 'string', enum: ['Warrior', 'Ranger', 'Wizard'], title: 'Hero Class', description: 'What class this is (if a hero) or is restricted to (if an item). Leave undefined for most items.'}
tier: {type: 'number', minimum: 0, title: 'Tier', description: 'What tier (fractional) this item or hero is in.'}
actions: c.object {title: 'Actions', additionalProperties: {$ref: '#/definitions/action'}}
soundTriggers: c.object {title: 'Sound Triggers', additionalProperties: c.array({}, {$ref: '#/definitions/sound'})},
say: c.object {format: 'slug-props', additionalProperties: {$ref: '#/definitions/sound'}},

View file

@ -139,6 +139,9 @@
margin: 4px
text-align: center
position: relative
&.silhouetted
cursor: default
strong
position: absolute
@ -275,7 +278,19 @@
.item-silhouette
@include filter(contrast(0%) brightness(0%))
opacity: 0.3
.required-level
position: absolute
left: 0
right: 5px
top: 70px
font-size: 20px
line-height: 20px
font-family: Open Sans Condensed
text-transform: uppercase
font-weight: bold
z-index: 2
//- Unlock buttons (both in list and details areas)

View file

@ -26,11 +26,16 @@
.nano-content
for item in itemCategoryCollections[category].models
- var hidden = item.comingSoon && !me.isAdmin()
div(class="item" + (hidden ? " hide" : ""), data-item-id=item.id)
- hidden = hidden || (!item.get('gems') && !item.owned)
div(class="item" + (hidden ? " hide" : "") + (item.silhouetted && !item.owned ? " silhouetted" : ""), data-item-id=item.id)
if item.silhouetted && !item.owned
span.glyphicon.glyphicon-lock.bolder
span.glyphicon.glyphicon-lock
img.item-silhouette(src=item.getPortraitURL())
if item.level
.required-level
div(data-i18n="general.player_level")
div= item.level
else
strong.big-font= item.name
img.item-img(src=item.getPortraitURL())

View file

@ -64,6 +64,8 @@
.user-status.header-font
span.gem.gem-20
span.spr= me.gems()
span.spl.spr(data-i18n="general.player_level")
span.spr= me.level()
if me.get('anonymous')
span.spr(data-i18n="play.anonymous_player") Anonymous Player
button.btn.btn-default.btn-flat.btn-sm(data-toggle='coco-modal', data-target='modal/AuthModal', data-i18n="login.log_in")

View file

@ -4,8 +4,6 @@ WizardLank = require 'lib/surface/WizardLank'
ThangType = require 'models/ThangType'
Simulator = require 'lib/simulator/Simulator'
InventoryModal = require 'views/game-menu/InventoryModal'
{me} = require '/lib/auth'
module.exports = class HomeView extends RootView
@ -40,4 +38,3 @@ module.exports = class HomeView extends RootView
afterInsert: ->
super(arguments...)
@openModalView(new InventoryModal({levelID: 'the-raised-sword'}))

View file

@ -44,14 +44,15 @@ module.exports = class InventoryModal extends ModalView
# TODO: switch to item store loading system?
@items.url = '/db/thang.type?view=items'
@items.setProjection [
'name',
'slug',
'components',
'original',
'rasterIcon',
'gems',
'description',
'heroClass',
'name'
'slug'
'components'
'original'
'rasterIcon'
'gems'
'tier'
'description'
'heroClass'
'i18n'
]
@supermodel.loadCollection(@items, 'items')

View file

@ -62,6 +62,7 @@ module.exports = class PlayItemsModal extends ModalView
'original'
'rasterIcon'
'gems'
'tier'
'i18n'
'heroClass'
]
@ -77,7 +78,8 @@ module.exports = class PlayItemsModal extends ModalView
gemsOwned = me.gems()
needMore = itemFetcher.models.length is PAGE_SIZE
for model in itemFetcher.models
continue unless cost = model.get('gems')
model.owned = me.ownsItem model.get('original')
continue unless (cost = model.get('gems')) or model.owned
category = slotToCategory[model.getAllowedSlots()[0]] or 'misc'
@itemCategoryCollections[category] ?= new Backbone.Collection()
collection = @itemCategoryCollections[category]
@ -85,10 +87,10 @@ module.exports = class PlayItemsModal extends ModalView
collection.add(model)
model.name = utils.i18n model.attributes, 'name'
model.affordable = cost <= gemsOwned
model.owned = me.ownsItem model.get('original')
model.silhouetted = model.isSilhouettedItem()
model.silhouetted = not model.owned and model.isSilhouettedItem()
model.level = model.levelRequiredForItem() if model.get('tier')?
model.equippable = 'Warrior' in model.getAllowedHeroClasses() # Temp: while there are no wizards/rangers
model.comingSoon = not model.getFrontFacingStats().props.length and not _.size model.getFrontFacingStats().stats # Temp: while there are placeholder items
model.comingSoon = not model.getFrontFacingStats().props.length and not _.size model.getFrontFacingStats().stats and not model.owned # Temp: while there are placeholder items
@idToItem[model.id] = model
if needMore
@ -127,7 +129,7 @@ module.exports = class PlayItemsModal extends ModalView
item = null
else
item = @idToItem[itemEl.data('item-id')]
if item.silhouetted
if item.silhouetted and not item.owned
item = null
else
itemEl.addClass('selected') unless wasSelected
@ -158,4 +160,3 @@ module.exports = class PlayItemsModal extends ModalView
button.addClass('confirm').text($.i18n.t('play.confirm'))
@$el.one 'click', (e) ->
button.removeClass('confirm').text($.i18n.t('play.unlock')) if e.target isnt button[0]

View file

@ -40,6 +40,7 @@ ThangTypeHandler = class ThangTypeHandler extends Handler
'description'
'gems'
'heroClass'
'tier'
'extendedName'
]
@ -61,7 +62,7 @@ ThangTypeHandler = class ThangTypeHandler extends Handler
query = slug: {$exists: true}
if req.query.view is 'items'
query.kind = 'Item'
query.gems = {$exists: true} # Items without gems don't show up anywhere
query.tier = {$exists: true} # Items without a tier don't show up anywhere, whereas items without gems don't show up in the store
else if req.query.view is 'heroes'
#query.kind = 'Hero' # TODO: when ChooseHeroView is refactored, just use this
query.original = {$in: _.values heroes} # TODO: when ChooseHeroView is refactored, don't do this