diff --git a/README.md b/README.md index 397ba146..c24b0c7c 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ Models support: | ------ | --------------- | ------------ | -------- | --------------------------------------- | | mdl | Quake 1 | 8 bit | Single | Unsupported grouped textures | | md2 | Quake 2 | 8 bit | Single | | +| mda | Anachronox | Part of md2 | Single | No tagged surfaces | | md2 | Anachronox | 8/10/16 bit | Single | No tagged surfaces, unchecked with game | | mdx | Kingpin | 8 bit | Multiple | No sfx support, unchecked with game | | fm | Heretic 2 | 8 bit | Multiple | | diff --git a/src/client/refresh/files/models.c b/src/client/refresh/files/models.c index 35063a46..610fe2f2 100644 --- a/src/client/refresh/files/models.c +++ b/src/client/refresh/files/models.c @@ -29,6 +29,10 @@ #include "models.h" +static void * +Mod_LoadModelFile(const char *mod_name, const void *buffer, int modfilelen, + struct image_s ***skins, int *numskins, readfile_t read_file, modtype_t *type); + /* ================= Mod_LoadSTvertList @@ -2856,6 +2860,80 @@ Mod_LoadModel_SDEF(const char *mod_name, const void *buffer, int modfilelen, return extradata; } +static void * +Mod_LoadModel_MDA_Text(const char *mod_name, char *curr_buff, + readfile_t read_file, struct image_s ***skins, int *numskins, modtype_t *type) +{ + char base_model[MAX_QPATH * 2] = {0}; + + while (curr_buff) + { + const char *token; + + token = COM_Parse(&curr_buff); + if (!*token) + { + continue; + } + + /* found basemodel */ + else if (!strncmp(token, "basemodel", 9)) + { + token = COM_Parse(&curr_buff); + if (!token) + { + return NULL; + } + strncpy(base_model, token, sizeof(base_model) - 1); + /* other fields is unused for now */ + break; + } + } + + if (base_model[0]) + { + void *extradata, *base; + int base_size; + + base_size = read_file(base_model, (void **)&base); + if (base_size <= 0) + { + R_Printf(PRINT_DEVELOPER, "%s: %s No base model for %s\n", + __func__, mod_name, base_model); + return NULL; + } + + /* little bit recursive load */ + extradata = Mod_LoadModelFile(mod_name, base, base_size, + skins, numskins, + read_file, type); + + free(base); + return extradata; + } + + return NULL; +} + +static void * +Mod_LoadModel_MDA(const char *mod_name, const void *buffer, int modfilelen, + readfile_t read_file, struct image_s ***skins, int *numskins, modtype_t *type) +{ + void *extradata; + char *text; + + text = malloc(modfilelen + 1 - 4); + memcpy(text, (char *)buffer + 4, modfilelen - 4); + text[modfilelen - 4] = 0; + + extradata = Mod_LoadModel_MDA_Text(mod_name, text, read_file, skins, + numskins, type); + + free(text); + + return extradata; +} + /* ================= Mod_LoadSprite_SP2 @@ -3037,6 +3115,11 @@ Mod_LoadModelFile(const char *mod_name, const void *buffer, int modfilelen, switch (LittleLong(*(unsigned *)buffer)) { + case MDAHEADER: + extradata = Mod_LoadModel_MDA(mod_name, buffer, modfilelen, + read_file, skins, numskins, type); + break; + case SDEFHEADER: extradata = Mod_LoadModel_SDEF(mod_name, buffer, modfilelen, read_file, skins, numskins, type); diff --git a/src/client/refresh/gl1/gl1_model.c b/src/client/refresh/gl1/gl1_model.c index 550c1303..4204d49c 100644 --- a/src/client/refresh/gl1/gl1_model.c +++ b/src/client/refresh/gl1/gl1_model.c @@ -477,6 +477,8 @@ Mod_ForName(const char *name, model_t *parent_model, qboolean crash) /* call the apropriate loader */ switch (LittleLong(*(unsigned *)buf)) { + case MDAHEADER: + /* fall through */ case SDEFHEADER: /* fall through */ case MDXHEADER: diff --git a/src/client/refresh/gl3/gl3_model.c b/src/client/refresh/gl3/gl3_model.c index 1b81363e..eeba2356 100644 --- a/src/client/refresh/gl3/gl3_model.c +++ b/src/client/refresh/gl3/gl3_model.c @@ -478,6 +478,8 @@ Mod_ForName(const char *name, gl3model_t *parent_model, qboolean crash) /* call the apropriate loader */ switch (LittleLong(*(unsigned *)buf)) { + case MDAHEADER: + /* fall through */ case SDEFHEADER: /* fall through */ case MDXHEADER: diff --git a/src/client/refresh/gl4/gl4_model.c b/src/client/refresh/gl4/gl4_model.c index 1ca12637..87357b7c 100644 --- a/src/client/refresh/gl4/gl4_model.c +++ b/src/client/refresh/gl4/gl4_model.c @@ -478,6 +478,8 @@ Mod_ForName(const char *name, gl4model_t *parent_model, qboolean crash) /* call the apropriate loader */ switch (LittleLong(*(unsigned *)buf)) { + case MDAHEADER: + /* fall through */ case SDEFHEADER: /* fall through */ case MDXHEADER: diff --git a/src/client/refresh/soft/sw_model.c b/src/client/refresh/soft/sw_model.c index a0ef20a4..aa249682 100644 --- a/src/client/refresh/soft/sw_model.c +++ b/src/client/refresh/soft/sw_model.c @@ -485,6 +485,8 @@ Mod_ForName(const char *name, model_t *parent_model, qboolean crash) /* call the apropriate loader */ switch (LittleLong(*(unsigned *)buf)) { + case MDAHEADER: + /* fall through */ case SDEFHEADER: /* fall through */ case MDXHEADER: diff --git a/src/client/refresh/vk/vk_model.c b/src/client/refresh/vk/vk_model.c index ba581b19..27710c8e 100644 --- a/src/client/refresh/vk/vk_model.c +++ b/src/client/refresh/vk/vk_model.c @@ -461,6 +461,8 @@ Mod_ForName(const char *name, model_t *parent_model, qboolean crash) /* call the apropriate loader */ switch (LittleLong(*(unsigned *)buf)) { + case MDAHEADER: + /* fall through */ case SDEFHEADER: /* fall through */ case MDXHEADER: diff --git a/src/common/header/files.h b/src/common/header/files.h index 079809eb..1fac939b 100644 --- a/src/common/header/files.h +++ b/src/common/header/files.h @@ -224,6 +224,7 @@ typedef struct /* .MD2 Anachronox triangle model file format */ +#define MDAHEADER (('1' << 24) + ('A' << 16) + ('D' << 8) + 'M') #define ALIAS_ANACHRONOX_VERSION 15 typedef struct diff --git a/src/game/g_spawn.c b/src/game/g_spawn.c index a3d5bdd2..0385ecf0 100644 --- a/src/game/g_spawn.c +++ b/src/game/g_spawn.c @@ -75,7 +75,7 @@ DynamicSpawn(edict_t *self, dynamicentity_t *data) { self->movetype = MOVETYPE_NONE; self->solid = SOLID_BBOX; - self->s.modelindex = gi.modelindex(""/*data->model_path*/); + self->s.modelindex = gi.modelindex(data->model_path); VectorCopy(data->mins, self->mins); VectorCopy(data->maxs, self->maxs); @@ -1810,8 +1810,14 @@ DynamicSpawnInit(void) break; } + /* skip empty */ + linesize = strspn(curr, "\n\r\t "); + curr += linesize; + + /* mark end line */ linesize = strcspn(curr, "\n\r"); curr[linesize] = 0; + if (*curr && strncmp(curr, "//", 2) && *curr != '\n' && *curr != '\r' && *curr != ';') {