mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-27 17:45:40 -05:00
Crude steps towards using your hero equipment in items levels.
This commit is contained in:
parent
9404c40b47
commit
0f983bdcf1
9 changed files with 108 additions and 60 deletions
|
@ -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"
|
||||
|
|
|
@ -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] = [[], {}]
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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'}
|
||||
|
|
Loading…
Reference in a new issue