From a0990054ea9780b311b2547d495e145a89774979 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Sun, 2 Jul 2023 23:19:01 +0530 Subject: [PATCH] end game and level select for hunt --- src/CameraController.hx | 16 +++++++++------- src/MarbleWorld.hx | 4 +++- src/Radar.hx | 4 ++++ src/Settings.hx | 5 ++++- src/Util.hx | 5 +++++ src/gui/EndGameGui.hx | 28 ++++++++++++++++++--------- src/gui/LevelSelectGui.hx | 20 +++++++++++++++++--- src/gui/PlayGui.hx | 2 ++ src/modes/GameMode.hx | 9 ++++++++- src/modes/HuntMode.hx | 40 +++++++++++++++++++++++++++++++++++++++ src/modes/NullMode.hx | 11 +++++++++++ 11 files changed, 122 insertions(+), 22 deletions(-) diff --git a/src/CameraController.hx b/src/CameraController.hx index c79fa382..e4d494be 100644 --- a/src/CameraController.hx +++ b/src/CameraController.hx @@ -249,13 +249,15 @@ class CameraController extends Object { if (this.finish) { // Move the target to the centre of the finish - var padMat = @:privateAccess this.level.endPad.getAbsPos(); - var offset = padMat.up(); - var padPos = padMat.getPosition(); - var focusPos = padPos.add(offset); - focusPos.scale(0.025); - focusPos = focusPos.add(lastTargetPos.multiply(0.975)); - marblePosition = focusPos; + if (@:privateAccess this.level.endPad != null) { + var padMat = @:privateAccess this.level.endPad.getAbsPos(); + var offset = padMat.up(); + var padPos = padMat.getPosition(); + var focusPos = padPos.add(offset); + focusPos.scale(0.025); + focusPos = focusPos.add(lastTargetPos.multiply(0.975)); + marblePosition = focusPos; + } } var up = new Vector(0, 0, 1); diff --git a/src/MarbleWorld.hx b/src/MarbleWorld.hx index 00c96a6e..0aae7250 100644 --- a/src/MarbleWorld.hx +++ b/src/MarbleWorld.hx @@ -1165,6 +1165,8 @@ class MarbleWorld extends Scheduler { } else if (this.timeState.currentAttemptTime + dt >= 3.5) { this.timeState.gameplayClock += ((this.timeState.currentAttemptTime + dt) - 3.5) * timeMultiplier; } + if (this.timeState.gameplayClock < 0) + this.gameMode.onTimeExpire(); } this.timeState.currentAttemptTime += dt; } else { @@ -1493,7 +1495,7 @@ class MarbleWorld extends Scheduler { } else { nextLevelCode(); } - }, mission, finishTime); + }, mission, this.gameMode.getFinishScore(), this.gameMode.getScoreType()); MarbleGame.canvas.pushDialog(egg); this.setCursorLock(false); return 0; diff --git a/src/Radar.hx b/src/Radar.hx index 21340ed8..a7bc7921 100644 --- a/src/Radar.hx +++ b/src/Radar.hx @@ -49,6 +49,10 @@ class Radar { } } + public function blink() { + time = 0; + } + public function reset() { time = 0; g.clear(); diff --git a/src/Settings.hx b/src/Settings.hx index ce085f3a..6c2b2b7b 100644 --- a/src/Settings.hx +++ b/src/Settings.hx @@ -1,5 +1,6 @@ package src; +import modes.GameMode.ScoreType; import h3d.Vector; import haxe.ds.Option; import gui.Canvas; @@ -241,11 +242,13 @@ class Settings { save(); } - public static function saveScore(mapPath:String, score:Score) { + public static function saveScore(mapPath:String, score:Score, scoreType:ScoreType = Time) { if (highScores.exists(mapPath)) { var scoreList = highScores.get(mapPath); scoreList.push(score); scoreList.sort((a, b) -> a.time == b.time ? 0 : (a.time > b.time ? 1 : -1)); + if (scoreType == Score) + scoreList.reverse(); } else { highScores.set(mapPath, [score]); } diff --git a/src/Util.hx b/src/Util.hx index ef3ec171..dcfeb077 100644 --- a/src/Util.hx +++ b/src/Util.hx @@ -297,6 +297,11 @@ class Util { return false; } + public static function formatScore(score:Float) { + var scoreInt = Std.int(Math.round(score)); + return '${scoreInt}'; + } + public static function formatTime(time:Float) { var et = time * 1000; var thousandth = Std.int(et % 10); diff --git a/src/gui/EndGameGui.hx b/src/gui/EndGameGui.hx index 7a3566e7..1207e621 100644 --- a/src/gui/EndGameGui.hx +++ b/src/gui/EndGameGui.hx @@ -1,5 +1,6 @@ package gui; +import modes.GameMode.ScoreType; import mis.MisParser; import hxd.BitmapData; import h2d.Tile; @@ -21,7 +22,8 @@ class EndGameGui extends GuiImage { var scoreSubmitted:Bool = false; - public function new(continueFunc:GuiControl->Void, restartFunc:GuiControl->Void, nextLevelFunc:GuiControl->Void, mission:Mission, timeState:TimeState) { + public function new(continueFunc:GuiControl->Void, restartFunc:GuiControl->Void, nextLevelFunc:GuiControl->Void, mission:Mission, score:Float, + scoreType:ScoreType) { var res = ResourceLoader.getImage("data/ui/xbox/BG_fadeOutSoftEdge.png").resource.toTile(); super(res); this.horizSizing = Width; @@ -86,12 +88,15 @@ class EndGameGui extends GuiImage { return arial14; } - var beatPar = timeState.gameplayClock < mission.qualifyTime; + var beatPar = score < mission.qualifyTime; var egResultLeft = new GuiMLText(arial14, mlFontLoader); egResultLeft.position = new Vector(28, 26); egResultLeft.extent = new Vector(180, 100); - egResultLeft.text.text = '

Time:
Par Time:
Rating:
My Best Time:

'; + if (scoreType == Time) + egResultLeft.text.text = '

Time:
Par Time:
Rating:
My Best Time:

'; + if (scoreType == Score) + egResultLeft.text.text = '

Score:
My Best Score:

'; endGameWnd.addChild(egResultLeft); var c0 = 0xEBEBEB; var c1 = 0x8DFF8D; @@ -111,15 +116,17 @@ class EndGameGui extends GuiImage { return (completionBonus + timeBonus) * difficulty; } - var rating = calcRating(timeState.gameplayClock * 1000, mission.qualifyTime * 1000, mission.goldTime * 1000, - Std.parseInt(mission.missionInfo.difficulty)); + var rating = calcRating(score * 1000, mission.qualifyTime * 1000, mission.goldTime * 1000, Std.parseInt(mission.missionInfo.difficulty)); - var myScore = {name: "Player", time: timeState.gameplayClock}; - Settings.saveScore(mission.path, myScore); + var myScore = {name: "Player", time: score}; + Settings.saveScore(mission.path, myScore, scoreType); var scoreData:Array = Settings.getScores(mission.path); while (scoreData.length < 1) { - scoreData.push({name: "Nardo Polo", time: 5999.999}); + if (scoreType == Score) + scoreData.push({name: "Nardo Polo", time: 0}); + if (scoreType == Time) + scoreData.push({name: "Nardo Polo", time: 5999.999}); } var bestScore = scoreData[0]; @@ -128,7 +135,10 @@ class EndGameGui extends GuiImage { egResultRight.position = new Vector(214, 26); egResultRight.extent = new Vector(180, 100); - egResultRight.text.text = '${Util.formatTime(timeState.gameplayClock)}
${Util.formatTime(mission.qualifyTime)}
${rating}
${Util.formatTime(bestScore.time)}'; + if (scoreType == Score) + egResultRight.text.text = '${Util.formatScore(score)}
${Util.formatScore(bestScore.time)}'; + if (scoreType == Time) + egResultRight.text.text = '${Util.formatTime(score)}
${Util.formatTime(mission.qualifyTime)}
${rating}
${Util.formatTime(bestScore.time)}'; endGameWnd.addChild(egResultRight); var bottomBar = new GuiControl(); diff --git a/src/gui/LevelSelectGui.hx b/src/gui/LevelSelectGui.hx index 774d3f62..2be94353 100644 --- a/src/gui/LevelSelectGui.hx +++ b/src/gui/LevelSelectGui.hx @@ -1,5 +1,6 @@ package gui; +import modes.GameMode.ScoreType; import src.Util; import haxe.io.Path; import h2d.filter.DropShadow; @@ -223,16 +224,29 @@ class LevelSelectGui extends GuiImage { loadText.text.visible = false; loadTextBg.text.visible = false; }); + + var scoreType = mis.missionInfo.gamemode != null + && mis.missionInfo.gamemode.toLowerCase() == 'scrum' ? ScoreType.Score : ScoreType.Time; + var myScore = Settings.getScores(mis.path); var scoreDisp = "None"; if (myScore.length != 0) - scoreDisp = Util.formatTime(myScore[0].time); + scoreDisp = scoreType == Time ? Util.formatTime(myScore[0].time) : Util.formatScore(myScore[0].time); var isPar = myScore.length != 0 && myScore[0].time < mis.qualifyTime; var scoreColor = "#EBEBEB"; if (isPar) scoreColor = "#8DFF8D"; - levelInfoMid.text.text = '

${scoreDisp}
${Util.formatTime(mis.qualifyTime)}

'; - levelInfoRight.text.text = '

Level ${mis.missionInfo.level}
Difficulty ${mis.missionInfo.difficulty}

'; + if (scoreType == Score && myScore.length == 0) + scoreColor = "#EBEBEB"; + if (scoreType == Time) { + levelInfoLeft.text.text = '

My Best Time:
Par Time:

'; + levelInfoMid.text.text = '

${scoreDisp}
${Util.formatTime(mis.qualifyTime)}

'; + } + if (scoreType == Score) { + levelInfoLeft.text.text = '

My Best Score:

'; + levelInfoMid.text.text = '

${scoreDisp}

'; + } + levelInfoRight.text.text = '

Level ${mis.missionInfo.level}
Difficulty ${mis.missionInfo.difficulty == null ? "" : mis.missionInfo.difficulty}

'; return true; } diff --git a/src/gui/PlayGui.hx b/src/gui/PlayGui.hx index 6134857c..0bf7a1fe 100644 --- a/src/gui/PlayGui.hx +++ b/src/gui/PlayGui.hx @@ -718,6 +718,8 @@ class PlayGui { // 1: green // 2: red public function formatTimer(time:Float) { + if (time < 0) + time = 0; // Can't support negatives for now var et = time * 1000; var thousandth = et % 10; var hundredth = Math.floor((et % 1000) / 10); diff --git a/src/modes/GameMode.hx b/src/modes/GameMode.hx index 90033ded..c32b41e6 100644 --- a/src/modes/GameMode.hx +++ b/src/modes/GameMode.hx @@ -6,13 +6,20 @@ import h3d.Vector; import src.MarbleWorld; import src.Mission; +enum ScoreType { + Time; + Score; +} + interface GameMode { public function getSpawnTransform():{position:Vector, orientation:Quat, up:Vector}; public function getRespawnTransform():{position:Vector, orientation:Quat, up:Vector}; public function missionScan(mission:Mission):Void; public function getStartTime():Float; public function timeMultiplier():Float; - + public function getScoreType():ScoreType; + public function getFinishScore():Float; + public function onTimeExpire():Void; public function onRestart():Void; public function onGemPickup(gem:Gem):Void; diff --git a/src/modes/HuntMode.hx b/src/modes/HuntMode.hx index d448b2b6..cc929125 100644 --- a/src/modes/HuntMode.hx +++ b/src/modes/HuntMode.hx @@ -1,5 +1,7 @@ package modes; +import gui.AchievementsGui; +import modes.GameMode.ScoreType; import shapes.GemBeam; import shapes.Gem; import src.Console; @@ -219,6 +221,7 @@ class HuntMode extends NullMode { var spawnGroup = pickGemSpawnGroup(); activeGemSpawnGroup = spawnGroup; fillGemGroup(spawnGroup); + @:privateAccess level.radar.blink(); } } @@ -312,4 +315,41 @@ class HuntMode extends NullMode { 'sound/gem_collect.wav' ]; } + + override function getScoreType():ScoreType { + return Score; + } + + override function onTimeExpire() { + if (level.finishTime != null) + return; + AudioManager.playSound(ResourceLoader.getResource('data/sound/finish.wav', ResourceLoader.getAudio, @:privateAccess level.soundResources)); + level.finishTime = level.timeState.clone(); + level.marble.setMode(Start); + level.marble.camera.finish = true; + level.finishYaw = level.marble.camera.CameraYaw; + level.finishPitch = level.marble.camera.CameraPitch; + level.displayAlert("Congratulations! You've finished!"); + if (!level.isWatching) { + var notifies = AchievementsGui.check(); + var delay = 5.0; + var achDelay = 0.0; + for (i in 0...9) { + if (notifies & (1 << i) > 0) + achDelay += 3; + } + if (notifies > 0) + achDelay += 0.5; + @:privateAccess level.schedule(level.timeState.currentAttemptTime + Math.max(delay, achDelay), () -> cast level.showFinishScreen()); + } + // Stop the ongoing sounds + if (@:privateAccess level.timeTravelSound != null) { + @:privateAccess level.timeTravelSound.stop(); + @:privateAccess level.timeTravelSound = null; + } + } + + override function getFinishScore():Float { + return points; + } } diff --git a/src/modes/NullMode.hx b/src/modes/NullMode.hx index a68cbdce..d93b827a 100644 --- a/src/modes/NullMode.hx +++ b/src/modes/NullMode.hx @@ -1,5 +1,6 @@ package modes; +import modes.GameMode.ScoreType; import shapes.Gem; import h3d.Quat; import h3d.Vector; @@ -83,4 +84,14 @@ class NullMode implements GameMode { public function getPreloadFiles() { return ['data/sound/gem_all.wav']; } + + public function onTimeExpire() {} + + public function getScoreType():ScoreType { + return Time; + } + + public function getFinishScore():Float { + return level.finishTime.gameplayClock; + } }