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();
for (auto &player : plr)
FreePlayerGFX(player);
ResetPlayerGFX(player);
FreeCursor();
#ifdef _DEBUG

9
Source/items.cpp

@ -884,13 +884,14 @@ void CalcPlrItemVals(int playerId, bool Loadgfx)
if (player._pgfxnum != g && Loadgfx) {
player._pgfxnum = g;
player._pGFXLoad = 0;
ResetPlayerGFX(player);
SetPlrAnims(player);
LoadPlrGFX(player, static_cast<player_graphic>(PFILE_STAND | PFILE_WALK));
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 {
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 {
player._pgfxnum = g;

6
Source/loadsave.cpp

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

8
Source/msg.cpp

@ -696,7 +696,7 @@ void DeltaSaveLevel()
for (int i = 0; i < MAX_PLRS; i++) {
if (i != myplr)
plr[i]._pGFXLoad = 0;
ResetPlayerGFX(plr[i]);
}
plr[myplr]._pLvlVisited[currlevel] = true;
delta_leave_sync(currlevel);
@ -2225,7 +2225,7 @@ static DWORD On_PLAYER_JOINLEVEL(TCmd *pCmd, int pnum)
else {
plr[pnum]._pLvlChanging = false;
if (plr[pnum]._pName[0] != 0 && !plr[pnum].plractive) {
InitPlrGFXMem(plr[pnum]);
ResetPlayerGFX(plr[pnum]);
plr[pnum].plractive = true;
gbActivePlayers++;
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) {
plr[pnum].position.tile = { p->x, p->y };
plr[pnum].plrlevel = p->wParam1;
plr[pnum]._pGFXLoad = 0;
ResetPlayerGFX(plr[pnum]);
if (currlevel == plr[pnum].plrlevel) {
SyncInitPlr(pnum);
if ((plr[pnum]._pHitPoints >> 6) > 0)
@ -2242,7 +2242,7 @@ static DWORD On_PLAYER_JOINLEVEL(TCmd *pCmd, int pnum)
else {
plr[pnum]._pgfxnum = 0;
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;
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]._pName[0] = '\0';
FreePlayerGFX(plr[pnum]);
ResetPlayerGFX(plr[pnum]);
gbActivePlayers--;
}
}
@ -749,7 +749,7 @@ bool NetInit(bool bSinglePlayer)
SetupLocalCoords();
multi_send_pinfo(-2, CMD_SEND_PLRINFO);
InitPlrGFXMem(plr[myplr]);
ResetPlayerGFX(plr[myplr]);
plr[myplr].plractive = true;
gbActivePlayers = 1;
@ -855,7 +855,7 @@ void recv_plrinfo(int pnum, TCmdPlrInfoHdr *p, bool recv)
return;
}
InitPlrGFXMem(plr[pnum]);
ResetPlayerGFX(plr[pnum]);
plr[pnum].plractive = true;
gbActivePlayers++;
@ -874,7 +874,7 @@ void recv_plrinfo(int pnum, TCmdPlrInfoHdr *p, bool recv)
} else {
plr[pnum]._pgfxnum = 0;
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;
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)
{
switch (graphic) {
case PFILE_STAND:
case player_graphic::Stand:
if (_pClass == HeroClass::Monk)
return 112;
return 96;
case PFILE_WALK:
case player_graphic::Walk:
if (_pClass == HeroClass::Monk)
return 112;
return 96;
case PFILE_ATTACK:
case player_graphic::Attack:
if (_pClass == HeroClass::Monk)
return 130;
if (_pClass == HeroClass::Warrior || _pClass == HeroClass::Barbarian) {
@ -394,23 +394,23 @@ int PlayerStruct::GetAnimationWidth(player_graphic graphic)
return 96;
}
return 128;
case PFILE_HIT:
case player_graphic::Hit:
if (_pClass == HeroClass::Monk)
return 98;
return 96;
case PFILE_LIGHTNING:
case PFILE_FIRE:
case PFILE_MAGIC:
case player_graphic::Lightning:
case player_graphic::Fire:
case player_graphic::Magic:
if (_pClass == HeroClass::Monk)
return 114;
if (_pClass == HeroClass::Sorcerer)
return 128;
return 96;
case PFILE_DEATH:
case player_graphic::Death:
if (_pClass == HeroClass::Monk)
return 160;
return 128;
case PFILE_BLOCK:
case player_graphic::Block:
if (_pClass == HeroClass::Monk)
return 98;
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 pszName[256];
const char *szCel;
std::unique_ptr<byte[]> *pData;
std::array<std::optional<CelSprite>, 8> *pAnim;
HeroClass c = player._pClass;
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]);
const char *cs = ClassPathTbl[static_cast<std::size_t>(c)];
for (unsigned i = 1; i <= PFILE_NONDEATH; i <<= 1) {
if ((i & gfxflag) == 0) {
continue;
}
switch (i) {
case PFILE_STAND:
szCel = "AS";
if (leveltype == DTYPE_TOWN) {
szCel = "ST";
}
pData = &player._pNData;
pAnim = &player._pNAnim;
break;
case PFILE_WALK:
szCel = "AW";
if (leveltype == DTYPE_TOWN) {
szCel = "WL";
}
pData = &player._pWData;
pAnim = &player._pWAnim;
break;
case PFILE_ATTACK:
if (leveltype == DTYPE_TOWN) {
continue;
}
szCel = "AT";
pData = &player._pAData;
pAnim = &player._pAAnim;
break;
case PFILE_HIT:
if (leveltype == DTYPE_TOWN) {
continue;
}
szCel = "HT";
pData = &player._pHData;
pAnim = &player._pHAnim;
break;
case PFILE_LIGHTNING:
if (leveltype == DTYPE_TOWN) {
continue;
}
szCel = "LM";
pData = &player._pLData;
pAnim = &player._pLAnim;
break;
case PFILE_FIRE:
if (leveltype == DTYPE_TOWN) {
continue;
}
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;
switch (graphic) {
case player_graphic::Stand:
szCel = "AS";
if (leveltype == DTYPE_TOWN)
szCel = "ST";
break;
case player_graphic::Walk:
szCel = "AW";
if (leveltype == DTYPE_TOWN)
szCel = "WL";
break;
case player_graphic::Attack:
if (leveltype == DTYPE_TOWN)
return;
szCel = "AT";
break;
case player_graphic::Hit:
if (leveltype == DTYPE_TOWN)
return;
szCel = "HT";
break;
case player_graphic::Lightning:
if (leveltype == DTYPE_TOWN)
return;
szCel = "LM";
break;
case player_graphic::Fire:
if (leveltype == DTYPE_TOWN)
return;
szCel = "FM";
break;
case player_graphic::Magic:
if (leveltype == DTYPE_TOWN)
return;
szCel = "QM";
break;
case player_graphic::Death:
if ((player._pgfxnum & 0xF) != 0)
return;
szCel = "DT";
break;
case player_graphic::Block:
if (leveltype == DTYPE_TOWN)
return;
if (!player._pBlockFlag)
return;
szCel = "BL";
break;
default:
app_fatal("PLR:2");
}
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)
@ -550,9 +513,14 @@ void InitPlayerGFX(int pnum)
if (player._pHitPoints >> 6 == 0) {
player._pgfxnum = 0;
LoadPlrGFX(player, PFILE_DEATH);
LoadPlrGFX(player, player_graphic::Death);
} 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);
}
void FreePlayerGFX(PlayerStruct &player)
{
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;
player.AnimInfo.pCelSprite = nullptr;
for (auto &animData : player.AnimationData) {
for (auto &celSprite : animData.CelSpritesForDirections)
celSprite = std::nullopt;
animData.RawData = nullptr;
}
}
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);
std::array<std::optional<CelSprite>, 8> *pCelSprites = nullptr;
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;
}
auto &CelSprites = player.AnimationData[static_cast<size_t>(graphic)].CelSpritesForDirections;
CelSprite *pCelSprite = nullptr;
if (pCelSprites != nullptr && (*pCelSprites)[dir])
pCelSprite = &*(*pCelSprites)[dir];
if (CelSprites[dir])
pCelSprite = &*CelSprites[dir];
player.AnimInfo.SetNewAnimation(pCelSprite, numberOfFrames, delayLen, flags, numSkippedFrames, distributeFramesBeforeFrame);
}
@ -1120,12 +1047,12 @@ void InitPlayer(int pnum, bool FirstTime)
if (player._pHitPoints >> 6 > 0) {
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.DelayCounter = GenerateRnd(3);
} else {
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;
}
@ -1299,7 +1226,7 @@ void StartStand(int pnum, Direction dir)
auto &player = plr[pnum];
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;
FixPlayerLocation(pnum, dir);
FixPlrWalkTags(pnum);
@ -1465,7 +1392,7 @@ void StartWalk(int pnum, int xvel, int yvel, int xoff, int yoff, int xadd, int y
skippedFrames = 2;
if (pmWillBeCalled)
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;
@ -1512,7 +1439,7 @@ void StartAttack(int pnum, Direction d)
auto animationFlags = AnimationDistributionFlags::ProcessAnimationPending;
if (player._pmode == PM_ATTACK)
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;
FixPlayerLocation(pnum, d);
SetPlayerOld(player);
@ -1540,7 +1467,7 @@ void StartRangeAttack(int pnum, Direction d, int cx, int cy)
auto animationFlags = AnimationDistributionFlags::ProcessAnimationPending;
if (player._pmode == PM_RATTACK)
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;
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
}
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;
FixPlayerLocation(pnum, dir);
@ -1592,13 +1519,13 @@ void StartSpell(int pnum, Direction d, int cx, int cy)
switch (spelldata[player._pSpell].sType) {
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;
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;
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;
}
} else {
@ -1709,7 +1636,7 @@ void StartPlrHit(int pnum, int dam, bool forcehit)
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;
FixPlayerLocation(pnum, pd);
@ -1796,11 +1723,11 @@ StartPlayerKill(int pnum, int earflag)
if (player._pgfxnum) {
player._pgfxnum = 0;
player._pGFXLoad = 0;
ResetPlayerGFX(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._pmode = PM_DEATH;
@ -3812,24 +3739,24 @@ void SyncPlrAnim(int pnum)
}
auto &player = plr[pnum];
dir = player._pdir;
player_graphic graphic;
switch (player._pmode) {
case PM_STAND:
player.AnimInfo.pCelSprite = &*player._pNAnim[dir];
case PM_NEWLVL:
case PM_QUIT:
graphic = player_graphic::Stand;
break;
case PM_WALK:
case PM_WALK2:
case PM_WALK3:
player.AnimInfo.pCelSprite = &*player._pWAnim[dir];
graphic = player_graphic::Walk;
break;
case PM_ATTACK:
player.AnimInfo.pCelSprite = &*player._pAAnim[dir];
break;
case PM_RATTACK:
player.AnimInfo.pCelSprite = &*player._pAAnim[dir];
graphic = player_graphic::Attack;
break;
case PM_BLOCK:
player.AnimInfo.pCelSprite = &*player._pBAnim[dir];
graphic = player_graphic::Block;
break;
case PM_SPELL:
if (pnum == myplr)
@ -3837,27 +3764,23 @@ void SyncPlrAnim(int pnum)
else
sType = STYPE_FIRE;
if (sType == STYPE_FIRE)
player.AnimInfo.pCelSprite = &*player._pFAnim[dir];
graphic = player_graphic::Fire;
if (sType == STYPE_LIGHTNING)
player.AnimInfo.pCelSprite = &*player._pLAnim[dir];
graphic = player_graphic::Lightning;
if (sType == STYPE_MAGIC)
player.AnimInfo.pCelSprite = &*player._pTAnim[dir];
graphic = player_graphic::Magic;
break;
case PM_GOTHIT:
player.AnimInfo.pCelSprite = &*player._pHAnim[dir];
break;
case PM_NEWLVL:
player.AnimInfo.pCelSprite = &*player._pNAnim[dir];
graphic = player_graphic::Hit;
break;
case PM_DEATH:
player.AnimInfo.pCelSprite = &*player._pDAnim[dir];
break;
case PM_QUIT:
player.AnimInfo.pCelSprite = &*player._pNAnim[dir];
graphic = player_graphic::Death;
break;
default:
app_fatal("SyncPlrAnim");
}
player.AnimInfo.pCelSprite = &*player.AnimationData[static_cast<size_t>(graphic)].CelSpritesForDirections[player._pdir];
}
void SyncInitPlrPos(int pnum)

71
Source/player.h

@ -77,21 +77,18 @@ enum inv_body_loc : uint8_t {
NUM_INVLOC,
};
enum player_graphic : uint16_t {
// clang-format off
PFILE_STAND = 1 << 0,
PFILE_WALK = 1 << 1,
PFILE_ATTACK = 1 << 2,
PFILE_HIT = 1 << 3,
PFILE_LIGHTNING = 1 << 4,
PFILE_FIRE = 1 << 5,
PFILE_MAGIC = 1 << 6,
PFILE_DEATH = 1 << 7,
PFILE_BLOCK = 1 << 8,
// everything except PFILE_DEATH
// 0b1_0111_1111
PFILE_NONDEATH = 0x17F
// clang-format on
enum class player_graphic : uint16_t {
Stand,
Walk,
Attack,
Hit,
Lightning,
Fire,
Magic,
Death,
Block,
LAST = Block
};
enum anim_weapon_id : uint8_t {
@ -149,6 +146,21 @@ enum player_weapon_type : uint8_t {
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 {
PlayerStruct() = default;
PlayerStruct(PlayerStruct &&) noexcept = default;
@ -237,25 +249,18 @@ struct PlayerStruct {
int deathFrame;
bool _pLvlVisited[NUMLEVELS];
bool _pSLvlVisited[NUMLEVELS]; // only 10 used
/** Using player_graphic as bitflags */
int _pGFXLoad;
std::array<std::optional<CelSprite>, 8> _pNAnim; // Stand animations
/*
* @brief Contains Data (Sprites) for the different Animations
*/
std::array<PlayerAnimationData, enum_size<player_graphic>::value> AnimationData;
int _pNFrames;
std::array<std::optional<CelSprite>, 8> _pWAnim; // Walk animations
int _pWFrames;
std::array<std::optional<CelSprite>, 8> _pAAnim; // Attack animations
int _pAFrames;
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 _pSFNum;
std::array<std::optional<CelSprite>, 8> _pHAnim; // Getting hit animations
int _pHFrames;
std::array<std::optional<CelSprite>, 8> _pDAnim; // Death animations
int _pDFrames;
std::array<std::optional<CelSprite>, 8> _pBAnim; // Block animations
int _pBFrames;
ItemStruct InvBody[NUM_INVLOC];
ItemStruct InvList[NUM_INV_GRID_ELEM];
@ -294,15 +299,6 @@ struct PlayerStruct {
uint8_t pDiabloKillLevel;
_difficulty pDifficulty;
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();
@ -408,10 +404,9 @@ extern PlayerStruct plr[MAX_PLRS];
extern bool deathflag;
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 InitPlrGFXMem(PlayerStruct &player);
void FreePlayerGFX(PlayerStruct &player);
void ResetPlayerGFX(PlayerStruct &player);
/**
* @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;
plr[pnum]._pHFrames = frames;
plr[pnum]._pIFlags = flags;
plr[pnum]._pGFXLoad = -1;
StartPlrHit(pnum, 5, Direction::DIR_S);
int i = 1;

Loading…
Cancel
Save