mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-01 15:50:11 -04:00
Hooked up hero choice from ChooseHeroView and PlayLevelModal. Tried to fix some oddities with achievements. Fixed #1564.
This commit is contained in:
parent
ae7a2dfe6a
commit
ae14bd1ced
17 changed files with 113 additions and 55 deletions
app
lib
schemas
styles
views
server
|
@ -89,9 +89,9 @@ module.exports = class LevelLoader extends CocoClass
|
|||
loadDependenciesForSession: (session) ->
|
||||
return unless @level.get('type', true) is 'hero'
|
||||
heroConfig = session.get('heroConfig')
|
||||
unless heroConfig
|
||||
heroConfig = {inventory: {}, thangType: '529ffbf1cf1818f2be000001'} # Temp: assign Tharin as the hero
|
||||
session.set 'heroConfig', heroConfig
|
||||
heroConfig ?= me.get('heroConfig')
|
||||
heroConfig ?= {inventory: {}, thangType: '529ffbf1cf1818f2be000001'} # If we got here not from PlayLevelModal (like level editor preview), assign Tharin as the hero.
|
||||
session.set 'heroConfig', heroConfig unless _.isEqual heroConfig, session.get('heroConfig')
|
||||
url = "/db/thang.type/#{heroConfig.thangType}/version?project=name,components,original"
|
||||
@worldNecessities.push @maybeLoadURL(url, ThangType, 'thang')
|
||||
|
||||
|
|
|
@ -59,12 +59,7 @@ _.extend LevelSessionSchema.properties,
|
|||
screenshot:
|
||||
type: 'string'
|
||||
|
||||
heroConfig: c.object {description: 'Which hero the player is using, equipped with what inventory.'},
|
||||
inventory:
|
||||
type: 'object'
|
||||
description: 'The inventory of the hero: slots to item ThangTypes.'
|
||||
additionalProperties: c.objectId(description: 'An item ThangType.')
|
||||
thangType: c.objectId(links: [{rel: 'db', href: '/db/thang.type/{($)}/version'}], title: 'Thang Type', description: 'The ThangType of the hero.', format: 'thang-type')
|
||||
heroConfig: c.HeroConfigSchema
|
||||
|
||||
state: c.object {},
|
||||
complete:
|
||||
|
|
|
@ -45,7 +45,7 @@ visa = c.shortString
|
|||
title: 'US Work Status'
|
||||
description: 'Are you authorized to work in the US, or do you need visa sponsorship? (If you live in Canada or Australia, mark authorized.)'
|
||||
enum: ['Authorized to work in the US', 'Need visa sponsorship']
|
||||
|
||||
|
||||
_.extend UserSchema.properties,
|
||||
email: c.shortString({title: 'Email', format: 'email'})
|
||||
firstName: c.shortString({title: 'First Name'})
|
||||
|
@ -64,6 +64,7 @@ _.extend UserSchema.properties,
|
|||
music: { type: 'boolean' }
|
||||
autocastDelay: { type: 'integer' }
|
||||
lastLevel: { type: 'string' }
|
||||
heroConfig: c.HeroConfigSchema
|
||||
|
||||
emailSubscriptions: c.array {uniqueItems: true}, {'enum': emailSubscriptions}
|
||||
emails: c.object {title: 'Email Settings', default: generalNews: {enabled: true}, anyNotes: {enabled: true}, recruitNotes: {enabled: true} },
|
||||
|
@ -114,7 +115,7 @@ _.extend UserSchema.properties,
|
|||
|
||||
simulatedBy: {type: 'integer', minimum: 0 }
|
||||
simulatedFor: {type: 'integer', minimum: 0 }
|
||||
|
||||
|
||||
jobProfile: c.object {title: 'Job Profile', default: { active: false, lookingFor: 'Full-time', jobTitle: 'Software Developer', city: 'Defaultsville, CA', country: 'USA', skills: ['javascript'], shortDescription: 'Programmer seeking to build great software.', longDescription: '* I write great code.\n* You need great code?\n* Great!' }},
|
||||
lookingFor: {title: 'Looking For', type: 'string', enum: ['Full-time', 'Part-time', 'Remote', 'Contracting', 'Internship'], description: 'What kind of developer position do you want?'}
|
||||
jobTitle: {type: 'string', maxLength: 50, title: 'Desired Job Title', description: 'What role are you looking for? Ex.: "Full Stack Engineer", "Front-End Developer", "iOS Developer"' }
|
||||
|
|
|
@ -202,3 +202,10 @@ me.activity = me.object {description: 'Stats on an activity'},
|
|||
count: {type: 'integer', minimum: 0}
|
||||
|
||||
me.terrainString = me.shortString {enum: ['Grass', 'Dungeon', 'Indoor'], title: 'Terrain', description: 'Which terrain type this is.'}
|
||||
|
||||
me.HeroConfigSchema = me.object {description: 'Which hero the player is using, equipped with what inventory.'},
|
||||
inventory:
|
||||
type: 'object'
|
||||
description: 'The inventory of the hero: slots to item ThangTypes.'
|
||||
additionalProperties: me.objectId(description: 'An item ThangType.')
|
||||
thangType: me.objectId(links: [{rel: 'db', href: '/db/thang.type/{($)}/version'}], title: 'Thang Type', description: 'The ThangType of the hero.', format: 'thang-type')
|
||||
|
|
|
@ -38,7 +38,3 @@ module.exports =
|
|||
|
||||
'supermodel:load-progress-changed': c.object {required: ['progress']},
|
||||
progress: {type: 'number', minimum: 0, maximum: 1}
|
||||
|
||||
'options:hero-changed': c.object {required: ['hero']},
|
||||
hero: {type: 'object'}
|
||||
locked: {type: 'boolean'}
|
||||
|
|
|
@ -155,4 +155,4 @@ module.exports =
|
|||
|
||||
'level:edit-wizard-settings': c.object {}
|
||||
|
||||
'level:inventory-changed': c.object {}
|
||||
'level:hero-config-changed': c.object {}
|
||||
|
|
|
@ -244,9 +244,10 @@ $user-achievements-scale: 0.8
|
|||
position: fixed
|
||||
right: 0px
|
||||
bottom: 0px
|
||||
z-index: 9001
|
||||
cursor: pointer
|
||||
|
||||
.popup
|
||||
cursor: default
|
||||
left: 600px
|
||||
|
||||
.user-level
|
||||
|
|
|
@ -32,11 +32,13 @@ $heroCanvasHeight: 330px
|
|||
height: $maxHeroPortraitSize
|
||||
margin: 0px 3px
|
||||
background-size: contain
|
||||
@include transition(0.5s ease)
|
||||
border: 2px solid black
|
||||
border-radius: 2px
|
||||
position: relative
|
||||
|
||||
&.initialized
|
||||
@include transition(0.5s ease)
|
||||
|
||||
&.active
|
||||
border-color: gold
|
||||
|
||||
|
|
|
@ -66,14 +66,14 @@ module.exports = class AchievementPopup extends CocoView
|
|||
super()
|
||||
@container.prepend @$el
|
||||
if @popup
|
||||
@$el.animate
|
||||
left: 0
|
||||
@$el.on 'click', (e) =>
|
||||
@$el.animate
|
||||
left: 600
|
||||
, =>
|
||||
hide = =>
|
||||
return if @destroyed
|
||||
@$el.animate {left: 600}, =>
|
||||
@$el.remove()
|
||||
@destroy()
|
||||
@$el.animate left: 0
|
||||
@$el.on 'click', hide
|
||||
_.delay hide, 10000 unless $('#editor-achievement-edit-view').length
|
||||
|
||||
getContainer: ->
|
||||
unless @container
|
||||
|
|
|
@ -50,15 +50,18 @@ module.exports = class ChooseHeroView extends CocoView
|
|||
afterRender: ->
|
||||
super()
|
||||
return unless @supermodel.finished()
|
||||
@$el.find('.hero-item:first-child, .hero-indicator:first-child').addClass('active')
|
||||
heroes = @heroes.models
|
||||
@$el.find('.hero-indicator').each ->
|
||||
heroID = $(@).data('hero-id')
|
||||
hero = _.find heroes, (hero) -> hero.get('original') is heroID
|
||||
$(@).css('background-image', "url(#{hero.getPortraitURL()})").tooltip()
|
||||
_.defer => $(@).addClass 'initialized'
|
||||
@canvasWidth = 313 # @$el.find('canvas').width() # unreliable, whatever
|
||||
@canvasHeight = @$el.find('canvas').height()
|
||||
@onHeroChanged direction: null, relatedTarget: @$el.find('.hero-item')[0]
|
||||
heroConfig = @options.session.get('heroConfig') ? me.get('heroConfig') ? {}
|
||||
heroIndex = Math.max 0, _.findIndex(heroes, ((hero) -> hero.get('original') is heroConfig.thangType))
|
||||
@$el.find(".hero-item:nth-child(#{heroIndex + 1}), .hero-indicator:nth-child(#{heroIndex + 1})").addClass('active')
|
||||
@onHeroChanged direction: null, relatedTarget: @$el.find('.hero-item')[heroIndex]
|
||||
|
||||
onHeroChanged: (e) ->
|
||||
direction = e.direction # 'left' or 'right'
|
||||
|
@ -70,8 +73,10 @@ module.exports = class ChooseHeroView extends CocoView
|
|||
size = 100 - (50 / 3) * distance
|
||||
$(@).css width: size, height: size, top: -(100 - size) / 2
|
||||
heroInfo = temporaryHeroInfo[hero.get('slug')]
|
||||
locked = heroInfo.status is 'Locked'
|
||||
hero = @loadHero hero, heroIndex
|
||||
Backbone.Mediator.publish 'options:hero-changed', hero: hero, locked: heroInfo.status is 'Locked'
|
||||
@selectedHero = hero unless locked
|
||||
$('#choose-inventory-button').prop 'disabled', locked
|
||||
|
||||
loadHero: (hero, heroIndex) ->
|
||||
createjs.Ticker.removeEventListener 'tick', stage for stage in _.values @stages
|
||||
|
@ -103,6 +108,10 @@ module.exports = class ChooseHeroView extends CocoView
|
|||
@listenToOnce fullHero, 'sync', onLoaded
|
||||
fullHero
|
||||
|
||||
onHidden: ->
|
||||
|
||||
|
||||
|
||||
temporaryHeroInfo =
|
||||
captain:
|
||||
fullName: 'Captain Anya Weston'
|
||||
|
|
|
@ -43,5 +43,27 @@ module.exports = class GameMenuModal extends ModalView
|
|||
onHidden: ->
|
||||
super()
|
||||
subview.onHidden?() for subviewKey, subview of @subviews
|
||||
me.patch()
|
||||
patchingMe = @updateHeroConfig()
|
||||
me.patch() unless patchingMe # Might need to patch for options menu
|
||||
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'game-menu-close', volume: 1
|
||||
|
||||
updateHeroConfig: ->
|
||||
sessionHeroConfig = @options.session.get('heroConfig') ? {}
|
||||
lastHeroConfig = me.get('heroConfig') ? {}
|
||||
thangType = @subviews.choose_hero_view.selectedHero.get 'original'
|
||||
inventory = @subviews.inventory_view.getCurrentEquipmentConfig()
|
||||
patchSession = patchMe = false
|
||||
props = thangType: thangType, inventory: inventory
|
||||
for key, val of props when val
|
||||
patchSession ||= not _.isEqual val, sessionHeroConfig[key]
|
||||
patchMe ||= not _.isEqual val, lastHeroConfig[key]
|
||||
sessionHeroConfig[key] = val
|
||||
lastHeroConfig[key] = val
|
||||
if patchSession
|
||||
@options.session.set 'heroConfig', sessionHeroConfig
|
||||
@options.session.patch success: ->
|
||||
_.defer -> Backbone.Mediator.publish 'level:hero-config-changed', {}
|
||||
if patchMe
|
||||
me.set 'heroConfig', lastHeroConfig
|
||||
me.patch()
|
||||
patchMe
|
||||
|
|
|
@ -24,7 +24,7 @@ module.exports = class InventoryView extends CocoView
|
|||
initialize: (options) ->
|
||||
super(arguments...)
|
||||
@items = new CocoCollection([], {model: ThangType})
|
||||
@equipment = options.equipment or @options.session?.get('heroConfig')?.inventory or {}
|
||||
@equipment = options.equipment or @options.session?.get('heroConfig')?.inventory or me.get('heroConfig')?.inventory or {}
|
||||
@items.url = '/db/thang.type?view=items&project=name,components,original,rasterIcon'
|
||||
@supermodel.loadCollection(@items, 'items')
|
||||
|
||||
|
@ -234,16 +234,6 @@ module.exports = class InventoryView extends CocoView
|
|||
continue unless slotItemID
|
||||
item = _.find @items.models, {id:slotItemID}
|
||||
config[slotName] = item.get('original')
|
||||
|
||||
config
|
||||
|
||||
onHidden: ->
|
||||
inventory = @getCurrentEquipmentConfig()
|
||||
heroConfig = @options.session.get('heroConfig') ? {}
|
||||
return if _.isEqual inventory, (heroConfig.inventory ? {})
|
||||
heroConfig.inventory = inventory
|
||||
heroConfig.thangType ?= '529ffbf1cf1818f2be000001' # Temp: assign Tharin as the hero
|
||||
@options.session.set 'heroConfig', heroConfig
|
||||
@options.session.patch success: ->
|
||||
_.defer ->
|
||||
Backbone.Mediator.publish 'level:inventory-changed', {}
|
||||
|
|
|
@ -552,10 +552,10 @@ hero = [
|
|||
y: 53.1
|
||||
}
|
||||
{
|
||||
name: 'Lowest Kithmen'
|
||||
name: 'Lowly Kithmen'
|
||||
type: 'hero'
|
||||
difficulty: 1
|
||||
id: 'lowest-kithguards'
|
||||
id: 'lowly-kithmen'
|
||||
image: '/file/db/level/525ef8ef06e1ab0962000003/commanding_followers_icon.png'
|
||||
description: 'Use your glasses to seek out and attack the Kithmen.'
|
||||
x: 39.4
|
||||
|
|
|
@ -70,7 +70,7 @@ module.exports = class PlayLevelView extends RootView
|
|||
'real-time-multiplayer:joined-game': 'onJoinedRealTimeMultiplayerGame'
|
||||
'real-time-multiplayer:left-game': 'onLeftRealTimeMultiplayerGame'
|
||||
'real-time-multiplayer:manual-cast': 'onRealTimeMultiplayerCast'
|
||||
'level:inventory-changed': 'onInventoryChanged'
|
||||
'level:hero-config-changed': 'onHeroConfigChanged'
|
||||
|
||||
events:
|
||||
'click #level-done-button': 'onDonePressed'
|
||||
|
@ -371,7 +371,7 @@ module.exports = class PlayLevelView extends RootView
|
|||
break
|
||||
Backbone.Mediator.publish 'tome:cast-spell', {}
|
||||
|
||||
onInventoryChanged: (e) ->
|
||||
onHeroConfigChanged: (e) ->
|
||||
# Doesn't work because the new inventory ThangTypes may not be loaded.
|
||||
#@setLevel @level, @supermodel
|
||||
#Backbone.Mediator.publish 'tome:cast-spell', {}
|
||||
|
|
|
@ -2,6 +2,8 @@ ModalView = require 'views/kinds/ModalView'
|
|||
template = require 'templates/play/modal/play-level-modal'
|
||||
ChooseHeroView = require 'views/game-menu/ChooseHeroView'
|
||||
InventoryView = require 'views/game-menu/InventoryView'
|
||||
PlayLevelView = require 'views/play/level/PlayLevelView'
|
||||
LevelSession = require 'models/LevelSession'
|
||||
|
||||
module.exports = class PlayLevelModal extends ModalView
|
||||
className: 'modal fade play-modal'
|
||||
|
@ -13,12 +15,17 @@ module.exports = class PlayLevelModal extends ModalView
|
|||
'click #choose-hero-button': 'onClickChooseHero'
|
||||
'click #play-level-button': 'onClickPlayLevel'
|
||||
|
||||
subscriptions:
|
||||
'options:hero-changed': 'onHeroChanged'
|
||||
|
||||
constructor: (options) ->
|
||||
super options
|
||||
@options.showDevBits = true
|
||||
@loadSession()
|
||||
|
||||
loadSession: ->
|
||||
url = "/db/level/#{@options.levelID}/session"
|
||||
#url += "?team=#{@team}" if @options.team # TODO: figure out how to get the teams for multiplayer PVP hero style
|
||||
session = new LevelSession().setURL url
|
||||
@session = @supermodel.loadModel(session, 'level_session').model
|
||||
@options.session = @session
|
||||
|
||||
getRenderData: (context={}) ->
|
||||
context = super(context)
|
||||
|
@ -30,14 +37,39 @@ module.exports = class PlayLevelModal extends ModalView
|
|||
afterRender: ->
|
||||
super()
|
||||
return unless @supermodel.finished()
|
||||
@session.url = -> '/db/level.session/' + @id
|
||||
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'game-menu-open', volume: 1
|
||||
@insertSubView @chooseHeroView = new ChooseHeroView @options
|
||||
@insertSubView @inventoryView = new InventoryView @options
|
||||
@inventoryView.$el.addClass 'secret'
|
||||
|
||||
onHidden: ->
|
||||
super()
|
||||
unless @navigatingToPlay
|
||||
skipSessionSave = not @options.session.get('levelName')? # Has to have been already started.
|
||||
@updateHeroConfig null, skipSessionSave
|
||||
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'game-menu-close', volume: 1
|
||||
super()
|
||||
|
||||
updateHeroConfig: (callback, skipSessionSave) ->
|
||||
sessionHeroConfig = @options.session.get('heroConfig') ? {}
|
||||
lastHeroConfig = me.get('heroConfig') ? {}
|
||||
thangType = @subviews.choose_hero_view.selectedHero.get 'original'
|
||||
inventory = @subviews.inventory_view.getCurrentEquipmentConfig()
|
||||
patchSession = patchMe = false
|
||||
props = thangType: thangType, inventory: inventory
|
||||
for key, val of props when val
|
||||
patchSession ||= not _.isEqual val, sessionHeroConfig[key]
|
||||
patchMe ||= not _.isEqual val, lastHeroConfig[key]
|
||||
sessionHeroConfig[key] = val
|
||||
lastHeroConfig[key] = val
|
||||
if patchMe
|
||||
me.set 'heroConfig', lastHeroConfig
|
||||
me.patch()
|
||||
if patchSession
|
||||
@options.session.set 'heroConfig', sessionHeroConfig
|
||||
@options.session.patch success: callback unless skipSessionSave
|
||||
else
|
||||
callback?()
|
||||
|
||||
onClickChooseInventory: (e) ->
|
||||
@chooseHeroView.$el.add('#choose-inventory-button, #choose-hero-header').addClass 'secret'
|
||||
|
@ -48,8 +80,10 @@ module.exports = class PlayLevelModal extends ModalView
|
|||
@inventoryView.$el.add('#choose-hero-button, #play-level-button, #choose-inventory-header').addClass 'secret'
|
||||
|
||||
onClickPlayLevel: (e) ->
|
||||
console.log 'should play!'
|
||||
|
||||
onHeroChanged: (e) ->
|
||||
@$el.find('#choose-inventory-button').prop 'disabled', Boolean e.locked
|
||||
@hero = e.hero
|
||||
@showLoading()
|
||||
@updateHeroConfig =>
|
||||
@navigatingToPlay = true
|
||||
Backbone.Mediator.publish 'router:navigate', {
|
||||
route: "/play/#{@options.levelPath || 'level'}/#{@options.levelID}",
|
||||
viewClass: PlayLevelView,
|
||||
viewArgs: [{supermodel: @supermodel}, @options.levelID]}
|
||||
|
|
|
@ -115,9 +115,9 @@ class EarnedAchievementHandler extends Handler
|
|||
earned.previouslyAchievedAmount = 0
|
||||
|
||||
expFunction = achievement.getExpFunction()
|
||||
newPoints = expFunction(earned.achievedAmount) * achievement.get('worth')
|
||||
newPoints = expFunction(earned.achievedAmount) * achievement.get('worth') ? 10
|
||||
else
|
||||
newPoints = achievement.get 'worth'
|
||||
newPoints = achievement.get('worth') ? 10
|
||||
|
||||
earned.earnedPoints = newPoints
|
||||
newTotalPoints += newPoints
|
||||
|
|
|
@ -193,7 +193,8 @@ UserSchema.statics.editableProperties = [
|
|||
'name', 'photoURL', 'password', 'anonymous', 'wizardColor1', 'volume',
|
||||
'firstName', 'lastName', 'gender', 'facebookID', 'gplusID', 'emails',
|
||||
'testGroupNumber', 'music', 'hourOfCode', 'hourOfCodeComplete', 'preferredLanguage',
|
||||
'wizard', 'aceConfig', 'autocastDelay', 'lastLevel', 'jobProfile', 'savedEmployerFilterAlerts'
|
||||
'wizard', 'aceConfig', 'autocastDelay', 'lastLevel', 'jobProfile', 'savedEmployerFilterAlerts',
|
||||
'heroConfig'
|
||||
]
|
||||
|
||||
UserSchema.plugin plugins.NamedPlugin
|
||||
|
|
Loading…
Add table
Reference in a new issue