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.
1213 lines
28 KiB
1213 lines
28 KiB
#include "diablo.h" |
|
|
|
DEVILUTION_BEGIN_NAMESPACE |
|
|
|
BYTE *tbuff; |
|
|
|
void LoadGame(BOOL firstflag) |
|
{ |
|
int i, j; |
|
DWORD dwLen; |
|
char szName[MAX_PATH]; |
|
BYTE *LoadBuff; |
|
int _ViewX, _ViewY, _nummonsters, _numitems, _nummissiles, _nobjects; |
|
|
|
FreeGameMem(); |
|
pfile_remove_temp_files(); |
|
pfile_get_game_name(szName); |
|
LoadBuff = pfile_read(szName, &dwLen); |
|
tbuff = LoadBuff; |
|
|
|
if (ILoad() != 'RETL') |
|
app_fatal("Invalid save file"); |
|
|
|
setlevel = OLoad(); |
|
setlvlnum = WLoad(); |
|
currlevel = WLoad(); |
|
leveltype = WLoad(); |
|
_ViewX = WLoad(); |
|
_ViewY = WLoad(); |
|
invflag = OLoad(); |
|
chrflag = OLoad(); |
|
_nummonsters = WLoad(); |
|
_numitems = WLoad(); |
|
_nummissiles = WLoad(); |
|
_nobjects = WLoad(); |
|
|
|
for (i = 0; i < NUMLEVELS; i++) { |
|
glSeedTbl[i] = ILoad(); |
|
gnLevelTypeTbl[i] = WLoad(); |
|
} |
|
|
|
LoadPlayer(myplr); |
|
|
|
for (i = 0; i < MAXQUESTS; i++) |
|
LoadQuest(i); |
|
for (i = 0; i < MAXPORTAL; i++) |
|
LoadPortal(i); |
|
|
|
LoadGameLevel(firstflag, 4); |
|
SyncInitPlr(myplr); |
|
SyncPlrAnim(myplr); |
|
|
|
ViewX = _ViewX; |
|
ViewY = _ViewY; |
|
nummonsters = _nummonsters; |
|
numitems = _numitems; |
|
nummissiles = _nummissiles; |
|
nobjects = _nobjects; |
|
|
|
for (i = 0; i < MAXMONSTERS; i++) |
|
monstkills[i] = ILoad(); |
|
|
|
if (leveltype != DTYPE_TOWN) { |
|
for (i = 0; i < MAXMONSTERS; i++) |
|
monstactive[i] = WLoad(); |
|
for (i = 0; i < nummonsters; i++) |
|
LoadMonster(monstactive[i]); |
|
for (i = 0; i < MAXMISSILES; i++) |
|
missileactive[i] = BLoad(); |
|
for (i = 0; i < MAXMISSILES; i++) |
|
missileavail[i] = BLoad(); |
|
for (i = 0; i < nummissiles; i++) |
|
LoadMissile(missileactive[i]); |
|
for (i = 0; i < MAXOBJECTS; i++) |
|
objectactive[i] = BLoad(); |
|
for (i = 0; i < MAXOBJECTS; i++) |
|
objectavail[i] = BLoad(); |
|
for (i = 0; i < nobjects; i++) |
|
LoadObject(objectactive[i]); |
|
for (i = 0; i < nobjects; i++) |
|
SyncObjectAnim(objectactive[i]); |
|
|
|
numlights = WLoad(); |
|
|
|
for (i = 0; i < MAXLIGHTS; i++) |
|
lightactive[i] = BLoad(); |
|
for (i = 0; i < numlights; i++) |
|
LoadLighting(lightactive[i]); |
|
|
|
visionid = WLoad(); |
|
numvision = WLoad(); |
|
|
|
for (i = 0; i < numvision; i++) |
|
LoadVision(i); |
|
} |
|
|
|
for (i = 0; i < MAXITEMS; i++) |
|
itemactive[i] = BLoad(); |
|
for (i = 0; i < MAXITEMS; i++) |
|
itemavail[i] = BLoad(); |
|
for (i = 0; i < numitems; i++) |
|
LoadItem(itemactive[i]); |
|
for (i = 0; i < 128; i++) |
|
UniqueItemFlag[i] = OLoad(); |
|
|
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
dLight[i][j] = BLoad(); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
dFlags[i][j] = BLoad(); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
dPlayer[i][j] = BLoad(); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
dItem[i][j] = BLoad(); |
|
} |
|
|
|
if (leveltype != DTYPE_TOWN) { |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
dMonster[i][j] = WLoad(); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
dDead[i][j] = BLoad(); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
dObject[i][j] = BLoad(); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
dLight[i][j] = BLoad(); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
dPreLight[i][j] = BLoad(); |
|
} |
|
for (j = 0; j < DMAXY; j++) { |
|
for (i = 0; i < DMAXX; i++) |
|
automapview[i][j] = OLoad(); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
dMissile[i][j] = BLoad(); |
|
} |
|
} |
|
|
|
numpremium = WLoad(); |
|
premiumlevel = WLoad(); |
|
|
|
for (i = 0; i < 6; i++) |
|
LoadPremium(i); |
|
|
|
automapflag = OLoad(); |
|
AutoMapScale = WLoad(); |
|
mem_free_dbg(LoadBuff); |
|
AutomapZoomReset(); |
|
ResyncQuests(); |
|
|
|
if (leveltype != DTYPE_TOWN) |
|
ProcessLightList(); |
|
|
|
RedoPlayerVision(); |
|
ProcessVisionList(); |
|
missiles_process_charge(); |
|
ResetPal(); |
|
SetCursor_(CURSOR_HAND); |
|
gbProcessPlayers = TRUE; |
|
} |
|
|
|
// Load a byte-size char from the buffer |
|
char BLoad() |
|
{ |
|
return *tbuff++; |
|
} |
|
|
|
// Redundant? |
|
int WLoad() |
|
{ |
|
int rv = *tbuff++ << 24; |
|
rv |= *tbuff++ << 16; |
|
rv |= *tbuff++ << 8; |
|
rv |= *tbuff++; |
|
|
|
return rv; |
|
} |
|
|
|
// Load a 32 bit integer from the buffer |
|
int ILoad() |
|
{ |
|
int rv = *tbuff++ << 24; |
|
rv |= *tbuff++ << 16; |
|
rv |= *tbuff++ << 8; |
|
rv |= *tbuff++; |
|
|
|
return rv; |
|
} |
|
|
|
BOOL OLoad() |
|
{ |
|
if (*tbuff++ == TRUE) |
|
return TRUE; |
|
else |
|
return FALSE; |
|
} |
|
|
|
// Consume an int from tbuff with memcpy - copies directly, doesn't change byte order |
|
void CopyInt(int & dst) |
|
{ |
|
memcpy(&dst, tbuff, 4); |
|
tbuff += 4; |
|
} |
|
|
|
void CopyInt(unsigned int & dst) |
|
{ |
|
memcpy(&dst, tbuff, 4); |
|
tbuff += 4; |
|
} |
|
|
|
void CopyShort(unsigned short & dst) |
|
{ |
|
memcpy(&dst, tbuff, 2); |
|
tbuff += 2; |
|
} |
|
|
|
void CopyShort(short & dst) |
|
{ |
|
memcpy(&dst, tbuff, 2); |
|
tbuff += 2; |
|
} |
|
|
|
void CopyShorts(const int n, unsigned short * dst) |
|
{ |
|
memcpy(dst, tbuff, 2 * n); |
|
tbuff += 2 * n; |
|
} |
|
|
|
// Copy an int array of size n |
|
void CopyInts(const int n, int* dst) |
|
{ |
|
memcpy(dst, tbuff, 4 * n); |
|
tbuff += 4 * n; |
|
} |
|
|
|
void CopyBytes(const int n, unsigned char *dst) |
|
{ |
|
memcpy(dst, tbuff, n); |
|
tbuff += n; |
|
} |
|
|
|
void CopyChar(unsigned char & dst) |
|
{ |
|
memcpy(&dst, tbuff, 1); |
|
tbuff += 1; |
|
} |
|
|
|
void CopyChar(char & dst) |
|
{ |
|
memcpy(&dst, tbuff, 1); |
|
tbuff += 1; |
|
} |
|
|
|
void CopyInt64(long long unsigned int & dst) |
|
{ |
|
memcpy(&dst, tbuff, 8); |
|
tbuff += 8; |
|
} |
|
|
|
void LoadPlayer(int i) |
|
{ |
|
PlayerStruct *pPlayer = &plr[i]; |
|
CopyInt(pPlayer->_pmode); |
|
CopyBytes(25, pPlayer->walkpath); |
|
CopyBytes(1, &pPlayer->plractive); |
|
tbuff += 2; // Some padding here? |
|
CopyInt(pPlayer->destAction); |
|
CopyInt(pPlayer->destParam1); |
|
CopyInt(pPlayer->destParam2); |
|
CopyInt(pPlayer->destParam3); |
|
CopyInt(pPlayer->destParam4); |
|
CopyInt(pPlayer->plrlevel); |
|
CopyInt(pPlayer->WorldX); |
|
CopyInt(pPlayer->WorldY); |
|
CopyInt(pPlayer->_px); |
|
CopyInt(pPlayer->_py); |
|
CopyInt(pPlayer->_ptargx); |
|
CopyInt(pPlayer->_ptargy); |
|
CopyInt(pPlayer->_pownerx); |
|
CopyInt(pPlayer->_pownery); |
|
CopyInt(pPlayer->_poldx); |
|
CopyInt(pPlayer->_poldy); |
|
CopyInt(pPlayer->_pxoff); |
|
CopyInt(pPlayer->_pyoff); |
|
CopyInt(pPlayer->_pxvel); |
|
CopyInt(pPlayer->_pyvel); |
|
CopyInt(pPlayer->_pdir); |
|
CopyInt(pPlayer->_nextdir); |
|
CopyInt(pPlayer->_pgfxnum); |
|
tbuff += 4; // Skip pointers |
|
CopyInt(pPlayer->_pAnimDelay); |
|
CopyInt(pPlayer->_pAnimCnt); |
|
CopyInt(pPlayer->_pAnimLen); |
|
CopyInt(pPlayer->_pAnimFrame); |
|
CopyInt(pPlayer->_pAnimWidth); |
|
CopyInt(pPlayer->_pAnimWidth2); |
|
CopyInt(pPlayer->_peflag); |
|
CopyInt(pPlayer->_plid); |
|
CopyInt(pPlayer->_pvid); |
|
|
|
CopyInt(pPlayer->_pSpell); |
|
CopyChar(pPlayer->_pSplType); |
|
CopyChar(pPlayer->_pSplFrom); |
|
CopyInt(pPlayer->_pTSpell); |
|
CopyChar(pPlayer->_pTSplType); |
|
tbuff += 5; |
|
CopyInt(pPlayer->_pRSpell); |
|
CopyChar(pPlayer->_pRSplType); |
|
tbuff += 3; |
|
CopyInt(pPlayer->_pSBkSpell); |
|
CopyChar(pPlayer->_pSBkSplType); |
|
|
|
CopyBytes(64, pPlayer->_pSplLvl); |
|
tbuff += 7; |
|
CopyInt64(pPlayer->_pMemSpells); |
|
CopyInt64(pPlayer->_pAblSpells); |
|
CopyInt64(pPlayer->_pScrlSpells); |
|
CopyChar(pPlayer->_pSpellFlags); |
|
tbuff += 3; |
|
CopyInts(4, pPlayer->_pSplHotKey); |
|
CopyBytes(4, pPlayer->_pSplTHotKey); |
|
CopyInt(pPlayer->_pwtype); |
|
CopyChar(pPlayer->_pBlockFlag); |
|
CopyChar(pPlayer->_pInvincible); |
|
CopyChar(pPlayer->_pLightRad); |
|
CopyChar(pPlayer->_pLvlChanging); |
|
CopyBytes(PLR_NAME_LEN, pPlayer->_pName); |
|
CopyChar(pPlayer->_pClass); |
|
tbuff += 3; |
|
CopyInt(pPlayer->_pStrength); |
|
CopyInt(pPlayer->_pBaseStr); |
|
CopyInt(pPlayer->_pMagic); |
|
CopyInt(pPlayer->_pBaseMag); |
|
CopyInt(pPlayer->_pDexterity); |
|
CopyInt(pPlayer->_pBaseDex); |
|
CopyInt(pPlayer->_pVitality); |
|
CopyInt(pPlayer->_pBaseVit); |
|
CopyInt(pPlayer->_pStatPts); |
|
CopyInt(pPlayer->_pDamageMod); |
|
CopyInt(pPlayer->_pBaseToBlk); |
|
CopyInt(pPlayer->_pHPBase); |
|
CopyInt(pPlayer->_pMaxHPBase); |
|
CopyInt(pPlayer->_pHitPoints); |
|
CopyInt(pPlayer->_pMaxHP); |
|
CopyInt(pPlayer->_pHPPer); |
|
CopyInt(pPlayer->_pManaBase); |
|
CopyInt(pPlayer->_pMaxManaBase); |
|
CopyInt(pPlayer->_pMana); |
|
CopyInt(pPlayer->_pMaxMana); |
|
CopyInt(pPlayer->_pManaPer); |
|
CopyChar(pPlayer->_pLevel); |
|
CopyChar(pPlayer->_pMaxLvl); |
|
tbuff += 2; |
|
CopyInt(pPlayer->_pExperience); |
|
CopyInt(pPlayer->_pMaxExp); |
|
CopyInt(pPlayer->_pNextExper); |
|
CopyChar(pPlayer->_pArmorClass); |
|
CopyChar(pPlayer->_pMagResist); |
|
CopyChar(pPlayer->_pFireResist); |
|
CopyChar(pPlayer->_pLghtResist); |
|
CopyInt(pPlayer->_pGold); |
|
CopyInt(pPlayer->_pInfraFlag); |
|
CopyInt(pPlayer->_pVar1); |
|
CopyInt(pPlayer->_pVar2); |
|
CopyInt(pPlayer->_pVar3); |
|
CopyInt(pPlayer->_pVar4); |
|
CopyInt(pPlayer->_pVar5); |
|
CopyInt(pPlayer->_pVar6); |
|
CopyInt(pPlayer->_pVar7); |
|
CopyInt(pPlayer->_pVar8); |
|
CopyBytes(NUMLEVELS, pPlayer->_pLvlVisited); |
|
CopyBytes(NUMLEVELS, pPlayer->_pSLvlVisited); // only 10 used |
|
tbuff += 2; |
|
CopyInt(pPlayer->_pGFXLoad); |
|
|
|
tbuff += sizeof(__uint32_t) * 8; // Skip 8 pointers |
|
CopyInt(pPlayer->_pNFrames); |
|
CopyInt(pPlayer->_pNWidth); |
|
|
|
tbuff += sizeof(__uint32_t) * 8; // Skip 8 pointers |
|
|
|
CopyInt(pPlayer->_pWFrames); |
|
CopyInt(pPlayer->_pWWidth); |
|
|
|
tbuff += sizeof(__uint32_t) * 8; // Skip 8 pointers |
|
|
|
CopyInt(pPlayer->_pAFrames); |
|
CopyInt(pPlayer->_pAWidth); |
|
CopyInt(pPlayer->_pAFNum); |
|
|
|
tbuff += sizeof(__uint32_t) * 24; // Skip 24 pointers |
|
|
|
CopyInt(pPlayer->_pSFrames); |
|
CopyInt(pPlayer->_pSWidth); |
|
CopyInt(pPlayer->_pSFNum); |
|
|
|
tbuff += sizeof(__uint32_t) * 8; // Skip 8 pointers |
|
|
|
CopyInt(pPlayer->_pHFrames); |
|
CopyInt(pPlayer->_pHWidth); |
|
|
|
tbuff += sizeof(__uint32_t) * 8; // Skip 8 pointers |
|
|
|
CopyInt(pPlayer->_pDFrames); |
|
CopyInt(pPlayer->_pDWidth); |
|
|
|
tbuff += sizeof(__uint32_t) * 8; // Skip 8 pointers |
|
|
|
CopyInt(pPlayer->_pBFrames); |
|
CopyInt(pPlayer->_pBWidth); |
|
|
|
CopyItems(NUM_INVLOC, pPlayer->InvBody); |
|
CopyItems(NUM_INV_GRID_ELEM, pPlayer->InvList); |
|
|
|
CopyInt(pPlayer->_pNumInv); |
|
CopyBytes(NUM_INV_GRID_ELEM, pPlayer->InvGrid); |
|
CopyItems(MAXBELTITEMS, pPlayer->SpdList); |
|
CopyItem(&pPlayer->HoldItem); |
|
CopyInt(pPlayer->_pIMinDam); |
|
CopyInt(pPlayer->_pIMaxDam); |
|
CopyInt(pPlayer->_pIAC); |
|
CopyInt(pPlayer->_pIBonusDam); |
|
CopyInt(pPlayer->_pIBonusToHit); |
|
CopyInt(pPlayer->_pIBonusAC); |
|
CopyInt(pPlayer->_pIBonusDamMod); |
|
tbuff += 4; |
|
CopyInt64(pPlayer->_pISpells); |
|
CopyInt(pPlayer->_pIFlags); |
|
CopyInt(pPlayer->_pIGetHit); |
|
CopyChar(pPlayer->_pISplLvlAdd); |
|
CopyChar(pPlayer->_pISplCost); |
|
tbuff += 2; |
|
CopyInt(pPlayer->_pISplDur); |
|
CopyInt(pPlayer->_pIEnAc); |
|
CopyInt(pPlayer->_pIFMinDam); |
|
CopyInt(pPlayer->_pIFMaxDam); |
|
CopyInt(pPlayer->_pILMinDam); |
|
CopyInt(pPlayer->_pILMaxDam); |
|
CopyInt(pPlayer->_pOilType); |
|
CopyChar(pPlayer->pTownWarps); |
|
CopyChar(pPlayer->pDungMsgs); |
|
CopyChar(pPlayer->pLvlLoad); |
|
CopyChar(pPlayer->pBattleNet); |
|
CopyChar(pPlayer->pManaShield); |
|
CopyBytes(3, pPlayer->bReserved); |
|
CopyShorts(8, pPlayer->wReserved); |
|
CopyInt(pPlayer->pDiabloKillLevel); |
|
CopyInts(7, pPlayer->dwReserved); |
|
|
|
// Omit 10 pointers |
|
|
|
} |
|
|
|
void LoadMonster(int i) |
|
{ |
|
MonsterStruct *pMonster = &monster[i]; |
|
|
|
CopyInt(pMonster->_mMTidx); |
|
CopyInt(pMonster->_mmode); |
|
|
|
CopyChar(pMonster->_mgoal); |
|
tbuff += 3; |
|
|
|
CopyInt(pMonster->_mgoalvar1); |
|
CopyInt(pMonster->_mgoalvar2); |
|
CopyInt(pMonster->_mgoalvar3); |
|
CopyInt(pMonster->field_18); |
|
|
|
CopyChar(pMonster->_pathcount); |
|
tbuff += 3; |
|
|
|
CopyInt(pMonster->_mx); |
|
CopyInt(pMonster->_my); |
|
CopyInt(pMonster->_mfutx); |
|
CopyInt(pMonster->_mfuty); |
|
CopyInt(pMonster->_moldx); |
|
CopyInt(pMonster->_moldy); |
|
CopyInt(pMonster->_mxoff); |
|
CopyInt(pMonster->_myoff); |
|
CopyInt(pMonster->_mxvel); |
|
CopyInt(pMonster->_myvel); |
|
CopyInt(pMonster->_mdir); |
|
CopyInt(pMonster->_menemy); |
|
|
|
CopyChar(pMonster->_menemyx); |
|
CopyChar(pMonster->_menemyy); |
|
CopyShort(pMonster->falign_52); |
|
|
|
tbuff += 4; // Skip pointer |
|
CopyInt(pMonster->_mAnimDelay); |
|
CopyInt(pMonster->_mAnimCnt); |
|
CopyInt(pMonster->_mAnimLen); |
|
CopyInt(pMonster->_mAnimFrame); |
|
CopyInt(pMonster->_meflag); |
|
CopyInt(pMonster->_mDelFlag); |
|
CopyInt(pMonster->_mVar1); |
|
CopyInt(pMonster->_mVar2); |
|
CopyInt(pMonster->_mVar3); |
|
CopyInt(pMonster->_mVar4); |
|
CopyInt(pMonster->_mVar5); |
|
CopyInt(pMonster->_mVar6); |
|
CopyInt(pMonster->_mVar7); |
|
CopyInt(pMonster->_mVar8); |
|
CopyInt(pMonster->_mmaxhp); |
|
CopyInt(pMonster->_mhitpoints); |
|
|
|
CopyChar(pMonster->_mAi); |
|
CopyChar(pMonster->_mint); |
|
CopyShort(pMonster->falign_9A); |
|
|
|
CopyInt(pMonster->_mFlags); |
|
|
|
CopyChar(pMonster->_msquelch); |
|
tbuff += 3; |
|
|
|
CopyInt(pMonster->falign_A4); |
|
CopyInt(pMonster->_lastx); |
|
CopyInt(pMonster->_lasty); |
|
CopyInt(pMonster->_mRndSeed); |
|
CopyInt(pMonster->_mAISeed); |
|
CopyInt(pMonster->falign_B8); |
|
|
|
CopyChar(pMonster->_uniqtype); |
|
CopyChar(pMonster->_uniqtrans); |
|
CopyChar(pMonster->_udeadval); |
|
CopyChar(pMonster->mWhoHit); |
|
|
|
CopyChar(pMonster->mLevel); |
|
CopyShort(pMonster->mExp); |
|
tbuff += 1; |
|
|
|
CopyChar(pMonster->mHit); |
|
CopyChar(pMonster->mMinDamage); |
|
CopyChar(pMonster->mMaxDamage); |
|
CopyChar(pMonster->mHit2); |
|
|
|
CopyChar(pMonster->mMinDamage2); |
|
CopyChar(pMonster->mMaxDamage2); |
|
CopyChar(pMonster->mArmorClass); |
|
CopyChar(pMonster->falign_CB); |
|
|
|
CopyShort(pMonster->mMagicRes); |
|
tbuff += 2; |
|
|
|
CopyInt(pMonster->mtalkmsg); |
|
|
|
CopyChar(pMonster->leader); |
|
CopyChar(pMonster->leaderflag); |
|
CopyChar(pMonster->packsize); |
|
CopyChar(pMonster->mlid); |
|
|
|
SyncMonsterAnim(i); |
|
} |
|
|
|
void LoadMissile(int i) |
|
{ |
|
MissileStruct *pMissile = &missile[i]; |
|
|
|
CopyInt(pMissile->_mitype); |
|
CopyInt(pMissile->_mix); |
|
CopyInt(pMissile->_miy); |
|
CopyInt(pMissile->_mixoff); |
|
CopyInt(pMissile->_miyoff); |
|
CopyInt(pMissile->_mixvel); |
|
CopyInt(pMissile->_miyvel); |
|
CopyInt(pMissile->_misx); |
|
CopyInt(pMissile->_misy); |
|
CopyInt(pMissile->_mitxoff); |
|
CopyInt(pMissile->_mityoff); |
|
CopyInt(pMissile->_mimfnum); |
|
CopyInt(pMissile->_mispllvl); |
|
CopyInt(pMissile->_miDelFlag); |
|
CopyChar(pMissile->_miAnimType); |
|
tbuff += 3; |
|
|
|
CopyInt(pMissile->_miAnimFlags); |
|
tbuff += 4; |
|
CopyInt(pMissile->_miAnimDelay); |
|
CopyInt(pMissile->_miAnimLen); |
|
CopyInt(pMissile->_miAnimWidth); |
|
CopyInt(pMissile->_miAnimWidth2); |
|
CopyInt(pMissile->_miAnimCnt); |
|
CopyInt(pMissile->_miAnimAdd); |
|
CopyInt(pMissile->_miAnimFrame); |
|
CopyInt(pMissile->_miDrawFlag); |
|
CopyInt(pMissile->_miLightFlag); |
|
CopyInt(pMissile->_miPreFlag); |
|
CopyInt(pMissile->_miUniqTrans); |
|
CopyInt(pMissile->_mirange); |
|
CopyInt(pMissile->_misource); |
|
CopyInt(pMissile->_micaster); |
|
CopyInt(pMissile->_midam); |
|
CopyInt(pMissile->_miHitFlag); |
|
CopyInt(pMissile->_midist); |
|
CopyInt(pMissile->_mlid); |
|
CopyInt(pMissile->_mirnd); |
|
CopyInt(pMissile->_miVar1); |
|
CopyInt(pMissile->_miVar2); |
|
CopyInt(pMissile->_miVar3); |
|
CopyInt(pMissile->_miVar4); |
|
CopyInt(pMissile->_miVar5); |
|
CopyInt(pMissile->_miVar6); |
|
CopyInt(pMissile->_miVar7); |
|
CopyInt(pMissile->_miVar8); |
|
} |
|
|
|
void LoadObject(int i) |
|
{ |
|
ObjectStruct *pObject = &object[i]; |
|
CopyInt(pObject->_otype); |
|
CopyInt(pObject->_ox); |
|
CopyInt(pObject->_oy); |
|
CopyInt(pObject->_oLight); |
|
CopyInt(pObject->_oAnimFlag); |
|
tbuff += 4; |
|
CopyInt(pObject->_oAnimDelay); |
|
CopyInt(pObject->_oAnimCnt); |
|
CopyInt(pObject->_oAnimLen); |
|
CopyInt(pObject->_oAnimFrame); |
|
CopyInt(pObject->_oAnimWidth); |
|
CopyInt(pObject->_oAnimWidth2); |
|
CopyInt(pObject->_oDelFlag); |
|
|
|
CopyChar(pObject->_oBreak); |
|
tbuff += 3; |
|
|
|
CopyInt(pObject->_oSolidFlag); |
|
CopyInt(pObject->_oMissFlag); |
|
|
|
CopyChar(pObject->_oSelFlag); |
|
tbuff += 3; |
|
|
|
CopyInt(pObject->_oPreFlag); |
|
CopyInt(pObject->_oTrapFlag); |
|
CopyInt(pObject->_oDoorFlag); |
|
CopyInt(pObject->_olid); |
|
CopyInt(pObject->_oRndSeed); |
|
CopyInt(pObject->_oVar1); |
|
CopyInt(pObject->_oVar2); |
|
CopyInt(pObject->_oVar3); |
|
CopyInt(pObject->_oVar4); |
|
CopyInt(pObject->_oVar5); |
|
CopyInt(pObject->_oVar6); |
|
CopyInt(pObject->_oVar7); |
|
CopyInt(pObject->_oVar8); |
|
} |
|
|
|
void LoadItem(int i) |
|
{ |
|
CopyItem(&item[i]); |
|
GetItemFrm(i); |
|
} |
|
|
|
void CopyItem(ItemStruct *pItem) |
|
{ |
|
CopyInt(pItem->_iSeed); |
|
CopyShort(pItem->_iCreateInfo); |
|
tbuff += 2; |
|
CopyInt(pItem->_itype); |
|
CopyInt(pItem->_ix); |
|
CopyInt(pItem->_iy); |
|
CopyInt(pItem->_iAnimFlag); |
|
tbuff += 4; // Skip pointer _iAnimData |
|
CopyInt(pItem->_iAnimLen); |
|
CopyInt(pItem->_iAnimFrame); |
|
CopyInt(pItem->_iAnimWidth); |
|
CopyInt(pItem->_iAnimWidth2); // width 2? |
|
CopyInt(pItem->_isin); // set when item is flagged for deletion, deprecated in 1.02 |
|
CopyChar(pItem->_iSelFlag); |
|
tbuff += 3; |
|
CopyInt(pItem->_iPostDraw); |
|
CopyInt(pItem->_iIdentified); |
|
CopyChar(pItem->_iMagical); |
|
CopyBytes(64, pItem->_iName); |
|
CopyBytes(64, pItem->_iIName); |
|
CopyChar(pItem->_iLoc); |
|
CopyChar(pItem->_iClass); |
|
tbuff += 1; |
|
CopyInt(pItem->_iCurs); |
|
CopyInt(pItem->_ivalue); |
|
CopyInt(pItem->_iIvalue); |
|
CopyInt(pItem->_iMinDam); |
|
CopyInt(pItem->_iMaxDam); |
|
CopyInt(pItem->_iAC); |
|
CopyInt(pItem->_iFlags); |
|
CopyInt(pItem->_iMiscId); |
|
CopyInt(pItem->_iSpell); |
|
CopyInt(pItem->_iCharges); |
|
CopyInt(pItem->_iMaxCharges); |
|
CopyInt(pItem->_iDurability); |
|
CopyInt(pItem->_iMaxDur); |
|
CopyInt(pItem->_iPLDam); |
|
CopyInt(pItem->_iPLToHit); |
|
CopyInt(pItem->_iPLAC); |
|
CopyInt(pItem->_iPLStr); |
|
CopyInt(pItem->_iPLMag); |
|
CopyInt(pItem->_iPLDex); |
|
CopyInt(pItem->_iPLVit); |
|
CopyInt(pItem->_iPLFR); |
|
CopyInt(pItem->_iPLLR); |
|
CopyInt(pItem->_iPLMR); |
|
CopyInt(pItem->_iPLMana); |
|
CopyInt(pItem->_iPLHP); |
|
CopyInt(pItem->_iPLDamMod); |
|
CopyInt(pItem->_iPLGetHit); |
|
CopyInt(pItem->_iPLLight); |
|
CopyChar(pItem->_iSplLvlAdd); |
|
CopyChar(pItem->_iRequest); |
|
tbuff += 2; |
|
CopyInt(pItem->_iUid); |
|
CopyInt(pItem->_iFMinDam); |
|
CopyInt(pItem->_iFMaxDam); |
|
CopyInt(pItem->_iLMinDam); |
|
CopyInt(pItem->_iLMaxDam); |
|
CopyInt(pItem->_iPLEnAc); |
|
CopyChar(pItem->_iPrePower); |
|
CopyChar(pItem->_iSufPower); |
|
tbuff += 2; |
|
CopyInt(pItem->_iVAdd1); |
|
CopyInt(pItem->_iVMult1); |
|
CopyInt(pItem->_iVAdd2); |
|
CopyInt(pItem->_iVMult2); |
|
CopyChar(pItem->_iMinStr); |
|
CopyChar(pItem->_iMinMag); |
|
CopyChar(pItem->_iMinDex); |
|
tbuff += 1; |
|
CopyInt(pItem->_iStatFlag); |
|
CopyInt(pItem->IDidx); |
|
CopyInt(pItem->offs016C); |
|
} |
|
|
|
void CopyItems(const int n, ItemStruct *pItem) |
|
{ |
|
for (int i = 0; i < n; i++) |
|
{ |
|
CopyItem(&pItem[i]); |
|
} |
|
} |
|
|
|
void LoadPremium(int i) |
|
{ |
|
memcpy(&premiumitem[i], tbuff, sizeof(*premiumitem)); |
|
tbuff += sizeof(*premiumitem); |
|
} |
|
|
|
void LoadQuest(int i) |
|
{ |
|
memcpy(&quests[i], tbuff, sizeof(*quests)); |
|
tbuff += sizeof(*quests); |
|
ReturnLvlX = WLoad(); |
|
ReturnLvlY = WLoad(); |
|
ReturnLvl = WLoad(); |
|
ReturnLvlT = WLoad(); |
|
DoomQuestState = WLoad(); |
|
} |
|
|
|
void LoadLighting(int i) |
|
{ |
|
memcpy(&LightList[i], tbuff, sizeof(*LightList)); |
|
tbuff += sizeof(*LightList); |
|
} |
|
|
|
void LoadVision(int i) |
|
{ |
|
memcpy(&VisionList[i], tbuff, sizeof(*VisionList)); |
|
tbuff += sizeof(*VisionList); |
|
} |
|
|
|
void LoadPortal(int i) |
|
{ |
|
memcpy(&portal[i], tbuff, sizeof(*portal)); |
|
tbuff += sizeof(*portal); |
|
} |
|
|
|
void SaveGame() |
|
{ |
|
int i, j; |
|
char szName[MAX_PATH]; |
|
|
|
DWORD dwLen = codec_get_encoded_len(FILEBUFF); |
|
BYTE *SaveBuff = DiabloAllocPtr(dwLen); |
|
tbuff = SaveBuff; |
|
|
|
ISave('RETL'); |
|
OSave((unsigned char)setlevel); |
|
WSave(setlvlnum); |
|
WSave(currlevel); |
|
WSave((unsigned char)leveltype); |
|
WSave(ViewX); |
|
WSave(ViewY); |
|
OSave(invflag); |
|
OSave(chrflag); |
|
WSave(nummonsters); |
|
WSave(numitems); |
|
WSave(nummissiles); |
|
WSave(nobjects); |
|
|
|
for (i = 0; i < NUMLEVELS; i++) { |
|
ISave(glSeedTbl[i]); |
|
WSave(gnLevelTypeTbl[i]); |
|
} |
|
|
|
SavePlayer(myplr); |
|
|
|
for (i = 0; i < MAXQUESTS; i++) |
|
SaveQuest(i); |
|
for (i = 0; i < MAXPORTAL; i++) |
|
SavePortal(i); |
|
for (i = 0; i < MAXMONSTERS; i++) |
|
ISave(monstkills[i]); |
|
|
|
if (leveltype != DTYPE_TOWN) { |
|
for (i = 0; i < MAXMONSTERS; i++) |
|
WSave(monstactive[i]); |
|
for (i = 0; i < nummonsters; i++) |
|
SaveMonster(monstactive[i]); |
|
for (i = 0; i < MAXMISSILES; i++) |
|
BSave(missileactive[i]); |
|
for (i = 0; i < MAXMISSILES; i++) |
|
BSave(missileavail[i]); |
|
for (i = 0; i < nummissiles; i++) |
|
SaveMissile(missileactive[i]); |
|
for (i = 0; i < MAXOBJECTS; i++) |
|
BSave(objectactive[i]); |
|
for (i = 0; i < MAXOBJECTS; i++) |
|
BSave(objectavail[i]); |
|
for (i = 0; i < nobjects; i++) |
|
SaveObject(objectactive[i]); |
|
|
|
WSave(numlights); |
|
|
|
for (i = 0; i < MAXLIGHTS; i++) |
|
BSave(lightactive[i]); |
|
for (i = 0; i < numlights; i++) |
|
SaveLighting(lightactive[i]); |
|
|
|
WSave(visionid); |
|
WSave(numvision); |
|
|
|
for (i = 0; i < numvision; i++) |
|
SaveVision(i); |
|
} |
|
|
|
for (i = 0; i < MAXITEMS; i++) |
|
BSave(itemactive[i]); |
|
for (i = 0; i < MAXITEMS; i++) |
|
BSave(itemavail[i]); |
|
for (i = 0; i < numitems; i++) |
|
SaveItem(itemactive[i]); |
|
for (i = 0; i < 128; i++) |
|
OSave(UniqueItemFlag[i]); |
|
|
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
BSave(dLight[i][j]); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
BSave(dFlags[i][j] & ~(BFLAG_MISSILE | BFLAG_VISIBLE | BFLAG_DEAD_PLAYER)); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
BSave(dPlayer[i][j]); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
BSave(dItem[i][j]); |
|
} |
|
|
|
if (leveltype != DTYPE_TOWN) { |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
WSave(dMonster[i][j]); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
BSave(dDead[i][j]); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
BSave(dObject[i][j]); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
BSave(dLight[i][j]); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
BSave(dPreLight[i][j]); |
|
} |
|
for (j = 0; j < DMAXY; j++) { |
|
for (i = 0; i < DMAXX; i++) |
|
OSave(automapview[i][j]); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
BSave(dMissile[i][j]); |
|
} |
|
} |
|
|
|
WSave(numpremium); |
|
WSave(premiumlevel); |
|
|
|
for (i = 0; i < 6; i++) |
|
SavePremium(i); |
|
|
|
OSave(automapflag); |
|
WSave(AutoMapScale); |
|
pfile_get_game_name(szName); |
|
dwLen = codec_get_encoded_len(tbuff - SaveBuff); |
|
pfile_write_save_file(szName, SaveBuff, tbuff - SaveBuff, dwLen); |
|
mem_free_dbg(SaveBuff); |
|
gbValidSaveFile = TRUE; |
|
pfile_rename_temp_to_perm(); |
|
pfile_write_hero(); |
|
} |
|
|
|
void BSave(char v) |
|
{ |
|
*tbuff++ = v; |
|
} |
|
|
|
void WSave(int v) |
|
{ |
|
*tbuff++ = v >> 24; |
|
*tbuff++ = v >> 16; |
|
*tbuff++ = v >> 8; |
|
*tbuff++ = v; |
|
} |
|
|
|
void ISave(int v) |
|
{ |
|
*tbuff++ = v >> 24; |
|
*tbuff++ = v >> 16; |
|
*tbuff++ = v >> 8; |
|
*tbuff++ = v; |
|
} |
|
|
|
void OSave(BOOL v) |
|
{ |
|
if (v != FALSE) |
|
*tbuff++ = TRUE; |
|
else |
|
*tbuff++ = FALSE; |
|
} |
|
|
|
void SavePlayer(int i) |
|
{ |
|
memcpy(tbuff, &plr[i], sizeof(*plr) - (10 * sizeof(void *))); |
|
tbuff += sizeof(*plr) - (10 * sizeof(void *)); // omit last 10 pointers |
|
} |
|
|
|
void SaveMonster(int i) |
|
{ |
|
memcpy(tbuff, &monster[i], sizeof(*monster) - (3 * sizeof(void *))); |
|
tbuff += sizeof(*monster) - (3 * sizeof(void *)); // omit last 3 pointers |
|
} |
|
|
|
void SaveMissile(int i) |
|
{ |
|
memcpy(tbuff, &missile[i], sizeof(*missile)); |
|
tbuff += sizeof(*missile); |
|
} |
|
|
|
void SaveObject(int i) |
|
{ |
|
memcpy(tbuff, &object[i], sizeof(*object)); |
|
tbuff += sizeof(*object); |
|
} |
|
|
|
void SaveItem(int i) |
|
{ |
|
memcpy(tbuff, &item[i], sizeof(*item)); |
|
tbuff += sizeof(*item); |
|
} |
|
|
|
void SavePremium(int i) |
|
{ |
|
memcpy(tbuff, &premiumitem[i], sizeof(*premiumitem)); |
|
tbuff += sizeof(*premiumitem); |
|
} |
|
|
|
void SaveQuest(int i) |
|
{ |
|
memcpy(tbuff, &quests[i], sizeof(*quests)); |
|
tbuff += sizeof(*quests); |
|
WSave(ReturnLvlX); |
|
WSave(ReturnLvlY); |
|
WSave(ReturnLvl); |
|
WSave(ReturnLvlT); |
|
WSave(DoomQuestState); |
|
} |
|
|
|
void SaveLighting(int i) |
|
{ |
|
memcpy(tbuff, &LightList[i], sizeof(*LightList)); |
|
tbuff += sizeof(*LightList); |
|
} |
|
|
|
void SaveVision(int i) |
|
{ |
|
memcpy(tbuff, &VisionList[i], sizeof(*VisionList)); |
|
tbuff += sizeof(*VisionList); |
|
} |
|
|
|
void SavePortal(int i) |
|
{ |
|
memcpy(tbuff, &portal[i], sizeof(*portal)); |
|
tbuff += sizeof(*portal); |
|
} |
|
|
|
void SaveLevel() |
|
{ |
|
int i, j; |
|
char szName[MAX_PATH]; |
|
int dwLen; |
|
unsigned char *SaveBuff; |
|
|
|
if (!currlevel) |
|
glSeedTbl[0] = GetRndSeed(); |
|
|
|
dwLen = codec_get_encoded_len(FILEBUFF); |
|
SaveBuff = DiabloAllocPtr(dwLen); |
|
tbuff = SaveBuff; |
|
|
|
if (leveltype != DTYPE_TOWN) { |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
BSave(dDead[i][j]); |
|
} |
|
} |
|
|
|
WSave(nummonsters); |
|
WSave(numitems); |
|
WSave(nobjects); |
|
|
|
if (leveltype != DTYPE_TOWN) { |
|
for (i = 0; i < MAXMONSTERS; i++) |
|
WSave(monstactive[i]); |
|
for (i = 0; i < nummonsters; i++) |
|
SaveMonster(monstactive[i]); |
|
for (i = 0; i < MAXOBJECTS; i++) |
|
BSave(objectactive[i]); |
|
for (i = 0; i < MAXOBJECTS; i++) |
|
BSave(objectavail[i]); |
|
for (i = 0; i < nobjects; i++) |
|
SaveObject(objectactive[i]); |
|
} |
|
|
|
for (i = 0; i < MAXITEMS; i++) |
|
BSave(itemactive[i]); |
|
for (i = 0; i < MAXITEMS; i++) |
|
BSave(itemavail[i]); |
|
for (i = 0; i < numitems; i++) |
|
SaveItem(itemactive[i]); |
|
|
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
BSave(dFlags[i][j] & ~(BFLAG_MISSILE | BFLAG_VISIBLE | BFLAG_DEAD_PLAYER)); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
BSave(dItem[i][j]); |
|
} |
|
|
|
if (leveltype != DTYPE_TOWN) { |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
WSave(dMonster[i][j]); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
BSave(dObject[i][j]); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
BSave(dLight[i][j]); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
BSave(dPreLight[i][j]); |
|
} |
|
for (j = 0; j < DMAXY; j++) { |
|
for (i = 0; i < DMAXX; i++) |
|
OSave(automapview[i][j]); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
BSave(dMissile[i][j]); |
|
} |
|
} |
|
|
|
GetTempLevelNames(szName); |
|
dwLen = codec_get_encoded_len(tbuff - SaveBuff); |
|
pfile_write_save_file(szName, SaveBuff, tbuff - SaveBuff, dwLen); |
|
mem_free_dbg(SaveBuff); |
|
|
|
if (setlevel == 0) |
|
plr[myplr]._pLvlVisited[currlevel] = 1; |
|
else |
|
plr[myplr]._pSLvlVisited[setlvlnum] = 1; |
|
} |
|
|
|
void LoadLevel() |
|
{ |
|
int i, j; |
|
DWORD dwLen; |
|
char szName[MAX_PATH]; |
|
BYTE *LoadBuff; |
|
|
|
GetPermLevelNames(szName); |
|
LoadBuff = pfile_read(szName, &dwLen); |
|
tbuff = LoadBuff; |
|
|
|
if (leveltype != DTYPE_TOWN) { |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
dDead[i][j] = BLoad(); |
|
} |
|
SetDead(); |
|
} |
|
|
|
nummonsters = WLoad(); |
|
numitems = WLoad(); |
|
nobjects = WLoad(); |
|
|
|
if (leveltype != DTYPE_TOWN) { |
|
for (i = 0; i < MAXMONSTERS; i++) |
|
monstactive[i] = WLoad(); |
|
for (i = 0; i < nummonsters; i++) |
|
LoadMonster(monstactive[i]); |
|
for (i = 0; i < MAXOBJECTS; i++) |
|
objectactive[i] = BLoad(); |
|
for (i = 0; i < MAXOBJECTS; i++) |
|
objectavail[i] = BLoad(); |
|
for (i = 0; i < nobjects; i++) |
|
LoadObject(objectactive[i]); |
|
for (i = 0; i < nobjects; i++) |
|
SyncObjectAnim(objectactive[i]); |
|
} |
|
|
|
for (i = 0; i < MAXITEMS; i++) |
|
itemactive[i] = BLoad(); |
|
for (i = 0; i < MAXITEMS; i++) |
|
itemavail[i] = BLoad(); |
|
for (i = 0; i < numitems; i++) |
|
LoadItem(itemactive[i]); |
|
|
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
dFlags[i][j] = BLoad(); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
dItem[i][j] = BLoad(); |
|
} |
|
|
|
if (leveltype != DTYPE_TOWN) { |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
dMonster[i][j] = WLoad(); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
dObject[i][j] = BLoad(); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
dLight[i][j] = BLoad(); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
dPreLight[i][j] = BLoad(); |
|
} |
|
for (j = 0; j < DMAXY; j++) { |
|
for (i = 0; i < DMAXX; i++) |
|
automapview[i][j] = OLoad(); |
|
} |
|
for (j = 0; j < MAXDUNY; j++) { |
|
for (i = 0; i < MAXDUNX; i++) |
|
dMissile[i][j] = 0; /// BUGFIX: supposed to load saved missiles with "BLoad()"? |
|
} |
|
} |
|
|
|
AutomapZoomReset(); |
|
ResyncQuests(); |
|
SyncPortals(); |
|
dolighting = 1; |
|
|
|
for (i = 0; i < MAX_PLRS; i++) { |
|
if (plr[i].plractive && currlevel == plr[i].plrlevel) |
|
LightList[plr[i]._plid]._lunflag = 1; |
|
} |
|
|
|
mem_free_dbg(LoadBuff); |
|
} |
|
|
|
DEVILUTION_END_NAMESPACE
|
|
|