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;
+ }
}