2014-12-16 20:46:24 -05:00
|
|
|
|
RootView = require 'views/core/RootView'
|
|
|
|
|
Campaign = require 'models/Campaign'
|
|
|
|
|
Level = require 'models/Level'
|
2014-12-18 01:53:04 -05:00
|
|
|
|
Achievement = require 'models/Achievement'
|
|
|
|
|
ThangType = require 'models/ThangType'
|
2014-12-22 10:29:29 -05:00
|
|
|
|
CampaignView = require 'views/play/CampaignView'
|
2014-12-16 20:46:24 -05:00
|
|
|
|
CocoCollection = require 'collections/CocoCollection'
|
2014-12-18 01:53:04 -05:00
|
|
|
|
treemaExt = require 'core/treema-ext'
|
|
|
|
|
utils = require 'core/utils'
|
2014-12-22 16:21:57 -05:00
|
|
|
|
SaveCampaignModal = require './SaveCampaignModal'
|
|
|
|
|
RelatedAchievementsCollection = require 'collections/RelatedAchievementsCollection'
|
2014-12-23 09:42:24 -05:00
|
|
|
|
CampaignLevelView = require './CampaignLevelView'
|
2014-12-18 01:53:04 -05:00
|
|
|
|
|
|
|
|
|
achievementProject = ['related', 'rewards', 'name', 'slug']
|
|
|
|
|
thangTypeProject = ['name', 'original', 'slug']
|
2014-12-16 20:46:24 -05:00
|
|
|
|
|
|
|
|
|
module.exports = class CampaignEditorView extends RootView
|
|
|
|
|
id: "campaign-editor-view"
|
|
|
|
|
template: require 'templates/editor/campaign/campaign-editor-view'
|
|
|
|
|
className: 'editor'
|
2014-12-22 16:21:57 -05:00
|
|
|
|
|
|
|
|
|
events:
|
|
|
|
|
'click #save-button': 'onClickSaveButton'
|
2014-12-16 20:46:24 -05:00
|
|
|
|
|
2014-12-22 10:29:29 -05:00
|
|
|
|
constructor: (options, @campaignHandle) ->
|
2014-12-18 01:53:04 -05:00
|
|
|
|
super(options)
|
2014-12-16 20:46:24 -05:00
|
|
|
|
|
2014-12-18 01:53:04 -05:00
|
|
|
|
# MIGRATION CODE
|
|
|
|
|
# for level in levels
|
|
|
|
|
# _.extend level, options[level.id]
|
|
|
|
|
# level.slug = level.id
|
|
|
|
|
# delete level.id
|
|
|
|
|
# delete level.nextLevels
|
|
|
|
|
# level.position = { x: level.x, y: level.y }
|
|
|
|
|
# delete level.x
|
|
|
|
|
# delete level.y
|
|
|
|
|
# if level.unlocksHero
|
|
|
|
|
# level.unlocks = [{
|
|
|
|
|
# original: level.unlocksHero.originalID
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# }]
|
|
|
|
|
# delete level.unlocksHero
|
|
|
|
|
# campaign.levels[level.original] = level
|
|
|
|
|
# @campaign = new Campaign(campaign)
|
2014-12-16 20:46:24 -05:00
|
|
|
|
#------------------------------------------------
|
2014-12-18 01:53:04 -05:00
|
|
|
|
|
2014-12-22 10:29:29 -05:00
|
|
|
|
@campaign = new Campaign({_id:@campaignHandle})
|
2014-12-16 20:46:24 -05:00
|
|
|
|
|
2014-12-18 01:53:04 -05:00
|
|
|
|
#--------------- temporary migration to change thang type slugs to originals
|
|
|
|
|
#- should keep around though for loading the names of items and heroes that are referenced
|
|
|
|
|
#- just load names instead of slugs, though
|
|
|
|
|
@sluggyThangs = new Backbone.Collection()
|
|
|
|
|
@listenToOnce @campaign, 'sync', ->
|
|
|
|
|
slugs = []
|
|
|
|
|
for level in _.values(@campaign.get('levels'))
|
|
|
|
|
slugs = slugs.concat(_.values(level.requiredGear)) if level.requiredGear
|
|
|
|
|
slugs = slugs.concat(_.values(level.restrictedGear)) if level.restrictedGear
|
|
|
|
|
slugs = slugs.concat(level.allowedHeroes) if level.allowedHeroes
|
|
|
|
|
slugs = _.uniq _.flatten slugs
|
|
|
|
|
for slug in slugs
|
|
|
|
|
thangType = new ThangType()
|
|
|
|
|
thangType.setProjection(thangTypeProject)
|
|
|
|
|
if utils.isID slug
|
|
|
|
|
thangType.setURL("/db/thang.type/#{slug}/version")
|
|
|
|
|
else
|
|
|
|
|
thangType.setURL("/db/thang.type/#{slug}")
|
|
|
|
|
@supermodel.loadModel(thangType, 'thang')
|
|
|
|
|
@sluggyThangs.add(thangType)
|
|
|
|
|
#---------------
|
|
|
|
|
@supermodel.loadModel(@campaign, 'campaign')
|
|
|
|
|
|
|
|
|
|
@levels = new CocoCollection([], {
|
|
|
|
|
model: Level
|
2014-12-22 10:29:29 -05:00
|
|
|
|
url: "/db/campaign/#{@campaignHandle}/levels"
|
2014-12-18 01:53:04 -05:00
|
|
|
|
project: Campaign.denormalizedLevelProperties
|
|
|
|
|
})
|
|
|
|
|
@supermodel.loadCollection(@levels, 'levels')
|
|
|
|
|
|
|
|
|
|
@achievements = new CocoCollection([], {
|
|
|
|
|
model: Achievement
|
2014-12-22 10:29:29 -05:00
|
|
|
|
url: "/db/campaign/#{@campaignHandle}/achievements"
|
2014-12-18 01:53:04 -05:00
|
|
|
|
project: achievementProject
|
|
|
|
|
})
|
|
|
|
|
@supermodel.loadCollection(@achievements, 'achievements')
|
2014-12-16 20:46:24 -05:00
|
|
|
|
|
2014-12-18 01:53:04 -05:00
|
|
|
|
@toSave = new Backbone.Collection()
|
2014-12-22 16:21:57 -05:00
|
|
|
|
@listenToOnce @campaign, 'sync', @onFundamentalLoaded
|
|
|
|
|
@listenToOnce @levels, 'sync', @onFundamentalLoaded
|
|
|
|
|
@listenToOnce @achievements, 'sync', @onFundamentalLoaded
|
|
|
|
|
|
|
|
|
|
onFundamentalLoaded: ->
|
|
|
|
|
# load any levels which
|
|
|
|
|
return unless @campaign.loaded and @levels.loaded and @achievements.loaded
|
|
|
|
|
for level in _.values(@campaign.get('levels'))
|
|
|
|
|
model = @levels.findWhere(original: level.original)
|
|
|
|
|
if not model
|
|
|
|
|
model = new Level({})
|
|
|
|
|
model.setProjection Campaign.denormalizedLevelProperties
|
|
|
|
|
model.setURL("/db/level/#{level.original}/version")
|
|
|
|
|
@levels.add @supermodel.loadModel(model, 'level').model
|
|
|
|
|
achievements = new RelatedAchievementsCollection level.original
|
|
|
|
|
achievements.setProjection achievementProject
|
|
|
|
|
@supermodel.loadCollection achievements, 'achievements'
|
|
|
|
|
@listenToOnce achievements, 'sync', ->
|
|
|
|
|
@achievements.add(achievements.models)
|
|
|
|
|
|
2014-12-18 01:53:04 -05:00
|
|
|
|
|
|
|
|
|
onLoaded: ->
|
2014-12-22 16:21:57 -05:00
|
|
|
|
@toSave.add @campaign if @campaign.hasLocalChanges()
|
2014-12-18 01:53:04 -05:00
|
|
|
|
campaignLevels = $.extend({}, @campaign.get('levels'))
|
|
|
|
|
for level in @levels.models
|
|
|
|
|
levelOriginal = level.get('original')
|
2014-12-22 12:06:17 -05:00
|
|
|
|
campaignLevel = campaignLevels[levelOriginal]
|
|
|
|
|
continue if not campaignLevel
|
2014-12-18 01:53:04 -05:00
|
|
|
|
|
|
|
|
|
#--------------- temporary migrations
|
|
|
|
|
if campaignLevel.restrictedGear
|
|
|
|
|
for slot, value of campaignLevel.restrictedGear
|
|
|
|
|
if _.isString(value)
|
|
|
|
|
campaignLevel.restrictedGear[slot] = [value]
|
|
|
|
|
#
|
|
|
|
|
if campaignLevel.requiredGear
|
|
|
|
|
for slot, value of campaignLevel.requiredGear
|
|
|
|
|
if _.isString(value)
|
|
|
|
|
campaignLevel.requiredGear[slot] = [value]
|
|
|
|
|
#
|
|
|
|
|
if campaignLevel.requiredGear
|
|
|
|
|
for gear in _.values(campaignLevel.requiredGear)
|
|
|
|
|
for slug, index in gear
|
|
|
|
|
thang = @sluggyThangs.findWhere({slug: slug})
|
|
|
|
|
continue unless thang
|
|
|
|
|
gear[index] = thang.get('original')
|
|
|
|
|
#
|
|
|
|
|
if campaignLevel.restrictedGear
|
|
|
|
|
for gear in _.values(campaignLevel.restrictedGear)
|
|
|
|
|
for slug, index in gear
|
|
|
|
|
thang = @sluggyThangs.findWhere({slug: slug})
|
|
|
|
|
continue unless thang
|
|
|
|
|
gear[index] = thang.get('original')
|
|
|
|
|
#
|
|
|
|
|
if campaignLevel.allowedHeroes
|
|
|
|
|
for slug, index in campaignLevel.allowedHeroes
|
|
|
|
|
thang = @sluggyThangs.findWhere({slug: slug})
|
|
|
|
|
continue unless thang
|
|
|
|
|
level.allowedHeroes[index] = thang.get('original')
|
|
|
|
|
#---------------
|
|
|
|
|
|
|
|
|
|
$.extend campaignLevel, _.omit(level.attributes, '_id')
|
|
|
|
|
achievements = @achievements.where {'related': levelOriginal}
|
|
|
|
|
rewards = []
|
|
|
|
|
for achievement in achievements
|
|
|
|
|
for rewardType, rewardArray of achievement.get('rewards')
|
|
|
|
|
for reward in rewardArray
|
|
|
|
|
rewardObject = { achievement: achievement.id }
|
|
|
|
|
|
|
|
|
|
if rewardType is 'heroes'
|
|
|
|
|
rewardObject.hero = reward
|
|
|
|
|
thangType = new ThangType({}, {project: thangTypeProject})
|
|
|
|
|
thangType.setURL("/db/thang.type/#{reward}/version")
|
|
|
|
|
@supermodel.loadModel(thangType, 'thang')
|
|
|
|
|
|
|
|
|
|
if rewardType is 'levels'
|
|
|
|
|
rewardObject.level = reward
|
|
|
|
|
if not @levels.findWhere({original: reward})
|
|
|
|
|
level = new Level({}, {project: Campaign.denormalizedLevelProperties})
|
|
|
|
|
level.setURL("/db/level/#{reward}/version")
|
|
|
|
|
@supermodel.loadModel(level, 'level')
|
|
|
|
|
|
|
|
|
|
if rewardType is 'items'
|
|
|
|
|
rewardObject.item = reward
|
|
|
|
|
thangType = new ThangType({}, {project: thangTypeProject})
|
|
|
|
|
thangType.setURL("/db/thang.type/#{reward}/version")
|
|
|
|
|
@supermodel.loadModel(thangType, 'thang')
|
|
|
|
|
|
|
|
|
|
rewards.push rewardObject
|
|
|
|
|
campaignLevel.rewards = rewards
|
|
|
|
|
delete campaignLevel.unlocks
|
|
|
|
|
campaignLevels[levelOriginal] = campaignLevel
|
|
|
|
|
|
|
|
|
|
@campaign.set('levels', campaignLevels)
|
2014-12-22 16:21:57 -05:00
|
|
|
|
|
|
|
|
|
for level in _.values campaignLevels
|
|
|
|
|
model = @levels.findWhere {original: level.original}
|
|
|
|
|
model.set key, level[key] for key in Campaign.denormalizedLevelProperties
|
|
|
|
|
# @toSave.add model if model.hasLocalChanges()
|
|
|
|
|
# @updateRewardsForLevel model, level.rewards
|
|
|
|
|
|
2014-12-18 01:53:04 -05:00
|
|
|
|
super()
|
|
|
|
|
|
2014-12-16 20:46:24 -05:00
|
|
|
|
getRenderData: ->
|
|
|
|
|
c = super()
|
|
|
|
|
c.campaign = @campaign
|
|
|
|
|
c
|
2014-12-22 16:21:57 -05:00
|
|
|
|
|
|
|
|
|
onClickSaveButton: ->
|
|
|
|
|
@toSave.set @toSave.filter (m) -> m.hasLocalChanges()
|
|
|
|
|
@openModalView new SaveCampaignModal({}, @toSave)
|
2014-12-16 20:46:24 -05:00
|
|
|
|
|
|
|
|
|
afterRender: ->
|
|
|
|
|
super()
|
|
|
|
|
treemaOptions =
|
|
|
|
|
schema: Campaign.schema
|
|
|
|
|
data: $.extend({}, @campaign.attributes)
|
|
|
|
|
callbacks:
|
|
|
|
|
change: @onTreemaChanged
|
|
|
|
|
select: @onTreemaSelectionChanged
|
|
|
|
|
dblclick: @onTreemaDoubleClicked
|
|
|
|
|
nodeClasses:
|
|
|
|
|
levels: LevelsNode
|
|
|
|
|
level: LevelNode
|
2014-12-19 16:46:01 -05:00
|
|
|
|
campaigns: CampaignsNode
|
|
|
|
|
campaign: CampaignNode
|
2014-12-18 01:53:04 -05:00
|
|
|
|
achievement: AchievementNode
|
|
|
|
|
supermodel: @supermodel
|
2014-12-16 20:46:24 -05:00
|
|
|
|
|
|
|
|
|
@treema = @$el.find('#campaign-treema').treema treemaOptions
|
|
|
|
|
@treema.build()
|
|
|
|
|
@treema.open()
|
2014-12-18 01:53:04 -05:00
|
|
|
|
@treema.childrenTreemas.levels?.open()
|
2014-12-16 20:46:24 -05:00
|
|
|
|
|
2014-12-22 12:06:17 -05:00
|
|
|
|
@campaignView = new CampaignView({editorMode: true, supermodel: @supermodel}, @campaignHandle)
|
|
|
|
|
@campaignView.highlightElement = _.noop # make it stop
|
|
|
|
|
@listenTo @campaignView, 'level-moved', @onCampaignLevelMoved
|
|
|
|
|
@listenTo @campaignView, 'adjacent-campaign-moved', @onAdjacentCampaignMoved
|
|
|
|
|
@listenTo @campaignView, 'level-clicked', @onCampaignLevelClicked
|
|
|
|
|
@insertSubView @campaignView
|
2014-12-18 01:53:04 -05:00
|
|
|
|
|
|
|
|
|
onTreemaChanged: (e, nodes) =>
|
|
|
|
|
for node in nodes
|
|
|
|
|
path = node.getPath()
|
|
|
|
|
if _.string.startsWith path, '/levels/'
|
|
|
|
|
parts = path.split('/')
|
|
|
|
|
original = parts[2]
|
|
|
|
|
level = @supermodel.getModelByOriginal Level, original
|
|
|
|
|
campaignLevel = @treema.get "/levels/#{original}"
|
2014-12-22 16:21:57 -05:00
|
|
|
|
|
|
|
|
|
@updateRewardsForLevel level, campaignLevel.rewards
|
|
|
|
|
|
|
|
|
|
level.set key, campaignLevel[key] for key in Campaign.denormalizedLevelProperties
|
|
|
|
|
@toSave.add level if level.hasLocalChanges()
|
2014-12-18 01:53:04 -05:00
|
|
|
|
|
|
|
|
|
@toSave.add @campaign
|
2014-12-22 12:06:17 -05:00
|
|
|
|
@campaign.set key, value for key, value of @treema.data
|
|
|
|
|
@campaignView.setCampaign(@campaign)
|
2014-12-18 01:53:04 -05:00
|
|
|
|
|
2014-12-23 09:42:24 -05:00
|
|
|
|
onTreemaDoubleClicked: (e, node) =>
|
|
|
|
|
path = node.getPath()
|
|
|
|
|
return unless _.string.startsWith path, '/levels/'
|
|
|
|
|
original = path.split('/')[2]
|
|
|
|
|
level = @supermodel.getModelByOriginal Level, original
|
|
|
|
|
@insertSubView new CampaignLevelView({}, level)
|
|
|
|
|
|
2014-12-22 10:54:07 -05:00
|
|
|
|
onCampaignLevelMoved: (e) ->
|
|
|
|
|
path = "levels/#{e.levelOriginal}/position"
|
|
|
|
|
@treema.set path, e.position
|
|
|
|
|
|
|
|
|
|
onAdjacentCampaignMoved: (e) ->
|
|
|
|
|
path = "adjacentCampaigns/#{e.campaignID}/position"
|
|
|
|
|
@treema.set path, e.position
|
|
|
|
|
|
2014-12-22 11:09:58 -05:00
|
|
|
|
onCampaignLevelClicked: (levelOriginal) ->
|
|
|
|
|
return unless levelTreema = @treema.childrenTreemas?.levels?.childrenTreemas?[levelOriginal]
|
|
|
|
|
levelTreema.select()
|
|
|
|
|
# levelTreema.open()
|
|
|
|
|
|
2014-12-18 01:53:04 -05:00
|
|
|
|
updateRewardsForLevel: (level, rewards) ->
|
|
|
|
|
achievements = @supermodel.getModels(Achievement)
|
|
|
|
|
achievements = (a for a in achievements when a.get('related') is level.get('original'))
|
|
|
|
|
for achievement in achievements
|
2014-12-22 16:21:57 -05:00
|
|
|
|
rewardSubset = (r for r in rewards when r.achievement is achievement.id)
|
|
|
|
|
oldRewards = achievement.get 'rewards'
|
2014-12-18 01:53:04 -05:00
|
|
|
|
newRewards = {}
|
2014-12-22 16:21:57 -05:00
|
|
|
|
|
|
|
|
|
heroes = _.compact((r.hero for r in rewardSubset))
|
|
|
|
|
newRewards.heroes = heroes if heroes.length
|
|
|
|
|
|
|
|
|
|
items = _.compact((r.item for r in rewardSubset))
|
|
|
|
|
newRewards.items = items if items.length
|
|
|
|
|
|
|
|
|
|
levels = _.compact((r.level for r in rewardSubset))
|
|
|
|
|
newRewards.levels = levels if levels.length
|
|
|
|
|
|
|
|
|
|
newRewards.gems = oldRewards.gems if oldRewards.gems
|
2014-12-18 01:53:04 -05:00
|
|
|
|
achievement.set 'rewards', newRewards
|
2014-12-22 16:21:57 -05:00
|
|
|
|
if achievement.hasLocalChanges()
|
|
|
|
|
@toSave.add achievement
|
2014-12-16 20:46:24 -05:00
|
|
|
|
|
|
|
|
|
class LevelsNode extends TreemaObjectNode
|
|
|
|
|
valueClass: 'treema-levels'
|
|
|
|
|
@levels: {}
|
|
|
|
|
|
|
|
|
|
buildValueForDisplay: (valEl, data) ->
|
|
|
|
|
@buildValueForDisplaySimply valEl, ''+_.size(data)
|
|
|
|
|
|
|
|
|
|
childPropertiesAvailable: -> @childSource
|
|
|
|
|
|
|
|
|
|
childSource: (req, res) =>
|
|
|
|
|
s = new Backbone.Collection([], {model:Level})
|
|
|
|
|
s.url = '/db/level'
|
|
|
|
|
s.fetch({data: {term:req.term, project: Campaign.denormalizedLevelProperties.join(',')}})
|
2014-12-22 12:06:17 -05:00
|
|
|
|
s.once 'sync', (collection) =>
|
|
|
|
|
for level in collection.models
|
|
|
|
|
LevelsNode.levels[level.get('original')] = level
|
|
|
|
|
@settings.supermodel.registerModel level
|
2014-12-16 20:46:24 -05:00
|
|
|
|
mapped = ({label: r.get('name'), value: r.get('original')} for r in collection.models)
|
|
|
|
|
res(mapped)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class LevelNode extends TreemaObjectNode
|
|
|
|
|
valueClass: 'treema-level'
|
|
|
|
|
buildValueForDisplay: (valEl, data) ->
|
|
|
|
|
@buildValueForDisplaySimply valEl, data.name
|
|
|
|
|
|
|
|
|
|
populateData: ->
|
|
|
|
|
return if @data.name?
|
|
|
|
|
data = _.pick LevelsNode.levels[@keyForParent].attributes, Campaign.denormalizedLevelProperties
|
|
|
|
|
_.extend @data, data
|
2014-12-19 16:46:01 -05:00
|
|
|
|
|
|
|
|
|
class CampaignsNode extends TreemaObjectNode
|
|
|
|
|
valueClass: 'treema-campaigns'
|
|
|
|
|
@campaigns: {}
|
|
|
|
|
|
|
|
|
|
buildValueForDisplay: (valEl, data) ->
|
|
|
|
|
@buildValueForDisplaySimply valEl, ''+_.size(data)
|
|
|
|
|
|
|
|
|
|
childPropertiesAvailable: -> @childSource
|
|
|
|
|
|
|
|
|
|
childSource: (req, res) =>
|
|
|
|
|
s = new Backbone.Collection([], {model:Campaign})
|
|
|
|
|
s.url = '/db/campaign'
|
|
|
|
|
s.fetch({data: {term:req.term, project: campaign.denormalizedCampaignProperties}})
|
|
|
|
|
s.once 'sync', (collection) ->
|
|
|
|
|
CampaignsNode.campaigns[campaign.id] = campaign for campaign in collection.models
|
|
|
|
|
mapped = ({label: r.get('name'), value: r.id} for r in collection.models)
|
|
|
|
|
res(mapped)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CampaignNode extends TreemaObjectNode
|
|
|
|
|
valueClass: 'treema-campaign'
|
|
|
|
|
buildValueForDisplay: (valEl, data) ->
|
|
|
|
|
@buildValueForDisplaySimply valEl, data.name
|
|
|
|
|
|
|
|
|
|
populateData: ->
|
|
|
|
|
return if @data.name?
|
|
|
|
|
data = _.pick CampaignsNode.campaigns[@keyForParent].attributes, Campaign.denormalizedCampaignProperties
|
|
|
|
|
_.extend @data, data
|
2014-12-18 01:53:04 -05:00
|
|
|
|
|
|
|
|
|
class AchievementNode extends treemaExt.IDReferenceNode
|
|
|
|
|
buildSearchURL: (term) -> "#{@url}?term=#{term}&project=#{achievementProject.join(',')}"
|
2014-12-19 16:46:01 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-12-16 20:46:24 -05:00
|
|
|
|
|
2014-12-22 12:06:17 -05:00
|
|
|
|
#campaign = {
|
|
|
|
|
# name: 'Dungeon'
|
|
|
|
|
# levels: {}
|
|
|
|
|
#}
|
|
|
|
|
#
|
|
|
|
|
#
|
|
|
|
|
#levels = [
|
|
|
|
|
# {
|
|
|
|
|
# name: 'Dungeons of Kithgard'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'dungeons-of-kithgard'
|
|
|
|
|
# original: '5411cb3769152f1707be029c'
|
|
|
|
|
# description: 'Grab the gem, but touch nothing else. Start here.'
|
|
|
|
|
# x: 14
|
|
|
|
|
# y: 15.5
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'gems-in-the-deep'
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'Gems in the Deep'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'gems-in-the-deep'
|
|
|
|
|
# original: '54173c90844506ae0195a0b4'
|
|
|
|
|
# description: 'Quickly collect the gems; you will need them.'
|
|
|
|
|
# x: 29
|
|
|
|
|
# y: 12
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'shadow-guard'
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'Shadow Guard'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'shadow-guard'
|
|
|
|
|
# original: '54174347844506ae0195a0b8'
|
|
|
|
|
# description: 'Evade the Kithgard minion.'
|
|
|
|
|
# x: 40.54
|
|
|
|
|
# y: 11.03
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'forgetful-gemsmith'
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'Kounter Kithwise'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'kounter-kithwise'
|
|
|
|
|
# original: '54527a6257e83800009730c7'
|
|
|
|
|
# description: 'Practice your evasion skills with more guards.'
|
|
|
|
|
# x: 35.37
|
|
|
|
|
# y: 20.61
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'crawlways-of-kithgard'
|
|
|
|
|
# practice: true
|
|
|
|
|
# requiresSubscription: true
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'Crawlways of Kithgard'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'crawlways-of-kithgard'
|
|
|
|
|
# original: '545287ef57e83800009730d5'
|
|
|
|
|
# description: 'Dart in and grab the gem–at the right moment.'
|
|
|
|
|
# x: 36.48
|
|
|
|
|
# y: 29.03
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'forgetful-gemsmith'
|
|
|
|
|
# practice: true
|
|
|
|
|
# requiresSubscription: true
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'Forgetful Gemsmith'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'forgetful-gemsmith'
|
|
|
|
|
# original: '544a98f62d002f0000fe331a'
|
|
|
|
|
# description: 'Grab even more gems as you practice moving.'
|
|
|
|
|
# x: 54.98
|
|
|
|
|
# y: 10.53
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'true-names'
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'True Names'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'true-names'
|
|
|
|
|
# original: '541875da4c16460000ab990f'
|
|
|
|
|
# description: 'Learn an enemy\'s true name to defeat it.'
|
|
|
|
|
# x: 68.44
|
|
|
|
|
# y: 10.70
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'the-raised-sword'
|
|
|
|
|
# unlocksHero: {
|
|
|
|
|
# img: '/file/db/thang.type/53e12be0d042f23505c3023b/portrait.png'
|
|
|
|
|
# originalID: '53e12be0d042f23505c3023b'
|
|
|
|
|
# }
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'Favorable Odds'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'favorable-odds'
|
|
|
|
|
# original: '5452972f57e83800009730de'
|
|
|
|
|
# description: 'Test out your battle skills by defeating more munchkins.'
|
|
|
|
|
# x: 88.25
|
|
|
|
|
# y: 14.92
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'the-raised-sword'
|
|
|
|
|
# practice: true
|
|
|
|
|
# requiresSubscription: true
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'The Raised Sword'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'the-raised-sword'
|
|
|
|
|
# original: '5418aec24c16460000ab9aa6'
|
|
|
|
|
# description: 'Learn to equip yourself for combat.'
|
|
|
|
|
# x: 81.51
|
|
|
|
|
# y: 17.92
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'haunted-kithmaze'
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'Haunted Kithmaze'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'haunted-kithmaze'
|
|
|
|
|
# original: '545a5914d820eb0000f6dc0a'
|
|
|
|
|
# description: 'The builders of Kithgard constructed many mazes to confuse travelers.'
|
|
|
|
|
# x: 78
|
|
|
|
|
# y: 29
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'the-second-kithmaze'
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'Riddling Kithmaze'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'riddling-kithmaze'
|
|
|
|
|
# original: '5418b9d64c16460000ab9ab4'
|
|
|
|
|
# description: 'If at first you go astray, change your loop to find the way.'
|
|
|
|
|
# x: 69.97
|
|
|
|
|
# y: 28.03
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'descending-further'
|
|
|
|
|
# practice: true
|
|
|
|
|
# requiresSubscription: true
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'Descending Further'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'descending-further'
|
|
|
|
|
# original: '5452a84d57e83800009730e4'
|
|
|
|
|
# description: 'Another day, another maze.'
|
|
|
|
|
# x: 61.68
|
|
|
|
|
# y: 22.80
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'the-second-kithmaze'
|
|
|
|
|
# practice: true
|
|
|
|
|
# requiresSubscription: true
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'The Second Kithmaze'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'the-second-kithmaze'
|
|
|
|
|
# original: '5418cf256bae62f707c7e1c3'
|
|
|
|
|
# description: 'Many have tried, few have found their way through this maze.'
|
|
|
|
|
# x: 54.49
|
|
|
|
|
# y: 26.49
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'dread-door'
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'Dread Door'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'dread-door'
|
|
|
|
|
# original: '5418d40f4c16460000ab9ac2'
|
|
|
|
|
# description: 'Behind a dread door lies a chest full of riches.'
|
|
|
|
|
# x: 60.52
|
|
|
|
|
# y: 33.70
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'known-enemy'
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'Known Enemy'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'known-enemy'
|
|
|
|
|
# original: '5452adea57e83800009730ee'
|
|
|
|
|
# description: 'Begin to use variables in your battles.'
|
|
|
|
|
# x: 67
|
|
|
|
|
# y: 39
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'master-of-names'
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'Master of Names'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'master-of-names'
|
|
|
|
|
# original: '5452c3ce57e83800009730f7'
|
|
|
|
|
# description: 'Use your glasses to defend yourself from the Kithmen.'
|
|
|
|
|
# x: 75
|
|
|
|
|
# y: 46
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'lowly-kithmen'
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'Lowly Kithmen'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'lowly-kithmen'
|
|
|
|
|
# original: '541b24511ccc8eaae19f3c1f'
|
|
|
|
|
# description: 'Now that you can see them, they\'re everywhere!'
|
|
|
|
|
# x: 85
|
|
|
|
|
# y: 40
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'closing-the-distance'
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'Closing the Distance'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'closing-the-distance'
|
|
|
|
|
# original: '541b288e1ccc8eaae19f3c25'
|
|
|
|
|
# description: 'Kithmen are not the only ones to stand in your way.'
|
|
|
|
|
# x: 93
|
|
|
|
|
# y: 47
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'the-final-kithmaze'
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'Tactical Strike'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'tactical-strike'
|
|
|
|
|
# original: '5452cfa706a59e000067e4f5'
|
|
|
|
|
# description: 'They\'re, uh, coming right for us! Sneak up behind them.'
|
|
|
|
|
# x: 83.23
|
|
|
|
|
# y: 52.73
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'the-final-kithmaze'
|
|
|
|
|
# practice: true
|
|
|
|
|
# requiresSubscription: true
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'The Final Kithmaze'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'the-final-kithmaze'
|
|
|
|
|
# original: '541b434e1ccc8eaae19f3c33'
|
|
|
|
|
# description: 'To escape you must find your way through an Elder Kithman\'s maze.'
|
|
|
|
|
# x: 86.95
|
|
|
|
|
# y: 64.70
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'kithgard-gates'
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'The Gauntlet'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'the-gauntlet'
|
|
|
|
|
# original: '5452d8b906a59e000067e4fa'
|
|
|
|
|
# description: 'Rush for the stairs, battling foes at every turn.'
|
|
|
|
|
# x: 76.50
|
|
|
|
|
# y: 72.69
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'kithgard-gates'
|
|
|
|
|
# practice: true
|
|
|
|
|
# requiresSubscription: true
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'Kithgard Gates'
|
|
|
|
|
# type: 'hero'
|
|
|
|
|
# id: 'kithgard-gates'
|
|
|
|
|
# original: '541c9a30c6362edfb0f34479'
|
|
|
|
|
# description: 'Escape the Kithgard dungeons and don\'t let the guardians get you.'
|
|
|
|
|
# x: 89
|
|
|
|
|
# y: 82
|
|
|
|
|
# nextLevels:
|
|
|
|
|
# continue: 'defense-of-plainswood'
|
|
|
|
|
# }
|
|
|
|
|
# {
|
|
|
|
|
# name: 'Cavern Survival'
|
|
|
|
|
# type: 'hero-ladder'
|
|
|
|
|
# id: 'cavern-survival'
|
|
|
|
|
# original: '544437e0645c0c0000c3291d'
|
|
|
|
|
# description: 'Stay alive longer than your opponent amidst hordes of ogres!'
|
|
|
|
|
# x: 17.54
|
|
|
|
|
# y: 78.39
|
|
|
|
|
# }
|
|
|
|
|
#]
|
|
|
|
|
#
|
|
|
|
|
#options =
|
|
|
|
|
# 'dungeons-of-kithgard':
|
|
|
|
|
# disableSpaces: true
|
|
|
|
|
# hidesSubmitUntilRun: true
|
|
|
|
|
# hidesPlayButton: true
|
|
|
|
|
# hidesRunShortcut: true
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots'}
|
|
|
|
|
# requiredCode: ['moveRight']
|
|
|
|
|
# 'gems-in-the-deep':
|
|
|
|
|
# disableSpaces: true
|
|
|
|
|
# hidesSubmitUntilRun: true
|
|
|
|
|
# hidesPlayButton: true
|
|
|
|
|
# hidesRunShortcut: true
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots'}
|
|
|
|
|
# 'shadow-guard':
|
|
|
|
|
# disableSpaces: true
|
|
|
|
|
# hidesSubmitUntilRun: true
|
|
|
|
|
# hidesPlayButton: true
|
|
|
|
|
# hidesRunShortcut: true
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots', 'right-hand': 'simple-sword'}
|
|
|
|
|
# 'kounter-kithwise':
|
|
|
|
|
# disableSpaces: true
|
|
|
|
|
# hidesPlayButton: true
|
|
|
|
|
# hidesRunShortcut: true
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots', 'right-hand': 'simple-sword', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# 'crawlways-of-kithgard':
|
|
|
|
|
# hidesPlayButton: true
|
|
|
|
|
# hidesRunShortcut: true
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots', 'right-hand': 'simple-sword', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# 'forgetful-gemsmith':
|
|
|
|
|
# disableSpaces: true
|
|
|
|
|
# hidesPlayButton: true
|
|
|
|
|
# hidesRunShortcut: true
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# 'true-names':
|
|
|
|
|
# disableSpaces: true
|
|
|
|
|
# hidesPlayButton: true
|
|
|
|
|
# hidesRunShortcut: true
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots', 'right-hand': 'simple-sword', waist: 'leather-belt'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# requiredCode: ['Brak']
|
|
|
|
|
# 'favorable-odds':
|
|
|
|
|
# disableSpaces: true
|
|
|
|
|
# hidesPlayButton: true
|
|
|
|
|
# hidesRunShortcut: true
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots', 'right-hand': 'simple-sword'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# 'the-raised-sword':
|
|
|
|
|
# disableSpaces: true
|
|
|
|
|
# hidesPlayButton: true
|
|
|
|
|
# hidesRunShortcut: true
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots', 'right-hand': 'simple-sword', torso: 'tarnished-bronze-breastplate'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# 'the-first-kithmaze':
|
|
|
|
|
# hidesRunShortcut: true
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots'}
|
|
|
|
|
# requiredCode: ['loop']
|
|
|
|
|
# 'haunted-kithmaze':
|
|
|
|
|
# hidesRunShortcut: true
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# moveRightLoopSnippet: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots'}
|
|
|
|
|
# requiredCode: ['loop']
|
|
|
|
|
# 'descending-further':
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots'}
|
|
|
|
|
# 'the-second-kithmaze':
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# moveRightLoopSnippet: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots'}
|
|
|
|
|
# 'dread-door':
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {'right-hand': 'simple-sword', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots'}
|
|
|
|
|
# 'known-enemy':
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {'right-hand': 'simple-sword', 'programming-book': 'programmaticon-i', torso: 'tarnished-bronze-breastplate'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots'}
|
|
|
|
|
# suspectCode: [{name: 'enemy-in-quotes', pattern: '[\'"]enemy'}] # '
|
|
|
|
|
# 'master-of-names':
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots', 'right-hand': 'simple-sword', 'programming-book': 'programmaticon-i', eyes: 'crude-glasses', torso: 'tarnished-bronze-breastplate'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots'}
|
|
|
|
|
# requiredCode: ['findNearestEnemy']
|
|
|
|
|
# suspectCode: [{name: 'lone-find-nearest-enemy', pattern: '^[ ]*(self|this|@)?[:.]?findNearestEnemy()'}]
|
|
|
|
|
# 'lowly-kithmen':
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots', 'right-hand': 'simple-sword', 'programming-book': 'programmaticon-i', eyes: 'crude-glasses', torso: 'tarnished-bronze-breastplate'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots'}
|
|
|
|
|
# requiredCode: ['findNearestEnemy']
|
|
|
|
|
# suspectCode: [{name: 'lone-find-nearest-enemy', pattern: '^[ ]*(self|this|@)?[:.]?findNearestEnemy()'}]
|
|
|
|
|
# 'closing-the-distance':
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots', 'right-hand': 'simple-sword', torso: 'tarnished-bronze-breastplate', eyes: 'crude-glasses'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots'}
|
|
|
|
|
# suspectCode: [{name: 'lone-find-nearest-enemy', pattern: '^[ ]*(self|this|@)?[:.]?findNearestEnemy()'}]
|
|
|
|
|
# 'tactical-strike':
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots', 'right-hand': 'simple-sword', torso: 'tarnished-bronze-breastplate', eyes: 'crude-glasses'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots'}
|
|
|
|
|
# suspectCode: [{name: 'lone-find-nearest-enemy', pattern: '^[ ]*(self|this|@)?[:.]?findNearestEnemy()'}]
|
|
|
|
|
# 'the-final-kithmaze':
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots', 'right-hand': 'simple-sword', torso: 'tarnished-bronze-breastplate', 'programming-book': 'programmaticon-i', eyes: 'crude-glasses'}
|
|
|
|
|
# suspectCode: [{name: 'lone-find-nearest-enemy', pattern: '^[ ]*(self|this|@)?[:.]?findNearestEnemy()'}]
|
|
|
|
|
# 'the-gauntlet':
|
|
|
|
|
# hidesHUD: true
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots', 'right-hand': 'simple-sword', torso: 'tarnished-bronze-breastplate', 'programming-book': 'programmaticon-i', eyes: 'crude-glasses'}
|
|
|
|
|
# restrictedGear: {feet: 'leather-boots', 'right-hand': 'crude-builders-hammer'}
|
|
|
|
|
# suspectCode: [{name: 'lone-find-nearest-enemy', pattern: '^[ ]*(self|this|@)?[:.]?findNearestEnemy()'}]
|
|
|
|
|
# 'kithgard-gates':
|
|
|
|
|
# hidesSay: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots', 'right-hand': 'crude-builders-hammer', torso: 'tarnished-bronze-breastplate'}
|
|
|
|
|
# restrictedGear: {'right-hand': 'simple-sword'}
|
|
|
|
|
# 'defense-of-plainswood':
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# requiredGear: {feet: 'simple-boots', 'right-hand': 'crude-builders-hammer'}
|
|
|
|
|
# restrictedGear: {'right-hand': 'simple-sword'}
|
|
|
|
|
# 'winding-trail':
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# requiredGear: {feet: 'leather-boots', 'right-hand': 'crude-builders-hammer'}
|
|
|
|
|
# restrictedGear: {feet: 'simple-boots', 'right-hand': 'simple-sword'}
|
|
|
|
|
# 'patrol-buster':
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# requiredGear: {feet: 'leather-boots', 'right-hand': 'simple-sword', 'programming-book': 'programmaticon-ii', eyes: 'crude-glasses'}
|
|
|
|
|
# restrictedGear: {feet: 'simple-boots', 'right-hand': 'crude-builders-hammer', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# 'endangered-burl':
|
|
|
|
|
# hidesRealTimePlayback: true
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# requiredGear: {feet: 'leather-boots', 'right-hand': 'simple-sword', 'programming-book': 'programmaticon-ii', eyes: 'crude-glasses'}
|
|
|
|
|
# restrictedGear: {feet: 'simple-boots', 'right-hand': 'crude-builders-hammer', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# 'village-guard':
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# lockDefaultCode: true
|
|
|
|
|
# requiredGear: {feet: 'leather-boots', 'right-hand': 'simple-sword', 'programming-book': 'programmaticon-ii', eyes: 'crude-glasses'}
|
|
|
|
|
# restrictedGear: {feet: 'simple-boots', 'right-hand': 'crude-builders-hammer', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# 'thornbush-farm':
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# lockDefaultCode: true
|
|
|
|
|
# requiredGear: {feet: 'leather-boots', 'right-hand': 'crude-builders-hammer', 'programming-book': 'programmaticon-ii', eyes: 'crude-glasses'}
|
|
|
|
|
# restrictedGear: {feet: 'simple-boots', 'right-hand': 'simple-sword', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# requiredCode: ['topEnemy']
|
|
|
|
|
# 'back-to-back':
|
|
|
|
|
# hidesCodeToolbar: true
|
|
|
|
|
# requiredGear: {feet: 'leather-boots', torso: 'tarnished-bronze-breastplate', waist: 'leather-belt', 'programming-book': 'programmaticon-ii', eyes: 'crude-glasses', 'right-hand': 'simple-sword', 'left-hand': 'wooden-shield'}
|
|
|
|
|
# restrictedGear: {feet: 'simple-boots', 'right-hand': 'crude-builders-hammer', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# 'ogre-encampment':
|
|
|
|
|
# requiredGear: {torso: 'tarnished-bronze-breastplate', waist: 'leather-belt', 'programming-book': 'programmaticon-ii', eyes: 'crude-glasses', 'right-hand': 'simple-sword', 'left-hand': 'wooden-shield'}
|
|
|
|
|
# restrictedGear: {feet: 'simple-boots', 'right-hand': 'crude-builders-hammer', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# 'woodland-cleaver':
|
|
|
|
|
# requiredGear: {torso: 'tarnished-bronze-breastplate', waist: 'leather-belt', 'programming-book': 'programmaticon-ii', eyes: 'crude-glasses', 'right-hand': 'long-sword', 'left-hand': 'wooden-shield', wrists: 'sundial-wristwatch', feet: 'leather-boots'}
|
|
|
|
|
# restrictedGear: {feet: 'simple-boots', 'right-hand': 'simple-sword', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# 'shield-rush':
|
|
|
|
|
# requiredGear: {torso: 'tarnished-bronze-breastplate', waist: 'leather-belt', 'programming-book': 'programmaticon-ii', eyes: 'crude-glasses', 'right-hand': 'long-sword', 'left-hand': 'bronze-shield', wrists: 'sundial-wristwatch'}
|
|
|
|
|
# restrictedGear: {'left-hand': 'wooden-shield', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
#
|
|
|
|
|
## Warrior branch
|
|
|
|
|
# 'peasant-protection':
|
|
|
|
|
# requiredGear: {torso: 'tarnished-bronze-breastplate', waist: 'leather-belt', 'programming-book': 'programmaticon-ii', eyes: 'wooden-glasses', 'right-hand': 'long-sword', 'left-hand': 'bronze-shield', wrists: 'sundial-wristwatch'}
|
|
|
|
|
# restrictedGear: {eyes: 'crude-glasses', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# 'munchkin-swarm':
|
|
|
|
|
# requiredGear: {torso: 'tarnished-bronze-breastplate', waist: 'leather-belt', 'programming-book': 'programmaticon-ii', eyes: 'wooden-glasses', 'right-hand': 'long-sword', 'left-hand': 'bronze-shield', wrists: 'sundial-wristwatch'}
|
|
|
|
|
# restrictedGear: {'programming-book': 'programmaticon-i', eyes: 'crude-glasses'}
|
|
|
|
|
#
|
|
|
|
|
## Ranger branch
|
|
|
|
|
# 'munchkin-harvest':
|
|
|
|
|
# requiredGear: {waist: 'leather-belt', 'programming-book': 'programmaticon-ii', eyes: 'wooden-glasses', 'right-hand': 'long-sword', 'left-hand': 'bronze-shield', wrists: 'sundial-wristwatch'}
|
|
|
|
|
# restrictedGear: {'programming-book': 'programmaticon-i'}
|
|
|
|
|
# allowedHeroes: ['captain', 'knight', 'samurai']
|
|
|
|
|
# 'swift-dagger':
|
|
|
|
|
# requiredGear: {waist: 'leather-belt', 'programming-book': 'programmaticon-ii', eyes: 'wooden-glasses', 'right-hand': 'crude-crossbow', 'left-hand': 'crude-dagger', wrists: 'sundial-wristwatch'}
|
|
|
|
|
# restrictedGear: {eyes: 'crude-glasses', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# allowedHeroes: ['ninja', 'trapper', 'forest-archer']
|
|
|
|
|
# 'shrapnel':
|
|
|
|
|
# requiredGear: {waist: 'leather-belt', 'programming-book': 'programmaticon-ii', eyes: 'wooden-glasses', 'right-hand': 'crude-crossbow', 'left-hand': 'weak-charge', wrists: 'sundial-wristwatch'}
|
|
|
|
|
# restrictedGear: {eyes: 'crude-glasses', 'left-hand': 'crude-dagger', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# allowedHeroes: ['ninja', 'trapper', 'forest-archer']
|
|
|
|
|
#
|
|
|
|
|
## Wizard branch
|
|
|
|
|
# 'arcane-ally':
|
|
|
|
|
# requiredGear: {waist: 'leather-belt', 'programming-book': 'programmaticon-ii', eyes: 'wooden-glasses', 'right-hand': 'long-sword', 'left-hand': 'bronze-shield', wrists: 'sundial-wristwatch'}
|
|
|
|
|
# restrictedGear: {eyes: 'crude-glasses', 'programming-book': 'programmaticon-i'}
|
|
|
|
|
# allowedHeroes: ['captain', 'knight', 'samurai']
|
|
|
|
|
# 'touch-of-death':
|
|
|
|
|
# requiredGear: {waist: 'leather-belt', 'programming-book': 'programmaticon-ii', eyes: 'wooden-glasses', 'right-hand': 'enchanted-stick', 'left-hand': 'unholy-tome-i', wrists: 'sundial-wristwatch'}
|
|
|
|
|
# restrictedGear: {'programming-book': 'programmaticon-i', eyes: 'crude-glasses'}
|
|
|
|
|
# allowedHeroes: ['librarian', 'potion-master', 'sorcerer']
|
|
|
|
|
# 'bonemender':
|
|
|
|
|
# requiredGear: {waist: 'leather-belt', 'programming-book': 'programmaticon-ii', eyes: 'wooden-glasses', 'right-hand': 'enchanted-stick', 'left-hand': 'book-of-life-i', wrists: 'sundial-wristwatch'}
|
|
|
|
|
# restrictedGear: {'left-hand': 'unholy-tome-i', 'programming-book': 'programmaticon-i', eyes: 'crude-glasses'}
|
|
|
|
|
# requiredCode: ['canCast']
|
|
|
|
|
# allowedHeroes: ['librarian', 'potion-master', 'sorcerer']
|
|
|
|
|
#
|
|
|
|
|
# 'coinucopia':
|
|
|
|
|
# requiredGear: {'programming-book': 'programmaticon-ii', feet: 'leather-boots', flag: 'basic-flags'}
|
|
|
|
|
# restrictedGear: {'programming-book': 'programmaticon-i', eyes: 'crude-glasses'}
|
|
|
|
|
# 'copper-meadows':
|
|
|
|
|
# requiredGear: {'programming-book': 'programmaticon-ii', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses'}
|
|
|
|
|
# restrictedGear: {'programming-book': 'programmaticon-i', eyes: 'crude-glasses'}
|
|
|
|
|
# 'drop-the-flag':
|
|
|
|
|
# requiredGear: {'programming-book': 'programmaticon-ii', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', 'right-hand': 'crude-builders-hammer'}
|
|
|
|
|
# restrictedGear: {'right-hand': 'long-sword', 'programming-book': 'programmaticon-i', eyes: 'crude-glasses'}
|
|
|
|
|
# 'deadly-pursuit':
|
|
|
|
|
# requiredGear: {'programming-book': 'programmaticon-ii', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', 'right-hand': 'crude-builders-hammer'}
|
|
|
|
|
# restrictedGear: {'right-hand': 'long-sword', 'programming-book': 'programmaticon-i', eyes: 'crude-glasses'}
|
|
|
|
|
# 'rich-forager':
|
|
|
|
|
# requiredGear: {'programming-book': 'programmaticon-ii', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', torso: 'tarnished-bronze-breastplate', 'right-hand': 'long-sword', 'left-hand': 'bronze-shield'}
|
|
|
|
|
# restrictedGear: {'right-hand': 'crude-builders-hammer', 'programming-book': 'programmaticon-i', eyes: 'crude-glasses'}
|
|
|
|
|
# 'multiplayer-treasure-grove':
|
|
|
|
|
# requiredGear: {'programming-book': 'programmaticon-ii', feet: 'leather-boots', flag: 'basic-flags', eyes: 'wooden-glasses', torso: 'tarnished-bronze-breastplate'}
|
|
|
|
|
# restrictedGear: {'programming-book': 'programmaticon-i', eyes: 'crude-glasses'}
|
|
|
|
|
# 'siege-of-stonehold':
|
|
|
|
|
# requiredGear: {}
|
|
|
|
|
# restrictedGear: {}
|
|
|
|
|
#
|
|
|
|
|
## Desert
|
|
|
|
|
# 'the-dunes':
|
|
|
|
|
# requiredGear: {}
|
|
|
|
|
# restrictedGear: {}
|
|
|
|
|
# 'the-mighty-sand-yak':
|
|
|
|
|
# requiredGear: {}
|
|
|
|
|
# restrictedGear: {}
|
|
|
|
|
# 'oasis':
|
|
|
|
|
# requiredGear: {}
|
|
|
|
|
# restrictedGear: {}
|