diff --git a/src/dehacked.c b/src/dehacked.c index df8284822..d36ff2e07 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -740,7 +740,7 @@ static void readlight(MYFILE *f, INT32 num) } #endif // HWRENDER -static void readspriteframe(MYFILE *f, INT32 num, INT32 frame) +static void readspriteframe(MYFILE *f, spriteinfo_t *sprinfo, UINT8 frame) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); char *word, *word2; @@ -797,21 +797,14 @@ static void readspriteframe(MYFILE *f, INT32 num, INT32 frame) strupr(word); value = atoi(word2); // used for numerical settings - if (frame >= 64) - { - deh_warning("Sprite %d: invalid frame %d", num, frame); - break; - } - #ifdef ROTSPRITE if (fastcmp(word, "XPIVOT")) - spriteinfo[num].pivot[frame].x = value; + sprinfo->pivot[frame].x = value; else if (fastcmp(word, "YPIVOT")) - spriteinfo[num].pivot[frame].y = value; + sprinfo->pivot[frame].y = value; #endif else { - //deh_warning("Sprite %d frame %d: unknown word '%s'", num, frame, word); f->curpos = lastline; break; } @@ -820,13 +813,19 @@ static void readspriteframe(MYFILE *f, INT32 num, INT32 frame) Z_Free(s); } -static void readspriteinfo(MYFILE *f, INT32 num) +static void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); char *word, *word2; char *tmp; INT32 value; char *lastline; + INT32 skinnumbers[MAXSKINS]; + INT32 foundskins = 0; + + // allocate a spriteinfo + spriteinfo_t *info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL); + info->available = true; do { @@ -880,21 +879,90 @@ static void readspriteinfo(MYFILE *f, INT32 num) #ifdef HWRENDER if (fastcmp(word, "LIGHTTYPE")) { - INT32 oldvar; - for (oldvar = 0; t_lspr[num] != &lspr[oldvar]; oldvar++) - ; - t_lspr[num] = &lspr[value]; + if (sprite2) + deh_warning("Sprite2 %s: invalid word '%s'", spr2names[num], word); + else + { + INT32 oldvar; + for (oldvar = 0; t_lspr[num] != &lspr[oldvar]; oldvar++) + ; + t_lspr[num] = &lspr[value]; + } } else #endif - if (fastcmp(word, "FRAME")) + if (fastcmp(word, "SKIN")) { - readspriteframe(f, num, R_Char2Frame(word2[0])); - spriteinfo[num].available = true; + INT32 skinnum = -1; + if (!sprite2) + { + deh_warning("Sprite %s: %s keyword found outside of SPRITE2INFO block, ignoring", spr2names[num], word); + continue; + } + + // make lowercase + strlwr(word2); + skinnum = R_SkinAvailable(word2); + if (skinnum == -1) + { + deh_warning("Sprite2 %s: unknown skin %s", spr2names[num], word2); + break; + } + + skinnumbers[foundskins] = skinnum; + foundskins++; + } + else if (fastcmp(word, "DEFAULT")) + { + if (!sprite2) + { + deh_warning("Sprite %s: %s keyword found outside of SPRITE2INFO block, ignoring", spr2names[num], word); + continue; + } + if (num < (INT32)free_spr2 && num >= (INT32)SPR2_FIRSTFREESLOT) + spr2defaults[num] = get_number(word2); + else + { + deh_warning("Sprite2 %s: out of range (%d - %d), ignoring", spr2names[num], SPR2_FIRSTFREESLOT, free_spr2-1); + continue; + } + } + else if (fastcmp(word, "FRAME")) + { + UINT8 frame = R_Char2Frame(word2[0]); + // frame number too high + if (frame >= 64) + { + if (sprite2) + deh_warning("Sprite2 %s: invalid frame %s", spr2names[num], word2); + else + deh_warning("Sprite %s: invalid frame %s", sprnames[num], word2); + break; + } + + // read sprite frame and store it on the spriteinfo_t struct + readspriteframe(f, info, frame); + if (sprite2) + { + INT32 i; + if (!foundskins) + { + deh_warning("Sprite2 %s: no skins specified", spr2names[num]); + break; + } + for (i = 0; i < foundskins; i++) + { + skin_t *skin = &skins[skinnumbers[i]]; + spriteinfo_t *sprinfo = skin->sprinfo; + M_Memcpy(&sprinfo[num], info, sizeof(spriteinfo_t)); + } + } + else + M_Memcpy(&spriteinfo[num], info, sizeof(spriteinfo_t)); } else { - //deh_warning("Sprite %d: unknown word '%s'", num, word); + //deh_warning("Sprite %s: unknown word '%s'", sprnames[num], word); f->curpos = lastline; break; } @@ -902,6 +970,7 @@ static void readspriteinfo(MYFILE *f, INT32 num) } while (!myfeof(f)); // finish when the line is empty Z_Free(s); + Z_Free(info); } static void readsprite2(MYFILE *f, INT32 num) @@ -4025,13 +4094,25 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) 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) - readspriteinfo(f, i); + readspriteinfo(f, i, false); else { deh_warning("Sprite number %d out of range (0 - %d)", i, NUMSPRITES-1); ignorelines(f); } } + else if (fastcmp(word, "SPRITE2INFO")) + { + if (i == 0 && word2[0] != '0') // If word2 isn't a number + i = get_sprite2(word2); // find a sprite by name + if (i < NUMPLAYERSPRITES && i >= 0) + readspriteinfo(f, i, true); + else + { + deh_warning("Sprite2 number %d out of range (0 - %d)", i, NUMPLAYERSPRITES-1); + ignorelines(f); + } + } else if (fastcmp(word, "LEVEL")) { // Support using the actual map name, diff --git a/src/p_setup.c b/src/p_setup.c index 047053f68..0c5729f50 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3471,13 +3471,7 @@ boolean P_AddWadFile(const char *wadfilename) if (!mapsadded) CONS_Printf(M_GetText("No maps added\n")); - // load SPRTINFO lumps - for (i = 0; i < numlumps; i++, lumpinfo++) - { - name = lumpinfo->name; - if (!stricmp(name, "SPRTINFO")) - R_ParseSPRTINFOLump(wadnum, i); - } + R_LoadSpriteInfoLumps(wadnum, numlumps); // reload status bar (warning should have valid player!) if (gamestate == GS_LEVEL) diff --git a/src/r_things.c b/src/r_things.c index d36c5c164..355c041fb 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -737,8 +737,7 @@ static vissprite_t *visspritechunks[MAXVISSPRITES >> VISSPRITECHUNKBITS] = {NULL // void R_InitSprites(void) { - size_t i, j; - lumpinfo_t *lumpinfo; + size_t i; #ifdef ROTSPRITE INT32 angle, realangle = 0; float fa; @@ -783,13 +782,7 @@ void R_InitSprites(void) { R_AddSkins((UINT16)i); R_PatchSkins((UINT16)i); - // load SPRTINFO lumps - lumpinfo = wadfiles[i]->lumpinfo; - for (j = 0; j < wadfiles[i]->numlumps; j++, lumpinfo++) - { - if (!stricmp(lumpinfo->name, "SPRTINFO")) - R_ParseSPRTINFOLump(i, j); - } + R_LoadSpriteInfoLumps(i, wadfiles[i]->numlumps); } ST_ReloadSkinFaceGraphics(); @@ -3887,3 +3880,21 @@ void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum) Z_Free(sprinfoToken); Z_Free((void *)sprinfoText); } + +void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps) +{ + lumpinfo_t *lumpinfo = wadfiles[wadnum]->lumpinfo; + UINT16 i; + char *name; + + for (i = 0; i < numlumps; i++, lumpinfo++) + { + name = lumpinfo->name; + // load SPRTINFO lumps + if (!stricmp(name, "SPRTINFO")) + R_ParseSPRTINFOLump(wadnum, i); + // load SPR_ lumps (as DEHACKED lump) + else if (!memcmp(name, "SPR_", 4)) + DEH_LoadDehackedLumpPwad(wadnum, i, false); + } +} diff --git a/src/r_things.h b/src/r_things.h index 281d430d3..c70051ee7 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -239,6 +239,8 @@ UINT32 R_GetSkinAvailabilities(void); INT32 R_SkinAvailable(const char *name); void R_PatchSkins(UINT16 wadnum); void R_AddSkins(UINT16 wadnum); + +void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps); void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum); UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player);