mirror of
https://github.com/perfect-dark-pc-port/perfect_dark.git
synced 2026-10-23 15:52:41 +02:00
port: modconfig: add user defined extended weather config
includes a way to specify weatherproof rooms and other hardcoded stuff this might break something, as it removes some hardcoded checks
This commit is contained in:
1 parent
d98575d77b
commit
704015deac
7 files changed
+517
-69
No files matched your search
+210
-66
@@ -13,6 +13,35 @@
|
||||
extern struct stagemusic g_StageTracks[];
|
||||
extern struct stageallocation g_StageAllocations8Mb[];
|
||||
|
||||
#define PARSE_STAGE_FLOAT(sec, name, v, min, max) \
|
||||
p = modConfigParseFloatValue(p, token, &v); \
|
||||
if (!p || v < (min) || v > (max)) { \
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: " sec " invalid " name " value: %s", stagenum, token); \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
#define PARSE_STAGE_INT(sec, name, v, min, max) \
|
||||
p = modConfigParseIntValue(p, token, &v); \
|
||||
if (!p || v < (min) || v > (max)) { \
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: " sec " invalid " name " value: %s", stagenum, token); \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
#define PARSE_STAGE_FILENAME(sec, name, v) \
|
||||
p = modConfigParseFileValue(p, token, &v); \
|
||||
if (!p) { \
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: " sec " invalid " name " value: %s", stagenum, token); \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
#define PARSE_STAGE_STRING(sec, name, v) \
|
||||
p = strParseToken(p, token, NULL); \
|
||||
if (!p) { \
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: " sec " invalid " name " value: %s", stagenum, token); \
|
||||
return NULL; \
|
||||
} \
|
||||
v = strUnquote(token);
|
||||
|
||||
static inline char *modConfigParseFileValue(char *p, char *token, s32 *filenum)
|
||||
{
|
||||
p = strParseToken(p, token, NULL);
|
||||
@@ -35,7 +64,7 @@ static inline char *modConfigParseFileValue(char *p, char *token, s32 *filenum)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline char *modConfigParseNumericValue(char *p, char *token, s32 *out)
|
||||
static inline char *modConfigParseIntValue(char *p, char *token, s32 *out)
|
||||
{
|
||||
p = strParseToken(p, token, NULL);
|
||||
if (!token[0]) {
|
||||
@@ -50,7 +79,22 @@ static inline char *modConfigParseNumericValue(char *p, char *token, s32 *out)
|
||||
return p;
|
||||
}
|
||||
|
||||
static inline char *modConfigParseStageMusic(char *p, char *token, s32 stagenum)
|
||||
static inline char *modConfigParseFloatValue(char *p, char *token, f32 *out)
|
||||
{
|
||||
p = strParseToken(p, token, NULL);
|
||||
if (!token[0]) {
|
||||
return NULL; // empty
|
||||
}
|
||||
char *endp = token;
|
||||
const f32 num = strtof(token, &endp);
|
||||
if (num == 0.f && (endp == token || *endp != '\0')) {
|
||||
return NULL;
|
||||
}
|
||||
*out = num;
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *modConfigParseStageMusic(char *p, char *token, s32 stagenum)
|
||||
{
|
||||
struct stagemusic *smus = NULL;
|
||||
for (struct stagemusic *p = g_StageTracks; p->stagenum; ++p) {
|
||||
@@ -76,25 +120,13 @@ static inline char *modConfigParseStageMusic(char *p, char *token, s32 stagenum)
|
||||
p = strParseToken(p, token, NULL);
|
||||
while (p && token[0] && strcmp(token, "}") != 0) {
|
||||
if (!strcmp(token, "primarytrack")) {
|
||||
p = modConfigParseNumericValue(p, token, &tmp);
|
||||
if (!p || tmp < 0 || tmp > 128) {
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: music: invalid primarytrack value: %s", stagenum, token);
|
||||
return NULL;
|
||||
}
|
||||
PARSE_STAGE_INT("music:", "primarytrack", tmp, 0, 128);
|
||||
smus->primarytrack = tmp;
|
||||
} else if (!strcmp(token, "ambienttrack")) {
|
||||
p = modConfigParseNumericValue(p, token, &tmp);
|
||||
if (!p || tmp < 0 || tmp > 128) {
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: music: invalid ambienttrack value: %s", stagenum, token);
|
||||
return NULL;
|
||||
}
|
||||
PARSE_STAGE_INT("music:", "ambienttrack", tmp, 0, 128);
|
||||
smus->ambienttrack = tmp;
|
||||
} else if (!strcmp(token, "xtrack")) {
|
||||
p = modConfigParseNumericValue(p, token, &tmp);
|
||||
if (!p || tmp < 0 || tmp > 128) {
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: music: invalid xtrack value: %s", stagenum, token);
|
||||
return NULL;
|
||||
}
|
||||
PARSE_STAGE_INT("music:", "xtrack", tmp, 0, 128);
|
||||
smus->xtrack = tmp;
|
||||
} else {
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: music: invalid key: %s", stagenum, token);
|
||||
@@ -111,7 +143,136 @@ static inline char *modConfigParseStageMusic(char *p, char *token, s32 stagenum)
|
||||
return p;
|
||||
}
|
||||
|
||||
static inline char *modConfigParseStage(char *p, char *token)
|
||||
static char *modConfigParseStageWeatherRooms(char *p, char *token, s32 stagenum, struct weathercfg *wcfg)
|
||||
{
|
||||
// determine where we can start adding rooms
|
||||
s32 idx;
|
||||
for (idx = 0; idx < WEATHERCFG_MAX_SKIPROOMS && wcfg->skiprooms[idx]; ++idx);
|
||||
|
||||
// eat opening bracket
|
||||
p = strParseToken(p, token, NULL);
|
||||
if (token[0] != '{' || token[1] != '\0') {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check if user wants to clear the whole list
|
||||
p = strParseToken(p, token, NULL);
|
||||
if (!strcmp(token, "clear")) {
|
||||
memset(wcfg->skiprooms, 0, sizeof(wcfg->skiprooms));
|
||||
idx = 0;
|
||||
p = strParseToken(p, token, NULL);
|
||||
}
|
||||
|
||||
s32 tmp = 0;
|
||||
while (p && token[0] && strcmp(token, "}") != 0) {
|
||||
if (token[0] == ',' && !token[1]) {
|
||||
p = strParseToken(p, token, NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
tmp = strtol(token, NULL, 0);
|
||||
if (tmp <= 0 || tmp > 32767) {
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: weather: rooms: invalid room %s", stagenum, token);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (idx < WEATHERCFG_MAX_SKIPROOMS) {
|
||||
wcfg->skiprooms[idx++] = tmp;
|
||||
}
|
||||
|
||||
p = strParseToken(p, token, NULL);
|
||||
}
|
||||
|
||||
if (token[0] != '}') {
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: weather: unterminated rooms block", stagenum);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *modConfigParseStageWeather(char *p, char *token, s32 stagenum)
|
||||
{
|
||||
s32 wi;
|
||||
struct weathercfg *wcfg = NULL;
|
||||
for (wi = 0; wi < ARRAYCOUNT(g_WeatherConfig) && g_WeatherConfig[wi].stagenum; ++wi) {
|
||||
if (g_WeatherConfig[wi].stagenum == stagenum) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (wi >= WEATHERCFG_MAX_STAGES) {
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: no more space for weather config", stagenum);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wcfg = &g_WeatherConfig[wi];
|
||||
|
||||
if (!wcfg->stagenum) {
|
||||
// new weather config; initialize with defaults
|
||||
*wcfg = g_DefaultWeatherConfig;
|
||||
wcfg->stagenum = stagenum;
|
||||
} else {
|
||||
// flags have to be re-specified
|
||||
wcfg->flags = 0;
|
||||
}
|
||||
|
||||
// eat opening bracket
|
||||
p = strParseToken(p, token, NULL);
|
||||
if (token[0] != '{' || token[1] != '\0') {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// parse keyvalues until } is reached
|
||||
s32 tmpi = 0;
|
||||
f32 tmpf = 0.f;
|
||||
p = strParseToken(p, token, NULL);
|
||||
while (p && token[0] && strcmp(token, "}") != 0) {
|
||||
if (!strcmp(token, "include_rooms") || !strcmp(token, "exclude_rooms")) {
|
||||
// include_rooms | exclude_rooms { ROOM_NUMBERS... }
|
||||
const s32 include = (token[0] == 'i');
|
||||
p = modConfigParseStageWeatherRooms(p, token, stagenum, wcfg);
|
||||
if (!p) {
|
||||
return NULL;
|
||||
}
|
||||
if (wcfg->skiprooms[0] && include) {
|
||||
wcfg->flags |= WEATHERFLAG_INCLUDE;
|
||||
}
|
||||
} else if (!strcmp(token, "cutscene_only")) {
|
||||
wcfg->flags |= WEATHERFLAG_CUTSCENE_ONLY;
|
||||
} else if (!strcmp(token, "constant_wind")) {
|
||||
PARSE_STAGE_FLOAT("weather:", "constant_wind (0)", wcfg->windanglerad, -M_TAU, M_TAU);
|
||||
PARSE_STAGE_FLOAT("weather:", "constant_wind (1)", wcfg->windspeedx, -1024.f, 1024.f);
|
||||
PARSE_STAGE_FLOAT("weather:", "constant_wind (2)", wcfg->windspeedz, -1024.f, 1024.f);
|
||||
wcfg->flags |= WEATHERFLAG_FORCE_WINDDIR;
|
||||
} else if (!strcmp(token, "windspeed")) {
|
||||
PARSE_STAGE_FLOAT("weather:", "windspeed", tmpf, -1024.f, 1024.f);
|
||||
wcfg->windspeed = tmpf;
|
||||
} else if (!strcmp(token, "ymin")) {
|
||||
PARSE_STAGE_FLOAT("weather:", "ymin", tmpf, -65536.f, 65536.f);
|
||||
wcfg->ymin = tmpf;
|
||||
} else if (!strcmp(token, "ymax")) {
|
||||
PARSE_STAGE_FLOAT("weather:", "ymax", tmpf, -65536.f, 65536.f);
|
||||
wcfg->ymax = tmpf;
|
||||
} else if (!strcmp(token, "zmax")) {
|
||||
PARSE_STAGE_FLOAT("weather:", "zmax", tmpf, -65536.f, 65536.f);
|
||||
wcfg->zmax = tmpf;
|
||||
} else {
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: weather: invalid key: %s", stagenum, token);
|
||||
return NULL;
|
||||
}
|
||||
p = strParseToken(p, token, NULL);
|
||||
}
|
||||
|
||||
if (token[0] != '}') {
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: unterminated weather block", stagenum);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *modConfigParseStage(char *p, char *token)
|
||||
{
|
||||
// stage number
|
||||
p = strParseToken(p, token, NULL);
|
||||
@@ -132,6 +293,9 @@ static inline char *modConfigParseStage(char *p, char *token)
|
||||
const s32 sidx = stageGetIndex(stagenum);
|
||||
if (sidx >= 0) {
|
||||
stab = &g_Stages[sidx];
|
||||
} else {
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: unknown stage number", stagenum);
|
||||
return NULL;
|
||||
}
|
||||
for (struct stageallocation *p = g_StageAllocations8Mb; p->stagenum; ++p) {
|
||||
if (p->stagenum == stagenum) {
|
||||
@@ -142,65 +306,36 @@ static inline char *modConfigParseStage(char *p, char *token)
|
||||
|
||||
// parse keyvalues until } is reached
|
||||
s32 tmp = 0;
|
||||
char *tmps = NULL;
|
||||
p = strParseToken(p, token, NULL);
|
||||
while (p && token[0] && strcmp(token, "}") != 0) {
|
||||
if (!strcmp(token, "bgfile")) {
|
||||
// bg FILE_NAME_OR_NUM
|
||||
p = modConfigParseFileValue(p, token, &tmp);
|
||||
if (p && stab) {
|
||||
stab->bgfileid = tmp;
|
||||
} else {
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: invalid bgfile value: %s", stagenum, token);
|
||||
return NULL;
|
||||
}
|
||||
PARSE_STAGE_FILENAME("", "bgfile", tmp);
|
||||
stab->bgfileid = tmp;
|
||||
} else if (!strcmp(token, "tilesfile")) {
|
||||
// tiles FILE_NAME_OR_NUM
|
||||
p = modConfigParseFileValue(p, token, &tmp);
|
||||
if (p && stab) {
|
||||
stab->tilefileid = tmp;
|
||||
} else {
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: invalid tilesfile value: %s", stagenum, token);
|
||||
return NULL;
|
||||
}
|
||||
// tilesfile FILE_NAME_OR_NUM
|
||||
PARSE_STAGE_FILENAME("", "tilesfile", tmp);
|
||||
stab->tilefileid = tmp;
|
||||
} else if (!strcmp(token, "padsfile")) {
|
||||
// tiles FILE_NAME_OR_NUM
|
||||
p = modConfigParseFileValue(p, token, &tmp);
|
||||
if (p && stab) {
|
||||
stab->padsfileid = tmp;
|
||||
} else {
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: invalid padsfile value: %s", stagenum, token);
|
||||
return NULL;
|
||||
}
|
||||
// padsfile FILE_NAME_OR_NUM
|
||||
PARSE_STAGE_FILENAME("", "padsfile", tmp);
|
||||
stab->padsfileid = tmp;
|
||||
} else if (!strcmp(token, "setupfile")) {
|
||||
// setup FILE_NAME_OR_NUM
|
||||
p = modConfigParseFileValue(p, token, &tmp);
|
||||
if (p && stab) {
|
||||
stab->setupfileid = tmp;
|
||||
} else {
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: invalid setupfile value: %s", stagenum, token);
|
||||
return NULL;
|
||||
}
|
||||
// setupfile FILE_NAME_OR_NUM
|
||||
PARSE_STAGE_FILENAME("", "setupfile", tmp);
|
||||
stab->setupfileid = tmp;
|
||||
} else if (!strcmp(token, "mpsetupfile")) {
|
||||
// mpsetup FILE_NAME_OR_NUM
|
||||
p = modConfigParseFileValue(p, token, &tmp);
|
||||
if (p && stab) {
|
||||
stab->mpsetupfileid = tmp;
|
||||
} else {
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: invalid mpsetupfile value: %s", stagenum, token);
|
||||
return NULL;
|
||||
}
|
||||
// mpsetupfile FILE_NAME_OR_NUM
|
||||
PARSE_STAGE_FILENAME("", "mpsetupfile", tmp);
|
||||
stab->mpsetupfileid = tmp;
|
||||
} else if (!strcmp(token, "allocation")) {
|
||||
// allocation "ALLOCSTRING"
|
||||
p = strParseToken(p, token, NULL);
|
||||
char *str = strUnquote(token);
|
||||
if (!p || !str[0] || !salloc) {
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: invalid allocation value: %s", stagenum, token);
|
||||
return NULL;
|
||||
}
|
||||
PARSE_STAGE_STRING("", "allocation", tmps);
|
||||
// FIXME: this leaks
|
||||
str = strDuplicate(str);
|
||||
if (str) {
|
||||
salloc->string = str;
|
||||
tmps = strDuplicate(tmps);
|
||||
if (tmps) {
|
||||
salloc->string = tmps;
|
||||
}
|
||||
} else if (!strcmp(token, "music")) {
|
||||
// music { KEYVALUES... }
|
||||
@@ -208,6 +343,15 @@ static inline char *modConfigParseStage(char *p, char *token)
|
||||
if (!p) {
|
||||
return NULL;
|
||||
}
|
||||
} else if (!strcmp(token, "weather")) {
|
||||
// weather { KEYVALUES... }
|
||||
p = modConfigParseStageWeather(p, token, stagenum);
|
||||
if (!p) {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
sysLogPrintf(LOG_ERROR, "modconfig: stage 0x%02x: invalid key: %s", stagenum, token);
|
||||
return NULL;
|
||||
}
|
||||
p = strParseToken(p, token, NULL);
|
||||
}
|
||||
|
||||
@@ -1686,6 +1686,9 @@ void bgBuildTables(s32 stagenum)
|
||||
g_Rooms[i].unk4d = 0;
|
||||
g_Rooms[i].lightop = 0;
|
||||
g_Rooms[i].unk4e_04 = 0;
|
||||
#ifndef PLATFORM_N64
|
||||
g_Rooms[i].extra_flags = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bgSetStageTranslationThing(g_Stages[g_StageIndex].unk14);
|
||||
|
||||
+219
-2
@@ -24,6 +24,179 @@
|
||||
|
||||
struct weatherdata *g_WeatherData = NULL;
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
|
||||
struct weathercfg g_WeatherConfig[WEATHERCFG_MAX_STAGES] = {
|
||||
{
|
||||
STAGE_G5BUILDING,
|
||||
WEATHERFLAG_CUTSCENE_ONLY,
|
||||
20.f,
|
||||
-800.f, 800.f,
|
||||
0.f,
|
||||
},
|
||||
{
|
||||
STAGE_CHICAGO,
|
||||
0,
|
||||
20.f,
|
||||
-800.f, 800.f,
|
||||
0.f,
|
||||
{
|
||||
ROOM_PETE_0062,
|
||||
ROOM_PETE_0061,
|
||||
ROOM_PETE_000F,
|
||||
ROOM_PETE_0052,
|
||||
ROOM_PETE_0045,
|
||||
ROOM_PETE_0044,
|
||||
ROOM_PETE_0043,
|
||||
ROOM_PETE_003D,
|
||||
ROOM_PETE_000E,
|
||||
ROOM_PETE_000D,
|
||||
ROOM_PETE_000C,
|
||||
ROOM_PETE_000B,
|
||||
ROOM_PETE_000A,
|
||||
ROOM_PETE_0009,
|
||||
ROOM_PETE_0008,
|
||||
ROOM_PETE_0007,
|
||||
ROOM_PETE_0006,
|
||||
ROOM_PETE_0005,
|
||||
ROOM_PETE_0004,
|
||||
ROOM_PETE_0037,
|
||||
ROOM_PETE_005B,
|
||||
ROOM_PETE_005F,
|
||||
ROOM_PETE_0060,
|
||||
ROOM_PETE_005D,
|
||||
ROOM_PETE_001D,
|
||||
ROOM_PETE_001F,
|
||||
ROOM_PETE_0027,
|
||||
ROOM_PETE_0050,
|
||||
ROOM_PETE_002C,
|
||||
ROOM_PETE_002F,
|
||||
ROOM_PETE_0030,
|
||||
ROOM_PETE_0011,
|
||||
ROOM_PETE_0024,
|
||||
ROOM_PETE_0033,
|
||||
ROOM_PETE_0034,
|
||||
ROOM_PETE_0035,
|
||||
ROOM_PETE_0036,
|
||||
ROOM_PETE_003C,
|
||||
ROOM_PETE_0046,
|
||||
ROOM_PETE_0047,
|
||||
ROOM_PETE_0049,
|
||||
ROOM_PETE_0055,
|
||||
ROOM_PETE_0056,
|
||||
ROOM_PETE_005E,
|
||||
ROOM_PETE_0063,
|
||||
ROOM_PETE_0069,
|
||||
ROOM_PETE_0003,
|
||||
ROOM_PETE_0016,
|
||||
ROOM_PETE_004F,
|
||||
ROOM_PETE_004B,
|
||||
ROOM_PETE_003F,
|
||||
ROOM_PETE_0013,
|
||||
ROOM_PETE_0019,
|
||||
0
|
||||
}
|
||||
},
|
||||
{
|
||||
STAGE_AIRBASE,
|
||||
WEATHERFLAG_INCLUDE | WEATHERFLAG_FORCE_WINDDIR,
|
||||
5.f,
|
||||
-800.f, 800.f,
|
||||
-2000.f,
|
||||
{
|
||||
ROOM_CAVE_0088,
|
||||
ROOM_CAVE_0091,
|
||||
ROOM_CAVE_0087,
|
||||
ROOM_CAVE_0090,
|
||||
ROOM_CAVE_0086,
|
||||
ROOM_CAVE_0080,
|
||||
ROOM_CAVE_0083,
|
||||
ROOM_CAVE_0084,
|
||||
ROOM_CAVE_0085,
|
||||
ROOM_CAVE_007F,
|
||||
ROOM_CAVE_007E,
|
||||
ROOM_CAVE_0082,
|
||||
ROOM_CAVE_008F,
|
||||
ROOM_CAVE_008E,
|
||||
ROOM_CAVE_007B,
|
||||
ROOM_CAVE_007C,
|
||||
ROOM_CAVE_007D,
|
||||
ROOM_CAVE_0081,
|
||||
ROOM_CAVE_006F,
|
||||
0
|
||||
},
|
||||
1.5707963705063f,
|
||||
0.f,
|
||||
-5.f
|
||||
},
|
||||
{
|
||||
STAGE_CRASHSITE,
|
||||
0,
|
||||
10.f,
|
||||
-500.f, 500.f,
|
||||
0.f,
|
||||
{
|
||||
ROOM_AZT_001F,
|
||||
ROOM_AZT_0020,
|
||||
ROOM_AZT_0021,
|
||||
ROOM_AZT_0022,
|
||||
ROOM_AZT_0023,
|
||||
ROOM_AZT_0024,
|
||||
ROOM_AZT_0051,
|
||||
ROOM_AZT_0052,
|
||||
ROOM_AZT_0053,
|
||||
ROOM_AZT_0054,
|
||||
ROOM_AZT_0055,
|
||||
ROOM_AZT_0056,
|
||||
ROOM_AZT_0057,
|
||||
ROOM_AZT_0058,
|
||||
ROOM_AZT_0059,
|
||||
ROOM_AZT_005A,
|
||||
ROOM_AZT_005B,
|
||||
ROOM_AZT_005C,
|
||||
ROOM_AZT_005D,
|
||||
ROOM_AZT_005E,
|
||||
ROOM_AZT_005F,
|
||||
ROOM_AZT_0060,
|
||||
ROOM_AZT_0061,
|
||||
ROOM_AZT_0062,
|
||||
ROOM_AZT_0063,
|
||||
ROOM_AZT_0064,
|
||||
ROOM_AZT_002D,
|
||||
ROOM_AZT_0040,
|
||||
ROOM_AZT_0041,
|
||||
ROOM_AZT_0042,
|
||||
ROOM_AZT_0043,
|
||||
ROOM_AZT_0044,
|
||||
ROOM_AZT_0045,
|
||||
ROOM_AZT_0046,
|
||||
ROOM_AZT_0047,
|
||||
ROOM_AZT_0048,
|
||||
ROOM_AZT_0049,
|
||||
ROOM_AZT_004A,
|
||||
ROOM_AZT_004B,
|
||||
ROOM_AZT_004C,
|
||||
ROOM_AZT_004D,
|
||||
ROOM_AZT_004E,
|
||||
ROOM_AZT_004F,
|
||||
ROOM_AZT_0050,
|
||||
0
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const struct weathercfg g_DefaultWeatherConfig = {
|
||||
0,
|
||||
0,
|
||||
20.f,
|
||||
-800.f, 800.f,
|
||||
0.f
|
||||
};
|
||||
|
||||
const struct weathercfg *g_CurWeatherConfig = &g_DefaultWeatherConfig;
|
||||
|
||||
#endif
|
||||
|
||||
Gfx *weatherRender(Gfx *gdl)
|
||||
{
|
||||
struct weatherdata *weather;
|
||||
@@ -32,6 +205,7 @@ Gfx *weatherRender(Gfx *gdl)
|
||||
return gdl;
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_N64
|
||||
if (g_StageIndex == STAGEINDEX_AIRBASE && g_Vars.currentplayer->cam_pos.z < -2000.0f) {
|
||||
return gdl;
|
||||
}
|
||||
@@ -39,6 +213,15 @@ Gfx *weatherRender(Gfx *gdl)
|
||||
if (g_StageIndex == STAGEINDEX_G5BUILDING && g_Vars.tickmode != TICKMODE_CUTSCENE) {
|
||||
return gdl;
|
||||
}
|
||||
#else
|
||||
if (g_CurWeatherConfig->zmax && g_Vars.currentplayer->cam_pos.z < g_CurWeatherConfig->zmax) {
|
||||
return gdl;
|
||||
}
|
||||
|
||||
if ((g_CurWeatherConfig->flags & WEATHERFLAG_CUTSCENE_ONLY) && g_Vars.tickmode != TICKMODE_CUTSCENE) {
|
||||
return gdl;
|
||||
}
|
||||
#endif
|
||||
|
||||
weather = g_WeatherData;
|
||||
|
||||
@@ -89,11 +272,15 @@ struct weatherparticledata *weatherAllocateParticles(void)
|
||||
|
||||
weatherSetBoundaries(data, 0, -800, 800);
|
||||
|
||||
#ifdef PLATFORM_N64
|
||||
if ((u32)g_StageIndex == STAGEINDEX_CRASHSITE) {
|
||||
weatherSetBoundaries(data, 1, -500, 500);
|
||||
} else {
|
||||
weatherSetBoundaries(data, 1, -800, 800);
|
||||
}
|
||||
#else
|
||||
weatherSetBoundaries(data, 1, g_CurWeatherConfig->ymin, g_CurWeatherConfig->ymax);
|
||||
#endif
|
||||
|
||||
weatherSetBoundaries(data, 2, -800, 800);
|
||||
|
||||
@@ -340,12 +527,22 @@ void weatherTickRain(struct weatherdata *weather)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_N64
|
||||
if (g_StageIndex == STAGEINDEX_AIRBASE) {
|
||||
// Force weather direction - but Air Base doesn't use rain...
|
||||
weather->windanglerad = 1.5707963705063f;
|
||||
weather->windspeedz = -weather->windspeed;
|
||||
weather->windspeedx = 0;
|
||||
} else if (weather->unk10 > 0) {
|
||||
}
|
||||
#else
|
||||
if (g_CurWeatherConfig->flags & WEATHERFLAG_FORCE_WINDDIR) {
|
||||
// force weather direction if requested
|
||||
weather->windanglerad = g_CurWeatherConfig->windanglerad;
|
||||
weather->windspeedz = g_CurWeatherConfig->windspeedz;
|
||||
weather->windspeedx = g_CurWeatherConfig->windspeedx;
|
||||
}
|
||||
#endif
|
||||
else if (weather->unk10 > 0) {
|
||||
s32 lvupdate = g_Vars.lvupdate60;
|
||||
|
||||
if (weather->unk10 < lvupdate) {
|
||||
@@ -437,11 +634,21 @@ void weatherTickSnow(struct weatherdata *weather)
|
||||
mainOverrideVariable("snowspeed", &g_SnowSpeed);
|
||||
mainOverrideVariable("snowspeedxtra", &g_SnowSpeedExtra);
|
||||
|
||||
#ifdef PLATFORM_N64
|
||||
if (g_StageIndex == STAGEINDEX_AIRBASE) {
|
||||
weather->windanglerad = 1.5707963705063f;
|
||||
weather->windspeedz = -weather->windspeed;
|
||||
weather->windspeedx = 0;
|
||||
} else if (weather->unk10 > 0) {
|
||||
}
|
||||
#else
|
||||
if (g_CurWeatherConfig->flags & WEATHERFLAG_FORCE_WINDDIR) {
|
||||
// force weather direction if requested
|
||||
weather->windanglerad = g_CurWeatherConfig->windanglerad;
|
||||
weather->windspeedz = g_CurWeatherConfig->windspeedz;
|
||||
weather->windspeedx = g_CurWeatherConfig->windspeedx;
|
||||
}
|
||||
#endif
|
||||
else if (weather->unk10 > 0) {
|
||||
s32 lvupdate = g_Vars.lvupdate60;
|
||||
|
||||
if (weather->unk10 < lvupdate) {
|
||||
@@ -618,6 +825,7 @@ void weatherConfigureSnow(u32 intensity)
|
||||
|
||||
bool weatherIsRoomWeatherProof(s32 room)
|
||||
{
|
||||
#ifdef PLATFORM_N64
|
||||
if (g_StageIndex == STAGEINDEX_CHICAGO) {
|
||||
// Rooms listed do not have weather
|
||||
if (room == ROOM_PETE_0062
|
||||
@@ -757,6 +965,15 @@ bool weatherIsRoomWeatherProof(s32 room)
|
||||
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if (room >= 0 && room < g_Vars.roomcount) {
|
||||
// check room's extra_flags
|
||||
if (g_Rooms[room].extra_flags & ROOMFLAG_EX_WEATHERPROOF) {
|
||||
// this room has no weather
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
+50
-1
@@ -11,16 +11,59 @@ u32 var800623f4 = 0x00000000;
|
||||
u32 var800623f8 = 0x00000000;
|
||||
u32 var800623fc = 0x00000000;
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
|
||||
static void weatherResetRooms(void)
|
||||
{
|
||||
if (g_CurWeatherConfig->flags & WEATHERFLAG_INCLUDE) {
|
||||
// weather is present only in skiprooms, so mark every room as weatherproof
|
||||
for (s32 i = 0; i < g_Vars.roomcount; ++i) {
|
||||
g_Rooms[i].extra_flags |= ROOMFLAG_EX_WEATHERPROOF;
|
||||
}
|
||||
// then unmark skiprooms
|
||||
for (s32 i = 0; i < WEATHERCFG_MAX_SKIPROOMS && g_CurWeatherConfig->skiprooms[i]; ++i) {
|
||||
const RoomNum room = g_CurWeatherConfig->skiprooms[i];
|
||||
if (room >= 0 && room < g_Vars.roomcount) {
|
||||
g_Rooms[room].extra_flags &= ~ROOMFLAG_EX_WEATHERPROOF;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// weather is present in all rooms except skiprooms
|
||||
for (s32 i = 0; i < WEATHERCFG_MAX_SKIPROOMS && g_CurWeatherConfig->skiprooms[i]; ++i) {
|
||||
const RoomNum room = g_CurWeatherConfig->skiprooms[i];
|
||||
if (room >= 0 && room < g_Vars.roomcount) {
|
||||
g_Rooms[room].extra_flags |= ROOMFLAG_EX_WEATHERPROOF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void weatherReset(void)
|
||||
{
|
||||
g_WeatherActive = false;
|
||||
g_WeatherData = NULL;
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
// find the weather config for this stage, if any
|
||||
g_CurWeatherConfig = &g_DefaultWeatherConfig;
|
||||
for (s32 i = 0; i < ARRAYCOUNT(g_WeatherConfig) && g_WeatherConfig[i].stagenum; ++i) {
|
||||
if (g_WeatherConfig[i].stagenum == g_Stages[g_StageIndex].id) {
|
||||
g_CurWeatherConfig = &g_WeatherConfig[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_CurWeatherConfig != &g_DefaultWeatherConfig)
|
||||
#else
|
||||
if ((g_StageIndex == STAGEINDEX_CHICAGO
|
||||
|| g_StageIndex == STAGEINDEX_AIRBASE
|
||||
|| g_StageIndex == STAGEINDEX_G5BUILDING
|
||||
|| g_StageIndex == STAGEINDEX_CRASHSITE)
|
||||
&& PLAYERCOUNT() < 2) {
|
||||
&& PLAYERCOUNT() < 2)
|
||||
#endif
|
||||
{
|
||||
g_WeatherData = mempAlloc(sizeof(struct weatherdata), MEMPOOL_STAGE);
|
||||
g_WeatherData->particledata[0] = weatherAllocateParticles();
|
||||
g_WeatherData->type = -1;
|
||||
@@ -28,6 +71,7 @@ void weatherReset(void)
|
||||
g_WeatherData->unk0c = 0;
|
||||
g_WeatherData->unk10 = 1;
|
||||
|
||||
#ifdef PLATFORM_N64
|
||||
if (g_StageIndex == STAGEINDEX_CHICAGO || g_StageIndex == STAGEINDEX_G5BUILDING) {
|
||||
g_WeatherData->windspeed = 20;
|
||||
} else if (g_StageIndex == STAGEINDEX_CRASHSITE) {
|
||||
@@ -35,6 +79,11 @@ void weatherReset(void)
|
||||
} else {
|
||||
g_WeatherData->windspeed = 5;
|
||||
}
|
||||
#else
|
||||
g_WeatherData->windspeed = g_CurWeatherConfig->windspeed;
|
||||
// set up the weatherproof flags in all rooms
|
||||
weatherResetRooms();
|
||||
#endif
|
||||
|
||||
g_WeatherData->audiohandles[0] = 0;
|
||||
g_WeatherData->audiohandles[1] = 0;
|
||||
|
||||
@@ -3594,6 +3594,9 @@
|
||||
#define ROOMFLAG_PLAYAMBIENTTRACK 0x4000
|
||||
#define ROOMFLAG_OUTDOORS 0x8000
|
||||
|
||||
// flags for the extra_flags field
|
||||
#define ROOMFLAG_EX_WEATHERPROOF 0x0001
|
||||
|
||||
#define RUMBLESTATE_1 1
|
||||
#define RUMBLESTATE_ENABLED_STOPPED 2
|
||||
#define RUMBLESTATE_ENABLED_STARTING 3
|
||||
@@ -4490,6 +4493,13 @@ enum weaponnum {
|
||||
#define WEATHERTYPE_RAIN 0
|
||||
#define WEATHERTYPE_SNOW 1
|
||||
|
||||
#define WEATHERCFG_MAX_SKIPROOMS 128
|
||||
#define WEATHERCFG_MAX_STAGES 16
|
||||
|
||||
#define WEATHERFLAG_INCLUDE 0x0001 // rooms listed in skiprooms are the only ones that have weather
|
||||
#define WEATHERFLAG_CUTSCENE_ONLY 0x0002 // weather only in cutscenes
|
||||
#define WEATHERFLAG_FORCE_WINDDIR 0x0004 // force constant wind direction
|
||||
|
||||
// Reasons for playing X music
|
||||
#define XREASON_0 0
|
||||
#define XREASON_DEFAULT 1
|
||||
|
||||
@@ -531,6 +531,10 @@ extern struct menudialogdef g_HangarListMenuDialog;
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
|
||||
extern struct weathercfg g_WeatherConfig[WEATHERCFG_MAX_STAGES];
|
||||
extern const struct weathercfg g_DefaultWeatherConfig;
|
||||
extern const struct weathercfg *g_CurWeatherConfig;
|
||||
|
||||
extern f32 g_PlayerCrosshairSway;
|
||||
extern f32 g_PlayerDefaultFovY;
|
||||
extern s32 g_PlayerMouseAimMode;
|
||||
|
||||
@@ -3670,6 +3670,10 @@ struct room {
|
||||
/*0x80*/ s32 gfxdatalen; // when inflated
|
||||
/*0x84*/ struct wallhit *opawallhits; // opaque
|
||||
/*0x88*/ struct wallhit *xluwallhits; // translucent
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
/*0x8c*/ u16 extra_flags;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct fireslotthing {
|
||||
@@ -4892,6 +4896,23 @@ struct weatherparticledata {
|
||||
/*0x3efc*/ u32 unk3efc;
|
||||
};
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
|
||||
struct weathercfg {
|
||||
s32 stagenum;
|
||||
u32 flags;
|
||||
f32 windspeed;
|
||||
f32 ymin;
|
||||
f32 ymax;
|
||||
f32 zmax;
|
||||
RoomNum skiprooms[WEATHERCFG_MAX_SKIPROOMS]; // if flags has WEATHERFLAG_INCLUDE, rooms that have weather, else rooms that don't
|
||||
f32 windanglerad; // wind fields only used if flags has WEATHERFLAG_FORCE_WINDDIR
|
||||
f32 windspeedx;
|
||||
f32 windspeedz;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct texture {
|
||||
u32 soundsurfacetype : 4;
|
||||
u32 surfacetype : 4;
|
||||
|
||||
Reference in new issue
Block a user