Spit and polish

* On the failure (but still success) dialog on Survival Mode levels
  (e.g. Azulian Tag): make the default be to retry the level but
  show a "pity" Next Level button below, as the level is marked as
  completed (silver score) and the next one is unlocked.
pull/84/head
Noah 2022-05-07 17:42:38 -07:00
parent ffc2c6f69b
commit 450c6b3bb2
3 changed files with 37 additions and 6 deletions

View File

@ -43,6 +43,7 @@ type Chunker struct {
requestsN1 map[render.Point]interface{} // chunks accessed last tick
requestsN2 map[render.Point]interface{} // 2 ticks ago (to free soon)
chunksToFree map[render.Point]uint64 // chopping block (free after X ticks)
ctfMu sync.Mutex // lock for chunksToFree
requestMu sync.Mutex
// The palette reference from first call to Inflate()
@ -299,6 +300,11 @@ func (c *Chunker) GetChunk(p render.Point) (*Chunk, bool) {
chunk, ok := c.Chunks[p]
c.chunkMu.RUnlock()
// Was it on the chopping block for garbage collection?
c.ctfMu.Lock()
delete(c.chunksToFree, p)
c.ctfMu.Unlock()
if ok {
// An empty chunk? We hang onto these until save time to commit
// the empty chunk to ZIP.
@ -392,6 +398,7 @@ func (c *Chunker) FreeCaches() int {
// Chunks requested 2 ticks ago but not this tick, put on the chopping
// block to free them later.
c.ctfMu.Lock()
for coord := range requestsN2 {
// Old point not requested recently?
if _, ok := requestsThisTick[coord]; !ok {
@ -411,6 +418,7 @@ func (c *Chunker) FreeCaches() int {
delete(c.chunksToFree, coord)
c.FreeChunk(coord)
}
c.ctfMu.Unlock()
// Rotate the cached ticks and clean the slate.
c.requestsN2 = c.requestsN1

View File

@ -18,11 +18,13 @@ type ConfigEndLevel struct {
Success bool // false = failure condition
// Handler functions - what you don't define will not
// show as buttons in the modal.
// show as buttons in the modal. Buttons display priority
// is as follows these docs in the source code.
OnNextLevel func() // Next Level (victory window)
OnRetryCheckpoint func() // Retry from Checkpoint (failed)
OnPityNextLevel func() // Pity "Next Level" (Azulian Tag)
OnRestartLevel func() // Restart Level
OnRetryCheckpoint func() // Continue from checkpoint
OnEditLevel func()
OnNextLevel func() // Next Level
OnEditLevel func() // Edit Level (if came from editor)
OnExitToMenu func() // Exit to Menu
// Set these values to show the "New Record!" part of the modal.
@ -152,6 +154,10 @@ func makeEndLevel(m *Modal, cfg ConfigEndLevel) *ui.Window {
Label: "Restart Level",
F: cfg.OnRestartLevel,
},
{
Label: "Next Level",
F: cfg.OnPityNextLevel,
},
{
Label: "Edit Level",
F: cfg.OnEditLevel,

View File

@ -561,8 +561,8 @@ func (s *PlayScene) FailLevel(message string) {
if s.Level.GameRule.Survival {
s.ShowEndLevelModal(
true,
"Level Completed",
false,
"You've died!",
fmt.Sprintf(
"%s\nCongrats on surviving for %s!",
message,
@ -639,6 +639,15 @@ func (s *PlayScene) ShowEndLevelModal(success bool, title, message string) {
config.OnEditLevel = s.EditLevel
}
// Survival Mode failure? The level is considered completed even if you
// die (silver high score) but the default button should be Retry rather
// than Next Level.
var survivalFailure bool
if !success && s.Level.GameRule.Survival {
survivalFailure = true
success = true // level is completed
}
// Beaten the level?
if success {
config.OnRetryCheckpoint = nil
@ -688,6 +697,14 @@ func (s *PlayScene) ShowEndLevelModal(success bool, title, message string) {
}
}
// Survival Mode failures: the Retry buttons should be higher
// priority than Next Level but they still get the (pity)
// Next Level button.
if survivalFailure {
config.OnPityNextLevel = config.OnNextLevel
config.OnNextLevel = nil
}
// Show the modal.
modal.EndLevel(config, title, message)