Licar mod for making TAS (tool assisted speedruns). This is a simple mod that only adds one feature: instead of completely restarting a map, the restart key rather rewinds time a little back. This allows to retry any part of a map as many times as one desires. It also helps to slow down time in the settings. diff --git a/data b/data index def2738..f77c9bb 100644 --- a/data +++ b/data @@ -209,3 +209,11 @@ air path #Rdrummy LCbonus1 13'16;00LCbonus1;999b1acd 0000399:0001:0089:0051:0079:0021:0093:0031:0089:0031:0119:0091:0053:00f1:01a3:00d1:0099:0201:0073:0051:0063:0051:0059:0051:00d9:00b1:0089:0041:00a3:0031:02b9:0048:0020:0081:0149:00c1:0059:0031:0113:0051:0019:0078:0099:0041 #Rdrummy LCbonus2 24'18;00LCbonus2;288d28fe 0000733:0001:0153:00d1:0023:0081:00d3:0041:0023:00a9:0128:0034:0036:00e4:005c:0054:0096:0044:007c:0024:0146:0112:0018:0029:00f1:0063:0061:00c3:0031:00c3:0031:0025:0031:0039:0081:0033:01d1:0083:0081:0073:0031:00e3:0071:00f9:0051:01b9:00c4:0040:0028:0069:0021:0043:00e1:0090:0046:00b0:0031:0043:0070:0024:0026:00e0:0018:0049:0018:0039:01a1:0039:0051:0049:0048:001c:0098:0050:0011:0039:0061:00d9:0041:00a9:0018:00c9:00e1:0083:0042:0010:0042:0093:00b1:0170:0022:0016:0042:0083:0141:0013:0021:0059:0041:0053 #Rdrummy LCpressforw1 21'31;00LCpressforw1;6363b43d 0000599:0001 +#RLCtiny1 17'457;00LCtiny1;ae1ab677 0000529:0001:01d3:0031:0139:0031:00f9:0051:00a9:0031:0059:0051:0029:0091:0089:0031:0010:0161:0079:0071:00a3:0061:0030:0481:00f3:0041:0063:0041:0043:00c1:0169:0080:0228:005c:0108:0010:0031:0013:01f1:0089:00b1:0115:0051:01f3:0031:00c9:0011:0133:0021 +#RLC1 15'048;00LC1;8bd6e314 0000456:0001:0079:0011:0049:0021:0059:0031:0059:0051:0149:0091:0029:0011:0049:0021:0029:0021:0069:0021:0069:0021:0029:0021:00e9:0095:0021:0049:0151:0069:0051:0029:0031:0059:0021:00f9:0041:0039:0021:0099:0011:00a9:0011:0063:0011:00b3:0011:0213:0031:0063:0021:0093:0051:0013:00b1:0023:0021:0013:0051:0013:0021:0063:0051:0033:0041:0073:0011:0063:0021:0063:0021:0199:0031:0283:0021:0163:0011 +#RLC5 22'737;00LC5;90f26004 0000689:0001:0099:0031:0089:0031:00f5:0021:0049:0101:0069:0041:0029:0021:0039:0021:0019:0021:0039:0021:0063:0041:00d9:0021:0063:0011:00a3:0011:0093:0021:0093:0021:0013:0011:0043:0051:0013:0061:0073:0031:0023:0031:00c3:0011:0023:0021:0043:0041:0033:0011:0023:0011:0013:0011:0033:0021:0023:0031:0023:0041:0079:0031:0133:0031:0023:0031:0069:0011:0223:0021:0033:0031:00a5:0021:0023:0021:0023:0071:0049:0021:0053:0021:00e9:0071:0029:0051:0019:0021:0093:0031:0053:0011:0059:0071:0109:0011:02e9:00c1:0053:0021:00e9:0021:0029:0021:0019:0045:0021:0049:0021:0029:0051:0019:0041:0069:0041:0059:0051:0029:0011:0029:0031:0019:0021:0039:0011:0119:0031:0029:0021:01b5:0031:0029:0011:0029:0031:0039:0011:0073:0021:0023:0031:0013:00c1:0019:0051:0069 +#RLC5 22'209;00LC5;90f26004 0000673:0001:0199:0061:0025:0031:0069:0021:0019:0091:0039:0041:0079:0031:00a9:0021:0153:0031:0063:0071:0039:0075:0011:0125:0021:01c9:0041:0059:0021:00c3:0011:00b9:0031:0079:0041:0069:0041:0059:0071:0019:0031:0019:0011:00b9:0031:0029:0011:0049:0011:0029:0021:0019:0011:0019:0031:0029:0021:0019:0041:0019:0021:0019:0021:00b9:0051:0089:0011:0085:0021:0069:0021:0083:0021:0023:0041:0013:0021:0129:0051:0025:0021:0049:0011:0049:0091:0023:0061:0033:0021:0023:0021:0059:0031:0069:00d1:0089:0051:0033:0011:0029:00a1:0039:0031:0019:0021:0033:0041:0045:0021:0019:0051:0039:0021:0019:0041:0039:0011:0059:0031:0029:0061:0029:0021:0019:0021:0029:0011:0083:0021:0033:0031:0079:0021:0039:0041:0105:0021:0069:0021:0049:0051:0043:0021:0023:0021:0023:0031:0013:0021:0013:0071:0053:0051:0013:0041:00a9 +#RLC5 21'615;00LC5;90f26004 0000655:0001:00b9:0061:01d5:0021:00e3:0011:01f3:0011:0073:0031:0023:0021:0209:0021:0099:0021:0029:0021:0049:0021:0029:0021:0023:0021:0049:0021:0069:0031:0019:0031:0029:0021:0049:0071:0019:0031:0019:0011:0059:0051:0029:0021:0019:0011:0029:0021:0019:0021:0019:0021:0029:0021:0029:0021:0019:0071:0063:0011:0049:0011:0029:0021:0019:0021:0053:0021:0023:0041:0049:0051:0039:0021:0093:0021:0023:0021:0033:0031:0013:0041:0023:0021:00d9:0031:0039:0021:0045:0029:0051:0029:00c1:0033:0081:0023:0041:0049:0021:0039:0021:0183:0021:0029:00c1:0059:0011:0029:0061:0029:0021:0029:0021:0039:0011:0029:0021:0099:0021:0039:0021:0019:0035:0011:0029:0031:0019:00c1:0019:0021:0053:0021:0039:0051:0049:0021:0019:0021:0019:0031:0119:0011:0059:0021:0175:0011:0089:0091:0043:0021:0013:0041:0013:0031:0043:00d1:0049:0061 +#RLC5 21'450;00LC5;90f26004 0000650:0001:00b9:0061:01d5:0021:00e3:0011:01f3:0011:0073:0031:0023:0021:0209:0021:0099:0021:0029:0021:0049:0021:0029:0021:0023:0021:0049:0021:0069:0031:0019:0031:0029:0021:0049:0071:0019:0031:0019:0011:0059:0051:0029:0021:0019:0011:0029:0021:0019:0021:0019:0021:0029:0021:0029:0021:0019:0071:0063:0011:0049:0011:0029:0021:0019:0021:0053:0021:0023:0041:0049:0051:0039:0021:0093:0021:0023:0021:0033:0031:0013:0041:0023:0021:00d9:0031:0039:0021:0045:0029:0051:0029:00c1:0033:0081:0023:0041:0049:0021:0039:0021:0183:0021:0029:00c1:0059:0011:0029:0061:0029:0021:0029:0021:0039:0011:0029:0021:0099:0021:0039:0021:0019:0035:0011:0029:0031:0019:00c1:0019:0021:0053:0021:0039:0051:0049:0021:0019:0021:0019:0031:0119:0011:0059:0021:0130:0011:0069:0031:00e9:0021:0083:00e1:0069:0071 +#RLC5 20'361;00LC5;90f26004 0000617:0031:0049:0041:0029:0021:0039:0021:0069:0051:0049:0081:0045:0011:0029:0021:0029:0021:0019:0011:0073:0031:0093:0031:0093:0031:00b3:0011:0049:0021:01e3:0031:0089:0051:0019:0021:0073:0041:0039:0021:0069:0031:0019:0021:0029:0021:0069:00a1:0029:0021:0019:0021:0019:0021:0019:0021:0019:0021:0019:0021:0019:0011:0029:0011:0019:0021:0019:0041:0019:0021:0019:0021:0019:0021:0019:0021:0019:0011:0089:0031:0019:0011:0049:0041:0039:0031:0019:0021:00b9:0021:00d3:0021:0043:0021:0043:0051:0099:0021:0019:0021:00d9:0021:0073:0021:0039:0031:0339:00b1:0019:0031:0103:0011:0095:0021:00b9:0021:0089:0021:0059:0051:0029:0031:0019:0031:0019:0021:0059:0021:0039:0021:0039:0021:0039:0021:01b5:0021:0173:0041:0023:0011:0013:00c1 +#RLC5 20'295;00LC5;90f26004 0000615:0031:0049:0041:0029:0021:0039:0021:0069:0051:0049:0081:0045:0011:0029:0021:0029:0021:0019:0011:0073:0031:0093:0031:0093:0031:00b3:0011:0049:0021:01e3:0031:0089:0051:0019:0021:0073:0041:0039:0021:0069:0031:0019:0021:0029:0021:0069:00a1:0029:0021:0019:0021:0019:0021:0019:0021:0019:0021:0019:0021:0019:0011:0029:0011:0019:0021:0019:0041:0019:0021:0019:0021:0019:0021:0019:0021:0019:0011:0089:0031:0019:0011:0049:0041:0039:0031:0019:0021:00b9:0021:00d3:0021:0043:0021:0043:0051:0099:0021:0019:0021:00d9:0021:0073:0021:0039:0031:0339:00b1:0019:0031:0103:0011:0095:0021:00b9:0021:0089:0021:0059:0051:0029:0031:0019:0031:0019:0021:0059:0021:0039:0021:0039:0021:0039:0021:0120:0021:0099:0021:0089:0011:00e3:0031:0013:00c1:0039:0031:0079 diff --git a/game.h b/game.h index b1db32c..e57b6a9 100644 --- a/game.h +++ b/game.h @@ -344,6 +344,9 @@ struct uint32_t runTime; ///< Current time of the run, in ticks. uint8_t mapBeaten; + uint8_t tasInputs[LCR_SETTING_TAS_MAX_INPUTS / 2 + 1]; + unsigned int tasInputCount; + char popupStr[LCR_POPUP_STR_SIZE]; uint8_t popupCountdown; @@ -504,8 +507,37 @@ void LCR_gameResetRun(uint8_t replay, uint8_t ghost) LCR_game.ghost.active = ghost; #endif - LCR_gameSetState(LCR_GAME_STATE_RUN_STARTING); LCR_game.runTime = 0; + + if (!LCR_racing.replay.on) + { + LCR_game.tasInputCount = + LCR_game.tasInputCount >= LCR_SETTING_TAS_REWIND ? + LCR_game.tasInputCount - LCR_SETTING_TAS_REWIND : 0; + + for (unsigned int i = 0; i < LCR_game.tasInputCount; ++i) + { + if (LCR_racingStep((LCR_game.tasInputs[i / 2] >> ((i % 2) * 4)) & 0x0f) + == LCR_RACING_EVENT_CP_TAKEN) + { + int carBlock[3]; + LCR_racingGetCarBlockCoords(carBlock); + LCR_rendererMarkTakenCP(carBlock[0],carBlock[1],carBlock[2]); + } + + LCR_game.runTime = LCR_racing.tick; + } + + LCR_gameSetState(LCR_GAME_STATE_RUN); + LCR_racingGetCarTransform(carTransform,carTransform + 3,0); + LCR_rendererSetCarTransform(carTransform,carTransform + 3); + LCR_rendererCameraReset(); + LCR_rendererLoadMapChunks(); + LCR_game.nextRenderFrameTime = LCR_game.time + 1000 / LCR_SETTING_FPS; + LCR_game.nextRacingTickTime = LCR_game.time + LCR_RACING_TICK_MS_RT; + } + else + LCR_gameSetState(LCR_GAME_STATE_RUN_STARTING); } void LCR_gameGetNthGhostSample(unsigned int n, @@ -867,6 +899,7 @@ uint8_t LCR_gameLoadMap(unsigned int mapIndex) result = LCR_mapLoadFromStr(LCR_gameGetNextDataStrChar,name); LCR_game.mapBeaten = LCR_mapIsBeaten(LCR_currentMap.name); + LCR_game.tasInputCount = 0; return result; } @@ -1765,6 +1798,23 @@ uint8_t LCR_gameStep(uint32_t time) (LCR_game.keyStates[LCR_KEY_DOWN] ? LCR_RACING_INPUT_BACK : 0) | (LCR_game.keyStates[LCR_KEY_LEFT] ? LCR_RACING_INPUT_LEFT : 0)); + if (!LCR_racing.replay.on) + { + if (LCR_game.tasInputCount >= LCR_SETTING_TAS_MAX_INPUTS) + { + LCR_LOG1("maximum TAS inputs reached!"); + } + else + { + uint8_t *inputRec = LCR_game.tasInputs + LCR_game.tasInputCount / 2; + + *inputRec = (LCR_game.tasInputCount % 2) ? + *inputRec | ((input & 0x0f) << 4) : (input & 0x0f); + + LCR_game.tasInputCount++; + } + } + #ifdef LCR_FPS_GET_MS frameTime = LCR_FPS_GET_MS; #endif diff --git a/settings.h b/settings.h index 332df45..eb87215 100644 --- a/settings.h +++ b/settings.h @@ -197,7 +197,7 @@ #ifndef LCR_SETTING_COUNTDOWN_MS /** Run start countdown length in milliseconds. */ - #define LCR_SETTING_COUNTDOWN_MS 2200 + #define LCR_SETTING_COUNTDOWN_MS 500 #endif #ifndef LCR_SETTING_MAP_CHUNK_RELOAD_INTERVAL @@ -296,4 +296,14 @@ #define LCR_SETTING_ONLY_SMALL_MAPS 0 #endif +#ifndef LCR_SETTING_TAS_MAX_INPUTS + /** Maximum possible length of a run in the TAS mod, in physics ticks. */ + #define LCR_SETTING_TAS_MAX_INPUTS 4096 +#endif + +#ifndef LCR_SETTING_TAS_REWIND + /** Length of TAS rewind, in physics ticks. */ + #define LCR_SETTING_TAS_REWIND 40 +#endif + #endif // guard