Crude steps towards using your hero equipment in items levels.

This commit is contained in:
Nick Winter 2014-08-14 15:09:10 -07:00
parent 9404c40b47
commit 0f983bdcf1
9 changed files with 108 additions and 60 deletions

View file

@ -31,6 +31,7 @@ module.exports = class LevelLoader extends CocoClass
@opponentSessionID = options.opponentSessionID
@team = options.team
@headless = options.headless
@inLevelEditor = options.inLevelEditor
@spectateMode = options.spectateMode ? false
@worldNecessities = []
@ -83,6 +84,7 @@ module.exports = class LevelLoader extends CocoClass
for itemThangType in _.values(heroConfig.inventory)
url = "/db/thang.type/#{itemThangType}/version?project=name,components,original"
@worldNecessities.push @maybeLoadURL(url, ThangType, 'thang')
@populateHero() if @level?.loaded
# Supermodel (Level) Loading
@ -96,6 +98,7 @@ module.exports = class LevelLoader extends CocoClass
onLevelLoaded: ->
@populateLevel()
@populateHero() if @session?.loaded
populateLevel: ->
thangIDs = []
@ -149,6 +152,16 @@ module.exports = class LevelLoader extends CocoClass
@worldNecessities = @worldNecessities.concat worldNecessities
populateHero: ->
return if @inLevelEditor
return unless @level.get('type') is 'hero' and hero = _.find @level.get('thangs'), id: 'Hero Placeholder'
heroConfig = @session.get('heroConfig')
hero.thangType = heroConfig.thangType
hero.inventory = heroConfig.inventory # Will take effect in Level's denormalizeThang
hero.placeholderComponents = hero.components # Will be replaced in Level's denormalizeThang
hero.components = []
#hero.id = ... ? # What do we want to do about this?
loadItemThangsEquippedByLevelThang: (levelThang) ->
return unless levelThang.components
for component in levelThang.components
@ -178,7 +191,7 @@ module.exports = class LevelLoader extends CocoClass
levelThang = $.extend true, {}, levelThang
@level.denormalizeThang(levelThang, @supermodel)
equipsComponent = _.find levelThang.components, {original: LevelComponent.EquipsID}
inventory = equipsComponent.config?.inventory
inventory = equipsComponent?.config?.inventory
continue unless inventory
for itemThangType in _.values inventory
url = "/db/thang.type/#{itemThangType}/version?project=name,components,original"

View file

@ -9,8 +9,7 @@ module.exports = class Level extends CocoModel
urlRoot: '/db/level'
serialize: (supermodel) ->
# o = _.cloneDeep @attributes # slow in level editor when there are hundreds of Thangs
o = $.extend true, {}, @attributes
o = @denormalize supermodel
# Figure out Components
o.levelComponents = _.cloneDeep (lc.attributes for lc in supermodel.getModels LevelComponent)
@ -31,6 +30,8 @@ module.exports = class Level extends CocoModel
denormalize: (supermodel) ->
o = $.extend true, {}, @attributes
if @get('type') is 'hero'
# TOOD: figure out if/when/how we are doing this for non-Hero levels that aren't expecting denormalization.
for levelThang in o.thangs
@denormalizeThang(levelThang, supermodel)
o
@ -41,16 +42,38 @@ module.exports = class Level extends CocoModel
configs = {}
for thangComponent in levelThang.components
configs[thangComponent.original] = thangComponent
placeholders = {}
for thangComponent in levelThang.placeholderComponents ? []
placeholders[thangComponent.original] = thangComponent
for defaultThangComponent in thangType.get('components')
if levelThangComponent = configs[defaultThangComponent.original]
# take the thang type default components and merge level-specific component config into it
# Take the ThangType default Components and merge level-specific Component config into it
copy = $.extend true, {}, defaultThangComponent.config
levelThangComponent.config = _.merge copy, levelThangComponent.config
else
# just add the component as is
levelThang.components.push $.extend true, {}, defaultThangComponent
# Just add the Component as is
levelThangComponent = $.extend true, {}, defaultThangComponent
levelThang.components.push levelThangComponent
if placeholderComponent = placeholders[defaultThangComponent.original]
placeholderConfig = placeholderComponent.config ? {}
if placeholderConfig.pos # Pull in Physical pos x and y
levelThangComponent.config.pos ?= {}
levelThangComponent.config.pos.x = placeholderConfig.pos.x
levelThangComponent.config.pos.y = placeholderConfig.pos.y
else if placeholderConfig.team # Pull in Allied team
levelThangComponent.config.team = placeholderConfig.team
else if placeholderConfig.programmableMethods
# Take the ThangType default Programmable and merge level-specific Component config into it
copy = $.extend true, {}, placeholderConfig
levelThangComponent.config = _.merge copy, levelThangComponent.config
if levelThang.inventory and equips = _.find levelThang.components, {original: LevelComponent.EquipsID}
# inventory is assigned from the LevelSession in LevelLoader's populateHero
equips.config.inventory = $.extend true, {}, levelThang.inventory
sortSystems: (levelSystems, systemModels) ->
[sorted, originalsSeen] = [[], {}]

View file

@ -56,9 +56,12 @@ _.extend LevelSessionSchema.properties,
screenshot:
type: 'string'
heroConfig: c.object {},
inventory: c.object()
thangType: c.objectId()
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')
state: c.object {},
complete:

View file

@ -12,8 +12,8 @@ nodes = require '../level/treema_nodes'
ThangType = require 'models/ThangType'
CocoCollection = require 'collections/CocoCollection'
class ThangTypeSearchCollection extends CocoCollection
url: '/db/thang.type?project=original,name,version,slug,kind,components'
class ItemThangTypeSearchCollection extends CocoCollection
url: '/db/thang.type?view=items&project=original,name,version,slug,kind,components'
model: ThangType
module.exports = class ThangComponentsEditView extends CocoView
@ -32,7 +32,7 @@ module.exports = class ThangComponentsEditView extends CocoView
@level = options.level
@loadComponents(@components)
# Need to grab the ThangTypes so that we can autocomplete items in inventory based on them.
@thangTypes = @supermodel.loadCollection(new ThangTypeSearchCollection(), 'thangs').model
@itemThangTypes = @supermodel.loadCollection(new ItemThangTypeSearchCollection(), 'thangs').model
loadComponents: (components) ->
for componentRef in components

View file

@ -47,7 +47,7 @@ module.exports = class LevelEditView extends RootView
super options
@supermodel.shouldSaveBackups = (model) ->
model.constructor.className in ['Level', 'LevelComponent', 'LevelSystem', 'ThangType']
@levelLoader = new LevelLoader supermodel: @supermodel, levelID: @levelID, headless: true
@levelLoader = new LevelLoader supermodel: @supermodel, levelID: @levelID, headless: true, inLevelEditor: true
@level = @levelLoader.level
@files = new DocumentFiles(@levelLoader.level)
@supermodel.loadCollection(@files, 'file_names')

View file

@ -335,8 +335,8 @@ module.exports = class ThangsTabView extends CocoView
adjustThangPos: (sprite, thang, pos) ->
snap = sprite?.data?.snap or sprite?.thangType?.get('snap') or {x: 0.01, y: 0.01} # Centimeter resolution by default
pos.x = Math.round((pos.x - thang.width / 2) / snap.x) * snap.x + thang.width / 2
pos.y = Math.round((pos.y - thang.height / 2) / snap.y) * snap.y + thang.height / 2
pos.x = Math.round((pos.x - (thang.width ? 1) / 2) / snap.x) * snap.x + (thang.width ? 1) / 2
pos.y = Math.round((pos.y - (thang.height ? 1) / 2) / snap.y) * snap.y + (thang.height ? 1) / 2
pos.z = thang.depth / 2
thang.pos = pos
@surface.spriteBoss.update true # Make sure Obstacle layer resets cache

View file

@ -9,7 +9,7 @@ module.exports = class InventoryView extends CocoView
id: 'inventory-view'
className: 'tab-pane'
template: template
slots: ["head","eyes","neck","torso","wrists","gloves","left-ring","right-ring","right-hand","left-hand","waist","feet","spellbook","programming-book","pet","minion","misc-0","misc-1","misc-2","misc-3","misc-4"]
slots: ['head', 'eyes', 'neck', 'torso', 'wrists', 'gloves', 'left-ring', 'right-ring', 'right-hand', 'left-hand', 'waist', 'feet', 'spellbook', 'programming-book', 'pet', 'minion', 'misc-0', 'misc-1', 'misc-2', 'misc-3', 'misc-4']
events:
'click .item-slot': 'onItemSlotClick'
@ -24,7 +24,7 @@ module.exports = class InventoryView extends CocoView
initialize: (options) ->
super(arguments...)
@items = new CocoCollection([], {model: ThangType})
@equipment = options.equipment or {}
@equipment = options.equipment or @options.session?.get('heroConfig')?.inventory or {}
@items.url = '/db/thang.type?view=items&project=name,description,components,original'
@supermodel.loadCollection(@items, 'items')
@ -236,3 +236,12 @@ module.exports = class InventoryView extends CocoView
config[slotName] = item.get('original')
config
onHidden: ->
inventory = @getCurrentEquipmentConfig()
heroConfig = @options.session.get('heroConfig') ? {}
unless _.isEqual inventory, heroConfig.inventory
heroConfig.inventory = inventory
heroConfig.thangType ?= '529ffbf1cf1818f2be000001' # Temp: assign Tharin as the hero
@options.session.set 'heroConfig', heroConfig
@options.session.patch()

View file

@ -9,7 +9,7 @@ import sys
current_directory = os.path.dirname(os.path.realpath(sys.argv[0]))
coco_path = os.getenv("COCO_DIR",os.path.join(current_directory,os.pardir))
brunch_path = coco_path + os.sep + "node_modules" + os.sep + ".bin" + os.sep + "brunch"
subprocess.Popen("ulimit -n 100000",shell=True)
subprocess.Popen("ulimit -n 10000", shell=True)
while True:
print("Starting brunch. After the first compile, it'll keep running and watch for changes.")
call(brunch_path + " w",shell=True,cwd=coco_path)

View file

@ -45,7 +45,7 @@ LevelSessionSchema.pre 'save', (next) ->
LevelSessionSchema.statics.privateProperties = ['code', 'submittedCode', 'unsubscribed']
LevelSessionSchema.statics.editableProperties = ['multiplayer', 'players', 'code', 'codeLanguage', 'completed', 'state',
'levelName', 'creatorName', 'levelID', 'screenshot',
'chat', 'teamSpells', 'submitted', 'submittedCodeLanguage', 'unsubscribed', 'playtime']
'chat', 'teamSpells', 'submitted', 'submittedCodeLanguage', 'unsubscribed', 'playtime', 'heroConfig']
LevelSessionSchema.statics.jsonSchema = jsonschema
LevelSessionSchema.index {user: 1, changed: -1}, {sparse: true, name: 'last played index'}