mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-02-17 17:02:18 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
40081fc853
11 changed files with 69 additions and 22 deletions
|
@ -167,6 +167,7 @@
|
||||||
medium: "Medium"
|
medium: "Medium"
|
||||||
hard: "Hard"
|
hard: "Hard"
|
||||||
player: "Player"
|
player: "Player"
|
||||||
|
player_level: "Level" # Like player level 5, not like level: Dungeons of Kithgard
|
||||||
|
|
||||||
units:
|
units:
|
||||||
second: "second"
|
second: "second"
|
||||||
|
|
|
@ -396,8 +396,16 @@ module.exports = class ThangType extends CocoModel
|
||||||
name: name, display: display
|
name: name, display: display
|
||||||
|
|
||||||
isSilhouettedItem: ->
|
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'
|
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')
|
points = me.get('points')
|
||||||
expectedTotalGems = (points ? 0) * 1.5 # Not actually true, but roughly kinda close for tier 0, kinda tier 1
|
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))
|
||||||
|
|
|
@ -63,9 +63,22 @@ module.exports = class User extends CocoModel
|
||||||
@expForLevel: (level) ->
|
@expForLevel: (level) ->
|
||||||
if level > 1 then Math.ceil Math.exp((level - 1)/ a) * b - c else 0
|
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: ->
|
level: ->
|
||||||
User.levelFromExp(@get('points'))
|
User.levelFromExp(@get('points'))
|
||||||
|
|
||||||
|
tier: ->
|
||||||
|
User.tierFromLevel @level()
|
||||||
|
|
||||||
gems: ->
|
gems: ->
|
||||||
gemsEarned = @get('earned')?.gems ? 0
|
gemsEarned = @get('earned')?.gems ? 0
|
||||||
gemsPurchased = @get('purchased')?.gems ? 0
|
gemsPurchased = @get('purchased')?.gems ? 0
|
||||||
|
@ -146,3 +159,5 @@ module.exports = class User extends CocoModel
|
||||||
@kithmazeGroup = 'haunted-kithmaze' if me.isAdmin()
|
@kithmazeGroup = 'haunted-kithmaze' if me.isAdmin()
|
||||||
application.tracker.identify kithmazeGroup: @kithmazeGroup unless me.isAdmin()
|
application.tracker.identify kithmazeGroup: @kithmazeGroup unless me.isAdmin()
|
||||||
@kithmazeGroup
|
@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]
|
||||||
|
|
|
@ -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
|
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.'}
|
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.'}
|
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'}}
|
actions: c.object {title: 'Actions', additionalProperties: {$ref: '#/definitions/action'}}
|
||||||
soundTriggers: c.object {title: 'Sound Triggers', additionalProperties: c.array({}, {$ref: '#/definitions/sound'})},
|
soundTriggers: c.object {title: 'Sound Triggers', additionalProperties: c.array({}, {$ref: '#/definitions/sound'})},
|
||||||
say: c.object {format: 'slug-props', additionalProperties: {$ref: '#/definitions/sound'}},
|
say: c.object {format: 'slug-props', additionalProperties: {$ref: '#/definitions/sound'}},
|
||||||
|
|
|
@ -139,6 +139,9 @@
|
||||||
margin: 4px
|
margin: 4px
|
||||||
text-align: center
|
text-align: center
|
||||||
position: relative
|
position: relative
|
||||||
|
|
||||||
|
&.silhouetted
|
||||||
|
cursor: default
|
||||||
|
|
||||||
strong
|
strong
|
||||||
position: absolute
|
position: absolute
|
||||||
|
@ -275,7 +278,19 @@
|
||||||
.item-silhouette
|
.item-silhouette
|
||||||
@include filter(contrast(0%) brightness(0%))
|
@include filter(contrast(0%) brightness(0%))
|
||||||
opacity: 0.3
|
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)
|
//- Unlock buttons (both in list and details areas)
|
||||||
|
|
||||||
|
|
|
@ -26,11 +26,16 @@
|
||||||
.nano-content
|
.nano-content
|
||||||
for item in itemCategoryCollections[category].models
|
for item in itemCategoryCollections[category].models
|
||||||
- var hidden = item.comingSoon && !me.isAdmin()
|
- 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
|
if item.silhouetted && !item.owned
|
||||||
span.glyphicon.glyphicon-lock.bolder
|
span.glyphicon.glyphicon-lock.bolder
|
||||||
span.glyphicon.glyphicon-lock
|
span.glyphicon.glyphicon-lock
|
||||||
img.item-silhouette(src=item.getPortraitURL())
|
img.item-silhouette(src=item.getPortraitURL())
|
||||||
|
if item.level
|
||||||
|
.required-level
|
||||||
|
div(data-i18n="general.player_level")
|
||||||
|
div= item.level
|
||||||
else
|
else
|
||||||
strong.big-font= item.name
|
strong.big-font= item.name
|
||||||
img.item-img(src=item.getPortraitURL())
|
img.item-img(src=item.getPortraitURL())
|
||||||
|
|
|
@ -64,6 +64,8 @@
|
||||||
.user-status.header-font
|
.user-status.header-font
|
||||||
span.gem.gem-20
|
span.gem.gem-20
|
||||||
span.spr= me.gems()
|
span.spr= me.gems()
|
||||||
|
span.spl.spr(data-i18n="general.player_level")
|
||||||
|
span.spr= me.level()
|
||||||
if me.get('anonymous')
|
if me.get('anonymous')
|
||||||
span.spr(data-i18n="play.anonymous_player") Anonymous Player
|
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")
|
button.btn.btn-default.btn-flat.btn-sm(data-toggle='coco-modal', data-target='modal/AuthModal', data-i18n="login.log_in")
|
||||||
|
|
|
@ -4,8 +4,6 @@ WizardLank = require 'lib/surface/WizardLank'
|
||||||
ThangType = require 'models/ThangType'
|
ThangType = require 'models/ThangType'
|
||||||
Simulator = require 'lib/simulator/Simulator'
|
Simulator = require 'lib/simulator/Simulator'
|
||||||
|
|
||||||
InventoryModal = require 'views/game-menu/InventoryModal'
|
|
||||||
|
|
||||||
{me} = require '/lib/auth'
|
{me} = require '/lib/auth'
|
||||||
|
|
||||||
module.exports = class HomeView extends RootView
|
module.exports = class HomeView extends RootView
|
||||||
|
@ -40,4 +38,3 @@ module.exports = class HomeView extends RootView
|
||||||
|
|
||||||
afterInsert: ->
|
afterInsert: ->
|
||||||
super(arguments...)
|
super(arguments...)
|
||||||
@openModalView(new InventoryModal({levelID: 'the-raised-sword'}))
|
|
|
@ -44,14 +44,15 @@ module.exports = class InventoryModal extends ModalView
|
||||||
# TODO: switch to item store loading system?
|
# TODO: switch to item store loading system?
|
||||||
@items.url = '/db/thang.type?view=items'
|
@items.url = '/db/thang.type?view=items'
|
||||||
@items.setProjection [
|
@items.setProjection [
|
||||||
'name',
|
'name'
|
||||||
'slug',
|
'slug'
|
||||||
'components',
|
'components'
|
||||||
'original',
|
'original'
|
||||||
'rasterIcon',
|
'rasterIcon'
|
||||||
'gems',
|
'gems'
|
||||||
'description',
|
'tier'
|
||||||
'heroClass',
|
'description'
|
||||||
|
'heroClass'
|
||||||
'i18n'
|
'i18n'
|
||||||
]
|
]
|
||||||
@supermodel.loadCollection(@items, 'items')
|
@supermodel.loadCollection(@items, 'items')
|
||||||
|
|
|
@ -62,6 +62,7 @@ module.exports = class PlayItemsModal extends ModalView
|
||||||
'original'
|
'original'
|
||||||
'rasterIcon'
|
'rasterIcon'
|
||||||
'gems'
|
'gems'
|
||||||
|
'tier'
|
||||||
'i18n'
|
'i18n'
|
||||||
'heroClass'
|
'heroClass'
|
||||||
]
|
]
|
||||||
|
@ -77,7 +78,8 @@ module.exports = class PlayItemsModal extends ModalView
|
||||||
gemsOwned = me.gems()
|
gemsOwned = me.gems()
|
||||||
needMore = itemFetcher.models.length is PAGE_SIZE
|
needMore = itemFetcher.models.length is PAGE_SIZE
|
||||||
for model in itemFetcher.models
|
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'
|
category = slotToCategory[model.getAllowedSlots()[0]] or 'misc'
|
||||||
@itemCategoryCollections[category] ?= new Backbone.Collection()
|
@itemCategoryCollections[category] ?= new Backbone.Collection()
|
||||||
collection = @itemCategoryCollections[category]
|
collection = @itemCategoryCollections[category]
|
||||||
|
@ -85,10 +87,10 @@ module.exports = class PlayItemsModal extends ModalView
|
||||||
collection.add(model)
|
collection.add(model)
|
||||||
model.name = utils.i18n model.attributes, 'name'
|
model.name = utils.i18n model.attributes, 'name'
|
||||||
model.affordable = cost <= gemsOwned
|
model.affordable = cost <= gemsOwned
|
||||||
model.owned = me.ownsItem model.get('original')
|
model.silhouetted = not model.owned and model.isSilhouettedItem()
|
||||||
model.silhouetted = model.isSilhouettedItem()
|
model.level = model.levelRequiredForItem() if model.get('tier')?
|
||||||
model.equippable = 'Warrior' in model.getAllowedHeroClasses() # Temp: while there are no wizards/rangers
|
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
|
@idToItem[model.id] = model
|
||||||
|
|
||||||
if needMore
|
if needMore
|
||||||
|
@ -127,7 +129,7 @@ module.exports = class PlayItemsModal extends ModalView
|
||||||
item = null
|
item = null
|
||||||
else
|
else
|
||||||
item = @idToItem[itemEl.data('item-id')]
|
item = @idToItem[itemEl.data('item-id')]
|
||||||
if item.silhouetted
|
if item.silhouetted and not item.owned
|
||||||
item = null
|
item = null
|
||||||
else
|
else
|
||||||
itemEl.addClass('selected') unless wasSelected
|
itemEl.addClass('selected') unless wasSelected
|
||||||
|
@ -158,4 +160,3 @@ module.exports = class PlayItemsModal extends ModalView
|
||||||
button.addClass('confirm').text($.i18n.t('play.confirm'))
|
button.addClass('confirm').text($.i18n.t('play.confirm'))
|
||||||
@$el.one 'click', (e) ->
|
@$el.one 'click', (e) ->
|
||||||
button.removeClass('confirm').text($.i18n.t('play.unlock')) if e.target isnt button[0]
|
button.removeClass('confirm').text($.i18n.t('play.unlock')) if e.target isnt button[0]
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ ThangTypeHandler = class ThangTypeHandler extends Handler
|
||||||
'description'
|
'description'
|
||||||
'gems'
|
'gems'
|
||||||
'heroClass'
|
'heroClass'
|
||||||
|
'tier'
|
||||||
'extendedName'
|
'extendedName'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -61,7 +62,7 @@ ThangTypeHandler = class ThangTypeHandler extends Handler
|
||||||
query = slug: {$exists: true}
|
query = slug: {$exists: true}
|
||||||
if req.query.view is 'items'
|
if req.query.view is 'items'
|
||||||
query.kind = 'Item'
|
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'
|
else if req.query.view is 'heroes'
|
||||||
#query.kind = 'Hero' # TODO: when ChooseHeroView is refactored, just use this
|
#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
|
query.original = {$in: _.values heroes} # TODO: when ChooseHeroView is refactored, don't do this
|
||||||
|
|
Loading…
Reference in a new issue