mirror of
https://github.com/s4Ys369/CHEATERex.git
synced 2025-01-22 07:32:10 -05:00
Upgrade to Time Trialsv2.2
featuring DynOsv0.4 by PeachyPeach
This commit is contained in:
parent
d20ac8573c
commit
58ae0d7777
19 changed files with 10815 additions and 7 deletions
3
Makefile
3
Makefile
|
@ -427,6 +427,9 @@ DEP_FILES := $(O_FILES:.o=.d) $(ULTRA_O_FILES:.o=.d) $(GODDARD_O_FILES:.o=.d) $(
|
||||||
# Segment elf files
|
# Segment elf files
|
||||||
SEG_FILES := $(SEGMENT_ELF_FILES) $(ACTOR_ELF_FILES) $(LEVEL_ELF_FILES)
|
SEG_FILES := $(SEGMENT_ELF_FILES) $(ACTOR_ELF_FILES) $(LEVEL_ELF_FILES)
|
||||||
|
|
||||||
|
# DynOS options txt files
|
||||||
|
include Makefile_dynos
|
||||||
|
|
||||||
##################### Compiler Options #######################
|
##################### Compiler Options #######################
|
||||||
INCLUDE_CFLAGS := -I include -I $(BUILD_DIR) -I $(BUILD_DIR)/include -I src -I .
|
INCLUDE_CFLAGS := -I include -I $(BUILD_DIR) -I $(BUILD_DIR)/include -I src -I .
|
||||||
ENDIAN_BITWIDTH := $(BUILD_DIR)/endian-and-bitwidth
|
ENDIAN_BITWIDTH := $(BUILD_DIR)/endian-and-bitwidth
|
||||||
|
|
21
Makefile_dynos
Normal file
21
Makefile_dynos
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# ----------------------
|
||||||
|
# Dynamic Options System
|
||||||
|
# ----------------------
|
||||||
|
|
||||||
|
DYNOS_INPUT_DIR := ./dynos
|
||||||
|
DYNOS_OUTPUT_DIR := $(BUILD_DIR)/$(BASEDIR)
|
||||||
|
DYNOS_COPY_TO_RES := \
|
||||||
|
mkdir -p $(DYNOS_INPUT_DIR); \
|
||||||
|
mkdir -p $(DYNOS_OUTPUT_DIR); \
|
||||||
|
for f in $(DYNOS_INPUT_DIR)/*.txt; do \
|
||||||
|
[ -f "$$f" ] || continue; \
|
||||||
|
cp -f $$f $(DYNOS_OUTPUT_DIR)/$$(basename -- $$f); \
|
||||||
|
done;
|
||||||
|
|
||||||
|
DYNOS := $(shell $(call DYNOS_COPY_TO_RES))
|
||||||
|
|
||||||
|
ifeq ($(VERSION),eu)
|
||||||
|
$(BUILD_DIR)/src/pc/dynamic_options.o: $(BUILD_DIR)/include/text_strings.h $(BUILD_DIR)/bin/eu/translation_en.o $(BUILD_DIR)/bin/eu/translation_de.o $(BUILD_DIR)/bin/eu/translation_fr.o
|
||||||
|
else
|
||||||
|
$(BUILD_DIR)/src/pc/dynamic_options.o: $(BUILD_DIR)/include/text_strings.h
|
||||||
|
endif
|
|
@ -13,6 +13,10 @@ Run `./extract_assets.py --clean && make clean` or `make distclean` to remove RO
|
||||||
|
|
||||||
## Additional Cheats
|
## Additional Cheats
|
||||||
* Instant Death/Level Exit L Trigger + R Trigger + A Button + B Button
|
* Instant Death/Level Exit L Trigger + R Trigger + A Button + B Button
|
||||||
|
* CHAOS Mode
|
||||||
|
* Time Stop
|
||||||
|
- Just press Y to stop time
|
||||||
|
- Can be reserved by CAP cheat or level transition
|
||||||
* FLYER
|
* FLYER
|
||||||
* All Jumps Triple
|
* All Jumps Triple
|
||||||
* Hover Mode
|
* Hover Mode
|
||||||
|
@ -76,8 +80,7 @@ Run `./extract_assets.py --clean && make clean` or `make distclean` to remove RO
|
||||||
* Bugfixes by JAGSTAX
|
* Bugfixes by JAGSTAX
|
||||||
* DynOS by PeachyPeach
|
* DynOS by PeachyPeach
|
||||||
-Exit to Main Menu by Adya
|
-Exit to Main Menu by Adya
|
||||||
-Go to Level Select by $4Y$
|
* And of course, CHEATERv9.5 by $4Y$, me
|
||||||
* And of course, CHEATERv9 by $4Y$, me
|
|
||||||
|
|
||||||
## How to add cheats/mods
|
## How to add cheats/mods
|
||||||
* Use `src/game/mario_cheats.c` for code
|
* Use `src/game/mario_cheats.c` for code
|
||||||
|
|
|
@ -10,6 +10,9 @@ Ejecuta `./extract_assets.py --clean && make clean` o `make distclean` para elim
|
||||||
|
|
||||||
## Trucos adicionales
|
## Trucos adicionales
|
||||||
* Muerte Instantanea/Salir del Nivel Gatillo L + Gatillo R + Boton A + Boton B
|
* Muerte Instantanea/Salir del Nivel Gatillo L + Gatillo R + Boton A + Boton B
|
||||||
|
* "CHAOS Mode"
|
||||||
|
* "Time Stop"
|
||||||
|
- Botón Y
|
||||||
* FLYER
|
* FLYER
|
||||||
* Todos los saltos triples
|
* Todos los saltos triples
|
||||||
* "HOVER MODE"
|
* "HOVER MODE"
|
||||||
|
@ -67,8 +70,7 @@ Ejecuta `./extract_assets.py --clean && make clean` o `make distclean` para elim
|
||||||
* "Bugfixes" por JAGSTAX
|
* "Bugfixes" por JAGSTAX
|
||||||
* "DynOS" por PeachyPeach
|
* "DynOS" por PeachyPeach
|
||||||
-"Exit to Main Menu" por Adya incluido
|
-"Exit to Main Menu" por Adya incluido
|
||||||
-"Go to Level Select" por $4Y$ incluido
|
* Y por supuesto, "CHEATERv9.5" por $4Y$, yo mismo
|
||||||
* Y por supuesto, "CHEATERv9" por $4Y$, yo mismo
|
|
||||||
|
|
||||||
## Como agregar los trucos/mods
|
## Como agregar los trucos/mods
|
||||||
* Usa `src/game/mario_cheats.c` para el código
|
* Usa `src/game/mario_cheats.c` para el código
|
||||||
|
|
25
dynos/time_trials_menu.txt
Normal file
25
dynos/time_trials_menu.txt
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
# Dynamic Options System aka DynOS v0.4
|
||||||
|
# By PeachyPeach
|
||||||
|
#
|
||||||
|
# This is a comment
|
||||||
|
# Here are the available commands:
|
||||||
|
# SUBMENU [Name] [Label] [Label2]
|
||||||
|
# TOGGLE [Name] [Label] [ConfigName] [InitialValue]
|
||||||
|
# SCROLL [Name] [Label] [ConfigName] [InitialValue] [Min] [Max] [Step]
|
||||||
|
# CHOICE [Name] [Label] [ConfigName] [InitialValue] [ChoiceStrings...]
|
||||||
|
# BIND [Name] [Label] [ConfigName] [Mask] [DefaultValues]
|
||||||
|
# BUTTON [Name] [Label] [FuncName]
|
||||||
|
# ENDMENU
|
||||||
|
#
|
||||||
|
# Valid Label characters:
|
||||||
|
# 0-9 A-Z a-z
|
||||||
|
# '.,-()&:!%?"~_
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
SUBMENU "time_trials_submenu" "Time Trials" "TIME TRIALS"
|
||||||
|
TOGGLE "time_trials" "Time Trials" "time_trials" 1
|
||||||
|
CHOICE "time_trials_ghost1" "Time Trials Ghost" "time_trials_ghost1" 1 "Hide" "Show"
|
||||||
|
CHOICE "time_trials_ghost2" "Time Trials Special Ghost" "time_trials_ghost2" 1 "Hide" "Show"
|
||||||
|
TOGGLE "time_trials_cheats" "Time Trials with Cheats" "time_trials_cheats" 0
|
||||||
|
ENDMENU
|
5479
enhancements/time_trials.2.2.patch
Normal file
5479
enhancements/time_trials.2.2.patch
Normal file
File diff suppressed because it is too large
Load diff
|
@ -2,7 +2,7 @@
|
||||||
#define AREA_H
|
#define AREA_H
|
||||||
|
|
||||||
#include <PR/ultratypes.h>
|
#include <PR/ultratypes.h>
|
||||||
|
#include "time_trials.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
#include "engine/graph_node.h"
|
#include "engine/graph_node.h"
|
||||||
|
|
|
@ -2716,9 +2716,11 @@ s16 render_pause_courses_and_castle(void) {
|
||||||
break;
|
break;
|
||||||
case DIALOG_STATE_HORIZONTAL:
|
case DIALOG_STATE_HORIZONTAL:
|
||||||
shade_screen();
|
shade_screen();
|
||||||
|
if (!time_trials_render_pause_castle_main_strings(gCurrSaveFileNum - 1, &gDialogLineNum)) {
|
||||||
print_hud_pause_colorful_str();
|
print_hud_pause_colorful_str();
|
||||||
render_pause_castle_menu_box(160, 143);
|
render_pause_castle_menu_box(160, 143);
|
||||||
render_pause_castle_main_strings(104, 60);
|
render_pause_castle_main_strings(104, 60);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef VERSION_EU
|
#ifdef VERSION_EU
|
||||||
if (gPlayer3Controller->buttonPressed & (A_BUTTON | Z_TRIG | START_BUTTON))
|
if (gPlayer3Controller->buttonPressed & (A_BUTTON | Z_TRIG | START_BUTTON))
|
||||||
|
@ -2921,7 +2923,7 @@ void render_course_complete_lvl_info_and_hud_str(void) {
|
||||||
play_star_fanfare_and_flash_hud(1, 1 << (gLastCompletedStarNum - 1));
|
play_star_fanfare_and_flash_hud(1, 1 << (gLastCompletedStarNum - 1));
|
||||||
|
|
||||||
if (gLastCompletedStarNum == 7) {
|
if (gLastCompletedStarNum == 7) {
|
||||||
name = segmented_to_virtual(actNameTbl[COURSE_STAGES_MAX * 6 + 1]);
|
name = segmented_to_virtual(actNameTbl[COURSE_STAGES_MAX * 6]);
|
||||||
} else {
|
} else {
|
||||||
name = segmented_to_virtual(actNameTbl[(gLastCompletedCourseNum - 1) * 6 + gLastCompletedStarNum - 1]);
|
name = segmented_to_virtual(actNameTbl[(gLastCompletedCourseNum - 1) * 6 + gLastCompletedStarNum - 1]);
|
||||||
}
|
}
|
||||||
|
@ -3121,6 +3123,7 @@ s16 render_menus_and_dialogs() {
|
||||||
s16 mode = 0;
|
s16 mode = 0;
|
||||||
|
|
||||||
create_dl_ortho_matrix();
|
create_dl_ortho_matrix();
|
||||||
|
time_trials_update(gMarioState, gMenuMode != -1);
|
||||||
|
|
||||||
if (gMenuMode != -1) {
|
if (gMenuMode != -1) {
|
||||||
switch (gMenuMode) {
|
switch (gMenuMode) {
|
||||||
|
|
|
@ -825,6 +825,7 @@ u32 interact_star_or_key(struct MarioState *m, UNUSED u32 interactType, struct O
|
||||||
// func_802521A0
|
// func_802521A0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
noExit = time_trials_save_time_and_stop_timer(gCurrSaveFileNum - 1, gCurrCourseNum, gCurrLevelNum, starIndex, (!noExit || grandStar));
|
||||||
if (grandStar) {
|
if (grandStar) {
|
||||||
return set_mario_action(m, ACT_JUMBO_STAR_CUTSCENE, 0);
|
return set_mario_action(m, ACT_JUMBO_STAR_CUTSCENE, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifdef EXT_OPTIONS_MENU
|
#ifdef EXT_OPTIONS_MENU
|
||||||
|
#ifdef DYNOS_INL
|
||||||
#include "sm64.h"
|
#include "sm64.h"
|
||||||
#include "text_strings.h"
|
#include "text_strings.h"
|
||||||
#include "engine/math_util.h"
|
#include "engine/math_util.h"
|
||||||
|
@ -690,4 +690,5 @@ void optmenu_check_buttons(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
#endif // EXT_OPTIONS_MENU
|
#endif // EXT_OPTIONS_MENU
|
||||||
|
|
1217
src/game/time_trials.c
Normal file
1217
src/game/time_trials.c
Normal file
File diff suppressed because it is too large
Load diff
24
src/game/time_trials.h
Normal file
24
src/game/time_trials.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef TIME_TRIALS_H
|
||||||
|
#define TIME_TRIALS_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
void time_trials_update(struct MarioState *m, bool isPaused);
|
||||||
|
u32 time_trials_save_time_and_stop_timer(s32 fileIndex, s32 course, s32 level, s32 star, bool exit);
|
||||||
|
s32 time_trials_render_pause_castle_main_strings(s32 fileIndex, s8 *index);
|
||||||
|
void time_trials_render_star_select_time(s32 fileIndex, s32 course, s32 star);
|
||||||
|
|
||||||
|
/* Options */
|
||||||
|
#include "pc/dynamic_options.h"
|
||||||
|
#define __time_trials__ dynos_get_value("time_trials")
|
||||||
|
#define __time_trials_ghost1__ dynos_get_value("time_trials_ghost1")
|
||||||
|
#define __time_trials_ghost2__ dynos_get_value("time_trials_ghost2")
|
||||||
|
#define __time_trials_cheats__ dynos_get_value("time_trials_cheats")
|
||||||
|
#define TIME_TRIALS_DISABLED (__time_trials__ == 0)
|
||||||
|
#define TIME_TRIALS_ENABLED (__time_trials__ == 1)
|
||||||
|
#define TIME_TRIALS_GHOST1_HIDE (__time_trials_ghost1__ == 0)
|
||||||
|
#define TIME_TRIALS_GHOST2_HIDE (__time_trials_ghost2__ == 0)
|
||||||
|
#define TIME_TRIALS_CHEATS_DISABLED (__time_trials_cheats__ == 0)
|
||||||
|
|
||||||
|
#endif // TIME_TRIALS_H
|
1898
src/game/time_trials_ghost_geo.inl
Normal file
1898
src/game/time_trials_ghost_geo.inl
Normal file
File diff suppressed because it is too large
Load diff
|
@ -368,6 +368,7 @@ Gfx *geo_act_selector_strings(s16 callContext, UNUSED struct GraphNode *node) {
|
||||||
#endif
|
#endif
|
||||||
if (callContext == GEO_CONTEXT_RENDER) {
|
if (callContext == GEO_CONTEXT_RENDER) {
|
||||||
print_act_selector_strings();
|
print_act_selector_strings();
|
||||||
|
time_trials_render_star_select_time(gCurrSaveFileNum - 1, gCurrCourseNum, sSelectedActIndex);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
1810
src/pc/dynamic_options.c
Normal file
1810
src/pc/dynamic_options.c
Normal file
File diff suppressed because it is too large
Load diff
33
src/pc/dynamic_options.h
Normal file
33
src/pc/dynamic_options.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef DYNAMIC_OPTIONS_H
|
||||||
|
#define DYNAMIC_OPTIONS_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
int dynos_get_value(const char *name);
|
||||||
|
void dynos_set_value(const char *name, int value);
|
||||||
|
void dynos_add_action(const char *funcName, bool (*funcPtr)(const char *), bool overwrite);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Warning: This is C++ code, use this macro inside a .cpp file
|
||||||
|
// The action signature is "bool (*) (const char *)"
|
||||||
|
// The input is the button name (not label)
|
||||||
|
// The output is the result of the action
|
||||||
|
#define DYNOS_DEFINE_ACTION(func) \
|
||||||
|
extern "C" { extern bool func(const char *); } \
|
||||||
|
class DynosAction_##func { \
|
||||||
|
public: \
|
||||||
|
inline DynosAction_##func() { \
|
||||||
|
dynos_add_action(#func, func, false); \
|
||||||
|
} \
|
||||||
|
private: \
|
||||||
|
static DynosAction_##func sDynosAction_##func; \
|
||||||
|
}; \
|
||||||
|
DynosAction_##func DynosAction_##func::sDynosAction_##func;
|
||||||
|
|
||||||
|
#endif // DYNAMIC_OPTIONS_H
|
16
src/pc/dynamic_options_cpp.cpp
Normal file
16
src/pc/dynamic_options_cpp.cpp
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#include "dynamic_options.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// DynOS Init
|
||||||
|
//
|
||||||
|
|
||||||
|
extern "C" { extern void dynos_init(void); }
|
||||||
|
class DynosInitialization { public: DynosInitialization() { dynos_init(); } };
|
||||||
|
static DynosInitialization sDynosInitialization;
|
||||||
|
|
||||||
|
//
|
||||||
|
// DynOS Actions
|
||||||
|
|
||||||
|
DYNOS_DEFINE_ACTION(dynos_return_to_main_menu);
|
||||||
|
DYNOS_DEFINE_ACTION(dynos_warp_to_level);
|
||||||
|
DYNOS_DEFINE_ACTION(dynos_restart_level);
|
250
src/pc/levels.c
Normal file
250
src/pc/levels.c
Normal file
|
@ -0,0 +1,250 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "levels.h"
|
||||||
|
#define STUB_LEVEL(_0, _1, _2, _3, _4, _5, _6, _7, _8)
|
||||||
|
#define DEFINE_LEVEL(_0, _1, _2, _name, _4, _5, _6, _7, _8, _9, _10) extern const LevelScript level_##_name##_entry[];
|
||||||
|
#include "levels/level_defines.h"
|
||||||
|
#undef DEFINE_LEVEL
|
||||||
|
#undef STUB_LEVEL
|
||||||
|
|
||||||
|
//
|
||||||
|
// Level, Course, Script
|
||||||
|
//
|
||||||
|
|
||||||
|
struct LevelCourseScript {
|
||||||
|
enum LevelNum level;
|
||||||
|
enum CourseNum course;
|
||||||
|
const LevelScript *script;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define STUB_LEVEL(_0, _1, _2, _3, _4, _5, _6, _7, _8)
|
||||||
|
#define DEFINE_LEVEL(_0, _level, _course, _name, _4, _5, _6, _7, _8, _9, _10) { _level, _course, level_##_name##_entry },
|
||||||
|
static const struct LevelCourseScript sLCS[] = {
|
||||||
|
#include "levels/level_defines.h"
|
||||||
|
};
|
||||||
|
#undef DEFINE_LEVEL
|
||||||
|
#undef STUB_LEVEL
|
||||||
|
|
||||||
|
static const LevelScript *lcs_get_script(enum LevelNum levelId) {
|
||||||
|
int lcsCount = (int) (sizeof(sLCS) / sizeof(sLCS[0]));
|
||||||
|
for (int i = 0; i != lcsCount; ++i) {
|
||||||
|
if (sLCS[i].level == levelId) {
|
||||||
|
return sLCS[i].script;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum CourseNum lcs_get_course(enum LevelNum levelId) {
|
||||||
|
int lcsCount = (int) (sizeof(sLCS) / sizeof(sLCS[0]));
|
||||||
|
for (int i = 0; i != lcsCount; ++i) {
|
||||||
|
if (sLCS[i].level == levelId) {
|
||||||
|
return sLCS[i].course;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return COURSE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Course, Name
|
||||||
|
//
|
||||||
|
|
||||||
|
struct CourseName {
|
||||||
|
enum CourseNum course;
|
||||||
|
const char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define _(x) x
|
||||||
|
#define COURSE_ACTS(_course, _name, _2, _3, _4, _5, _6, _7) { _course, _name },
|
||||||
|
#define SECRET_STAR(_course, _name) { _course, _name },
|
||||||
|
#define CASTLE_SECRET_STARS(_0)
|
||||||
|
#define EXTRA_TEXT(_0, _1)
|
||||||
|
static const struct CourseName sCN[] = {
|
||||||
|
#include "text/us/courses.h"
|
||||||
|
};
|
||||||
|
#undef _
|
||||||
|
#undef COURSE_ACTS
|
||||||
|
#undef SECRET_STAR
|
||||||
|
#undef CASTLE_SECRET_STARS
|
||||||
|
#undef EXTRA_TEXT
|
||||||
|
|
||||||
|
static const char *cn_get_name(enum LevelNum levelId) {
|
||||||
|
static const char *sDefault = " CASTLE";
|
||||||
|
static const char *sBowser1 = " BOWSER 1";
|
||||||
|
static const char *sBowser2 = " BOWSER 2";
|
||||||
|
static const char *sBowser3 = " BOWSER 3";
|
||||||
|
if (levelId == LEVEL_BOWSER_1) return sBowser1;
|
||||||
|
if (levelId == LEVEL_BOWSER_2) return sBowser2;
|
||||||
|
if (levelId == LEVEL_BOWSER_3) return sBowser3;
|
||||||
|
int cnCount = (int) (sizeof(sCN) / sizeof(sCN[0]));
|
||||||
|
for (int i = 0; i != cnCount; ++i) {
|
||||||
|
if (sCN[i].course == lcs_get_course(levelId)) {
|
||||||
|
return (strlen(sCN[i].name) > 3 ? sCN[i].name : sDefault);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *level_create_name(const char *cname) {
|
||||||
|
cname += 3; // remove course number
|
||||||
|
int len = (int) strlen(cname);
|
||||||
|
char *name = calloc(len + 1, sizeof(char));
|
||||||
|
memcpy(name, cname, len + 1);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *level_create_name_decapitalized(const char *name) {
|
||||||
|
int len = (int) strlen(name);
|
||||||
|
char *decaps = calloc(len + 1, sizeof(char));
|
||||||
|
memcpy(decaps, name, len + 1);
|
||||||
|
bool wasSpace = true;
|
||||||
|
for (int i = 0; i != len; ++i) {
|
||||||
|
char c = decaps[i];
|
||||||
|
if (c >= 'A' && c <= 'Z') {
|
||||||
|
if (wasSpace) {
|
||||||
|
wasSpace = false;
|
||||||
|
} else {
|
||||||
|
decaps[i] += ('a' - 'A');
|
||||||
|
}
|
||||||
|
} else if (c != '\'') {
|
||||||
|
wasSpace = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return decaps;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Data
|
||||||
|
//
|
||||||
|
|
||||||
|
static int sLevelCount = 0;
|
||||||
|
static int sLevelCountNoCastle = 0;
|
||||||
|
static enum LevelNum *sLevelList = NULL;
|
||||||
|
static enum LevelNum *sLevelListNoCastle = NULL;
|
||||||
|
static enum LevelNum *sLevelListOrdered = NULL;
|
||||||
|
static enum LevelNum *sLevelListOrderedNoCastle = NULL;
|
||||||
|
static const char **sLevelNames = NULL;
|
||||||
|
static const char **sLevelNamesDecaps = NULL;
|
||||||
|
static const LevelScript **sLevelScripts = NULL;
|
||||||
|
static enum CourseNum *sLevelCourses = NULL;
|
||||||
|
|
||||||
|
// Runs only once
|
||||||
|
static void level_init_data() {
|
||||||
|
static bool inited = false;
|
||||||
|
if (!inited) {
|
||||||
|
|
||||||
|
// Level count
|
||||||
|
sLevelCount = (int) sizeof(sLCS) / sizeof(sLCS[0]);
|
||||||
|
|
||||||
|
// Level count (no Castle)
|
||||||
|
sLevelCountNoCastle = 0;
|
||||||
|
for (int i = 0; i != sLevelCount; ++i) {
|
||||||
|
if (sLCS[i].course != COURSE_NONE && sLCS[i].course != COURSE_CAKE_END) {
|
||||||
|
sLevelCountNoCastle++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lists allocation
|
||||||
|
sLevelList = calloc(sLevelCount, sizeof(enum LevelNum));
|
||||||
|
sLevelListNoCastle = calloc(sLevelCountNoCastle, sizeof(enum LevelNum));
|
||||||
|
sLevelListOrdered = calloc(sLevelCount, sizeof(enum LevelNum));
|
||||||
|
sLevelListOrderedNoCastle = calloc(sLevelCountNoCastle, sizeof(enum LevelNum));
|
||||||
|
sLevelNames = calloc(LEVEL_COUNT, sizeof(const char *));
|
||||||
|
sLevelNamesDecaps = calloc(LEVEL_COUNT, sizeof(const char *));
|
||||||
|
sLevelScripts = calloc(LEVEL_COUNT, sizeof(const LevelScript *));
|
||||||
|
sLevelCourses = calloc(LEVEL_COUNT, sizeof(enum CourseNum));
|
||||||
|
|
||||||
|
// Level list
|
||||||
|
for (int i = 0; i != sLevelCount; ++i) {
|
||||||
|
sLevelList[i] = sLCS[i].level;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Level list ordered by course id
|
||||||
|
for (int i = 0, k = 0; i < COURSE_END; ++i) {
|
||||||
|
for (int j = 0; j < sLevelCount; ++j) {
|
||||||
|
if (sLCS[j].course == (enum CourseNum) i) {
|
||||||
|
sLevelListOrdered[k++] = sLCS[j].level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Level list (no Castle)
|
||||||
|
for (int i = 0, k = 0; i != sLevelCount; ++i) {
|
||||||
|
if (sLCS[i].course != COURSE_NONE && sLCS[i].course != COURSE_CAKE_END) {
|
||||||
|
sLevelListNoCastle[k++] = sLCS[i].level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Level list ordered by course id (no Castle)
|
||||||
|
for (int i = 0, k = 0; i < COURSE_END; ++i) {
|
||||||
|
if (i != COURSE_NONE && i != COURSE_CAKE_END) {
|
||||||
|
for (int j = 0; j < sLevelCount; ++j) {
|
||||||
|
if (sLCS[j].course == (enum CourseNum) i) {
|
||||||
|
sLevelListOrderedNoCastle[k++] = sLCS[j].level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Level names
|
||||||
|
for (int i = 0; i != LEVEL_COUNT; ++i) {
|
||||||
|
const char *cname = cn_get_name(i);
|
||||||
|
sLevelNames[i] = level_create_name(cname);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Level names decapitalized
|
||||||
|
for (int i = 0; i != LEVEL_COUNT; ++i) {
|
||||||
|
sLevelNamesDecaps[i] = level_create_name_decapitalized(sLevelNames[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Level scripts
|
||||||
|
for (int i = 0; i != LEVEL_COUNT; ++i) {
|
||||||
|
sLevelScripts[i] = lcs_get_script(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Level courses
|
||||||
|
for (int i = 0; i != LEVEL_COUNT; ++i) {
|
||||||
|
sLevelCourses[i] = lcs_get_course(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Done
|
||||||
|
inited = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Getters
|
||||||
|
//
|
||||||
|
|
||||||
|
int level_get_count(bool noCastle) {
|
||||||
|
level_init_data();
|
||||||
|
return (noCastle ? sLevelCountNoCastle : sLevelCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
const enum LevelNum *level_get_list(bool ordered, bool noCastle) {
|
||||||
|
level_init_data();
|
||||||
|
if (ordered) return (noCastle ? sLevelListOrderedNoCastle : sLevelListOrdered);
|
||||||
|
return (noCastle ? sLevelListNoCastle : sLevelList);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *level_get_name(enum LevelNum levelId) {
|
||||||
|
level_init_data();
|
||||||
|
return sLevelNames[levelId];
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *level_get_name_decapitalized(enum LevelNum levelId) {
|
||||||
|
level_init_data();
|
||||||
|
return sLevelNamesDecaps[levelId];
|
||||||
|
}
|
||||||
|
|
||||||
|
const LevelScript *level_get_script(enum LevelNum levelId) {
|
||||||
|
level_init_data();
|
||||||
|
return sLevelScripts[levelId];
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CourseNum level_get_course(enum LevelNum levelId) {
|
||||||
|
level_init_data();
|
||||||
|
return sLevelCourses[levelId];
|
||||||
|
}
|
||||||
|
|
21
src/pc/levels.h
Normal file
21
src/pc/levels.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef LEVELS_H
|
||||||
|
#define LEVELS_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
This file helps to provide useful info about the game's levels:
|
||||||
|
level list, name, script, and course id.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "types.h"
|
||||||
|
#include "level_table.h"
|
||||||
|
#include "course_table.h"
|
||||||
|
|
||||||
|
int level_get_count(bool noCastle);
|
||||||
|
const enum LevelNum *level_get_list(bool ordered, bool noCastle);
|
||||||
|
const char *level_get_name(enum LevelNum levelId);
|
||||||
|
const char *level_get_name_decapitalized(enum LevelNum levelId);
|
||||||
|
const LevelScript *level_get_script(enum LevelNum levelId);
|
||||||
|
enum CourseNum level_get_course(enum LevelNum levelId);
|
||||||
|
|
||||||
|
#endif // LEVELS_H
|
Loading…
Reference in a new issue