mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-26 22:13:32 -04:00
Hiding locked items with no slot selected. Silhouetting items that are too far above you. Only showing items with a gem cost in the inventory screen. Sorting items by gem cost. Animating double-clicking items to show their motion to the slot, sort of.
This commit is contained in:
parent
56ae82757a
commit
47c090f7c7
6 changed files with 67 additions and 22 deletions
app
models
styles/game-menu
templates/game-menu
views/game-menu
server
|
@ -294,7 +294,11 @@ module.exports = class ThangType extends CocoModel
|
|||
itemComponentRef = _.find(
|
||||
@get('components') or [],
|
||||
(compRef) -> compRef.original is LevelComponent.ItemID)
|
||||
return itemComponentRef?.config?.slots or []
|
||||
return itemComponentRef?.config?.slots or ['right-hand'] # ['right-hand'] is default
|
||||
|
||||
getAllowedHeroClasses: ->
|
||||
return [heroClass] if heroClass = @get 'heroClass'
|
||||
['Warrior', 'Ranger', 'Wizard']
|
||||
|
||||
getFrontFacingStats: ->
|
||||
components = @get('components') or []
|
||||
|
@ -341,3 +345,10 @@ module.exports = class ThangType extends CocoModel
|
|||
display = display.join ', '
|
||||
display = display.replace /9001m?/, 'Infinity'
|
||||
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'
|
||||
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
|
||||
|
|
|
@ -14,6 +14,11 @@ $selectedAreaHeight: 150px
|
|||
$stashMargin: 20px
|
||||
$stashWidth: $totalWidth - $equippedWidth - $stashMargin
|
||||
|
||||
.ui-effects-transfer
|
||||
outline: 2px solid #28f
|
||||
@include box-shadow(0 0 10px #28f)
|
||||
z-index: 9001
|
||||
|
||||
#inventory-view
|
||||
position: relative
|
||||
height: $inventoryHeight
|
||||
|
@ -200,6 +205,11 @@ $stashWidth: $totalWidth - $equippedWidth - $stashMargin
|
|||
padding: 4px
|
||||
background-color: white
|
||||
|
||||
&.Warrior .list-group-item:not(.Warrior), &.Ranger .list-group-item:not(.Ranger), &.Wizard .list-group-item:not(.Wizard)
|
||||
// Our code hides and shows (modifies display), but we can be invisible this other way.
|
||||
visibility: hidden
|
||||
position: absolute
|
||||
|
||||
.list-group-item
|
||||
padding: 4px 0
|
||||
@include transition(0.5s ease)
|
||||
|
@ -244,6 +254,18 @@ $stashWidth: $totalWidth - $equippedWidth - $stashMargin
|
|||
.item-info:after
|
||||
content: ' (locked)'
|
||||
|
||||
&.silhouette
|
||||
h4
|
||||
visibility: hidden
|
||||
position: absolute
|
||||
h4:before
|
||||
content: '???'
|
||||
visibility: visible
|
||||
.item-info:after
|
||||
display: none
|
||||
img
|
||||
@include filter(contrast(25%) brightness(25%))
|
||||
|
||||
.item-view
|
||||
cursor: pointer
|
||||
|
||||
|
|
|
@ -55,5 +55,5 @@
|
|||
h4#locked-description
|
||||
ul.list-group
|
||||
for item in lockedItems
|
||||
li.list-group-item(class=item.classes, data-item-id=item.get('original'))
|
||||
li.list-group-item(class=item.classes, data-item-id=item.get('original'), style="display: none")
|
||||
|
||||
|
|
|
@ -48,15 +48,24 @@ module.exports = class InventoryView extends CocoView
|
|||
context.equipped = _.values(@equipment)
|
||||
context.items = @items.models
|
||||
|
||||
context.unlockedItems = []
|
||||
context.lockedItems = []
|
||||
for item in @items.models
|
||||
item.classes = item.getAllowedSlots()
|
||||
item.classes.push 'equipped' if item.get('original') in context.equipped
|
||||
locked = @allowedItems and not (item.get('original') in @allowedItems)
|
||||
item.classes.push 'locked' if locked
|
||||
(if locked then context.lockedItems else context.unlockedItems).push item
|
||||
@items.models.sort (a, b) -> ('locked' in a.classes) - ('locked' in b.classes)
|
||||
item.classes.push 'locked' if locked and item.get('slug') isnt 'simple-boots'
|
||||
for heroClass in item.getAllowedHeroClasses()
|
||||
item.classes.push heroClass
|
||||
item.classes.push 'silhouette' if item.isSilhouettedItem()
|
||||
|
||||
@items.models.sort (a, b) ->
|
||||
lockScore = 90019001 * (('locked' in a.classes) - ('locked' in b.classes))
|
||||
gemScore = a.get('gems') - b.get('gems')
|
||||
lockScore + gemScore
|
||||
|
||||
context.unlockedItems = []
|
||||
context.lockedItems = []
|
||||
for item in @items.models
|
||||
(if 'locked' in item.classes then context.lockedItems else context.unlockedItems).push item
|
||||
|
||||
context.slots = @slots
|
||||
context.equipment = _.clone @equipment
|
||||
|
@ -184,6 +193,7 @@ module.exports = class InventoryView extends CocoView
|
|||
@onSelectionChanged()
|
||||
slot = @getSelectedSlot()
|
||||
slot = @$el.find('.item-slot:not(.disabled):first') if not slot.length
|
||||
$(e.target).effect('transfer', to: slot, duration: 500, easing: 'easeOutCubic') if e
|
||||
@unequipItemFromSlot(slot)
|
||||
@equipSelectedItemToSlot(slot)
|
||||
@onSelectionChanged()
|
||||
|
@ -261,9 +271,9 @@ module.exports = class InventoryView extends CocoView
|
|||
@hideSelectedSlotItem()
|
||||
else
|
||||
unlockedCount = @$el.find('#available-equipment .list-group-item:not(.locked)').show().length
|
||||
lockedCount = @$el.find('#available-equipment .list-group-item.locked').show().length
|
||||
@$el.find('#available-equipment .list-group-item.locked').hide()
|
||||
@$el.find('#unlocked-description').text("#{unlockedCount} items owned").toggle unlockedCount > 0
|
||||
@$el.find('#locked-description').text("#{lockedCount} items locked").toggle lockedCount > 0
|
||||
@$el.find('#locked-description').text("#{lockedCount} items locked").hide()
|
||||
#@$el.find('#available-equipment .list-group-item.equipped').hide()
|
||||
|
||||
@$el.find('.item-slot').removeClass('disabled')
|
||||
|
@ -327,30 +337,30 @@ module.exports = class InventoryView extends CocoView
|
|||
# This is temporary, until we have a more general way of awarding items and configuring needed/locked items per level.
|
||||
gear =
|
||||
'simple-boots': '53e237bf53457600003e3f05'
|
||||
'longsword': '53e218d853457600003e3ebe'
|
||||
'simple-sword': '53e218d853457600003e3ebe'
|
||||
'leather-tunic': '53e22eac53457600003e3efc'
|
||||
'leather-boots': '53e2384453457600003e3f07'
|
||||
'programmaticon-i': '53e4108204c00d4607a89f78'
|
||||
'crude-glasses': '53e238df53457600003e3f0b'
|
||||
'crude-wooden-glasses': '53e238df53457600003e3f0b'
|
||||
'builders-hammer': '53f4e6e3d822c23505b74f42'
|
||||
gearByLevel =
|
||||
'dungeons-of-kithgard': {feet: 'simple-boots'}
|
||||
'gems-in-the-deep': {feet: 'simple-boots'}
|
||||
'forgetful-gemsmith': {feet: 'simple-boots'}
|
||||
'shadow-guard': {feet: 'simple-boots'}
|
||||
'true-names': {feet: 'simple-boots', 'right-hand': 'longsword'}
|
||||
'the-raised-sword': {feet: 'simple-boots', 'right-hand': 'longsword', torso: 'leather-tunic'}
|
||||
'true-names': {feet: 'simple-boots', 'right-hand': 'simple-sword'}
|
||||
'the-raised-sword': {feet: 'simple-boots', 'right-hand': 'simple-sword', torso: 'leather-tunic'}
|
||||
'the-first-kithmaze': {feet: 'simple-boots', 'programming-book': 'programmaticon-i'}
|
||||
'the-second-kithmaze': {feet: 'simple-boots', 'programming-book': 'programmaticon-i'}
|
||||
'new-sight': {'right-hand': 'longsword', 'programming-book': 'programmaticon-i'}
|
||||
'lowly-kithmen': {feet: 'simple-boots', 'right-hand': 'longsword', 'programming-book': 'programmaticon-i', eyes: 'crude-glasses'}
|
||||
'closing-the-distance': {feet: 'simple-boots', 'right-hand': 'longsword', torso: 'leather-tunic', eyes: 'crude-glasses'}
|
||||
'the-final-kithmaze': {feet: 'simple-boots', 'right-hand': 'longsword', torso: 'leather-tunic', 'programming-book': 'programmaticon-i', eyes: 'crude-glasses'}
|
||||
'new-sight': {'right-hand': 'simple-sword', 'programming-book': 'programmaticon-i'}
|
||||
'lowly-kithmen': {feet: 'simple-boots', 'right-hand': 'simple-sword', 'programming-book': 'programmaticon-i', eyes: 'crude-wooden-glasses'}
|
||||
'closing-the-distance': {feet: 'simple-boots', 'right-hand': 'simple-sword', torso: 'leather-tunic', eyes: 'crude-wooden-glasses'}
|
||||
'the-final-kithmaze': {feet: 'simple-boots', 'right-hand': 'simple-sword', torso: 'leather-tunic', 'programming-book': 'programmaticon-i', eyes: 'crude-wooden-glasses'}
|
||||
'kithgard-gates': {feet: 'simple-boots', 'right-hand': 'builders-hammer', torso: 'leather-tunic'}
|
||||
'defense-of-plainswood': {feet: 'simple-boots', 'right-hand': 'builders-hammer'}
|
||||
'winding-trail': {feet: 'leather-boots', 'right-hand': 'builders-hammer'}
|
||||
'thornbush-farm': {feet: 'leather-boots', 'right-hand': 'builders-hammer', eyes: 'crude-glasses'}
|
||||
'a-fiery-trap': {feet: 'leather-boots', 'right-hand': 'builders-hammer', eyes: 'crude-glasses'}
|
||||
'thornbush-farm': {feet: 'leather-boots', 'right-hand': 'builders-hammer', eyes: 'crude-wooden-glasses'}
|
||||
'a-fiery-trap': {feet: 'leather-boots', 'right-hand': 'builders-hammer', eyes: 'crude-wooden-glasses'}
|
||||
return unless necessaryGear = gearByLevel[@options.levelID]
|
||||
if @inserted
|
||||
if @supermodel.finished()
|
||||
|
@ -363,7 +373,7 @@ module.exports = class InventoryView extends CocoView
|
|||
inWorldMap = $('#world-map-view').length
|
||||
for slot, item of necessaryGear
|
||||
continue if item is 'leather-tunic' and inWorldMap # Don't tell them they need it until they need it in the level
|
||||
continue if equipment[slot] and not ((item is 'builders-hammer' and equipment[slot] is gear.longsword) or (item is 'leather-boots' and equipment[slot] is gear['simple-boots']))
|
||||
continue if equipment[slot] and not ((item is 'builders-hammer' and equipment[slot] is gear['simple-sword']) or (item is 'leather-boots' and equipment[slot] is gear['simple-boots']))
|
||||
availableSlotSelector = "#available-equipment li[data-item-id='#{gear[item]}']"
|
||||
@highlightElement availableSlotSelector, delay: 500, sides: ['right'], rotation: Math.PI / 2
|
||||
@$el.find(availableSlotSelector).addClass 'should-equip'
|
||||
|
@ -386,6 +396,7 @@ module.exports = class InventoryView extends CocoView
|
|||
onHeroSelectionUpdated: (e) ->
|
||||
@selectedHero = e.hero
|
||||
@loadHero()
|
||||
@$el.removeClass('Warrior Ranger Wizard').addClass(@selectedHero.get('heroClass'))
|
||||
|
||||
loadHero: ->
|
||||
return unless @supermodel.finished() and @selectedHero and not @$el.hasClass 'secret'
|
||||
|
|
|
@ -46,9 +46,9 @@ module.exports = class Handler
|
|||
omissions = ['original'].concat(deltasLib.DOC_SKIP_PATHS)
|
||||
delta = differ.diff(_.omit(document.toObject(), omissions), _.omit(req.body, omissions))
|
||||
flattened = deltasLib.flattenDelta(delta)
|
||||
_.all(flattened, (delta) ->
|
||||
_.all flattened, (delta) ->
|
||||
# sometimes coverage gets moved around... allow other changes to happen to i18nCoverage
|
||||
return _.isArray(delta.o) and (('i18n' in delta.dataPath and delta.o.length is 1) or 'i18nCoverage' in delta.dataPath))
|
||||
return _.isArray(delta.o) and (('i18n' in delta.dataPath and delta.o.length is 1) or 'i18nCoverage' in delta.dataPath)
|
||||
|
||||
formatEntity: (req, document) -> document?.toObject()
|
||||
getEditableProperties: (req, document) ->
|
||||
|
|
|
@ -60,6 +60,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
|
||||
else if req.query.view is 'heroes'
|
||||
#query.kind = 'Hero' # TODO: when all the heroes are tagged, just use this
|
||||
query.original = {$in: _.values heroes} # TODO: when all the heroes are tagged, don't do this
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue