diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 5251e0b301d21001ed1f30846f831a38f958a23f..70520af8dbe743adb45fc1d199d7cecafbb13606 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5094,22 +5094,29 @@ static void HWR_ProjectSprite(mobj_t *thing) I_Error("sprframes NULL for sprite %d\n", thing->sprite); #endif - if (sprframe->rotate) - { - // choose a different rotation based on player view - ang = R_PointToAngle(thing->x, thing->y); // uses viewx,viewy - rot = (ang-thing->angle+ANGLE_202h)>>29; - //Fab: lumpid is the index for spritewidth,spriteoffset... tables - lumpoff = sprframe->lumpid[rot]; - flip = sprframe->flip & (1<<rot); - } - else + if (sprframe->rotate == SRF_SINGLE) { // use single rotation for all views rot = 0; //Fab: for vis->patch below lumpoff = sprframe->lumpid[0]; //Fab: see note above flip = sprframe->flip; // Will only be 0x00 or 0xFF } + else + { + // choose a different rotation based on player view + ang = R_PointToAngle (thing->x, thing->y) - thing->angle; + + if ((ang < ANGLE_180) && (sprframe->rotate & SRF_RIGHT)) // See from right + rot = 6; // F7 slot + else if ((ang >= ANGLE_180) && (sprframe->rotate & SRF_LEFT)) // See from left + rot = 2; // F3 slot + else // Normal behaviour + rot = (ang+ANGLE_202h)>>29; + + //Fab: lumpid is the index for spritewidth,spriteoffset... tables + lumpoff = sprframe->lumpid[rot]; + flip = sprframe->flip & (1<<rot); + } if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)thing->skin)->highresscale); diff --git a/src/r_defs.h b/src/r_defs.h index 2c5860ee767f54653a538e82b3d015643c48bad9..568db09267628d5a58f8c9b5f57d703ed50cc631 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -729,23 +729,35 @@ typedef struct #pragma pack() #endif +typedef enum +{ + SRF_SINGLE = 0, // 0-angle for all rotations + SRF_3D = 1, // Angles 1-8 + SRF_LEFT = 2, // Left side has single patch + SRF_RIGHT = 4, // Right side has single patch + SRF_2D = 6, // SRF_LEFT|SRF_RIGHT + SRF_NONE = 0xff // Initial value +} spriterotateflags_t; // SRF's up! + // // Sprites are patches with a special naming convention so they can be // recognized by R_InitSprites. // The base name is NNNNFx or NNNNFxFx, with x indicating the rotation, -// x = 0, 1-7. +// x = 0, 1-8, L/R // The sprite and frame specified by a thing_t is range checked at run time. // A sprite is a patch_t that is assumed to represent a three dimensional // object and may have multiple rotations predrawn. // Horizontal flipping is used to save space, thus NNNNF2F5 defines a mirrored patch. // Some sprites will only have one picture used for all views: NNNNF0 +// Some sprites will take the entirety of the left side: NNNNFL +// Or the right side: NNNNFR +// Or both, mirrored: NNNNFLFR // typedef struct { - // If false use 0 for any position. // Note: as eight entries are available, we might as well insert the same // name eight times. - UINT8 rotate; + UINT8 rotate; // see spriterotateflags_t above // Lump to use for view angles 0-7. lumpnum_t lumppat[8]; // lump number 16 : 16 wad : lump diff --git a/src/r_things.c b/src/r_things.c index 84dff718272b06158348c8622eb1c64265386f93..a7f3fa41d87014f73518a187acd0efa88234cc05 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -100,7 +100,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch lumppat <<= 16; lumppat += lump; - if (frame >= 64 || rotation > 8) + if (frame >= 64 || !(R_ValidSpriteAngle(rotation))) I_Error("R_InstallSpriteLump: Bad frame characters in lump %s", W_CheckNameForNum(lumppat)); if (maxframe ==(size_t)-1 || frame > maxframe) @@ -109,31 +109,65 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch if (rotation == 0) { // the lump should be used for all rotations - if (sprtemp[frame].rotate == 0) + if (sprtemp[frame].rotate == SRF_SINGLE) CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple rot = 0 lump\n", spritename, cn); - - if (sprtemp[frame].rotate == 1) + else if (sprtemp[frame].rotate != SRF_NONE) // Let's complain for both 1-8 and L/R rotations. CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, cn); - sprtemp[frame].rotate = 0; + sprtemp[frame].rotate = SRF_SINGLE; for (r = 0; r < 8; r++) { sprtemp[frame].lumppat[r] = lumppat; sprtemp[frame].lumpid[r] = lumpid; } - sprtemp[frame].flip = flipped ? UINT8_MAX : 0; + sprtemp[frame].flip = flipped ? UINT8_MAX : 0; // 11111111 in binary return; } - // the lump is only used for one rotation - if (sprtemp[frame].rotate == 0) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, cn); + if (rotation == ROT_L || rotation == ROT_R) + { + UINT8 rightfactor = ((rotation == ROT_R) ? 4 : 0); + + // the lump should be used for half of all rotations + if (sprtemp[frame].rotate == SRF_SINGLE) + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has L/R rotations and a rot = 0 lump\n", spritename, cn); + else if (sprtemp[frame].rotate == SRF_3D) + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn); + // Let's not complain about multiple L/R rotations. It's not worth the effort. + + if (sprtemp[frame].rotate == SRF_NONE) + sprtemp[frame].rotate = SRF_SINGLE; - sprtemp[frame].rotate = 1; + sprtemp[frame].rotate |= ((rotation == ROT_R) ? SRF_RIGHT : SRF_LEFT); + + if (sprtemp[frame].rotate == (SRF_3D|SRF_2D)) + sprtemp[frame].rotate = SRF_2D; // SRF_3D|SRF_2D being enabled at the same time doesn't HURT in the current sprite angle implementation, but it DOES mean more to check in some of the helper functions. Let's not allow this scenario to happen. + + for (r = 1; r < 4; r++) // Don't set for front/back frames + { + sprtemp[frame].lumppat[r + rightfactor] = lumppat; + sprtemp[frame].lumpid[r + rightfactor] = lumpid; + } + sprtemp[frame].flip |= (flipped ? (0x0F << rightfactor) : 0); // 00001111 or 11110000 in binary, depending on rotation being ROT_L or ROT_R + return; + } + + // the lump is only used for one rotation + if (sprtemp[frame].rotate == SRF_SINGLE) + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has 1-8 rotations and a rot = 0 lump\n", spritename, cn); + else if ((sprtemp[frame].rotate != SRF_3D) && (sprtemp[frame].rotate != SRF_NONE)) + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn); // make 0 based rotation--; + if (rotation == 0 || rotation == 4) // Front or back... + sprtemp[frame].rotate = SRF_3D; // Prevent L and R changeover + else if (rotation > 3) // Right side + sprtemp[frame].rotate = (SRF_3D | (sprtemp[frame].rotate & SRF_LEFT)); // Continue allowing L frame changeover + else // if (rotation <= 3) // Left side + sprtemp[frame].rotate = (SRF_3D | (sprtemp[frame].rotate & SRF_RIGHT)); // Continue allowing R frame changeover + if (sprtemp[frame].lumppat[rotation] != LUMPERROR) CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %c%c has two lumps mapped to it\n", spritename, cn, '1'+rotation); @@ -195,7 +229,7 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, frame = R_Char2Frame(lumpinfo[l].name[4]); rotation = (UINT8)(lumpinfo[l].name[5] - '0'); - if (frame >= 64 || rotation > 8) // Give an actual NAME error -_-... + if (frame >= 64 || !(R_ValidSpriteAngle(rotation))) // Give an actual NAME error -_-... { CONS_Alert(CONS_WARNING, M_GetText("Bad sprite name: %s\n"), W_CheckNameForNumPwad(wadnum,l)); continue; @@ -278,16 +312,23 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, { switch (sprtemp[frame].rotate) { - case 0xff: + case SRF_NONE: // no rotations were found for that frame at all I_Error("R_AddSingleSpriteDef: No patches found for %.4s frame %c", sprname, R_Frame2Char(frame)); break; - case 0: + case SRF_SINGLE: // only the first rotation is needed break; - case 1: + case SRF_2D: // both Left and Right rotations + // we test to see whether the left and right slots are present + if ((sprtemp[frame].lumppat[2] == LUMPERROR) || (sprtemp[frame].lumppat[6] == LUMPERROR)) + I_Error("R_AddSingleSpriteDef: Sprite %s frame %c is missing rotations", + sprname, R_Frame2Char(frame)); + break; + + default: // must have all 8 frames for (rotation = 0; rotation < 8; rotation++) // we test the patch lump, or the id lump whatever @@ -1152,22 +1193,29 @@ static void R_ProjectSprite(mobj_t *thing) ang_scale = abs(FINESINE(ang>>ANGLETOFINESHIFT)); } - if (sprframe->rotate) - { - // choose a different rotation based on player view - //ang = R_PointToAngle (thing->x, thing->y); - rot = (ang-thing->angle+ANGLE_202h)>>29; - //Fab: lumpid is the index for spritewidth,spriteoffset... tables - lump = sprframe->lumpid[rot]; - flip = sprframe->flip & (1<<rot); - } - else + if (sprframe->rotate == SRF_SINGLE) { // use single rotation for all views rot = 0; //Fab: for vis->patch below lump = sprframe->lumpid[0]; //Fab: see note above flip = sprframe->flip; // Will only be 0x00 or 0xFF } + else + { + // choose a different rotation based on player view + ang = R_PointToAngle (thing->x, thing->y) - thing->angle; + + if ((ang < ANGLE_180) && (sprframe->rotate & SRF_RIGHT)) // See from right + rot = 6; // F7 slot + else if ((ang >= ANGLE_180) && (sprframe->rotate & SRF_LEFT)) // See from left + rot = 2; // F3 slot + else // Normal behaviour + rot = (ang+ANGLE_202h)>>29; + + //Fab: lumpid is the index for spritewidth,spriteoffset... tables + lump = sprframe->lumpid[rot]; + flip = sprframe->flip & (1<<rot); + } I_Assert(lump < max_spritelumps); diff --git a/src/r_things.h b/src/r_things.h index 9a4ba1999a8b23872b26335c3f7ea99470c26217..9b6020ceafdbb4501b93a5c1482788273e29dd83 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -17,6 +17,10 @@ #include "sounds.h" #include "r_plane.h" +// "Left" and "Right" character symbols for additional rotation functionality +#define ROT_L ('L' - '0') +#define ROT_R ('R' - '0') + // number of sprite lumps for spritewidth,offset,topoffset lookup tables // Fab: this is a hack : should allocate the lookup tables per sprite #define MAXVISSPRITES 2048 // added 2-2-98 was 128 @@ -231,4 +235,9 @@ FUNCMATH FUNCINLINE static ATTRINLINE UINT8 R_Char2Frame(char cn) #endif } +FUNCMATH FUNCINLINE static ATTRINLINE boolean R_ValidSpriteAngle(UINT8 rotation) +{ + return ((rotation <= 8) || (rotation == ROT_L) || (rotation == ROT_R)); +} + #endif //__R_THINGS__