From 4da6169892eabdaa5b3b69410fe142d057da7165 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Fri, 25 Aug 2017 18:00:20 +0100 Subject: [PATCH 1/5] Add spr2defaults[] array to make sprite2 defaulting system much, much simpler to manage. This is in preparation for a seperate project which still involves sprite2s. --- src/dehacked.c | 80 +++++++++++++++++++++++++-- src/info.c | 83 +++++++++++++++++++++++++++- src/info.h | 7 ++- src/lua_baselib.c | 2 + src/lua_infolib.c | 81 +++++++++++++++++++++++++++ src/r_things.c | 136 +++------------------------------------------- 6 files changed, 251 insertions(+), 138 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 719476543..cdfbc5e22 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -64,6 +64,7 @@ memset(used_spr,0,sizeof(UINT8) * ((NUMSPRITEFREESLOTS / 8) + 1));\ static mobjtype_t get_mobjtype(const char *word); static statenum_t get_state(const char *word); static spritenum_t get_sprite(const char *word); +static playersprite_t get_sprite2(const char *word); static sfxenum_t get_sfx(const char *word); #ifdef MUSICSLOT_COMPATIBILITY static UINT16 get_mus(const char *word, UINT8 dehacked_mode); @@ -769,6 +770,49 @@ static void readspritelight(MYFILE *f, INT32 num) } #endif // HWRENDER +static void readsprite2(MYFILE *f, INT32 num) +{ + char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); + char *word, *word2; + char *tmp; + + do + { + if (myfgets(s, MAXLINELEN, f)) + { + if (s[0] == '\n') + break; + + tmp = strchr(s, '#'); + if (tmp) + *tmp = '\0'; + if (s == tmp) + continue; // Skip comment lines, but don't break. + + word = strtok(s, " "); + if (word) + strupr(word); + else + break; + + word2 = strtok(NULL, " = "); + if (word2) + strupr(word2); + else + break; + if (word2[strlen(word2)-1] == '\n') + word2[strlen(word2)-1] = '\0'; + + if (fastcmp(word, "DEFAULT")) + spr2defaults[num] = get_number(word2); + else + deh_warning("Sprite2 %s: unknown word '%s'", spr2names[num], word); + } + } while (!myfeof(f)); // finish when the line is empty + + Z_Free(s); +} + static const struct { const char *name; const UINT16 flag; @@ -3020,9 +3064,21 @@ static void DEH_LoadDehackedFile(MYFILE *f) ignorelines(f); } } + else if (fastcmp(word, "SPRITE2")) + { + if (i == 0 && word2[0] != '0') // If word2 isn't a number + i = get_sprite2(word2); // find a sprite by name + if (i < (INT32)free_spr2 && i >= (INT32)SPR2_FIRSTFREESLOT) + readsprite2(f, i); + else + { + deh_warning("Sprite2 number %d out of range (%d - %d)", i, SPR2_FIRSTFREESLOT, free_spr2-1); + ignorelines(f); + } + } +#ifdef HWRENDER else if (fastcmp(word, "LIGHT")) { -#ifdef HWRENDER // TODO: Read lights by name if (i > 0 && i < NUMLIGHTS) readlight(f, i); @@ -3031,22 +3087,20 @@ static void DEH_LoadDehackedFile(MYFILE *f) deh_warning("Light number %d out of range (1 - %d)", i, NUMLIGHTS-1); ignorelines(f); } -#endif } else if (fastcmp(word, "SPRITE")) { -#ifdef HWRENDER if (i == 0 && word2[0] != '0') // If word2 isn't a number i = get_sprite(word2); // find a sprite by name - if (i < NUMSPRITES && i >= 0) + if (i < NUMSPRITES && i > 0) readspritelight(f, i); else { deh_warning("Sprite number %d out of range (0 - %d)", i, NUMSPRITES-1); ignorelines(f); } -#endif } +#endif else if (fastcmp(word, "LEVEL")) { // Support using the actual map name, @@ -7290,6 +7344,20 @@ static spritenum_t get_sprite(const char *word) return SPR_NULL; } +static playersprite_t get_sprite2(const char *word) +{ // Returns the value of SPR2_ enumerations + playersprite_t i; + if (*word >= '0' && *word <= '9') + return atoi(word); + if (fastncmp("SPR2_",word,5)) + word += 5; // take off the SPR2_ + for (i = 0; i < NUMPLAYERSPRITES; i++) + if (!spr2names[i][4] && memcmp(word,spr2names[i],4)==0) + return i; + deh_warning("Couldn't find sprite named 'SPR2_%s'",word); + return SPR2_STND; +} + static sfxenum_t get_sfx(const char *word) { // Returns the value of SFX_ enumerations sfxenum_t i; @@ -7735,7 +7803,7 @@ static inline int lib_freeslot(lua_State *L) else if (fastcmp(type, "SPR2")) { // Search if we already have an SPR2 by that name... - enum playersprite i; + playersprite_t i; for (i = SPR2_FIRSTFREESLOT; i < free_spr2; i++) if (memcmp(spr2names[i],word,4) == 0) break; diff --git a/src/info.c b/src/info.c index 2d6c9a3d1..dc774bb9c 100644 --- a/src/info.c +++ b/src/info.c @@ -481,7 +481,88 @@ char spr2names[NUMPLAYERSPRITES][5] = "SIGN", "LIFE" }; -enum playersprite free_spr2 = SPR2_FIRSTFREESLOT; +playersprite_t free_spr2 = SPR2_FIRSTFREESLOT; + +playersprite_t spr2defaults[NUMPLAYERSPRITES] = { + 0, // SPR2_STND, + 0, // SPR2_WAIT, + 0, // SPR2_WALK, + SPR2_WALK, // SPR2_RUN , + SPR2_FRUN, // SPR2_DASH, + 0, // SPR2_PAIN, + SPR2_PAIN, // SPR2_STUN, + 0, // SPR2_DEAD, + SPR2_DEAD, // SPR2_DRWN, + 0, // SPR2_ROLL, + SPR2_SPNG, // SPR2_GASP, + 0, // SPR2_JUMP, (conditional) + SPR2_FALL, // SPR2_SPNG, + SPR2_WALK, // SPR2_FALL, + 0, // SPR2_EDGE, + SPR2_FALL, // SPR2_RIDE, + + SPR2_ROLL, // SPR2_SPIN, + + SPR2_SPNG, // SPR2_FLY , + SPR2_FLY , // SPR2_SWIM, + 0, // SPR2_TIRE, (conditional) + + SPR2_FLY , // SPR2_GLID, + SPR2_CLMB, // SPR2_CLNG, + SPR2_ROLL, // SPR2_CLMB, + + SPR2_WALK, // SPR2_FLT , + SPR2_RUN , // SPR2_FRUN, + + SPR2_FALL, // SPR2_BNCE, + SPR2_ROLL, // SPR2_BLND, + + 0, // SPR2_FIRE, + + SPR2_ROLL, // SPR2_TWIN, + + SPR2_TWIN, // SPR2_MLEE, + 0, // SPR2_MLEL, + + 0, // SPR2_TRNS, + + 0, // SPR2_NSTD, + 0, // SPR2_NFLT, + 0, // SPR2_NSTN, + SPR2_NSTN, // SPR2_NPUL, + 0, // SPR2_NATK, + + 0, // SPR2_NGT0, (should never be referenced) + SPR2_NGT0, // SPR2_NGT1, + SPR2_NGT1, // SPR2_NGT2, + SPR2_NGT2, // SPR2_NGT3, + SPR2_NGT3, // SPR2_NGT4, + SPR2_NGT4, // SPR2_NGT5, + SPR2_NGT5, // SPR2_NGT6, + SPR2_NGT0, // SPR2_NGT7, + SPR2_NGT7, // SPR2_NGT8, + SPR2_NGT8, // SPR2_NGT9, + SPR2_NGT9, // SPR2_NGTA, + SPR2_NGTA, // SPR2_NGTB, + SPR2_NGTB, // SPR2_NGTC, + + SPR2_NGT0, // SPR2_DRL0, + SPR2_NGT1, // SPR2_DRL1, + SPR2_NGT2, // SPR2_DRL2, + SPR2_NGT3, // SPR2_DRL3, + SPR2_NGT4, // SPR2_DRL4, + SPR2_NGT5, // SPR2_DRL5, + SPR2_NGT6, // SPR2_DRL6, + SPR2_NGT7, // SPR2_DRL7, + SPR2_NGT8, // SPR2_DRL8, + SPR2_NGT9, // SPR2_DRL9, + SPR2_NGTA, // SPR2_DRLA, + SPR2_NGTB, // SPR2_DRLB, + SPR2_NGTC, // SPR2_DRLC, + + 0, // SPR2_SIGN, + 0, // SPR2_LIFE +}; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) state_t states[NUMSTATES] = diff --git a/src/info.h b/src/info.h index cd79b12a9..4ae5fcf63 100644 --- a/src/info.h +++ b/src/info.h @@ -604,7 +604,7 @@ typedef enum sprite // Make sure to be conscious of FF_FRAMEMASK and the fact sprite2 is stored as a UINT8 whenever you change this table. // Currently, FF_FRAMEMASK is 0xff, or 255 - but the second half is used by FF_SPR2SUPER, so the limitation is 0x7f. // Since this is zero-based, there can be at most 128 different SPR2_'s without changing that. -enum playersprite +typedef enum playersprite { SPR2_STND = 0, SPR2_WAIT, @@ -690,7 +690,7 @@ enum playersprite SPR2_FIRSTFREESLOT, SPR2_LASTFREESLOT = 0x7f, NUMPLAYERSPRITES -}; +} playersprite_t; typedef enum state { @@ -3193,8 +3193,9 @@ typedef struct extern state_t states[NUMSTATES]; extern char sprnames[NUMSPRITES + 1][5]; extern char spr2names[NUMPLAYERSPRITES][5]; +extern playersprite_t spr2defaults[NUMPLAYERSPRITES]; extern state_t *astate; -extern enum playersprite free_spr2; +extern playersprite_t free_spr2; typedef enum mobj_type { diff --git a/src/lua_baselib.c b/src/lua_baselib.c index be1455415..b88a9712e 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -462,6 +462,8 @@ static int lib_pSpawnLockOn(lua_State *L) return LUA_ErrInvalid(L, "mobj_t"); if (!player) return LUA_ErrInvalid(L, "player_t"); + if (state >= NUMSTATES) + return luaL_error(L, "state %d out of range (0 - %d)", state, NUMSTATES-1); if (P_IsLocalPlayer(player)) // Only display it on your own view. { mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 9361abe94..c3803f7e2 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -127,6 +127,74 @@ static int lib_getSpr2name(lua_State *L) return 0; } +static int lib_getSpr2default(lua_State *L) +{ + UINT32 i; + + lua_remove(L, 1); // don't care about spr2defaults[] dummy userdata. + + if (lua_isnumber(L, 1)) + i = lua_tonumber(L, 1); + else if (lua_isstring(L, 1)) + { + const char *name = lua_tostring(L, 1); + for (i = 0; i < free_spr2; i++) + if (fastcmp(name, spr2names[i])) + break; + } + else + return luaL_error(L, "spr2defaults[] invalid index"); + + if (i >= free_spr2) + return 0; + + lua_pushinteger(L, spr2defaults[i]); + return 1; +} + +static int lib_setSpr2default(lua_State *L) +{ + UINT32 i; + UINT8 j = 0; + + lua_remove(L, 1); // don't care about spr2defaults[] dummy userdata. + + if (lua_isnumber(L, 1)) + i = lua_tonumber(L, 1); + else if (lua_isstring(L, 1)) + { + const char *name = lua_tostring(L, 1); + for (i = 0; i < free_spr2; i++) + if (fastcmp(name, spr2names[i])) + break; + if (i == free_spr2) + return luaL_error(L, "spr2defaults[] invalid index"); + } + else + return luaL_error(L, "spr2defaults[] invalid index"); + + if (i < SPR2_FIRSTFREESLOT || i >= free_spr2) + return luaL_error(L, "spr2defaults[] index %d out of range (%d - %d)", i, SPR2_FIRSTFREESLOT, free_spr2-1); + + if (lua_isnumber(L, 2)) + j = lua_tonumber(L, 2); + else if (lua_isstring(L, 2)) + { + const char *name = lua_tostring(L, 2); + for (j = 0; j < free_spr2; j++) + if (fastcmp(name, spr2names[j])) + break; + if (j == free_spr2) + return luaL_error(L, "spr2defaults[] invalid index"); + } + + if (j >= free_spr2) + j = 0; // return luaL_error(L, "spr2defaults[] set %d out of range (%d - %d)", j, 0, free_spr2-1); + + spr2defaults[i] = j; + return 0; +} + static int lib_spr2namelen(lua_State *L) { lua_pushinteger(L, free_spr2); @@ -984,6 +1052,19 @@ int LUA_InfoLib(lua_State *L) lua_setmetatable(L, -2); lua_setglobal(L, "spr2names"); + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getSpr2default); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_setSpr2default); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, lib_spr2namelen); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "spr2defaults"); + lua_newuserdata(L, 0); lua_createtable(L, 0, 2); lua_pushcfunction(L, lib_getState); diff --git a/src/r_things.c b/src/r_things.c index b2437d4ac..ebec4a14a 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2431,13 +2431,14 @@ CV_PossibleValue_t skin_cons_t[MAXSKINS+1]; UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) { - UINT8 super = (spr2 & FF_SPR2SUPER); + UINT8 super = (spr2 & FF_SPR2SUPER), i = 0; if (!skin) return 0; while (!(skin->sprites[spr2].numframes) - && spr2 != SPR2_STND) + && spr2 != SPR2_STND + && ++i != 32) // recursion limiter { if (spr2 & FF_SPR2SUPER) { @@ -2447,83 +2448,18 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) switch(spr2) { - case SPR2_RUN: - spr2 = SPR2_WALK; - break; - case SPR2_STUN: - spr2 = SPR2_PAIN; - break; - case SPR2_DRWN: - spr2 = SPR2_DEAD; - break; - case SPR2_SPIN: - spr2 = SPR2_ROLL; - break; - case SPR2_GASP: - spr2 = SPR2_SPNG; - break; + + // Normal special cases. case SPR2_JUMP: spr2 = ((player ? player->charflags : skin->flags) & SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_ROLL; break; - case SPR2_SPNG: // spring - spr2 = SPR2_FALL; - break; - case SPR2_FALL: - spr2 = SPR2_WALK; - break; - case SPR2_RIDE: - spr2 = SPR2_FALL; - break; - - case SPR2_FLY : - spr2 = SPR2_SPNG; - break; - case SPR2_SWIM: - spr2 = SPR2_FLY ; - break; case SPR2_TIRE: spr2 = (player && player->charability == CA_SWIM) ? SPR2_SWIM : SPR2_FLY; break; - case SPR2_GLID: - spr2 = SPR2_FLY; - break; - case SPR2_CLMB: - spr2 = SPR2_ROLL; - break; - case SPR2_CLNG: - spr2 = SPR2_CLMB; - break; - - case SPR2_FLT : - spr2 = SPR2_WALK; - break; - case SPR2_FRUN: - spr2 = SPR2_RUN ; - break; - - case SPR2_DASH: - spr2 = SPR2_FRUN; - break; - - case SPR2_BNCE: - spr2 = SPR2_FALL; - break; - case SPR2_BLND: - spr2 = SPR2_ROLL; - break; - - case SPR2_TWIN: - spr2 = SPR2_ROLL; - break; - - case SPR2_MLEE: - spr2 = SPR2_TWIN; - break; - // NiGHTS sprites. case SPR2_NSTD: spr2 = SPR2_STND; @@ -2535,72 +2471,16 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) break; case SPR2_NSTN: spr2 = SPR2_STUN; - break; - case SPR2_NPUL: - spr2 = SPR2_NSTN; + super = FF_SPR2SUPER; break; case SPR2_NATK: spr2 = SPR2_ROLL; super = FF_SPR2SUPER; break; - /*case SPR2_NGT0: - spr2 = SPR2_NFLT; - break;*/ - case SPR2_NGT1: - case SPR2_NGT7: - case SPR2_DRL0: - spr2 = SPR2_NGT0; - break; - case SPR2_NGT2: - case SPR2_DRL1: - spr2 = SPR2_NGT1; - break; - case SPR2_NGT3: - case SPR2_DRL2: - spr2 = SPR2_NGT2; - break; - case SPR2_NGT4: - case SPR2_DRL3: - spr2 = SPR2_NGT3; - break; - case SPR2_NGT5: - case SPR2_DRL4: - spr2 = SPR2_NGT4; - break; - case SPR2_NGT6: - case SPR2_DRL5: - spr2 = SPR2_NGT5; - break; - case SPR2_DRL6: - spr2 = SPR2_NGT6; - break; - case SPR2_NGT8: - case SPR2_DRL7: - spr2 = SPR2_NGT7; - break; - case SPR2_NGT9: - case SPR2_DRL8: - spr2 = SPR2_NGT8; - break; - case SPR2_NGTA: - case SPR2_DRL9: - spr2 = SPR2_NGT9; - break; - case SPR2_NGTB: - case SPR2_DRLA: - spr2 = SPR2_NGTA; - break; - case SPR2_NGTC: - case SPR2_DRLB: - spr2 = SPR2_NGTB; - break; - case SPR2_DRLC: - spr2 = SPR2_NGTC; - break; - // Dunno? Just go to standing then. + // Use the handy list, that's what it's there for! default: - spr2 = SPR2_STND; + spr2 = spr2defaults[spr2]; break; } From 76300026f823291ac1d5f1457c7a8c739d4373a1 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 26 Aug 2017 18:56:23 +0100 Subject: [PATCH 2/5] * Added support for sprite2s to MD2s! - Name each frame either SPR2_**** or SUPER**** (where **** is the 4-character name) - If the name is 3 characters, '.' is accepted as a substitute for the '_', but a space/absent isn't (for tool-related reasons). - Adds a big sprite2 index array to all models, even non-player ones. Sorry! * Made MD2 frame interpoleration only work across the same spriteset (and sprite2set). * Made MD2 frame interpoleration happen when there's less than a quarter of a second between frames, as opposed to the hardcoded specific animation disabling. * Fixed sprite2-related typo in dehacked.c. --- src/dehacked.c | 2 +- src/hardware/hw_md2.c | 141 ++++++++++++++++++++++++++++++++++++------ src/hardware/hw_md2.h | 4 +- src/info.c | 8 +-- src/r_things.c | 21 +------ 5 files changed, 133 insertions(+), 43 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index cdfbc5e22..385411748 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7982,7 +7982,7 @@ static inline int lib_getenum(lua_State *L) if (mathlib) return luaL_error(L, "sprite '%s' could not be found.\n", word); return 0; } - else if (fastncmp("SPR2_",word,4)) { + else if (fastncmp("SPR2_",word,5)) { p = word+5; for (i = 0; i < (fixed_t)free_spr2; i++) if (!spr2names[i][4]) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index df2c9f59a..14879b2b7 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -28,6 +28,7 @@ #include "../doomdef.h" #include "../doomstat.h" +#include "../fastcmp.h" #ifdef HWRENDER #include "hw_drv.h" @@ -395,6 +396,29 @@ static md2_model_t *md2_readModel(const char *filename) } strcpy(model->frames[i].name, frame->name); + if (frame->name[0] == 'S') + { + boolean super; + if ((super = (fastncmp("UPER", frame->name+1, 4))) // SUPER + || fastncmp("PR2_", frame->name+1, 4)) // SPR2_ + { + UINT8 spr2; + for (spr2 = 0; spr2 < free_spr2; spr2++) + if (fastncmp(frame->name+5,spr2names[spr2],3) + && ((frame->name[8] == spr2names[spr2][3]) + || (frame->name[8] == '.' && spr2names[spr2][3] == '_'))) + break; + + if (spr2 < free_spr2) + { + if (super) + spr2 |= FF_SPR2SUPER; + if (model->spr2frames[spr2][1]++ == 0) // numspr2frames + model->spr2frames[spr2][0] = i; // starting frame + CONS_Debug(DBG_RENDER, "frame %s, sprite2 %s - starting frame %d, number of frames %d\n", frame->name, spr2names[spr2 & ~FF_SPR2SUPER], model->spr2frames[spr2][0], model->spr2frames[spr2][1]); + } + } + } for (j = 0; j < model->header.numVertices; j++) { model->frames[i].vertices[j].vertex[0] = (float) ((INT32) frame->alias_vertices[j].vertex[0]) * frame->scale[0] + frame->translate[0]; @@ -1078,6 +1102,51 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, con res? run? */ + +static UINT8 P_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *player) +{ + UINT8 super = 0, i = 0; + + if (!md2 || !skin) + return 0; + + while (!(md2->model->spr2frames[spr2][1]) + && spr2 != SPR2_STND + && ++i != 32) // recursion limiter + { + if (spr2 & FF_SPR2SUPER) + { + super = FF_SPR2SUPER; + spr2 &= ~FF_SPR2SUPER; + continue; + } + + switch(spr2) + { + + // Normal special cases. + case SPR2_JUMP: + spr2 = ((player + ? player->charflags + : skin->flags) + & SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_ROLL; + break; + case SPR2_TIRE: + spr2 = (player && player->charability == CA_SWIM) ? SPR2_SWIM : SPR2_FLY; + break; + + // Use the handy list, that's what it's there for! + default: + spr2 = spr2defaults[spr2]; + break; + } + + spr2 |= super; + } + + return spr2; +} + #define NORMALFOG 0x00000000 #define FADEFOG 0x19000000 void HWR_DrawMD2(gr_vissprite_t *spr) @@ -1225,31 +1294,67 @@ void HWR_DrawMD2(gr_vissprite_t *spr) tics = spr->mobj->anim_duration; } - //FIXME: this is not yet correct - frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->header.numFrames; - buff = md2->model->glCommandBuffer; - curr = &md2->model->frames[frame]; - if (cv_grmd2.value == 1) +#define INTERPOLERATION_LIMIT TICRATE/4 + + if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { - // frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation - if (spr->mobj->frame & FF_ANIMATE) + UINT8 spr2 = P_GetModelSprite2(md2, spr->mobj->skin, spr->mobj->sprite2, spr->mobj->player); + UINT8 mod = md2->model->spr2frames[spr2][1] ? md2->model->spr2frames[spr2][1] : md2->model->header.numFrames; + //FIXME: this is not yet correct + frame = md2->model->spr2frames[spr2][0] + ((spr->mobj->frame & FF_FRAMEMASK) % mod); + buff = md2->model->glCommandBuffer; + curr = &md2->model->frames[frame]; + if (cv_grmd2.value == 1 && tics <= INTERPOLERATION_LIMIT) { - UINT32 nextframe = (spr->mobj->frame & FF_FRAMEMASK) + 1; - if (nextframe >= (UINT32)spr->mobj->state->var1) - nextframe = (spr->mobj->state->frame & FF_FRAMEMASK); - nextframe %= md2->model->header.numFrames; - next = &md2->model->frames[nextframe]; - } - else - { - if (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL - && !(spr->mobj->player && spr->mobj->state->nextstate == S_PLAY_WAIT && spr->mobj->state == &states[S_PLAY_STND])) + if (durs > INTERPOLERATION_LIMIT) + durs = INTERPOLERATION_LIMIT; + + if (spr->mobj->frame & FF_ANIMATE + || (spr->mobj->state->nextstate != S_NULL + && states[spr->mobj->state->nextstate].sprite == spr->mobj->sprite + && (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) == spr->mobj->sprite2)) { - const UINT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames; + UINT32 nextframe = (spr->mobj->frame & FF_FRAMEMASK) + 1; + if (nextframe >= (UINT32)((skin_t*)spr->mobj->skin)->sprites[spr->mobj->sprite2].numframes) + nextframe = 0; + nextframe = md2->model->spr2frames[spr2][0] + (nextframe % md2->model->spr2frames[spr2][1]); next = &md2->model->frames[nextframe]; } } } + else + { + //FIXME: this is not yet correct + frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->header.numFrames; + buff = md2->model->glCommandBuffer; + curr = &md2->model->frames[frame]; + if (cv_grmd2.value == 1 && tics <= INTERPOLERATION_LIMIT) + { + if (durs > INTERPOLERATION_LIMIT) + durs = INTERPOLERATION_LIMIT; + + // frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation + if (spr->mobj->frame & FF_ANIMATE) + { + UINT32 nextframe = (spr->mobj->frame & FF_FRAMEMASK) + 1; + if (nextframe >= (UINT32)spr->mobj->state->var1) + nextframe = (spr->mobj->state->frame & FF_FRAMEMASK); + nextframe %= md2->model->header.numFrames; + next = &md2->model->frames[nextframe]; + } + else + { + if (spr->mobj->state->nextstate != S_NULL + && states[spr->mobj->state->nextstate].sprite == spr->mobj->sprite) + { + const UINT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames; + next = &md2->model->frames[nextframe]; + } + } + } + } + +#undef INTERPOLERATION_LIMIT //Hurdler: it seems there is still a small problem with mobj angle p.x = FIXED_TO_FLOAT(spr->mobj->x); diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index 299d12400..b183e4367 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -22,6 +22,7 @@ #define _HW_MD2_H_ #include "hw_glob.h" +#include "../info.h" // magic number "IDP2" or 844121161 #define MD2_IDENT (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I') @@ -111,7 +112,8 @@ typedef struct md2_textureCoordinate_t *texCoords; md2_triangle_t *triangles; md2_frame_t *frames; - INT32 *glCommandBuffer; + size_t spr2frames[2*NUMPLAYERSPRITES][2]; + INT32 *glCommandBuffer; } ATTRPACK md2_model_t; #if defined(_MSC_VER) diff --git a/src/info.c b/src/info.c index dc774bb9c..c8bea7803 100644 --- a/src/info.c +++ b/src/info.c @@ -526,11 +526,11 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { 0, // SPR2_TRNS, - 0, // SPR2_NSTD, - 0, // SPR2_NFLT, - 0, // SPR2_NSTN, + FF_SPR2SUPER|SPR2_STND, // SPR2_NSTD, + FF_SPR2SUPER|SPR2_FLT , // SPR2_NFLT, + FF_SPR2SUPER|SPR2_STUN, // SPR2_NSTN, SPR2_NSTN, // SPR2_NPUL, - 0, // SPR2_NATK, + FF_SPR2SUPER|SPR2_ROLL, // SPR2_NATK, 0, // SPR2_NGT0, (should never be referenced) SPR2_NGT0, // SPR2_NGT1, diff --git a/src/r_things.c b/src/r_things.c index ebec4a14a..67aa4e585 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2431,7 +2431,7 @@ CV_PossibleValue_t skin_cons_t[MAXSKINS+1]; UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) { - UINT8 super = (spr2 & FF_SPR2SUPER), i = 0; + UINT8 super = 0, i = 0; if (!skin) return 0; @@ -2442,6 +2442,7 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) { if (spr2 & FF_SPR2SUPER) { + super = FF_SPR2SUPER; spr2 &= ~FF_SPR2SUPER; continue; } @@ -2460,24 +2461,6 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) spr2 = (player && player->charability == CA_SWIM) ? SPR2_SWIM : SPR2_FLY; break; - // NiGHTS sprites. - case SPR2_NSTD: - spr2 = SPR2_STND; - super = FF_SPR2SUPER; - break; - case SPR2_NFLT: - spr2 = SPR2_FLT ; - super = FF_SPR2SUPER; - break; - case SPR2_NSTN: - spr2 = SPR2_STUN; - super = FF_SPR2SUPER; - break; - case SPR2_NATK: - spr2 = SPR2_ROLL; - super = FF_SPR2SUPER; - break; - // Use the handy list, that's what it's there for! default: spr2 = spr2defaults[spr2]; From 973f700dcf27dfa769e613de52e1d2fae74e7968 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sun, 27 Aug 2017 14:56:07 +0100 Subject: [PATCH 3/5] * Make the model->spr2frames dynamically allocated. (There's only two settings - on and off - but that's better than it perpetually being on...) * Fix up defaulting for DEAD to go to PAIN. --- src/hardware/hw_md2.c | 29 +++++++++++++++++++++-------- src/hardware/hw_md2.h | 2 +- src/info.c | 2 +- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 14879b2b7..967dfa03f 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -266,6 +266,9 @@ static void md2_freeModel (md2_model_t *model) free(model->frames); } + if (model->spr2frames) + free(model->spr2frames); + if (model->glCommandBuffer) free(model->glCommandBuffer); @@ -411,11 +414,21 @@ static md2_model_t *md2_readModel(const char *filename) if (spr2 < free_spr2) { + if (!model->spr2frames) + { + model->spr2frames = calloc(sizeof (size_t), 2*NUMPLAYERSPRITES*2); + if (!model->spr2frames) + { + md2_freeModel (model); + fclose(file); + return 0; + } + } if (super) spr2 |= FF_SPR2SUPER; - if (model->spr2frames[spr2][1]++ == 0) // numspr2frames - model->spr2frames[spr2][0] = i; // starting frame - CONS_Debug(DBG_RENDER, "frame %s, sprite2 %s - starting frame %d, number of frames %d\n", frame->name, spr2names[spr2 & ~FF_SPR2SUPER], model->spr2frames[spr2][0], model->spr2frames[spr2][1]); + if (model->spr2frames[spr2*2 + 1]++ == 0) // numspr2frames + model->spr2frames[spr2*2] = i; // starting frame + CONS_Debug(DBG_RENDER, "frame %s, sprite2 %s - starting frame %d, number of frames %d\n", frame->name, spr2names[spr2 & ~FF_SPR2SUPER], model->spr2frames[spr2*2], model->spr2frames[spr2*2 + 1]); } } } @@ -1110,7 +1123,7 @@ static UINT8 P_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *p if (!md2 || !skin) return 0; - while (!(md2->model->spr2frames[spr2][1]) + while (!(md2->model->spr2frames[spr2*2 + 1]) && spr2 != SPR2_STND && ++i != 32) // recursion limiter { @@ -1296,12 +1309,12 @@ void HWR_DrawMD2(gr_vissprite_t *spr) #define INTERPOLERATION_LIMIT TICRATE/4 - if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) + if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY && md2->model->spr2frames) { UINT8 spr2 = P_GetModelSprite2(md2, spr->mobj->skin, spr->mobj->sprite2, spr->mobj->player); - UINT8 mod = md2->model->spr2frames[spr2][1] ? md2->model->spr2frames[spr2][1] : md2->model->header.numFrames; + UINT8 mod = md2->model->spr2frames[spr2*2 + 1] ? md2->model->spr2frames[spr2*2 + 1] : md2->model->header.numFrames; //FIXME: this is not yet correct - frame = md2->model->spr2frames[spr2][0] + ((spr->mobj->frame & FF_FRAMEMASK) % mod); + frame = md2->model->spr2frames[spr2*2] + ((spr->mobj->frame & FF_FRAMEMASK) % mod); buff = md2->model->glCommandBuffer; curr = &md2->model->frames[frame]; if (cv_grmd2.value == 1 && tics <= INTERPOLERATION_LIMIT) @@ -1317,7 +1330,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) UINT32 nextframe = (spr->mobj->frame & FF_FRAMEMASK) + 1; if (nextframe >= (UINT32)((skin_t*)spr->mobj->skin)->sprites[spr->mobj->sprite2].numframes) nextframe = 0; - nextframe = md2->model->spr2frames[spr2][0] + (nextframe % md2->model->spr2frames[spr2][1]); + nextframe = md2->model->spr2frames[spr2*2] + (nextframe % mod); next = &md2->model->frames[nextframe]; } } diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index b183e4367..c7cda35af 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -112,7 +112,7 @@ typedef struct md2_textureCoordinate_t *texCoords; md2_triangle_t *triangles; md2_frame_t *frames; - size_t spr2frames[2*NUMPLAYERSPRITES][2]; + size_t *spr2frames; // size_t spr2frames[2*NUMPLAYERSPRITES][2]; INT32 *glCommandBuffer; } ATTRPACK md2_model_t; diff --git a/src/info.c b/src/info.c index c8bea7803..99f17884c 100644 --- a/src/info.c +++ b/src/info.c @@ -491,7 +491,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { SPR2_FRUN, // SPR2_DASH, 0, // SPR2_PAIN, SPR2_PAIN, // SPR2_STUN, - 0, // SPR2_DEAD, + SPR2_PAIN, // SPR2_DEAD, SPR2_DEAD, // SPR2_DRWN, 0, // SPR2_ROLL, SPR2_SPNG, // SPR2_GASP, From 79dab78fd33170e4ba907a6b8fa46c5ad8bdfccf Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sun, 27 Aug 2017 16:35:19 +0100 Subject: [PATCH 4/5] * Support FF_SPR2ENDSTATE in interpoleration. * Fix skidding interpoleration bug. --- src/hardware/hw_md2.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 967dfa03f..f89a7dc4d 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1322,16 +1322,20 @@ void HWR_DrawMD2(gr_vissprite_t *spr) if (durs > INTERPOLERATION_LIMIT) durs = INTERPOLERATION_LIMIT; - if (spr->mobj->frame & FF_ANIMATE + if (spr->mobj->player && spr->mobj->player->skidtime && spr->mobj->state-states == S_PLAY_WALK) // temporary hack + ; + else if (spr->mobj->frame & FF_ANIMATE || (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite == spr->mobj->sprite && (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) == spr->mobj->sprite2)) { UINT32 nextframe = (spr->mobj->frame & FF_FRAMEMASK) + 1; - if (nextframe >= (UINT32)((skin_t*)spr->mobj->skin)->sprites[spr->mobj->sprite2].numframes) - nextframe = 0; - nextframe = md2->model->spr2frames[spr2*2] + (nextframe % mod); - next = &md2->model->frames[nextframe]; + nextframe %= mod; + if (nextframe || !(spr->mobj->state->frame & FF_SPR2ENDSTATE)) + { + nextframe += md2->model->spr2frames[spr2*2]; + next = &md2->model->frames[nextframe]; + } } } } From 3c785cbe94359a742c305bd890fcb953fe2051f8 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 9 Sep 2017 22:12:23 +0100 Subject: [PATCH 5/5] * Add Skid SPR2/state in preperation for directionchar. * Clean up spr2 md2 code. * Experimented but then commented out some stuff for homing attack. --- src/dehacked.c | 1 + src/hardware/hw_md2.c | 23 +++++++++++------------ src/info.c | 3 +++ src/info.h | 2 ++ src/p_mobj.c | 1 + src/p_user.c | 7 +++++-- 6 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 385411748..c17bf2f8a 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -3356,6 +3356,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_PLAY_STND", "S_PLAY_WAIT", "S_PLAY_WALK", + "S_PLAY_SKID", "S_PLAY_RUN", "S_PLAY_DASH", "S_PLAY_PAIN", diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index f89a7dc4d..708da2c15 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1313,29 +1313,28 @@ void HWR_DrawMD2(gr_vissprite_t *spr) { UINT8 spr2 = P_GetModelSprite2(md2, spr->mobj->skin, spr->mobj->sprite2, spr->mobj->player); UINT8 mod = md2->model->spr2frames[spr2*2 + 1] ? md2->model->spr2frames[spr2*2 + 1] : md2->model->header.numFrames; + if (mod > ((skin_t *)spr->mobj->skin)->sprites[spr2].numframes) + mod = ((skin_t *)spr->mobj->skin)->sprites[spr2].numframes; //FIXME: this is not yet correct - frame = md2->model->spr2frames[spr2*2] + ((spr->mobj->frame & FF_FRAMEMASK) % mod); + frame = (spr->mobj->frame & FF_FRAMEMASK); + if (frame >= mod) + frame = 0; buff = md2->model->glCommandBuffer; - curr = &md2->model->frames[frame]; + curr = &md2->model->frames[md2->model->spr2frames[spr2*2] + frame]; if (cv_grmd2.value == 1 && tics <= INTERPOLERATION_LIMIT) { if (durs > INTERPOLERATION_LIMIT) durs = INTERPOLERATION_LIMIT; - if (spr->mobj->player && spr->mobj->player->skidtime && spr->mobj->state-states == S_PLAY_WALK) // temporary hack - ; - else if (spr->mobj->frame & FF_ANIMATE + if (spr->mobj->frame & FF_ANIMATE || (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite == spr->mobj->sprite && (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) == spr->mobj->sprite2)) { - UINT32 nextframe = (spr->mobj->frame & FF_FRAMEMASK) + 1; - nextframe %= mod; - if (nextframe || !(spr->mobj->state->frame & FF_SPR2ENDSTATE)) - { - nextframe += md2->model->spr2frames[spr2*2]; - next = &md2->model->frames[nextframe]; - } + if (++frame >= mod) + frame = 0; + if (frame || !(spr->mobj->state->frame & FF_SPR2ENDSTATE)) + next = &md2->model->frames[md2->model->spr2frames[spr2*2] + frame]; } } } diff --git a/src/info.c b/src/info.c index 99f17884c..d62111640 100644 --- a/src/info.c +++ b/src/info.c @@ -405,6 +405,7 @@ char spr2names[NUMPLAYERSPRITES][5] = "STND", "WAIT", "WALK", + "SKID", "RUN_", "DASH", "PAIN", @@ -487,6 +488,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { 0, // SPR2_STND, 0, // SPR2_WAIT, 0, // SPR2_WALK, + SPR2_WALK, // SPR2_SKID, SPR2_WALK, // SPR2_RUN , SPR2_FRUN, // SPR2_DASH, 0, // SPR2_PAIN, @@ -593,6 +595,7 @@ state_t states[NUMSTATES] = {SPR_PLAY, SPR2_STND|FF_ANIMATE, 105, {NULL}, 0, 7, S_PLAY_WAIT}, // S_PLAY_STND {SPR_PLAY, SPR2_WAIT|FF_ANIMATE, -1, {NULL}, 0, 16, S_NULL}, // S_PLAY_WAIT {SPR_PLAY, SPR2_WALK, 4, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_WALK + {SPR_PLAY, SPR2_SKID, 1, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_SKID {SPR_PLAY, SPR2_RUN , 2, {NULL}, 0, 0, S_PLAY_RUN}, // S_PLAY_RUN {SPR_PLAY, SPR2_DASH, 2, {NULL}, 0, 0, S_PLAY_DASH}, // S_PLAY_DASH {SPR_PLAY, SPR2_PAIN|FF_ANIMATE, 350, {NULL}, 0, 4, S_PLAY_FALL}, // S_PLAY_PAIN diff --git a/src/info.h b/src/info.h index 4ae5fcf63..7bc7e673a 100644 --- a/src/info.h +++ b/src/info.h @@ -609,6 +609,7 @@ typedef enum playersprite SPR2_STND = 0, SPR2_WAIT, SPR2_WALK, + SPR2_SKID, SPR2_RUN , SPR2_DASH, SPR2_PAIN, @@ -713,6 +714,7 @@ typedef enum state S_PLAY_STND, S_PLAY_WAIT, S_PLAY_WALK, + S_PLAY_SKID, S_PLAY_RUN, S_PLAY_DASH, S_PLAY_PAIN, diff --git a/src/p_mobj.c b/src/p_mobj.c index 8f9c44fdb..1834901ed 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -250,6 +250,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) player->panim = PA_EDGE; break; case S_PLAY_WALK: + case S_PLAY_SKID: case S_PLAY_FLOAT: player->panim = PA_WALK; break; diff --git a/src/p_user.c b/src/p_user.c index 09cafa0b3..6f364ebc8 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4370,6 +4370,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockon)); if (lockon) { + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockon->x, lockon->y); player->homing = 3*TICRATE; } @@ -6674,8 +6675,8 @@ static void P_SkidStuff(player_t *player) // If your push angle is more than this close to a full 180 degrees, trigger a skid. if (dang > ANGLE_157h) { - if (player->panim != PA_WALK) - P_SetPlayerMobjState(player->mo, S_PLAY_WALK); + if (player->mo->state-states != S_PLAY_SKID) + P_SetPlayerMobjState(player->mo, S_PLAY_SKID); player->mo->tics = player->skidtime = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; S_StartSound(player->mo, sfx_skid); } @@ -7418,6 +7419,8 @@ static void P_MovePlayer(player_t *player) if (!(player->mo->tracer->flags & MF_BOSS)) player->pflags &= ~PF_THOKKED; + + // P_SetPlayerMobjState(player->mo, S_PLAY_SPRING); -- Speed didn't like it, RIP } }