mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-03-31 07:12:49 -04:00
Added optional goals. Working on lines-of-code goal. Fixed bugs with HeroVictoryModal not firing.
This commit is contained in:
parent
67166f1496
commit
ec3e1d0bce
6 changed files with 32 additions and 7 deletions
app
lib/world
schemas
styles/play
views/play/level/modal
|
@ -45,7 +45,7 @@ module.exports = class GoalManager extends CocoClass
|
|||
'world:thang-left-map': 'onThangLeftMap'
|
||||
'world:thang-collected-item': 'onThangCollectedItem'
|
||||
'world:user-code-problem': 'onUserCodeProblem'
|
||||
'world:ended': 'onWorldEnded'
|
||||
'world:lines-of-code-counted': 'onLinesOfCodeCounted'
|
||||
|
||||
onLevelRestarted: ->
|
||||
@goals = []
|
||||
|
@ -116,10 +116,12 @@ module.exports = class GoalManager extends CocoClass
|
|||
checkOverallStatus: (ignoreIncomplete=false) ->
|
||||
overallStatus = null
|
||||
goals = if @goalStates then _.values @goalStates else []
|
||||
goals = (g for g in goals when not g.optional)
|
||||
goals = (g for g in goals when g.team in [undefined, @team]) if @team
|
||||
statuses = if @goalStates then (goal.status for goal in goals) else []
|
||||
overallStatus = 'success' if statuses.length > 0 and _.every(statuses, (s) -> s is 'success' or (ignoreIncomplete and s is null))
|
||||
overallStatus = 'failure' if statuses.length > 0 and 'failure' in statuses
|
||||
#console.log 'got overallStatus', overallStatus, 'from goals', goals, 'goalStates', @goalStates, 'statuses', statuses
|
||||
overallStatus
|
||||
|
||||
# WORLD GOAL TRACKING
|
||||
|
@ -132,6 +134,7 @@ module.exports = class GoalManager extends CocoClass
|
|||
status: null # should eventually be either 'success', 'failure', or 'incomplete'
|
||||
keyFrame: 0 # when it became a 'success' or 'failure'
|
||||
team: goal.team
|
||||
optional: goal.optional
|
||||
}
|
||||
@initGoalState(state, [goal.killThangs, goal.saveThangs], 'killed')
|
||||
for getTo in goal.getAllToLocations ? []
|
||||
|
@ -142,7 +145,7 @@ module.exports = class GoalManager extends CocoClass
|
|||
@initGoalState(state, [goal.leaveOffSides?.who, goal.keepFromLeavingOffSides?.who], 'left')
|
||||
@initGoalState(state, [goal.collectThangs?.targets, goal.keepFromCollectingThangs?.targets], 'collected')
|
||||
@initGoalState(state, [goal.linesOfCode?.who], 'lines') # TODO: find out how many lines there are
|
||||
@initGoalState(state, [goal.codeProblems?.who], 'problems') # TODO: count initial problems, not just runtime
|
||||
@initGoalState(state, [goal.codeProblems], 'problems') # TODO: count initial problems, not just runtime
|
||||
@goalStates[goal.id] = state
|
||||
|
||||
onThangDied: (e, frameNumber) ->
|
||||
|
@ -192,11 +195,21 @@ module.exports = class GoalManager extends CocoClass
|
|||
|
||||
onUserCodeProblem: (e, frameNumber) ->
|
||||
for goal in @goals ? [] when goal.codeProblems
|
||||
@checkCodeProblem goal.id, goal.codeProblems.who, e.thang, frameNumber
|
||||
@checkCodeProblem goal.id, goal.codeProblems, e.thang, frameNumber
|
||||
|
||||
checkCodeProblem: (goalID, who, thang, frameNumber) ->
|
||||
return unless thang.id in who or thang.team in who
|
||||
@updateGoalState goal.id, thang.id, 'problems', frameNumber
|
||||
@updateGoalState goalID, thang.id, 'problems', frameNumber
|
||||
|
||||
onLinesOfCodeCounted: (e, frameNumber) ->
|
||||
for goal in @goals ? [] when goal.linesOfCode
|
||||
@checkLinesOfCode goal.id, goal.linesOfCode, e.thang, e.linesUsed, frameNumber
|
||||
|
||||
checkLinesOfCode: (goalID, who, thang, linesUsed, frameNumber) ->
|
||||
return unless thang.id in who or thang.team in who
|
||||
# TODO: somehow pull in linesUsed
|
||||
console.log 'checkLinesOfCode', goalID, who, thang, linesUsed, frameNumber
|
||||
#@updateGoalState goalID, thang.id, 'lines', frameNumber
|
||||
|
||||
wrapUpGoalStates: (finalFrame) ->
|
||||
for goalID, state of @goalStates
|
||||
|
@ -258,12 +271,12 @@ module.exports = class GoalManager extends CocoClass
|
|||
# saveThangs: by default we would want to save all the Thangs, which means that we would want none of them to be 'done'
|
||||
numNeeded = _.size(stateThangs) - Math.max((goal.howMany ? 1), _.size stateThangs) + 1
|
||||
numDone = _.filter(stateThangs).length
|
||||
#console.log 'needed', numNeeded, 'done', numDone, 'of total', _.size(stateThangs), 'with how many', goal.howMany, 'and stateThangs', stateThangs, 'for', goalID, thangID, 'on frame', frameNumber
|
||||
console.log 'needed', numNeeded, 'done', numDone, 'of total', _.size(stateThangs), 'with how many', goal.howMany, 'and stateThangs', stateThangs, 'for', goalID, thangID, 'on frame', frameNumber
|
||||
return unless numDone >= numNeeded
|
||||
return if state.status and not success # already failed it; don't wipe keyframe
|
||||
state.status = if success then 'success' else 'failure'
|
||||
state.keyFrame = frameNumber
|
||||
#console.log goalID, 'became', success, 'on frame', frameNumber, 'with overallStatus', @checkOverallStatus true
|
||||
console.log goalID, 'became', success, 'on frame', frameNumber, 'with overallStatus', @checkOverallStatus true
|
||||
if overallStatus = @checkOverallStatus true
|
||||
matchedGoals = (_.find(@goals, {id: goalID}) for goalID, goalState of @goalStates when goalState.status is overallStatus)
|
||||
mostEagerGoal = _.min matchedGoals, 'worldEndsAfter'
|
||||
|
|
|
@ -307,7 +307,7 @@ module.exports = class World
|
|||
publishNote: (channel, event) ->
|
||||
event ?= {}
|
||||
channel = 'world:' + channel
|
||||
for script in @scripts
|
||||
for script in @scripts ? []
|
||||
continue if script.channel isnt channel
|
||||
scriptNote = new WorldScriptNote script, event
|
||||
continue if scriptNote.invalid
|
||||
|
|
|
@ -31,6 +31,7 @@ GoalSchema = c.object {title: 'Goal', description: 'A goal that the player can a
|
|||
worldEndsAfter: {title: 'World Ends After', description: 'When included, ends the world this many seconds after this goal succeeds or fails.', type: 'number', minimum: 0, exclusiveMinimum: true, maximum: 300, default: 3}
|
||||
howMany: {title: 'How Many', description: 'When included, require only this many of the listed goal targets instead of all of them.', type: 'integer', minimum: 1}
|
||||
hiddenGoal: {title: 'Hidden', description: 'Hidden goals don\'t show up in the goals area for the player until they\'re failed. (Usually they\'re obvious, like "don\'t die".)', 'type': 'boolean' }
|
||||
optional: {title: 'Optional', description: 'Optional goals do not need to be completed for overallStatus to be success.', type: 'boolean'}
|
||||
team: c.shortString(title: 'Team', description: 'Name of the team this goal is for, if it is not for all of the playable teams.')
|
||||
killThangs: c.array {title: 'Kill Thangs', description: 'A list of Thang IDs the player should kill, or team names.', uniqueItems: true, minItems: 1, 'default': ['ogres']}, thang
|
||||
saveThangs: c.array {title: 'Save Thangs', description: 'A list of Thang IDs the player should save, or team names', uniqueItems: true, minItems: 1, 'default': ['humans']}, thang
|
||||
|
@ -62,6 +63,8 @@ GoalSchema = c.object {title: 'Goal', description: 'A goal that the player can a
|
|||
keepFromCollectingThangs: c.object {title: 'Keep From Collecting', description: 'Thangs that the player must prevent other Thangs from collecting.', required: ['who', 'targets']},
|
||||
who: c.array {title: 'Who', description: 'The Thangs which must not collect the target items.', minItems: 1}, thang
|
||||
targets: c.array {title: 'Targets', description: 'The target items which the Thangs must not collect.', minItems: 1}, thang
|
||||
codeProblems: c.array {title: 'Code Problems', description: 'A list of Thang IDs that should not have any code problems, or team names.', uniqueItems: true, minItems: 1, 'default': ['humans']}, thang
|
||||
linesOfCode: {title: 'Lines of Code', description: 'A mapping of Thang IDs or teams to how many many lines of code should be allowed (well, statements).', type: 'object', default: {humans: 10}, additionalProperties: {type: 'integer', description: 'How many lines to allow for this Thang.'}}
|
||||
|
||||
ResponseSchema = c.object {title: 'Dialogue Button', description: 'A button to be shown to the user with the dialogue.', required: ['text']},
|
||||
text: {title: 'Title', description: 'The text that will be on the button', 'default': 'Okay', type: 'string', maxLength: 30}
|
||||
|
|
|
@ -39,3 +39,7 @@ module.exports =
|
|||
level: {type: 'string', enum: ['info', 'warning', 'error']}
|
||||
type: {type: 'string'}
|
||||
error: {type: 'object'}
|
||||
|
||||
'world:lines-of-code-counted': c.object {required: ['thang', 'linesUsed']},
|
||||
thang: {type: 'object'}
|
||||
linesUsed: {type: 'integer'}
|
||||
|
|
|
@ -287,3 +287,7 @@ $gameControlMargin: 30px
|
|||
|
||||
&.vol-down .glyphicon.glyphicon-volume-down
|
||||
display: inline-block
|
||||
|
||||
body:not(.ipad) #world-map-view
|
||||
.level-info-container
|
||||
pointer-events: none
|
||||
|
|
|
@ -93,6 +93,7 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
c.thangTypes = @thangTypes
|
||||
c.me = me
|
||||
c.readyToRank = @level.get('type', true) is 'hero-ladder' and @session.readyToRank()
|
||||
c.level = @level
|
||||
return c
|
||||
|
||||
afterRender: ->
|
||||
|
|
Loading…
Add table
Reference in a new issue