2014-11-28 20:49:41 -05:00
ModalView = require ' views/core/ModalView '
2014-09-17 21:56:08 -04:00
template = require ' templates/play/modal/play-items-modal '
2014-11-24 13:51:20 -05:00
buyGemsPromptTemplate = require ' templates/play/modal/buy-gems-prompt '
2014-11-10 18:24:05 -05:00
ItemDetailsView = require ' ./ItemDetailsView '
2014-11-24 13:51:20 -05:00
BuyGemsModal = require ' views/play/modal/BuyGemsModal '
2016-02-25 18:24:16 -05:00
CreateAccountModal = require ' views/core/CreateAccountModal '
2014-11-01 17:15:57 -04:00
2014-09-17 21:56:08 -04:00
CocoCollection = require ' collections/CocoCollection '
ThangType = require ' models/ThangType '
2014-11-01 17:15:57 -04:00
LevelComponent = require ' models/LevelComponent '
2015-01-13 18:34:06 -05:00
Level = require ' models/Level '
2014-11-01 17:15:57 -04:00
Purchase = require ' models/Purchase '
2014-11-28 20:49:41 -05:00
utils = require ' core/utils '
2014-11-01 17:15:57 -04:00
PAGE_SIZE = 200
slotToCategory = {
' right-hand ' : ' primary '
' left-hand ' : ' secondary '
' head ' : ' armor '
' torso ' : ' armor '
' gloves ' : ' armor '
' feet ' : ' armor '
' eyes ' : ' accessories '
' neck ' : ' accessories '
' wrists ' : ' accessories '
' left-ring ' : ' accessories '
' right-ring ' : ' accessories '
' waist ' : ' accessories '
' pet ' : ' misc '
' minion ' : ' misc '
' flag ' : ' misc '
' misc-0 ' : ' misc '
' misc-1 ' : ' misc '
' programming-book ' : ' books '
}
2014-09-17 21:56:08 -04:00
module.exports = class PlayItemsModal extends ModalView
className: ' modal fade play-modal '
template: template
id: ' play-items-modal '
2014-11-01 17:15:57 -04:00
events:
' click .item ' : ' onItemClicked '
' shown.bs.tab ' : ' onTabClicked '
' click .unlock-button ' : ' onUnlockButtonClicked '
2014-11-24 13:51:20 -05:00
' click .buy-gems-prompt-button ' : ' onBuyGemsPromptButtonClicked '
2014-11-01 17:15:57 -04:00
' click # close-modal ' : ' hide '
2014-11-24 13:51:20 -05:00
' click ' : ' onClickedSomewhere '
2014-12-01 20:33:37 -05:00
' update .tab-pane .nano ' : ' onScrollItemPane '
2015-01-12 18:30:09 -05:00
' click # hero-type-select label ' : ' onClickHeroTypeSelect '
2014-09-17 21:56:08 -04:00
constructor: (options) ->
2014-12-01 20:33:37 -05:00
@onScrollItemPane = _ . throttle ( _ . bind ( @ onScrollItemPane , @ ) , 200 )
2014-09-17 21:56:08 -04:00
super options
2014-11-01 17:15:57 -04:00
@items = new Backbone . Collection ( )
@itemCategoryCollections = { }
2014-11-04 10:19:30 -05:00
2014-11-01 17:15:57 -04:00
project = [
' name '
' components.config '
' components.original '
' slug '
' original '
' rasterIcon '
' gems '
2014-11-11 01:07:55 -05:00
' tier '
2014-11-25 13:28:31 -05:00
' description '
2014-11-01 17:15:57 -04:00
' i18n '
2014-11-04 10:19:30 -05:00
' heroClass '
2014-11-01 17:15:57 -04:00
]
2014-11-04 10:19:30 -05:00
2014-11-01 17:15:57 -04:00
itemFetcher = new CocoCollection ( [ ] , { url: ' /db/thang.type?view=items ' , project: project , model: ThangType } )
itemFetcher.skip = 0
itemFetcher . fetch ( { data: { skip: 0 , limit: PAGE_SIZE } } )
@ listenTo itemFetcher , ' sync ' , @ onItemsFetched
2015-08-15 16:12:33 -04:00
@ stopListening @ supermodel , ' loaded-all '
2014-11-01 17:15:57 -04:00
@ supermodel . loadCollection ( itemFetcher , ' items ' )
@idToItem = { }
onItemsFetched: (itemFetcher) ->
gemsOwned = me . gems ( )
needMore = itemFetcher . models . length is PAGE_SIZE
for model in itemFetcher . models
2014-11-11 01:07:55 -05:00
model.owned = me . ownsItem model . get ( ' original ' )
continue unless ( cost = model . get ( ' gems ' ) ) or model . owned
2014-11-01 17:15:57 -04:00
category = slotToCategory [ model . getAllowedSlots ( ) [ 0 ] ] or ' misc '
@ itemCategoryCollections [ category ] ? = new Backbone . Collection ( )
collection = @ itemCategoryCollections [ category ]
2014-11-26 12:22:30 -05:00
collection.comparator = (m) -> m . get ( ' tier ' ) ? m . get ( ' gems ' )
2014-11-01 17:15:57 -04:00
collection . add ( model )
model.name = utils . i18n model . attributes , ' name '
model.affordable = cost <= gemsOwned
2014-11-11 01:07:55 -05:00
model.silhouetted = not model . owned and model . isSilhouettedItem ( )
model.level = model . levelRequiredForItem ( ) if model . get ( ' tier ' ) ?
2014-11-24 13:51:20 -05:00
model.unequippable = not _ . intersection ( me . getHeroClasses ( ) , model . getAllowedHeroClasses ( ) ) . length
2014-11-21 19:23:26 -05:00
model.comingSoon = not model . getFrontFacingStats ( ) . props . length and not _ . size ( model . getFrontFacingStats ( ) . stats ) and not model . owned # Temp: while there are placeholder items
2014-11-01 17:15:57 -04:00
@ idToItem [ model . id ] = model
2014-09-17 21:56:08 -04:00
2015-02-24 15:14:56 -05:00
if itemFetcher . skip isnt 0
# Make sure we render the newly fetched items, except the first time (when it happens automatically).
@ render ( )
2014-11-01 17:15:57 -04:00
if needMore
itemFetcher . skip += PAGE_SIZE
itemFetcher . fetch ( { data: { skip: itemFetcher . skip , limit: PAGE_SIZE } } )
2014-11-04 10:19:30 -05:00
2014-09-17 21:56:08 -04:00
getRenderData: (context={}) ->
context = super ( context )
2014-11-01 17:15:57 -04:00
context.itemCategoryCollections = @ itemCategoryCollections
context.itemCategories = _ . keys @ itemCategoryCollections
context.itemCategoryNames = ( $ . i18n . t " items. #{ category } " for category in context . itemCategories )
context.gems = me . gems ( )
2014-09-17 21:56:08 -04:00
context
afterRender: ->
super ( )
return unless @ supermodel . finished ( )
2015-08-17 15:34:34 -04:00
@ playSound ' game-menu-open '
2014-11-01 17:15:57 -04:00
@ $el . find ( ' .nano:visible ' ) . nanoScroller ( { alwaysVisible: true } )
@itemDetailsView = new ItemDetailsView ( )
@ insertSubView ( @ itemDetailsView )
2014-11-21 19:23:26 -05:00
@ $el . find ( " a[href= ' # item-category-armor ' ] " ) . click ( ) # Start on armor tab, if it's there.
2015-01-13 18:34:06 -05:00
earnedLevels = me . get ( ' earned ' ) ? . levels or [ ]
if Level . levels [ ' defense-of-plainswood ' ] not in earnedLevels
@ $el . find ( ' # misc-tab ' ) . hide ( )
2015-04-20 18:46:25 -04:00
@ $el . find ( ' # hero-type-select # warrior ' ) . click ( ) # Start on warrior tab, if low level.
2014-09-17 21:56:08 -04:00
onHidden: ->
super ( )
2015-08-17 15:34:34 -04:00
@ playSound ' game-menu-close '
2014-09-17 21:56:08 -04:00
2014-11-04 10:19:30 -05:00
2014-11-01 17:15:57 -04:00
#- Click events
2014-11-04 10:19:30 -05:00
2014-11-01 17:15:57 -04:00
onItemClicked: (e) ->
return if $ ( e . target ) . closest ( ' .unlock-button ' ) . length
2014-11-26 09:58:23 -05:00
@ playSound ' menu-button-click '
2014-11-01 17:15:57 -04:00
itemEl = $ ( e . target ) . closest ( ' .item ' )
wasSelected = itemEl . hasClass ( ' selected ' )
@ $el . find ( ' .item.selected ' ) . removeClass ( ' selected ' )
if wasSelected
item = null
else
item = @ idToItem [ itemEl . data ( ' item-id ' ) ]
2014-11-11 01:07:55 -05:00
if item . silhouetted and not item . owned
2014-11-01 17:15:57 -04:00
item = null
else
itemEl . addClass ( ' selected ' ) unless wasSelected
@ itemDetailsView . setItem ( item )
2014-11-04 10:19:30 -05:00
2014-11-01 17:15:57 -04:00
onTabClicked: (e) ->
2014-11-26 09:58:23 -05:00
@ playSound ' game-menu-tab-switch '
2014-12-01 20:33:37 -05:00
nano = $ ( $ ( e . target ) . attr ( ' href ' ) ) . find ( ' .nano ' )
nano . nanoScroller ( { alwaysVisible: true } )
@paneNanoContent = nano . find ( ' .nano-content ' )
@ onScrollItemPane ( )
onScrollItemPane: ->
# dynamically load visible items when the user scrolls enough to see them
2014-12-06 15:02:48 -05:00
return console . error " Couldn ' t update scroll, since paneNanoContent wasn ' t initialized. " unless @ paneNanoContent
2014-12-01 20:33:37 -05:00
items = @ paneNanoContent . find ( ' .item:not(.loaded) ' )
threshold = @ paneNanoContent . height ( ) + 100
for itemEl in items
itemEl = $ ( itemEl )
if itemEl . position ( ) . top < threshold
$ ( itemEl ) . addClass ( ' loaded ' )
item = @ idToItem [ itemEl . data ( ' item-id ' ) ]
itemEl . find ( ' .item-silhouette, .item-img ' ) . attr ( ' src ' , item . getPortraitURL ( ) )
2014-11-01 17:15:57 -04:00
2015-01-12 18:30:09 -05:00
onClickHeroTypeSelect: (e) ->
value = $ ( e . target ) . closest ( ' label ' ) . attr ( ' id ' )
tabContent = @ $el . find ( ' .tab-content ' )
tabContent . removeClass ( ' filter-wizard filter-ranger filter-warrior ' )
tabContent . addClass ( " filter- #{ value } " ) if value isnt ' all '
2014-11-01 17:15:57 -04:00
onUnlockButtonClicked: (e) ->
2014-11-24 13:51:20 -05:00
e . stopPropagation ( )
2014-11-10 18:24:05 -05:00
button = $ ( e . target ) . closest ( ' button ' )
2014-11-24 13:51:20 -05:00
item = @ idToItem [ button . data ( ' item-id ' ) ]
affordable = item . affordable
if not affordable
2014-11-26 09:58:23 -05:00
@ playSound ' menu-button-click '
2016-08-17 13:00:56 -04:00
@ askToBuyGems button unless me . isOnFreeOnlyServer ( )
2014-11-24 13:51:20 -05:00
else if button . hasClass ( ' confirm ' )
2014-11-26 09:58:23 -05:00
@ playSound ' menu-button-unlock-end '
2014-11-01 17:15:57 -04:00
purchase = Purchase . makeFor ( item )
purchase . save ( )
2014-11-04 10:19:30 -05:00
2014-11-01 17:15:57 -04:00
#- set local changes to mimic what should happen on the server...
purchased = me . get ( ' purchased ' ) ? { }
purchased . items ? = [ ]
purchased . items . push ( item . get ( ' original ' ) )
item.owned = true
me . set ( ' purchased ' , purchased )
me . set ( ' spent ' , ( me . get ( ' spent ' ) ? 0 ) + item . get ( ' gems ' ) )
2014-11-04 10:19:30 -05:00
2014-11-01 17:15:57 -04:00
#- ...then rerender key bits
@ renderSelectors ( " .item[data-item-id= ' #{ item . id } ' ] " , " # gems-count " )
@ itemDetailsView . render ( )
2014-11-21 19:23:26 -05:00
Backbone . Mediator . publish ' store:item-purchased ' , item: item , itemSlug: item . get ( ' slug ' )
2014-11-01 17:15:57 -04:00
else
2014-11-26 09:58:23 -05:00
@ playSound ' menu-button-unlock-start '
2014-11-01 17:15:57 -04:00
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 ]
2014-11-24 13:51:20 -05:00
2015-02-11 17:09:00 -05:00
askToSignUp: ->
2016-02-25 18:24:16 -05:00
createAccountModal = new CreateAccountModal supermodel: @ supermodel
return @ openModalView createAccountModal
2015-02-11 17:09:00 -05:00
2014-11-24 13:51:20 -05:00
askToBuyGems: (unlockButton) ->
@ $el . find ( ' .unlock-button ' ) . popover ' destroy '
popoverTemplate = buyGemsPromptTemplate { }
unlockButton . popover (
animation: true
trigger: ' manual '
2014-12-07 18:29:19 -05:00
placement: ' top '
2014-11-24 13:51:20 -05:00
content: ' ' # template has it
container: @ $el
template: popoverTemplate
) . popover ' show '
popover = unlockButton . data ( ' bs.popover ' )
popover ? . $tip ? . i18n ( )
onBuyGemsPromptButtonClicked: (e) ->
2014-11-26 09:58:23 -05:00
@ playSound ' menu-button-click '
2015-02-11 17:09:00 -05:00
return @ askToSignUp ( ) if me . get ( ' anonymous ' )
2014-11-24 13:51:20 -05:00
@ openModalView new BuyGemsModal ( )
onClickedSomewhere: (e) ->
return if @ destroyed
@ $el . find ( ' .unlock-button ' ) . popover ' destroy '
destroy: ->
@ $el . find ( ' .unlock-button ' ) . popover ' destroy '
super ( )