You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

287 lines
7.9 KiB

/**
* @file pack.cpp
*
* Implementation of functions for minifying player data structure.
*/
#include "all.h"
DEVILUTION_BEGIN_NAMESPACE
static void PackItem(PkItemStruct *id, ItemStruct *is)
{
if (is->_itype == ITYPE_NONE) {
id->idx = 0xFFFF;
} else {
id->idx = SwapLE16(is->IDidx);
if (is->IDidx == IDI_EAR) {
id->iCreateInfo = is->_iName[8] | (is->_iName[7] << 8);
id->iSeed = SwapLE32(is->_iName[12] | ((is->_iName[11] | ((is->_iName[10] | (is->_iName[9] << 8)) << 8)) << 8));
id->bId = is->_iName[13];
id->bDur = is->_iName[14];
id->bMDur = is->_iName[15];
id->bCh = is->_iName[16];
id->bMCh = is->_iName[17];
id->wValue = SwapLE16(is->_ivalue | (is->_iName[18] << 8) | ((is->_iCurs - ICURS_EAR_SORCEROR) << 6));
id->dwBuff = SwapLE32(is->_iName[22] | ((is->_iName[21] | ((is->_iName[20] | (is->_iName[19] << 8)) << 8)) << 8));
} else {
id->iSeed = SwapLE32(is->_iSeed);
id->iCreateInfo = SwapLE16(is->_iCreateInfo);
id->bId = is->_iIdentified + 2 * is->_iMagical;
id->bDur = is->_iDurability;
id->bMDur = is->_iMaxDur;
id->bCh = is->_iCharges;
id->bMCh = is->_iMaxCharges;
if (is->IDidx == IDI_GOLD)
id->wValue = SwapLE16(is->_ivalue);
}
}
}
void PackPlayer(PkPlayerStruct *pPack, int pnum, BOOL manashield)
{
PlayerStruct *pPlayer;
int i;
ItemStruct *pi;
PkItemStruct *pki;
memset(pPack, 0, sizeof(*pPack));
pPlayer = &plr[pnum];
pPack->destAction = pPlayer->destAction;
pPack->destParam1 = pPlayer->destParam1;
pPack->destParam2 = pPlayer->destParam2;
pPack->plrlevel = pPlayer->plrlevel;
pPack->px = pPlayer->_px;
pPack->py = pPlayer->_py;
pPack->targx = pPlayer->_ptargx;
pPack->targy = pPlayer->_ptargy;
strcpy(pPack->pName, pPlayer->_pName);
pPack->pClass = pPlayer->_pClass;
pPack->pBaseStr = pPlayer->_pBaseStr;
pPack->pBaseMag = pPlayer->_pBaseMag;
pPack->pBaseDex = pPlayer->_pBaseDex;
pPack->pBaseVit = pPlayer->_pBaseVit;
pPack->pLevel = pPlayer->_pLevel;
pPack->pStatPts = pPlayer->_pStatPts;
pPack->pExperience = SwapLE32(pPlayer->_pExperience);
pPack->pGold = SwapLE32(pPlayer->_pGold);
pPack->pHPBase = SwapLE32(pPlayer->_pHPBase);
pPack->pMaxHPBase = SwapLE32(pPlayer->_pMaxHPBase);
pPack->pManaBase = SwapLE32(pPlayer->_pManaBase);
pPack->pMaxManaBase = SwapLE32(pPlayer->_pMaxManaBase);
pPack->pMemSpells = SDL_SwapLE64(pPlayer->_pMemSpells);
for (i = 0; i < 37; i++) // Should be MAX_SPELLS but set to 37 to make save games compatible
pPack->pSplLvl[i] = pPlayer->_pSplLvl[i];
#ifdef HELLFIRE
for (i = 37; i < 47; i++)
pPack->pSplLvl2[i - 37] = pPlayer->_pSplLvl[i];
#endif
pki = &pPack->InvBody[0];
pi = &pPlayer->InvBody[0];
for (i = 0; i < NUM_INVLOC; i++) {
PackItem(pki, pi);
pki++;
pi++;
}
pki = &pPack->InvList[0];
pi = &pPlayer->InvList[0];
for (i = 0; i < NUM_INV_GRID_ELEM; i++) {
PackItem(pki, pi);
pki++;
pi++;
}
for (i = 0; i < NUM_INV_GRID_ELEM; i++)
pPack->InvGrid[i] = pPlayer->InvGrid[i];
pPack->_pNumInv = pPlayer->_pNumInv;
pki = &pPack->SpdList[0];
pi = &pPlayer->SpdList[0];
for (i = 0; i < MAXBELTITEMS; i++) {
PackItem(pki, pi);
pki++;
pi++;
}
#ifdef HELLFIRE
pPack->wReflection = pPlayer->wReflection;
pPack->pDifficulty = pPlayer->pDifficulty;
pPack->pDamAcFlags = pPlayer->pDamAcFlags;
#endif
pPack->pDiabloKillLevel = SwapLE32(pPlayer->pDiabloKillLevel);
if (gbMaxPlayers == 1 || manashield)
pPack->pManaShield = SwapLE32(pPlayer->pManaShield);
else
pPack->pManaShield = FALSE;
}
/**
* Expand a PkItemStruct in to a ItemStruct
*
* Note: last slot of item[MAXITEMS+1] used as temporary buffer
* find real name reference below, possibly [sizeof(item[])/sizeof(ItemStruct)]
* @param is The source packed item
* @param id The distination item
*/
#ifndef HELLFIRE
static
#endif
void UnPackItem(PkItemStruct *is, ItemStruct *id)
{
WORD idx = SwapLE16(is->idx);
if (idx == 0xFFFF) {
id->_itype = ITYPE_NONE;
} else {
if (idx == IDI_EAR) {
RecreateEar(
MAXITEMS,
SwapLE16(is->iCreateInfo),
SwapLE32(is->iSeed),
is->bId,
is->bDur,
is->bMDur,
is->bCh,
is->bMCh,
SwapLE16(is->wValue),
SwapLE32(is->dwBuff));
} else {
RecreateItem(MAXITEMS, idx, SwapLE16(is->iCreateInfo), SwapLE32(is->iSeed), SwapLE16(is->wValue));
item[MAXITEMS]._iMagical = is->bId >> 1;
item[MAXITEMS]._iIdentified = is->bId & 1;
item[MAXITEMS]._iDurability = is->bDur;
item[MAXITEMS]._iMaxDur = is->bMDur;
item[MAXITEMS]._iCharges = is->bCh;
item[MAXITEMS]._iMaxCharges = is->bMCh;
}
*id = item[MAXITEMS];
}
}
void VerifyGoldSeeds(PlayerStruct *pPlayer)
{
int i, j;
for (i = 0; i < pPlayer->_pNumInv; i++) {
if (pPlayer->InvList[i].IDidx == IDI_GOLD) {
for (j = 0; j < pPlayer->_pNumInv; j++) {
if (i != j) {
if (pPlayer->InvList[j].IDidx == IDI_GOLD && pPlayer->InvList[i]._iSeed == pPlayer->InvList[j]._iSeed) {
pPlayer->InvList[i]._iSeed = GetRndSeed();
j = -1;
}
}
}
}
}
}
void UnPackPlayer(PkPlayerStruct *pPack, int pnum, BOOL killok)
{
PlayerStruct *pPlayer;
int i;
ItemStruct *pi;
PkItemStruct *pki;
pPlayer = &plr[pnum];
ClearPlrRVars(pPlayer);
pPlayer->_px = pPack->px;
pPlayer->_py = pPack->py;
pPlayer->_pfutx = pPack->px;
pPlayer->_pfuty = pPack->py;
pPlayer->_ptargx = pPack->targx;
pPlayer->_ptargy = pPack->targy;
pPlayer->plrlevel = pPack->plrlevel;
ClrPlrPath(pnum);
pPlayer->destAction = ACTION_NONE;
strcpy(pPlayer->_pName, pPack->pName);
pPlayer->_pClass = pPack->pClass;
InitPlayer(pnum, TRUE);
pPlayer->_pBaseStr = pPack->pBaseStr;
pPlayer->_pStrength = pPack->pBaseStr;
pPlayer->_pBaseMag = pPack->pBaseMag;
pPlayer->_pMagic = pPack->pBaseMag;
pPlayer->_pBaseDex = pPack->pBaseDex;
pPlayer->_pDexterity = pPack->pBaseDex;
pPlayer->_pBaseVit = pPack->pBaseVit;
pPlayer->_pVitality = pPack->pBaseVit;
pPlayer->_pLevel = pPack->pLevel;
pPlayer->_pStatPts = pPack->pStatPts;
pPlayer->_pExperience = SwapLE32(pPack->pExperience);
pPlayer->_pGold = SwapLE32(pPack->pGold);
pPlayer->_pMaxHPBase = SwapLE32(pPack->pMaxHPBase);
pPlayer->_pHPBase = SwapLE32(pPack->pHPBase);
pPlayer->_pBaseToBlk = ToBlkTbl[pPlayer->_pClass];
if (!killok)
if ((int)(pPlayer->_pHPBase & 0xFFFFFFC0) < 64)
pPlayer->_pHPBase = 64;
pPlayer->_pMaxManaBase = SwapLE32(pPack->pMaxManaBase);
pPlayer->_pManaBase = SwapLE32(pPack->pManaBase);
pPlayer->_pMemSpells = SDL_SwapLE64(pPack->pMemSpells);
for (i = 0; i < 37; i++) // Should be MAX_SPELLS but set to 37 to make save games compatible
pPlayer->_pSplLvl[i] = pPack->pSplLvl[i];
#ifdef HELLFIRE
for (i = 37; i < 47; i++)
pPlayer->_pSplLvl[i] = pPack->pSplLvl2[i - 37];
#endif
pki = &pPack->InvBody[0];
pi = &pPlayer->InvBody[0];
for (i = 0; i < NUM_INVLOC; i++) {
UnPackItem(pki, pi);
pki++;
pi++;
}
pki = &pPack->InvList[0];
pi = &pPlayer->InvList[0];
for (i = 0; i < NUM_INV_GRID_ELEM; i++) {
UnPackItem(pki, pi);
pki++;
pi++;
}
for (i = 0; i < NUM_INV_GRID_ELEM; i++)
pPlayer->InvGrid[i] = pPack->InvGrid[i];
pPlayer->_pNumInv = pPack->_pNumInv;
VerifyGoldSeeds(pPlayer);
pki = &pPack->SpdList[0];
pi = &pPlayer->SpdList[0];
for (i = 0; i < MAXBELTITEMS; i++) {
UnPackItem(pki, pi);
pki++;
pi++;
}
if (pnum == myplr) {
for (i = 0; i < 20; i++)
witchitem[i]._itype = ITYPE_NONE;
}
CalcPlrInv(pnum, FALSE);
pPlayer->wReflection = pPack->wReflection;
pPlayer->pTownWarps = 0;
pPlayer->pDungMsgs = 0;
pPlayer->pDungMsgs2 = 0;
pPlayer->pLvlLoad = 0;
pPlayer->pDiabloKillLevel = SwapLE32(pPack->pDiabloKillLevel);
pPlayer->pBattleNet = pPack->pBattleNet;
pPlayer->pManaShield = pPack->pManaShield;
pPlayer->pDifficulty = SwapLE32(pPack->pDifficulty);
pPlayer->pDamAcFlags = SwapLE32(pPack->pDamAcFlags);
}
DEVILUTION_END_NAMESPACE