diff --git a/src/dehacked.c b/src/dehacked.c index 5bcb64073..cf654dcd7 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9364,6 +9364,13 @@ struct { {"DI_SOUTHEAST",DI_SOUTHEAST}, {"NUMDIRS",NUMDIRS}, +#ifdef ROTSPRITE + // Sprite roll axis (rollaxis_t) + {"ROLLAXIS_X",ROLLAXIS_X}, + {"ROLLAXIS_Y",ROLLAXIS_Y}, + {"ROLLAXIS_Z",ROLLAXIS_Z}, +#endif + // Buttons (ticcmd_t) {"BT_WEAPONMASK",BT_WEAPONMASK}, //our first four bits. {"BT_WEAPONNEXT",BT_WEAPONNEXT}, diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index eed96ddc0..c1996ea4b 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -117,7 +117,8 @@ typedef struct boolean flip; // screenflip #ifdef ROTSPRITE boolean roll; - SINT8 nightsroll; + UINT8 rollaxis; + SINT8 rollflip; FLOAT rollangle; // done to not override USE_FTRANSFORM_ANGLEZ FLOAT centerx, centery; #endif diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index c4b28076b..2c5ab07db 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -961,6 +961,10 @@ void HWR_DrawModel(gr_vissprite_t *spr) const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !(spr->mobj->frame & FF_VERTICALFLIP)); spritedef_t *sprdef; spriteframe_t *sprframe; +#ifdef ROTSPRITE + spriteinfo_t *sprinfo; + angle_t ang; +#endif INT32 mod; float finalscale; @@ -984,9 +988,17 @@ void HWR_DrawModel(gr_vissprite_t *spr) { md2 = &md2_playermodels[(skin_t*)spr->mobj->skin-skins]; md2->skin = (skin_t*)spr->mobj->skin-skins; +#ifdef ROTSPRITE + sprinfo = &((skin_t *)spr->mobj->skin)->sprinfo[spr->mobj->sprite2]; +#endif } else + { md2 = &md2_models[spr->mobj->sprite]; +#ifdef ROTSPRITE + sprinfo = &spriteinfo[spr->mobj->sprite]; +#endif + } if (md2->error) return; // we already failed loading this before :( @@ -1175,29 +1187,28 @@ void HWR_DrawModel(gr_vissprite_t *spr) #ifdef ROTSPRITE p.rollangle = 0.0f; - p.nightsroll = 0; + p.rollaxis = 0; + p.rollflip = 0; if (spr->mobj->rollangle) { - // do i have to support ROTANGLES here?????? fixed_t anglef = AngleFixed(spr->mobj->rollangle); p.rollangle = FIXED_TO_FLOAT(anglef); - // pivot + p.roll = true; + + // rotation pivot p.centerx = FIXED_TO_FLOAT(spr->mobj->radius/2); p.centery = FIXED_TO_FLOAT(spr->mobj->height/2); - p.roll = true; - // NiGHTS-specific conditional - //if (spr->mobj->player) - { - statenum_t state = spr->mobj->state-states; - if ((state == S_PLAY_NIGHTS_FLY0) || (state == S_PLAY_NIGHTS_DRILL0)) - { - angle_t ang = R_PointToAngle (spr->mobj->x, spr->mobj->y) - (spr->mobj->player ? spr->mobj->player->drawangle : spr->mobj->angle); - if ((sprframe->rotate & SRF_RIGHT) && (ang < ANGLE_180)) // See from right - p.nightsroll = 1; - else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left - p.nightsroll = -1; - } - } + + // roll axis + if (sprinfo->available) + p.rollaxis = (UINT8)(sprinfo->pivot[(spr->mobj->frame & FF_FRAMEMASK)].rollaxis); + + // for NiGHTS specifically but should work everywhere else + ang = R_PointToAngle (spr->mobj->x, spr->mobj->y) - (spr->mobj->player ? spr->mobj->player->drawangle : spr->mobj->angle); + if ((sprframe->rotate & SRF_RIGHT) && (ang < ANGLE_180)) // See from right + p.rollflip = 1; + else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left + p.rollflip = -1; } #endif diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 4388214ec..b05a5dd83 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2069,11 +2069,14 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 #ifdef ROTSPRITE if (pos->roll) { + float roll = (1.0f * pos->rollflip); pglTranslatef(pos->centerx, pos->centery, 0); - if (pos->nightsroll != 0) - pglRotatef(pos->rollangle, 0.0f, 0.0f, (1.0f * pos->nightsroll)); - else - pglRotatef(pos->rollangle, 1.0f, 0.0f, 0.0f); + if (pos->rollaxis == 2) // Z + pglRotatef(pos->rollangle, 0.0f, 0.0f, roll); + else if (pos->rollaxis == 1) // Y + pglRotatef(pos->rollangle, 0.0f, roll, 0.0f); + else // X + pglRotatef(pos->rollangle, roll, 0.0f, 0.0f); pglTranslatef(-pos->centerx, -pos->centery, 0); } #endif diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 4cb851dca..2782e6b29 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -305,8 +305,10 @@ static int PopPivotSubTable(spriteframepivot_t *pivot, lua_State *L, int stk, in pivot[idx].x = (INT32)value; else if (ikey == 2 || (key && fastcmp(key, "y"))) pivot[idx].y = (INT32)value; + else if (ikey == 3 || (key && fastcmp(key, "rollaxis"))) + pivot[idx].rollaxis = (UINT8)value; else if (ikey == -1 && (key != NULL)) - FIELDERROR("pivot key", va("x or y expected, got %s", key)); + FIELDERROR("pivot key", va("x, y or roll axis expected, got %s", key)); ok = 1; //info->available = true; // the pivot for this frame is available lua_pop(L, 1); @@ -328,7 +330,7 @@ static int PopPivotTable(spriteinfo_t *info, lua_State *L, int stk) // stk = 0 has the pivot table // stk = 1 has the frame key // stk = 2 has the frame table - // stk = 3 has either "x" or "y" or a number as key + // stk = 3 has either "x" or "y" or "rollaxis" or a number as key // stk = 4 has the value for the key mentioned above while (lua_next(L, stk)) { @@ -568,6 +570,8 @@ static int framepivot_get(lua_State *L) lua_pushinteger(L, framepivot->x); else if (fastcmp("y", field)) lua_pushinteger(L, framepivot->y); + else if (fastcmp("rollaxis", field)) + lua_pushinteger(L, (UINT8)framepivot->rollaxis); else return luaL_error(L, va("Field %s does not exist in spriteframepivot_t", field)); @@ -590,6 +594,8 @@ static int framepivot_set(lua_State *L) framepivot->x = luaL_checkinteger(L, 3); else if (fastcmp("y", field)) framepivot->y = luaL_checkinteger(L, 3); + else if (fastcmp("rollaxis", field)) + framepivot->rollaxis = (UINT8)luaL_checkinteger(L, 3); else return luaL_error(L, va("Field %s does not exist in spriteframepivot_t", field)); diff --git a/src/r_patch.c b/src/r_patch.c index ce68b49ae..6f6050ce9 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -791,6 +791,7 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) #ifdef ROTSPRITE INT16 frameXPivot = 0; INT16 frameYPivot = 0; + rollaxis_t frameRollAxis = 0; #endif // Sprite identifier @@ -839,6 +840,17 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) sprinfoToken = M_GetToken(NULL); frameYPivot = atoi(sprinfoToken); } + else if (stricmp(sprinfoToken, "ROLLAXIS")==0) + { + Z_Free(sprinfoToken); + sprinfoToken = M_GetToken(NULL); + if ((stricmp(sprinfoToken, "X")==0) || (stricmp(sprinfoToken, "XAXIS")==0)) + frameRollAxis = ROLLAXIS_X; + else if ((stricmp(sprinfoToken, "Y")==0) || (stricmp(sprinfoToken, "YAXIS")==0)) + frameRollAxis = ROLLAXIS_Y; + else if ((stricmp(sprinfoToken, "Z")==0) || (stricmp(sprinfoToken, "ZAXIS")==0)) + frameRollAxis = ROLLAXIS_Z; + } #endif Z_Free(sprinfoToken); @@ -856,6 +868,7 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) #ifdef ROTSPRITE info->pivot[frameFrame].x = frameXPivot; info->pivot[frameFrame].y = frameYPivot; + info->pivot[frameFrame].rollaxis = frameRollAxis; #endif } diff --git a/src/r_patch.h b/src/r_patch.h index b840823d8..fa6785792 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -19,9 +19,17 @@ // structs #ifdef ROTSPRITE +typedef enum +{ + ROLLAXIS_X, // the default + ROLLAXIS_Y, + ROLLAXIS_Z +} rollaxis_t; + typedef struct { INT32 x, y; + rollaxis_t rollaxis; } spriteframepivot_t; #endif diff --git a/src/r_things.c b/src/r_things.c index 2df80b0c4..3d2f2a846 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1148,7 +1148,9 @@ static void R_ProjectSprite(mobj_t *thing) spritedef_t *sprdef; spriteframe_t *sprframe; +#ifdef ROTSPRITE spriteinfo_t *sprinfo; +#endif size_t lump; size_t rot; @@ -1223,20 +1225,26 @@ static void R_ProjectSprite(mobj_t *thing) if (thing->skin && thing->sprite == SPR_PLAY) { sprdef = &((skin_t *)thing->skin)->sprites[thing->sprite2]; +#ifdef ROTSPRITE sprinfo = &((skin_t *)thing->skin)->sprinfo[thing->sprite2]; +#endif if (rot >= sprdef->numframes) { CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid skins[\"%s\"].sprites[%sSPR2_%s] frame %s\n"), ((skin_t *)thing->skin)->name, ((thing->sprite2 & FF_SPR2SUPER) ? "FF_SPR2SUPER|": ""), spr2names[(thing->sprite2 & ~FF_SPR2SUPER)], sizeu5(rot)); thing->sprite = states[S_UNKNOWN].sprite; thing->frame = states[S_UNKNOWN].frame; sprdef = &sprites[thing->sprite]; +#ifdef ROTSPRITE sprinfo = NULL; +#endif rot = thing->frame&FF_FRAMEMASK; } } else { sprdef = &sprites[thing->sprite]; +#ifdef ROTSPRITE sprinfo = NULL; +#endif } if (rot >= sprdef->numframes)