Browse Source

Unify player_graphic memory handling

pull/2049/head
obligaron 5 years ago committed by Anders Jenbo
parent
commit
d97131349e
  1. 2
      Source/diablo.cpp
  2. 9
      Source/items.cpp
  3. 6
      Source/loadsave.cpp
  4. 8
      Source/msg.cpp
  5. 8
      Source/multi.cpp
  6. 295
      Source/player.cpp
  7. 71
      Source/player.h
  8. 1
      test/player_test.cpp

2
Source/diablo.cpp

@ -335,7 +335,7 @@ static void free_game()
FreeStoreMem(); FreeStoreMem();
for (auto &player : plr) for (auto &player : plr)
FreePlayerGFX(player); ResetPlayerGFX(player);
FreeCursor(); FreeCursor();
#ifdef _DEBUG #ifdef _DEBUG

9
Source/items.cpp

@ -884,13 +884,14 @@ void CalcPlrItemVals(int playerId, bool Loadgfx)
if (player._pgfxnum != g && Loadgfx) { if (player._pgfxnum != g && Loadgfx) {
player._pgfxnum = g; player._pgfxnum = g;
player._pGFXLoad = 0; ResetPlayerGFX(player);
SetPlrAnims(player); SetPlrAnims(player);
LoadPlrGFX(player, static_cast<player_graphic>(PFILE_STAND | PFILE_WALK));
if (player._pmode == PM_STAND) { if (player._pmode == PM_STAND) {
player.AnimInfo.ChangeAnimationData(&*player._pNAnim[player._pdir], player._pNFrames, 3); LoadPlrGFX(player, player_graphic::Stand);
player.AnimInfo.ChangeAnimationData(&*player.AnimationData[static_cast<size_t>(player_graphic::Stand)].CelSpritesForDirections[player._pdir], player._pNFrames, 3);
} else { } else {
player.AnimInfo.ChangeAnimationData(&*player._pWAnim[player._pdir], player._pWFrames, 0); LoadPlrGFX(player, player_graphic::Walk);
player.AnimInfo.ChangeAnimationData(&*player.AnimationData[static_cast<size_t>(player_graphic::Walk)].CelSpritesForDirections[player._pdir], player._pWFrames, 0);
} }
} else { } else {
player._pgfxnum = g; player._pgfxnum = g;

6
Source/loadsave.cpp

@ -432,7 +432,8 @@ static void LoadPlayer(LoadHelper *file, int p)
file->skip(2); // Alignment file->skip(2); // Alignment
pPlayer->_pGFXLoad = file->nextLE<int32_t>(); // skip _pGFXLoad
file->skip(4);
file->skip(4 * 8); // Skip pointers _pNAnim file->skip(4 * 8); // Skip pointers _pNAnim
pPlayer->_pNFrames = file->nextLE<int32_t>(); pPlayer->_pNFrames = file->nextLE<int32_t>();
// skip _pNWidth // skip _pNWidth
@ -1428,7 +1429,8 @@ static void SavePlayer(SaveHelper *file, int p)
file->skip(2); // Alignment file->skip(2); // Alignment
file->writeLE<int32_t>(pPlayer->_pGFXLoad); // Write _pGFXLoad for vanilla compatibility
file->writeLE<int32_t>(0);
file->skip(4 * 8); // Skip pointers _pNAnim file->skip(4 * 8); // Skip pointers _pNAnim
file->writeLE<int32_t>(pPlayer->_pNFrames); file->writeLE<int32_t>(pPlayer->_pNFrames);
// Skip _pNWidth // Skip _pNWidth

8
Source/msg.cpp

@ -696,7 +696,7 @@ void DeltaSaveLevel()
for (int i = 0; i < MAX_PLRS; i++) { for (int i = 0; i < MAX_PLRS; i++) {
if (i != myplr) if (i != myplr)
plr[i]._pGFXLoad = 0; ResetPlayerGFX(plr[i]);
} }
plr[myplr]._pLvlVisited[currlevel] = true; plr[myplr]._pLvlVisited[currlevel] = true;
delta_leave_sync(currlevel); delta_leave_sync(currlevel);
@ -2225,7 +2225,7 @@ static DWORD On_PLAYER_JOINLEVEL(TCmd *pCmd, int pnum)
else { else {
plr[pnum]._pLvlChanging = false; plr[pnum]._pLvlChanging = false;
if (plr[pnum]._pName[0] != 0 && !plr[pnum].plractive) { if (plr[pnum]._pName[0] != 0 && !plr[pnum].plractive) {
InitPlrGFXMem(plr[pnum]); ResetPlayerGFX(plr[pnum]);
plr[pnum].plractive = true; plr[pnum].plractive = true;
gbActivePlayers++; gbActivePlayers++;
EventPlrMsg(fmt::format(_("Player '{:s}' (level {:d}) just joined the game"), plr[pnum]._pName, plr[pnum]._pLevel).c_str()); EventPlrMsg(fmt::format(_("Player '{:s}' (level {:d}) just joined the game"), plr[pnum]._pName, plr[pnum]._pLevel).c_str());
@ -2234,7 +2234,7 @@ static DWORD On_PLAYER_JOINLEVEL(TCmd *pCmd, int pnum)
if (plr[pnum].plractive && myplr != pnum) { if (plr[pnum].plractive && myplr != pnum) {
plr[pnum].position.tile = { p->x, p->y }; plr[pnum].position.tile = { p->x, p->y };
plr[pnum].plrlevel = p->wParam1; plr[pnum].plrlevel = p->wParam1;
plr[pnum]._pGFXLoad = 0; ResetPlayerGFX(plr[pnum]);
if (currlevel == plr[pnum].plrlevel) { if (currlevel == plr[pnum].plrlevel) {
SyncInitPlr(pnum); SyncInitPlr(pnum);
if ((plr[pnum]._pHitPoints >> 6) > 0) if ((plr[pnum]._pHitPoints >> 6) > 0)
@ -2242,7 +2242,7 @@ static DWORD On_PLAYER_JOINLEVEL(TCmd *pCmd, int pnum)
else { else {
plr[pnum]._pgfxnum = 0; plr[pnum]._pgfxnum = 0;
plr[pnum]._pmode = PM_DEATH; plr[pnum]._pmode = PM_DEATH;
NewPlrAnim(plr[pnum], PFILE_DEATH, DIR_S, plr[pnum]._pDFrames, 1); NewPlrAnim(plr[pnum], player_graphic::Death, DIR_S, plr[pnum]._pDFrames, 1);
plr[pnum].AnimInfo.CurrentFrame = plr[pnum].AnimInfo.NumberOfFrames - 1; plr[pnum].AnimInfo.CurrentFrame = plr[pnum].AnimInfo.NumberOfFrames - 1;
dFlags[plr[pnum].position.tile.x][plr[pnum].position.tile.y] |= BFLAG_DEAD_PLAYER; dFlags[plr[pnum].position.tile.x][plr[pnum].position.tile.y] |= BFLAG_DEAD_PLAYER;
} }

8
Source/multi.cpp

@ -275,7 +275,7 @@ static void multi_player_left_msg(int pnum, bool left)
} }
plr[pnum].plractive = false; plr[pnum].plractive = false;
plr[pnum]._pName[0] = '\0'; plr[pnum]._pName[0] = '\0';
FreePlayerGFX(plr[pnum]); ResetPlayerGFX(plr[pnum]);
gbActivePlayers--; gbActivePlayers--;
} }
} }
@ -749,7 +749,7 @@ bool NetInit(bool bSinglePlayer)
SetupLocalCoords(); SetupLocalCoords();
multi_send_pinfo(-2, CMD_SEND_PLRINFO); multi_send_pinfo(-2, CMD_SEND_PLRINFO);
InitPlrGFXMem(plr[myplr]); ResetPlayerGFX(plr[myplr]);
plr[myplr].plractive = true; plr[myplr].plractive = true;
gbActivePlayers = 1; gbActivePlayers = 1;
@ -855,7 +855,7 @@ void recv_plrinfo(int pnum, TCmdPlrInfoHdr *p, bool recv)
return; return;
} }
InitPlrGFXMem(plr[pnum]); ResetPlayerGFX(plr[pnum]);
plr[pnum].plractive = true; plr[pnum].plractive = true;
gbActivePlayers++; gbActivePlayers++;
@ -874,7 +874,7 @@ void recv_plrinfo(int pnum, TCmdPlrInfoHdr *p, bool recv)
} else { } else {
plr[pnum]._pgfxnum = 0; plr[pnum]._pgfxnum = 0;
plr[pnum]._pmode = PM_DEATH; plr[pnum]._pmode = PM_DEATH;
NewPlrAnim(player, PFILE_DEATH, DIR_S, plr[pnum]._pDFrames, 1); NewPlrAnim(player, player_graphic::Death, DIR_S, plr[pnum]._pDFrames, 1);
plr[pnum].AnimInfo.CurrentFrame = plr[pnum].AnimInfo.NumberOfFrames - 1; plr[pnum].AnimInfo.CurrentFrame = plr[pnum].AnimInfo.NumberOfFrames - 1;
dFlags[plr[pnum].position.tile.x][plr[pnum].position.tile.y] |= BFLAG_DEAD_PLAYER; dFlags[plr[pnum].position.tile.x][plr[pnum].position.tile.y] |= BFLAG_DEAD_PLAYER;
} }

295
Source/player.cpp

@ -377,15 +377,15 @@ void PlayerStruct::Reset()
int PlayerStruct::GetAnimationWidth(player_graphic graphic) int PlayerStruct::GetAnimationWidth(player_graphic graphic)
{ {
switch (graphic) { switch (graphic) {
case PFILE_STAND: case player_graphic::Stand:
if (_pClass == HeroClass::Monk) if (_pClass == HeroClass::Monk)
return 112; return 112;
return 96; return 96;
case PFILE_WALK: case player_graphic::Walk:
if (_pClass == HeroClass::Monk) if (_pClass == HeroClass::Monk)
return 112; return 112;
return 96; return 96;
case PFILE_ATTACK: case player_graphic::Attack:
if (_pClass == HeroClass::Monk) if (_pClass == HeroClass::Monk)
return 130; return 130;
if (_pClass == HeroClass::Warrior || _pClass == HeroClass::Barbarian) { if (_pClass == HeroClass::Warrior || _pClass == HeroClass::Barbarian) {
@ -394,23 +394,23 @@ int PlayerStruct::GetAnimationWidth(player_graphic graphic)
return 96; return 96;
} }
return 128; return 128;
case PFILE_HIT: case player_graphic::Hit:
if (_pClass == HeroClass::Monk) if (_pClass == HeroClass::Monk)
return 98; return 98;
return 96; return 96;
case PFILE_LIGHTNING: case player_graphic::Lightning:
case PFILE_FIRE: case player_graphic::Fire:
case PFILE_MAGIC: case player_graphic::Magic:
if (_pClass == HeroClass::Monk) if (_pClass == HeroClass::Monk)
return 114; return 114;
if (_pClass == HeroClass::Sorcerer) if (_pClass == HeroClass::Sorcerer)
return 128; return 128;
return 96; return 96;
case PFILE_DEATH: case player_graphic::Death:
if (_pClass == HeroClass::Monk) if (_pClass == HeroClass::Monk)
return 160; return 160;
return 128; return 128;
case PFILE_BLOCK: case player_graphic::Block:
if (_pClass == HeroClass::Monk) if (_pClass == HeroClass::Monk)
return 98; return 98;
return 96; return 96;
@ -431,13 +431,11 @@ void SetPlayerGPtrs(const char *path, std::unique_ptr<byte[]> &data, std::array<
} }
} }
void LoadPlrGFX(PlayerStruct &player, player_graphic gfxflag) void LoadPlrGFX(PlayerStruct &player, player_graphic graphic)
{ {
char prefix[16]; char prefix[16];
char pszName[256]; char pszName[256];
const char *szCel; const char *szCel;
std::unique_ptr<byte[]> *pData;
std::array<std::optional<CelSprite>, 8> *pAnim;
HeroClass c = player._pClass; HeroClass c = player._pClass;
if (c == HeroClass::Bard && hfbard_mpq == nullptr) { if (c == HeroClass::Bard && hfbard_mpq == nullptr) {
@ -449,96 +447,61 @@ void LoadPlrGFX(PlayerStruct &player, player_graphic gfxflag)
sprintf(prefix, "%c%c%c", CharChar[static_cast<std::size_t>(c)], ArmourChar[player._pgfxnum >> 4], WepChar[player._pgfxnum & 0xF]); sprintf(prefix, "%c%c%c", CharChar[static_cast<std::size_t>(c)], ArmourChar[player._pgfxnum >> 4], WepChar[player._pgfxnum & 0xF]);
const char *cs = ClassPathTbl[static_cast<std::size_t>(c)]; const char *cs = ClassPathTbl[static_cast<std::size_t>(c)];
for (unsigned i = 1; i <= PFILE_NONDEATH; i <<= 1) { switch (graphic) {
if ((i & gfxflag) == 0) { case player_graphic::Stand:
continue; szCel = "AS";
} if (leveltype == DTYPE_TOWN)
szCel = "ST";
switch (i) { break;
case PFILE_STAND: case player_graphic::Walk:
szCel = "AS"; szCel = "AW";
if (leveltype == DTYPE_TOWN) { if (leveltype == DTYPE_TOWN)
szCel = "ST"; szCel = "WL";
} break;
pData = &player._pNData; case player_graphic::Attack:
pAnim = &player._pNAnim; if (leveltype == DTYPE_TOWN)
break; return;
case PFILE_WALK: szCel = "AT";
szCel = "AW"; break;
if (leveltype == DTYPE_TOWN) { case player_graphic::Hit:
szCel = "WL"; if (leveltype == DTYPE_TOWN)
} return;
pData = &player._pWData; szCel = "HT";
pAnim = &player._pWAnim; break;
break; case player_graphic::Lightning:
case PFILE_ATTACK: if (leveltype == DTYPE_TOWN)
if (leveltype == DTYPE_TOWN) { return;
continue; szCel = "LM";
} break;
szCel = "AT"; case player_graphic::Fire:
pData = &player._pAData; if (leveltype == DTYPE_TOWN)
pAnim = &player._pAAnim; return;
break; szCel = "FM";
case PFILE_HIT: break;
if (leveltype == DTYPE_TOWN) { case player_graphic::Magic:
continue; if (leveltype == DTYPE_TOWN)
} return;
szCel = "HT"; szCel = "QM";
pData = &player._pHData; break;
pAnim = &player._pHAnim; case player_graphic::Death:
break; if ((player._pgfxnum & 0xF) != 0)
case PFILE_LIGHTNING: return;
if (leveltype == DTYPE_TOWN) { szCel = "DT";
continue; break;
} case player_graphic::Block:
szCel = "LM"; if (leveltype == DTYPE_TOWN)
pData = &player._pLData; return;
pAnim = &player._pLAnim; if (!player._pBlockFlag)
break; return;
case PFILE_FIRE: szCel = "BL";
if (leveltype == DTYPE_TOWN) { break;
continue; default:
} app_fatal("PLR:2");
szCel = "FM";
pData = &player._pFData;
pAnim = &player._pFAnim;
break;
case PFILE_MAGIC:
if (leveltype == DTYPE_TOWN) {
continue;
}
szCel = "QM";
pData = &player._pTData;
pAnim = &player._pTAnim;
break;
case PFILE_DEATH:
if ((player._pgfxnum & 0xF) != 0) {
continue;
}
szCel = "DT";
pData = &player._pDData;
pAnim = &player._pDAnim;
break;
case PFILE_BLOCK:
if (leveltype == DTYPE_TOWN) {
continue;
}
if (!player._pBlockFlag) {
continue;
}
szCel = "BL";
pData = &player._pBData;
pAnim = &player._pBAnim;
break;
default:
app_fatal("PLR:2");
}
sprintf(pszName, "PlrGFX\\%s\\%s\\%s%s.CL2", cs, prefix, prefix, szCel);
SetPlayerGPtrs(pszName, *pData, *pAnim, player.GetAnimationWidth(static_cast<player_graphic>(i)));
player._pGFXLoad |= i;
} }
sprintf(pszName, "PlrGFX\\%s\\%s\\%s%s.CL2", cs, prefix, prefix, szCel);
auto &animationData = player.AnimationData[static_cast<size_t>(graphic)];
SetPlayerGPtrs(pszName, animationData.RawData, animationData.CelSpritesForDirections, player.GetAnimationWidth(graphic));
} }
void InitPlayerGFX(int pnum) void InitPlayerGFX(int pnum)
@ -550,9 +513,14 @@ void InitPlayerGFX(int pnum)
if (player._pHitPoints >> 6 == 0) { if (player._pHitPoints >> 6 == 0) {
player._pgfxnum = 0; player._pgfxnum = 0;
LoadPlrGFX(player, PFILE_DEATH); LoadPlrGFX(player, player_graphic::Death);
} else { } else {
LoadPlrGFX(player, PFILE_NONDEATH); for (int i = 0; i < enum_size<player_graphic>::value; i++) {
auto graphic = static_cast<player_graphic>(i);
if (graphic == player_graphic::Death)
continue;
LoadPlrGFX(player, graphic);
}
} }
} }
@ -568,67 +536,26 @@ static HeroClass GetPlrGFXClass(HeroClass c)
} }
} }
void InitPlrGFXMem(PlayerStruct &player) void ResetPlayerGFX(PlayerStruct &player)
{ {
FreePlayerGFX(player); player.AnimInfo.pCelSprite = nullptr;
} for (auto &animData : player.AnimationData) {
for (auto &celSprite : animData.CelSpritesForDirections)
void FreePlayerGFX(PlayerStruct &player) celSprite = std::nullopt;
{ animData.RawData = nullptr;
player._pNData = nullptr; }
player._pWData = nullptr;
player._pAData = nullptr;
player._pHData = nullptr;
player._pLData = nullptr;
player._pFData = nullptr;
player._pTData = nullptr;
player._pDData = nullptr;
player._pBData = nullptr;
player._pGFXLoad = 0;
} }
void NewPlrAnim(PlayerStruct &player, player_graphic graphic, Direction dir, int numberOfFrames, int delayLen, AnimationDistributionFlags flags /*= AnimationDistributionFlags::None*/, int numSkippedFrames /*= 0*/, int distributeFramesBeforeFrame /*= 0*/) void NewPlrAnim(PlayerStruct &player, player_graphic graphic, Direction dir, int numberOfFrames, int delayLen, AnimationDistributionFlags flags /*= AnimationDistributionFlags::None*/, int numSkippedFrames /*= 0*/, int distributeFramesBeforeFrame /*= 0*/)
{ {
if ((player._pGFXLoad & graphic) != graphic) if (player.AnimationData[static_cast<size_t>(graphic)].RawData == nullptr)
LoadPlrGFX(player, graphic); LoadPlrGFX(player, graphic);
std::array<std::optional<CelSprite>, 8> *pCelSprites = nullptr; auto &CelSprites = player.AnimationData[static_cast<size_t>(graphic)].CelSpritesForDirections;
switch (graphic) {
case PFILE_STAND:
pCelSprites = &player._pNAnim;
break;
case PFILE_WALK:
pCelSprites = &player._pWAnim;
break;
case PFILE_ATTACK:
pCelSprites = &player._pAAnim;
break;
case PFILE_HIT:
pCelSprites = &player._pHAnim;
break;
case PFILE_LIGHTNING:
pCelSprites = &player._pLAnim;
break;
case PFILE_FIRE:
pCelSprites = &player._pFAnim;
break;
case PFILE_MAGIC:
pCelSprites = &player._pTAnim;
break;
case PFILE_DEATH:
pCelSprites = &player._pDAnim;
break;
case PFILE_BLOCK:
pCelSprites = &player._pBAnim;
break;
default:
Log("NewPlrAnim: Unkown graphic {}", graphic);
break;
}
CelSprite *pCelSprite = nullptr; CelSprite *pCelSprite = nullptr;
if (pCelSprites != nullptr && (*pCelSprites)[dir]) if (CelSprites[dir])
pCelSprite = &*(*pCelSprites)[dir]; pCelSprite = &*CelSprites[dir];
player.AnimInfo.SetNewAnimation(pCelSprite, numberOfFrames, delayLen, flags, numSkippedFrames, distributeFramesBeforeFrame); player.AnimInfo.SetNewAnimation(pCelSprite, numberOfFrames, delayLen, flags, numSkippedFrames, distributeFramesBeforeFrame);
} }
@ -1120,12 +1047,12 @@ void InitPlayer(int pnum, bool FirstTime)
if (player._pHitPoints >> 6 > 0) { if (player._pHitPoints >> 6 > 0) {
player._pmode = PM_STAND; player._pmode = PM_STAND;
NewPlrAnim(player, PFILE_STAND, DIR_S, player._pNFrames, 3); NewPlrAnim(player, player_graphic::Stand, DIR_S, player._pNFrames, 3);
player.AnimInfo.CurrentFrame = GenerateRnd(player._pNFrames - 1) + 1; player.AnimInfo.CurrentFrame = GenerateRnd(player._pNFrames - 1) + 1;
player.AnimInfo.DelayCounter = GenerateRnd(3); player.AnimInfo.DelayCounter = GenerateRnd(3);
} else { } else {
player._pmode = PM_DEATH; player._pmode = PM_DEATH;
NewPlrAnim(player, PFILE_DEATH, DIR_S, player._pDFrames, 1); NewPlrAnim(player, player_graphic::Death, DIR_S, player._pDFrames, 1);
player.AnimInfo.CurrentFrame = player.AnimInfo.NumberOfFrames - 1; player.AnimInfo.CurrentFrame = player.AnimInfo.NumberOfFrames - 1;
} }
@ -1299,7 +1226,7 @@ void StartStand(int pnum, Direction dir)
auto &player = plr[pnum]; auto &player = plr[pnum];
if (!player._pInvincible || player._pHitPoints != 0 || pnum != myplr) { if (!player._pInvincible || player._pHitPoints != 0 || pnum != myplr) {
NewPlrAnim(player, PFILE_STAND, dir, player._pNFrames, 3); NewPlrAnim(player, player_graphic::Stand, dir, player._pNFrames, 3);
player._pmode = PM_STAND; player._pmode = PM_STAND;
FixPlayerLocation(pnum, dir); FixPlayerLocation(pnum, dir);
FixPlrWalkTags(pnum); FixPlrWalkTags(pnum);
@ -1465,7 +1392,7 @@ void StartWalk(int pnum, int xvel, int yvel, int xoff, int yoff, int xadd, int y
skippedFrames = 2; skippedFrames = 2;
if (pmWillBeCalled) if (pmWillBeCalled)
skippedFrames += 1; skippedFrames += 1;
NewPlrAnim(player, PFILE_WALK, EndDir, player._pWFrames, 0, AnimationDistributionFlags::ProcessAnimationPending, skippedFrames); NewPlrAnim(player, player_graphic::Walk, EndDir, player._pWFrames, 0, AnimationDistributionFlags::ProcessAnimationPending, skippedFrames);
player._pdir = EndDir; player._pdir = EndDir;
@ -1512,7 +1439,7 @@ void StartAttack(int pnum, Direction d)
auto animationFlags = AnimationDistributionFlags::ProcessAnimationPending; auto animationFlags = AnimationDistributionFlags::ProcessAnimationPending;
if (player._pmode == PM_ATTACK) if (player._pmode == PM_ATTACK)
animationFlags = static_cast<AnimationDistributionFlags>(animationFlags | AnimationDistributionFlags::RepeatedAction); animationFlags = static_cast<AnimationDistributionFlags>(animationFlags | AnimationDistributionFlags::RepeatedAction);
NewPlrAnim(player, PFILE_ATTACK, d, player._pAFrames, 0, animationFlags, skippedAnimationFrames, player._pAFNum); NewPlrAnim(player, player_graphic::Attack, d, player._pAFrames, 0, animationFlags, skippedAnimationFrames, player._pAFNum);
player._pmode = PM_ATTACK; player._pmode = PM_ATTACK;
FixPlayerLocation(pnum, d); FixPlayerLocation(pnum, d);
SetPlayerOld(player); SetPlayerOld(player);
@ -1540,7 +1467,7 @@ void StartRangeAttack(int pnum, Direction d, int cx, int cy)
auto animationFlags = AnimationDistributionFlags::ProcessAnimationPending; auto animationFlags = AnimationDistributionFlags::ProcessAnimationPending;
if (player._pmode == PM_RATTACK) if (player._pmode == PM_RATTACK)
animationFlags = static_cast<AnimationDistributionFlags>(animationFlags | AnimationDistributionFlags::RepeatedAction); animationFlags = static_cast<AnimationDistributionFlags>(animationFlags | AnimationDistributionFlags::RepeatedAction);
NewPlrAnim(player, PFILE_ATTACK, d, player._pAFrames, 0, animationFlags, skippedAnimationFrames, player._pAFNum); NewPlrAnim(player, player_graphic::Attack, d, player._pAFrames, 0, animationFlags, skippedAnimationFrames, player._pAFNum);
player._pmode = PM_RATTACK; player._pmode = PM_RATTACK;
FixPlayerLocation(pnum, d); FixPlayerLocation(pnum, d);
@ -1567,7 +1494,7 @@ void StartPlrBlock(int pnum, Direction dir)
skippedAnimationFrames = (player._pBFrames - 2); // ISPL_FASTBLOCK means we cancel the animation if frame 2 was shown skippedAnimationFrames = (player._pBFrames - 2); // ISPL_FASTBLOCK means we cancel the animation if frame 2 was shown
} }
NewPlrAnim(player, PFILE_BLOCK, dir, player._pBFrames, 2, AnimationDistributionFlags::SkipsDelayOfLastFrame, skippedAnimationFrames); NewPlrAnim(player, player_graphic::Block, dir, player._pBFrames, 2, AnimationDistributionFlags::SkipsDelayOfLastFrame, skippedAnimationFrames);
player._pmode = PM_BLOCK; player._pmode = PM_BLOCK;
FixPlayerLocation(pnum, dir); FixPlayerLocation(pnum, dir);
@ -1592,13 +1519,13 @@ void StartSpell(int pnum, Direction d, int cx, int cy)
switch (spelldata[player._pSpell].sType) { switch (spelldata[player._pSpell].sType) {
case STYPE_FIRE: case STYPE_FIRE:
NewPlrAnim(player, PFILE_FIRE, d, player._pSFrames, 0, animationFlags, 0, player._pSFNum); NewPlrAnim(player, player_graphic::Fire, d, player._pSFrames, 0, animationFlags, 0, player._pSFNum);
break; break;
case STYPE_LIGHTNING: case STYPE_LIGHTNING:
NewPlrAnim(player, PFILE_LIGHTNING, d, player._pSFrames, 0, animationFlags, 0, player._pSFNum); NewPlrAnim(player, player_graphic::Lightning, d, player._pSFrames, 0, animationFlags, 0, player._pSFNum);
break; break;
case STYPE_MAGIC: case STYPE_MAGIC:
NewPlrAnim(player, PFILE_MAGIC, d, player._pSFrames, 0, animationFlags, 0, player._pSFNum); NewPlrAnim(player, player_graphic::Magic, d, player._pSFrames, 0, animationFlags, 0, player._pSFNum);
break; break;
} }
} else { } else {
@ -1709,7 +1636,7 @@ void StartPlrHit(int pnum, int dam, bool forcehit)
skippedAnimationFrames = 0; skippedAnimationFrames = 0;
} }
NewPlrAnim(player, PFILE_HIT, pd, player._pHFrames, 0, AnimationDistributionFlags::None, skippedAnimationFrames); NewPlrAnim(player, player_graphic::Hit, pd, player._pHFrames, 0, AnimationDistributionFlags::None, skippedAnimationFrames);
player._pmode = PM_GOTHIT; player._pmode = PM_GOTHIT;
FixPlayerLocation(pnum, pd); FixPlayerLocation(pnum, pd);
@ -1796,11 +1723,11 @@ StartPlayerKill(int pnum, int earflag)
if (player._pgfxnum) { if (player._pgfxnum) {
player._pgfxnum = 0; player._pgfxnum = 0;
player._pGFXLoad = 0; ResetPlayerGFX(player);
SetPlrAnims(player); SetPlrAnims(player);
} }
NewPlrAnim(player, PFILE_DEATH, player._pdir, player._pDFrames, 1); NewPlrAnim(player, player_graphic::Death, player._pdir, player._pDFrames, 1);
player._pBlockFlag = false; player._pBlockFlag = false;
player._pmode = PM_DEATH; player._pmode = PM_DEATH;
@ -3812,24 +3739,24 @@ void SyncPlrAnim(int pnum)
} }
auto &player = plr[pnum]; auto &player = plr[pnum];
dir = player._pdir; player_graphic graphic;
switch (player._pmode) { switch (player._pmode) {
case PM_STAND: case PM_STAND:
player.AnimInfo.pCelSprite = &*player._pNAnim[dir]; case PM_NEWLVL:
case PM_QUIT:
graphic = player_graphic::Stand;
break; break;
case PM_WALK: case PM_WALK:
case PM_WALK2: case PM_WALK2:
case PM_WALK3: case PM_WALK3:
player.AnimInfo.pCelSprite = &*player._pWAnim[dir]; graphic = player_graphic::Walk;
break; break;
case PM_ATTACK: case PM_ATTACK:
player.AnimInfo.pCelSprite = &*player._pAAnim[dir];
break;
case PM_RATTACK: case PM_RATTACK:
player.AnimInfo.pCelSprite = &*player._pAAnim[dir]; graphic = player_graphic::Attack;
break; break;
case PM_BLOCK: case PM_BLOCK:
player.AnimInfo.pCelSprite = &*player._pBAnim[dir]; graphic = player_graphic::Block;
break; break;
case PM_SPELL: case PM_SPELL:
if (pnum == myplr) if (pnum == myplr)
@ -3837,27 +3764,23 @@ void SyncPlrAnim(int pnum)
else else
sType = STYPE_FIRE; sType = STYPE_FIRE;
if (sType == STYPE_FIRE) if (sType == STYPE_FIRE)
player.AnimInfo.pCelSprite = &*player._pFAnim[dir]; graphic = player_graphic::Fire;
if (sType == STYPE_LIGHTNING) if (sType == STYPE_LIGHTNING)
player.AnimInfo.pCelSprite = &*player._pLAnim[dir]; graphic = player_graphic::Lightning;
if (sType == STYPE_MAGIC) if (sType == STYPE_MAGIC)
player.AnimInfo.pCelSprite = &*player._pTAnim[dir]; graphic = player_graphic::Magic;
break; break;
case PM_GOTHIT: case PM_GOTHIT:
player.AnimInfo.pCelSprite = &*player._pHAnim[dir]; graphic = player_graphic::Hit;
break;
case PM_NEWLVL:
player.AnimInfo.pCelSprite = &*player._pNAnim[dir];
break; break;
case PM_DEATH: case PM_DEATH:
player.AnimInfo.pCelSprite = &*player._pDAnim[dir]; graphic = player_graphic::Death;
break;
case PM_QUIT:
player.AnimInfo.pCelSprite = &*player._pNAnim[dir];
break; break;
default: default:
app_fatal("SyncPlrAnim"); app_fatal("SyncPlrAnim");
} }
player.AnimInfo.pCelSprite = &*player.AnimationData[static_cast<size_t>(graphic)].CelSpritesForDirections[player._pdir];
} }
void SyncInitPlrPos(int pnum) void SyncInitPlrPos(int pnum)

71
Source/player.h

@ -77,21 +77,18 @@ enum inv_body_loc : uint8_t {
NUM_INVLOC, NUM_INVLOC,
}; };
enum player_graphic : uint16_t { enum class player_graphic : uint16_t {
// clang-format off Stand,
PFILE_STAND = 1 << 0, Walk,
PFILE_WALK = 1 << 1, Attack,
PFILE_ATTACK = 1 << 2, Hit,
PFILE_HIT = 1 << 3, Lightning,
PFILE_LIGHTNING = 1 << 4, Fire,
PFILE_FIRE = 1 << 5, Magic,
PFILE_MAGIC = 1 << 6, Death,
PFILE_DEATH = 1 << 7, Block,
PFILE_BLOCK = 1 << 8,
// everything except PFILE_DEATH LAST = Block
// 0b1_0111_1111
PFILE_NONDEATH = 0x17F
// clang-format on
}; };
enum anim_weapon_id : uint8_t { enum anim_weapon_id : uint8_t {
@ -149,6 +146,21 @@ enum player_weapon_type : uint8_t {
WT_RANGED, WT_RANGED,
}; };
/*
* @brief Contains Data (CelSprites) for a player graphic (player_graphic)
*/
struct PlayerAnimationData {
/*
* @brief CelSprites for the different directions
*/
std::array<std::optional<CelSprite>, 8> CelSpritesForDirections;
/*
* @brief Raw Data (binary) of the CL2 file.
* Is referenced from CelSprite in CelSpritesForDirections
*/
std::unique_ptr<byte[]> RawData;
};
struct PlayerStruct { struct PlayerStruct {
PlayerStruct() = default; PlayerStruct() = default;
PlayerStruct(PlayerStruct &&) noexcept = default; PlayerStruct(PlayerStruct &&) noexcept = default;
@ -237,25 +249,18 @@ struct PlayerStruct {
int deathFrame; int deathFrame;
bool _pLvlVisited[NUMLEVELS]; bool _pLvlVisited[NUMLEVELS];
bool _pSLvlVisited[NUMLEVELS]; // only 10 used bool _pSLvlVisited[NUMLEVELS]; // only 10 used
/** Using player_graphic as bitflags */ /*
int _pGFXLoad; * @brief Contains Data (Sprites) for the different Animations
std::array<std::optional<CelSprite>, 8> _pNAnim; // Stand animations */
std::array<PlayerAnimationData, enum_size<player_graphic>::value> AnimationData;
int _pNFrames; int _pNFrames;
std::array<std::optional<CelSprite>, 8> _pWAnim; // Walk animations
int _pWFrames; int _pWFrames;
std::array<std::optional<CelSprite>, 8> _pAAnim; // Attack animations
int _pAFrames; int _pAFrames;
int _pAFNum; int _pAFNum;
std::array<std::optional<CelSprite>, 8> _pLAnim; // Lightning spell cast animations
std::array<std::optional<CelSprite>, 8> _pFAnim; // Fire spell cast animations
std::array<std::optional<CelSprite>, 8> _pTAnim; // Generic spell cast animations
int _pSFrames; int _pSFrames;
int _pSFNum; int _pSFNum;
std::array<std::optional<CelSprite>, 8> _pHAnim; // Getting hit animations
int _pHFrames; int _pHFrames;
std::array<std::optional<CelSprite>, 8> _pDAnim; // Death animations
int _pDFrames; int _pDFrames;
std::array<std::optional<CelSprite>, 8> _pBAnim; // Block animations
int _pBFrames; int _pBFrames;
ItemStruct InvBody[NUM_INVLOC]; ItemStruct InvBody[NUM_INVLOC];
ItemStruct InvList[NUM_INV_GRID_ELEM]; ItemStruct InvList[NUM_INV_GRID_ELEM];
@ -294,15 +299,6 @@ struct PlayerStruct {
uint8_t pDiabloKillLevel; uint8_t pDiabloKillLevel;
_difficulty pDifficulty; _difficulty pDifficulty;
uint32_t pDamAcFlags; uint32_t pDamAcFlags;
std::unique_ptr<byte[]> _pNData;
std::unique_ptr<byte[]> _pWData;
std::unique_ptr<byte[]> _pAData;
std::unique_ptr<byte[]> _pLData;
std::unique_ptr<byte[]> _pFData;
std::unique_ptr<byte[]> _pTData;
std::unique_ptr<byte[]> _pHData;
std::unique_ptr<byte[]> _pDData;
std::unique_ptr<byte[]> _pBData;
void CalcScrolls(); void CalcScrolls();
@ -408,10 +404,9 @@ extern PlayerStruct plr[MAX_PLRS];
extern bool deathflag; extern bool deathflag;
extern int ToBlkTbl[enum_size<HeroClass>::value]; extern int ToBlkTbl[enum_size<HeroClass>::value];
void LoadPlrGFX(PlayerStruct &player, player_graphic gfxflag); void LoadPlrGFX(PlayerStruct &player, player_graphic graphic);
void InitPlayerGFX(int pnum); void InitPlayerGFX(int pnum);
void InitPlrGFXMem(PlayerStruct &player); void ResetPlayerGFX(PlayerStruct &player);
void FreePlayerGFX(PlayerStruct &player);
/** /**
* @brief Sets the new Player Animation with all relevant information for rendering * @brief Sets the new Player Animation with all relevant information for rendering

1
test/player_test.cpp

@ -13,7 +13,6 @@ int RunBlockTest(int frames, int flags)
int pnum = 0; int pnum = 0;
plr[pnum]._pHFrames = frames; plr[pnum]._pHFrames = frames;
plr[pnum]._pIFlags = flags; plr[pnum]._pIFlags = flags;
plr[pnum]._pGFXLoad = -1;
StartPlrHit(pnum, 5, Direction::DIR_S); StartPlrHit(pnum, 5, Direction::DIR_S);
int i = 1; int i = 1;

Loading…
Cancel
Save