Add replay validation
This commit is contained in:
parent
f0d8521e90
commit
57097c57bb
3 changed files with 78 additions and 20 deletions
4
TODO.txt
4
TODO.txt
|
@ -2,6 +2,7 @@ fuck issue trackers :D
|
|||
|
||||
=========== GENERAL ==============
|
||||
|
||||
- menu: key repeat?
|
||||
- controller supports? analog input could be "tapping" the keys with varying
|
||||
frequency
|
||||
- frontends:
|
||||
|
@ -44,6 +45,7 @@ fuck issue trackers :D
|
|||
=========== HANDLED ==============
|
||||
|
||||
- should drifting make a sound? NO NEED
|
||||
- replay validation? maybe yes?
|
||||
- ghost color
|
||||
- make reverse maps
|
||||
- remake TM maps in the third party repo
|
||||
|
@ -71,8 +73,6 @@ fuck issue trackers :D
|
|||
again (reshape iterations, tension, ...); seem acceptable now maybe?
|
||||
- in tiny resolution the sky jumps when rotating
|
||||
- car particles seem too big in low res
|
||||
- replay validation? MAYBE NOT, make a separate tool if needed, shouldn't likely
|
||||
be part of the game
|
||||
- at high resolution (like 1920) buggy triangles sometimes appeard, tried to
|
||||
fix this in S3L now but needs to be tested
|
||||
- shift the car texture a bit to align the wheels? KINDA DOESN'T GETT BETTER NOW
|
||||
|
|
18
game.h
18
game.h
|
@ -853,8 +853,8 @@ uint8_t LCR_gameLoadMap(unsigned int mapIndex)
|
|||
/**
|
||||
Loads replay by its index, returns index of a map for the replay (and the map
|
||||
will be loaded as with LCR_mapLoadFromStr) or -1 if the map wasn't found or -2
|
||||
if the replay couldn't be loaded. This function potentially reloads current
|
||||
map!
|
||||
if the replay couldn't be loaded or -3 if the replay is invalid. This function
|
||||
potentially reloads current map!
|
||||
*/
|
||||
unsigned int LCR_gameLoadReplay(unsigned int replayIndex)
|
||||
{
|
||||
|
@ -900,7 +900,7 @@ unsigned int LCR_gameLoadReplay(unsigned int replayIndex)
|
|||
LCR_LOG2("map name hash matches");
|
||||
|
||||
if (LCR_gameLoadMap(mapIndex) && mapHash == LCR_currentMap.hash)
|
||||
return mapIndex;
|
||||
return LCR_replayValidate() ? mapIndex : -3;
|
||||
else
|
||||
{
|
||||
LCR_LOG2("bad map");
|
||||
|
@ -1243,7 +1243,7 @@ void LCR_gameDraw3DView(void)
|
|||
LCR_GameUnit carTransform[6];
|
||||
|
||||
LCR_GameUnit physicsInterpolationParam =
|
||||
!(LCR_racing.playingReplay && LCR_replayHasFinished()) ?
|
||||
!(LCR_racing.replay.on && LCR_replayHasFinished()) ?
|
||||
LCR_GAME_UNIT -
|
||||
((LCR_game.nextRacingTickTime - LCR_game.time) * LCR_GAME_UNIT)
|
||||
/ LCR_RACING_TICK_MS
|
||||
|
@ -1388,7 +1388,7 @@ void LCR_gameHandleInput(void)
|
|||
LCR_currentMap.targetTime = LCR_game.runTime;
|
||||
}
|
||||
|
||||
LCR_gameResetRun(LCR_racing.playingReplay,LCR_game.ghost.active);
|
||||
LCR_gameResetRun(LCR_racing.replay.on,LCR_game.ghost.active);
|
||||
}
|
||||
}
|
||||
else if (LCR_game.state == LCR_GAME_STATE_RUN_STARTING)
|
||||
|
@ -1448,7 +1448,7 @@ void LCR_gameHandleInput(void)
|
|||
LCR_rendererMoveCamera(offsets,offsets + 3);
|
||||
}
|
||||
else if (LCR_game.keyStates[LCR_KEY_A] == 1)
|
||||
LCR_gameResetRun(LCR_racing.playingReplay,LCR_game.ghost.active);
|
||||
LCR_gameResetRun(LCR_racing.replay.on,LCR_game.ghost.active);
|
||||
}
|
||||
else // LCR_GAME_STATE_MENU
|
||||
{
|
||||
|
@ -1549,7 +1549,7 @@ void LCR_gameHandleInput(void)
|
|||
|
||||
case 3:
|
||||
if (LCR_game.statePrev == LCR_GAME_STATE_RUN_FINISHED &&
|
||||
!LCR_racing.playingReplay)
|
||||
!LCR_racing.replay.on)
|
||||
LCR_gameSaveReplay();
|
||||
else
|
||||
LCR_gamePopupMessage(LCR_texts[LCR_TEXTS_FAIL]);
|
||||
|
@ -1719,12 +1719,12 @@ uint8_t LCR_gameStep(uint32_t time)
|
|||
LCR_LOG1_NUM(LCR_game.runTime);
|
||||
|
||||
if (LCR_game.runTime <= LCR_currentMap.targetTime &&
|
||||
!LCR_racing.playingReplay)
|
||||
!LCR_racing.replay.on)
|
||||
{
|
||||
LCR_gameSaveReplay();
|
||||
|
||||
if (!LCR_game.mapBeaten && !LCR_game.ghost.active &&
|
||||
!LCR_racing.playingReplay)
|
||||
!LCR_racing.replay.on)
|
||||
{
|
||||
LCR_LOG1("map beaten");
|
||||
LCR_game.mapBeaten = 1;
|
||||
|
|
74
racing.h
74
racing.h
|
@ -168,10 +168,9 @@ struct
|
|||
|
||||
uint16_t crashState;
|
||||
|
||||
uint8_t playingReplay;
|
||||
|
||||
struct
|
||||
{
|
||||
uint8_t on; ///< Currently playing replay?
|
||||
uint16_t eventCount;
|
||||
uint16_t events[LCR_SETTING_REPLAY_MAX_SIZE];
|
||||
|
||||
|
@ -376,7 +375,7 @@ int LCR_replayHasFinished(void)
|
|||
for (int i = 0; i < LCR_racing.replay.eventCount; ++i)
|
||||
totalTime += LCR_racing.replay.events[i] >> 4;
|
||||
|
||||
return totalTime >= LCR_racing.replay.achievedTime;
|
||||
return totalTime > LCR_racing.replay.achievedTime;
|
||||
}
|
||||
|
||||
return LCR_racing.replay.currentEvent > LCR_racing.replay.eventCount;
|
||||
|
@ -445,7 +444,8 @@ int LCR_replayRecordEvent(uint32_t frame, uint8_t input)
|
|||
|
||||
frame -= previousFrame; // convert to offset
|
||||
|
||||
while (frame > 4095 && LCR_racing.replay.eventCount < LCR_SETTING_REPLAY_MAX_SIZE)
|
||||
while (frame > 4095 && LCR_racing.replay.eventCount <
|
||||
LCR_SETTING_REPLAY_MAX_SIZE)
|
||||
{
|
||||
// add intermediate events
|
||||
frame -= 4095;
|
||||
|
@ -982,7 +982,7 @@ void LCR_racingRestart(uint8_t replay)
|
|||
LCR_racing.tick = 0;
|
||||
LCR_racing.fanForce = 0;
|
||||
|
||||
LCR_racing.playingReplay = replay;
|
||||
LCR_racing.replay.on = replay;
|
||||
|
||||
TPE_bodyActivate(&(LCR_racing.carBody));
|
||||
LCR_racing.wheelCollisions = 0;
|
||||
|
@ -1066,7 +1066,7 @@ void LCR_racingInit(void)
|
|||
TPE_worldInit(&(LCR_racing.physicsWorld),
|
||||
&(LCR_racing.carBody),1,_LCR_racingEnvironmentFunction);
|
||||
|
||||
LCR_racing.playingReplay = 0;
|
||||
LCR_racing.replay.on = 0;
|
||||
LCR_racing.physicsWorld.collisionCallback = _LCR_racingCollisionHandler;
|
||||
}
|
||||
|
||||
|
@ -1217,7 +1217,7 @@ uint32_t LCR_racingStep(unsigned int input)
|
|||
|
||||
LCR_racing.groundMaterial = LCR_BLOCK_MATERIAL_CONCRETE;
|
||||
|
||||
if (LCR_racing.playingReplay)
|
||||
if (LCR_racing.replay.on)
|
||||
{
|
||||
if (LCR_racing.tick == 0)
|
||||
LCR_replayInitPlaying();
|
||||
|
@ -1637,7 +1637,7 @@ uint32_t LCR_racingStep(unsigned int input)
|
|||
{
|
||||
result |= LCR_RACING_EVENT_FINISHED;
|
||||
|
||||
if (!LCR_racing.playingReplay)
|
||||
if (!LCR_racing.replay.on)
|
||||
LCR_replayRecordEvent(LCR_racing.tick,LCR_REPLAY_EVENT_END);
|
||||
}
|
||||
}
|
||||
|
@ -1678,4 +1678,62 @@ void LCR_physicsDebugDraw(LCR_GameUnit camPos[3], LCR_GameUnit camRot[2],
|
|||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
Validates replay, i.e. checks if it finishes and whether its achieved time
|
||||
agrees with the stored time. The function can only be called when both the
|
||||
replay and the correct map are loaded. The loaded replay's playing position
|
||||
will be reset after this function returns.
|
||||
*/
|
||||
int LCR_replayValidate(void)
|
||||
{
|
||||
LCR_LOG1("validating replay");
|
||||
|
||||
int result = 0;
|
||||
|
||||
LCR_racingRestart(1);
|
||||
|
||||
while (LCR_racing.tick < 0x00f00000 // no infinite loops
|
||||
&& LCR_racing.tick <= LCR_racing.replay.achievedTime)
|
||||
{
|
||||
int coords[3];
|
||||
|
||||
LCR_racingStep(0);
|
||||
LCR_racingGetCarBlockCoords(coords);
|
||||
|
||||
coords[0] = LCR_mapGetBlockAt(coords[0],coords[1],coords[2]);
|
||||
|
||||
if (coords[0] && LCR_currentMap.blocks[coords[0] * LCR_BLOCK_SIZE] ==
|
||||
LCR_BLOCK_FINISH)
|
||||
{
|
||||
uint8_t allCPsTaken = 1; // reuse as variable
|
||||
|
||||
for (int i = 0; i < LCR_currentMap.blockCount; ++i)
|
||||
if (LCR_currentMap.blocks[i * LCR_BLOCK_SIZE] == LCR_BLOCK_CHECKPOINT_0)
|
||||
{
|
||||
allCPsTaken = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (allCPsTaken)
|
||||
{
|
||||
result = LCR_racing.tick == (LCR_racing.replay.achievedTime + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
LCR_LOG1("replay valid");
|
||||
}
|
||||
else
|
||||
{
|
||||
LCR_LOG1("replay invalid!");
|
||||
}
|
||||
|
||||
LCR_racingRestart(1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // guard
|
||||
|
|
Loading…
Reference in a new issue