You can now buy cross-class items once you have a hero of that class. When you click to buy an item you can't afford, it takes you to the gem shop. Increased amount of items you can purchase a bit more.

This commit is contained in:
Nick Winter 2014-11-24 10:51:20 -08:00
parent f9e6c167bc
commit 9accd0cb04
10 changed files with 161 additions and 50 deletions

View file

@ -96,10 +96,10 @@
logging_in: "Logging In"
log_out: "Log Out"
recover: "recover account"
authenticate_gplus: 'Authenticate G+'
load_profile: 'Load G+ Profile'
load_email: 'Load G+ Email'
finishing: 'Finishing'
authenticate_gplus: "Authenticate G+"
load_profile: "Load G+ Profile"
load_email: "Load G+ Email"
finishing: "Finishing"
signup:
create_account_title: "Create Account to Save Progress"
@ -319,12 +319,15 @@
unequip: "Unequip"
buy_gems:
few_gems: 'A few gems'
pile_gems: 'Pile of gems'
chest_gems: 'Chest of gems'
purchasing: 'Purchasing...'
declined: 'Your card was declined'
retrying: 'Server error, retrying.'
few_gems: "A few gems"
pile_gems: "Pile of gems"
chest_gems: "Chest of gems"
purchasing: "Purchasing..."
declined: "Your card was declined"
retrying: "Server error, retrying."
prompt_title: "Not Enough Gems"
prompt_body: "Do you want to get more?"
prompt_button: "Enter Shop"
choose_hero:
choose_hero: "Choose Your Hero"

View file

@ -19,6 +19,10 @@ module.exports = class ThangType extends CocoModel
librarian: '52fbf74b7e01835453bd8d8e'
'potion-master': '52e9adf7427172ae56002172'
sorcerer: '52fd1524c7e6cf99160e7bc9'
@heroClasses:
Warrior: ['captain', 'knight', 'samurai']
Ranger: ['ninja', 'forest-archer', 'trapper']
Wizard: ['librarian', 'potion-master', 'sorcerer']
@items:
'simple-boots': '53e237bf53457600003e3f05'
urlRoot: '/db/thang.type'
@ -447,7 +451,7 @@ module.exports = class ThangType extends CocoModel
levelRequiredForItem: ->
return console.error "Trying to determine what level is required for #{@get('name')}, but it has no tier." unless @get('tier')?
itemTier = @get 'tier'
playerTier = itemTier / 2
playerTier = itemTier / 2.5
playerLevel = me.constructor.levelForTier playerTier
#console.log 'Level required for', @get('name'), 'is', playerLevel, 'player tier', playerTier, 'because it is itemTier', itemTier, 'which is normally level', me.constructor.levelForTier(itemTier)
playerLevel

View file

@ -95,6 +95,13 @@ module.exports = class User extends CocoModel
ownsItem: (itemOriginal) -> itemOriginal in @items()
ownsLevel: (levelOriginal) -> levelOriginal in @levels()
getHeroClasses: ->
idsToSlugs = _.invert ThangType.heroes
myHeroSlugs = (idsToSlugs[id] for id in @heroes())
myHeroClasses = []
myHeroClasses.push heroClass for heroClass, heroSlugs of ThangType.heroClasses when _.intersection(myHeroSlugs, heroSlugs).length
myHeroClasses
getBranchingGroup: ->
return @branchingGroup if @branchingGroup
group = me.get('testGroupNumber') % 4
@ -107,4 +114,14 @@ module.exports = class User extends CocoModel
application.tracker.identify branchingGroup: @branchingGroup unless me.isAdmin()
@branchingGroup
getGemPromptGroup: ->
return @gemPromptGroup if @gemPromptGroup
group = me.get('testGroupNumber') % 8
@gemPromptGroup = switch group
when 0, 1, 2, 3 then 'prompt'
when 4, 5, 6, 7 then 'no-prompt'
@gemPromptGroup = 'prompt' if me.isAdmin()
application.tracker.identify gemPromptGroup: @gemPromptGroup unless me.isAdmin()
@gemPromptGroup
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

@ -228,6 +228,9 @@ kbd
border-width: 15px 20px
.arrow
display: none
.btn
font-size: 20px
width: 100%
.btn.btn-illustrated
background: 0
@ -242,6 +245,9 @@ kbd
font-weight: bold
color: rgb(248, 197, 146)
&:hover
color: lighten(rgb(248, 197, 146), 5%)
&:active
border-image: url(/images/common/button-background-pressed-border.png) 14 16 16 20 fill round
padding: 2px 0 0 2px

View file

@ -307,6 +307,13 @@
opacity: 1
color: rgba(255,255,255, 0.4)
// Make sure this shows up above our modals.
.popover.buy-gems-prompt
z-index: 1050
text-align: center
button
margin-top: 20px
//- Use the two-column layout and background image if we are on a narrow screen.

View file

@ -0,0 +1,6 @@
.popover.buy-gems-prompt(role="tooltip")
.arrow
h2(data-i18n="buy_gems.prompt_title") Not Enough Gems
p(data-i18n="buy_gems.prompt_body") Do you want to get more?
button.btn.btn-success.btn-illustrated.btn-lg.buy-gems-prompt-button(data-i18n="buy_gems.prompt_button") Enter Shop

View file

@ -37,7 +37,7 @@ if item && !item.owned
// Temp, while we only have Warriors: prevent them from buying non-Warrior stuff
button.btn.big-font.disabled.unequippable #{item.get('heroClass')} Only
else
button#selected-item-unlock-button.btn.big-font.unlock-button(disabled=!item.affordable, data-item-id=item.id)
button#selected-item-unlock-button.btn.big-font.unlock-button(data-item-id=item.id)
span(data-i18n="play.unlock") Unlock
span.spl= '('+item.get('gems')
img(src="/images/common/gem.png", draggable="false")

View file

@ -53,7 +53,7 @@
// Temp, while we only have Warriors: prevent them from buying non-Warrior stuff
span.big-font.unequippable= item.get('heroClass')
else
button.btn.unlock-button.big-font(data-i18n="play.unlock", disabled=!item.affordable, data-item-id=item.id)
button.btn.unlock-button.big-font(data-i18n="play.unlock", data-item-id=item.id)
.clearfix
#item-details-view

View file

@ -1,5 +1,6 @@
ModalView = require 'views/kinds/ModalView'
template = require 'templates/game-menu/inventory-modal'
buyGemsPromptTemplate = require 'templates/play/modal/buy-gems-prompt'
{me} = require 'lib/auth'
ThangType = require 'models/ThangType'
CocoCollection = require 'collections/CocoCollection'
@ -8,6 +9,7 @@ SpriteBuilder = require 'lib/sprites/SpriteBuilder'
ItemDetailsView = require 'views/play/modal/ItemDetailsView'
Purchase = require 'models/Purchase'
LevelOptions = require 'lib/LevelOptions'
BuyGemsModal = require 'views/play/modal/BuyGemsModal'
hasGoneFullScreenOnce = false
@ -31,6 +33,8 @@ module.exports = class InventoryModal extends ModalView
'click #equip-item-viewed': 'onClickEquipItemViewed'
'click #unequip-item-viewed': 'onClickUnequipItemViewed'
'click #close-modal': 'hide'
'click .buy-gems-prompt-button': 'onBuyGemsPromptButtonClicked'
'click': 'onClickedSomewhere'
shortcuts:
'esc': 'clearSelection'
@ -224,40 +228,6 @@ module.exports = class InventoryModal extends ModalView
@selectUnequippedItem(itemEl)
@equipSelectedItem()
onUnlockButtonClicked: (e) ->
button = $(e.target).closest('button')
if button.hasClass('confirm')
item = @items.get($(e.target).data('item-id'))
purchase = Purchase.makeFor(item)
purchase.save()
#- set local changes to mimic what should happen on the server...
purchased = me.get('purchased') ? {}
purchased.items ?= []
purchased.items.push(item.get('original'))
me.set('purchased', purchased)
me.set('spent', (me.get('spent') ? 0) + item.get('gems'))
#- ...then rerender key bits
@itemGroups.lockedItems.remove(item)
# Redo all item sorting to make sure that we don't clobber state changes since last render.
equipped = _.values @getCurrentEquipmentConfig()
@sortItem(item, equipped) for item in @items.models
@renderSelectors('#unequipped', '#gems-count')
@requireLevelEquipment()
@delegateEvents()
@setUpDraggableEventsForAvailableEquipment()
@itemDetailsView.setItem(item)
Backbone.Mediator.publish 'store:item-purchased', item: item, itemSlug: item.get('slug')
else
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]
#- Select/equip higher-level, all encompassing methods the callbacks all use
selectItemSlot: (slotEl) ->
@ -470,7 +440,70 @@ module.exports = class InventoryModal extends ModalView
else
callback?()
#- TODO: DRY this between PlayItemsModal and InventoryModal
onUnlockButtonClicked: (e) ->
e.stopPropagation()
button = $(e.target).closest('button')
item = @items.get(button.data('item-id'))
affordable = item.affordable
if not affordable
@askToBuyGems button
else if button.hasClass('confirm')
purchase = Purchase.makeFor(item)
purchase.save()
#- set local changes to mimic what should happen on the server...
purchased = me.get('purchased') ? {}
purchased.items ?= []
purchased.items.push(item.get('original'))
me.set('purchased', purchased)
me.set('spent', (me.get('spent') ? 0) + item.get('gems'))
#- ...then rerender key bits
@itemGroups.lockedItems.remove(item)
# Redo all item sorting to make sure that we don't clobber state changes since last render.
equipped = _.values @getCurrentEquipmentConfig()
@sortItem(item, equipped) for item in @items.models
@renderSelectors('#unequipped', '#gems-count')
@requireLevelEquipment()
@delegateEvents()
@setUpDraggableEventsForAvailableEquipment()
@itemDetailsView.setItem(item)
Backbone.Mediator.publish 'store:item-purchased', item: item, itemSlug: item.get('slug')
else
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]
askToBuyGems: (unlockButton) ->
if me.getGemPromptGroup() is 'no-prompt'
return @openModalView new BuyGemsModal()
@$el.find('.unlock-button').popover 'destroy'
popoverTemplate = buyGemsPromptTemplate {}
unlockButton.popover(
animation: true
trigger: 'manual'
placement: 'top'
content: ' ' # template has it
container: @$el
template: popoverTemplate
).popover 'show'
popover = unlockButton.data('bs.popover')
popover?.$tip?.i18n()
onBuyGemsPromptButtonClicked: (e) ->
@openModalView new BuyGemsModal()
onClickedSomewhere: (e) ->
return if @destroyed
@$el.find('.unlock-button').popover 'destroy'
destroy: ->
@$el.find('.unlock-button').popover 'destroy'
@stage?.removeAllChildren()
super()

View file

@ -1,6 +1,8 @@
ModalView = require 'views/kinds/ModalView'
template = require 'templates/play/modal/play-items-modal'
buyGemsPromptTemplate = require 'templates/play/modal/buy-gems-prompt'
ItemDetailsView = require './ItemDetailsView'
BuyGemsModal = require 'views/play/modal/BuyGemsModal'
CocoCollection = require 'collections/CocoCollection'
ThangType = require 'models/ThangType'
@ -46,7 +48,9 @@ module.exports = class PlayItemsModal extends ModalView
'click .item': 'onItemClicked'
'shown.bs.tab': 'onTabClicked'
'click .unlock-button': 'onUnlockButtonClicked'
'click .buy-gems-prompt-button': 'onBuyGemsPromptButtonClicked'
'click #close-modal': 'hide'
'click': 'onClickedSomewhere'
constructor: (options) ->
super options
@ -89,7 +93,7 @@ module.exports = class PlayItemsModal extends ModalView
model.affordable = cost <= gemsOwned
model.silhouetted = not model.owned and model.isSilhouettedItem()
model.level = model.levelRequiredForItem() if model.get('tier')?
model.unequippable = not ('Warrior' in model.getAllowedHeroClasses()) # Temp: while there are no wizards/rangers
model.unequippable = not _.intersection(me.getHeroClasses(), model.getAllowedHeroClasses()).length
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
@ -140,9 +144,14 @@ module.exports = class PlayItemsModal extends ModalView
$($(e.target).attr('href')).find('.nano').nanoScroller({alwaysVisible: true})
onUnlockButtonClicked: (e) ->
e.stopPropagation()
button = $(e.target).closest('button')
if button.hasClass('confirm')
item = @idToItem[$(e.target).data('item-id')]
item = @idToItem[button.data('item-id')]
affordable = item.affordable
if not affordable
@askToBuyGems button
else if button.hasClass('confirm')
purchase = Purchase.makeFor(item)
purchase.save()
@ -163,3 +172,29 @@ 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]
askToBuyGems: (unlockButton) ->
if me.getGemPromptGroup() is 'no-prompt'
return @openModalView new BuyGemsModal()
@$el.find('.unlock-button').popover 'destroy'
popoverTemplate = buyGemsPromptTemplate {}
unlockButton.popover(
animation: true
trigger: 'manual'
content: ' ' # template has it
container: @$el
template: popoverTemplate
).popover 'show'
popover = unlockButton.data('bs.popover')
popover?.$tip?.i18n()
onBuyGemsPromptButtonClicked: (e) ->
@openModalView new BuyGemsModal()
onClickedSomewhere: (e) ->
return if @destroyed
@$el.find('.unlock-button').popover 'destroy'
destroy: ->
@$el.find('.unlock-button').popover 'destroy'
super()