Browse Source

Merge branch 'master' of github.com:diasurgical/devilution

pull/914/head
Anders Jenbo 5 years ago
parent
commit
4ae75753c8
  1. 36
      Source/loadsave.cpp
  2. 2
      Source/missiles.cpp
  3. 382
      Source/monster.cpp
  4. 1572
      Source/msg.cpp
  5. 110
      Source/msg.h
  6. 540
      Source/multi.cpp
  7. 27
      Source/multi.h
  8. 52
      Source/nthread.cpp
  9. 6
      Source/nthread.h
  10. 48
      Source/objects.cpp
  11. 134
      Source/objects.h
  12. 1
      Source/pack.h
  13. 9
      Source/palette.h
  14. 14
      Source/path.h
  15. 272
      Source/pfile.cpp
  16. 13
      Source/pfile.h
  17. 4
      Source/quests.cpp
  18. 2
      Source/themes.cpp
  19. 8
      enums.h

36
Source/loadsave.cpp

@ -672,6 +672,25 @@ static void LoadPortal(int i)
CopyInt(tbuff, &pPortal->setlvl);
}
static bool IsHeaderValid(int magicNumber)
{
if (gbIsSpawn) {
if (magicNumber != 'SHAR') {
return false;
}
} else {
#ifdef HELLFIRE
if (magicNumber != 'HELF') {
#else
if (magicNumber != 'RETL') {
#endif
return false;
}
}
return true;
}
/**
* @brief Load game state
* @param firstflag Can be set to false if we are simply reloading the current game
@ -690,13 +709,7 @@ void LoadGame(BOOL firstflag)
LoadBuff = pfile_read(szName, &dwLen);
tbuff = LoadBuff;
#ifdef HELLFIRE
if (ILoad() != 'HELF')
#elif defined(SPAWN)
if (ILoad() != 'SHAR')
#else
if (ILoad() != 'RETL')
#endif
if (!IsHeaderValid(ILoad()))
app_fatal("Invalid save file");
setlevel = OLoad();
@ -1453,12 +1466,13 @@ void SaveGame()
BYTE *SaveBuff = DiabloAllocPtr(dwLen);
tbuff = SaveBuff;
if (gbIsSpawn)
ISave('SHAR');
else
#ifdef HELLFIRE
ISave('HELF');
#elif defined(SPAWN)
ISave('SHAR');
ISave('HELF');
#else
ISave('RETL');
ISave('RETL');
#endif
OSave(setlevel);
WSave(setlvlnum);

2
Source/missiles.cpp

@ -2116,7 +2116,7 @@ void AddRndTeleport(int mi, int sx, int sy, int dx, int dy, int midir, char mien
if (nTries > 500) {
r1 = 0;
r2 = 0;
break;
break; //BUGFIX: warps player to 0/0 in hellfire, change to return or use 1.09's version of the code
}
r1 = random_(58, 3) + 4;
r2 = random_(58, 3) + 4;

382
Source/monster.cpp

@ -225,46 +225,46 @@ void GetLevelMTypes()
else
mamask = 3; // monster availability mask
AddMonsterType(MT_GOLEM, 2);
AddMonsterType(MT_GOLEM, PLACE_SPECIAL);
if (currlevel == 16) {
AddMonsterType(MT_ADVOCATE, 1);
AddMonsterType(MT_RBLACK, 1);
AddMonsterType(MT_DIABLO, 2);
AddMonsterType(MT_ADVOCATE, PLACE_SCATTER);
AddMonsterType(MT_RBLACK, PLACE_SCATTER);
AddMonsterType(MT_DIABLO, PLACE_SPECIAL);
return;
}
#ifdef HELLFIRE
if (currlevel == 18)
AddMonsterType(117, 1);
AddMonsterType(MT_HORKSPWN, PLACE_SCATTER);
if (currlevel == 19) {
AddMonsterType(117, 1);
AddMonsterType(123, 4);
AddMonsterType(MT_HORKSPWN, PLACE_SCATTER);
AddMonsterType(MT_HORKDMN, PLACE_UNIQUE);
}
if (currlevel == 20)
AddMonsterType(124, 4);
AddMonsterType(MT_DEFILER, PLACE_UNIQUE);
if (currlevel == 24) {
AddMonsterType(133, 1);
AddMonsterType(137, 2);
AddMonsterType(MT_ARCHLICH, PLACE_SCATTER);
AddMonsterType(MT_NAKRUL, PLACE_SPECIAL);
}
#endif
if (!setlevel) {
if (QuestStatus(Q_BUTCHER))
AddMonsterType(MT_CLEAVER, 2);
AddMonsterType(MT_CLEAVER, PLACE_SPECIAL);
if (QuestStatus(Q_GARBUD))
AddMonsterType(UniqMonst[UMT_GARBUD].mtype, 4);
AddMonsterType(UniqMonst[UMT_GARBUD].mtype, PLACE_UNIQUE);
if (QuestStatus(Q_ZHAR))
AddMonsterType(UniqMonst[UMT_ZHAR].mtype, 4);
AddMonsterType(UniqMonst[UMT_ZHAR].mtype, PLACE_UNIQUE);
if (QuestStatus(Q_LTBANNER))
AddMonsterType(UniqMonst[UMT_SNOTSPIL].mtype, 4);
AddMonsterType(UniqMonst[UMT_SNOTSPIL].mtype, PLACE_UNIQUE);
if (QuestStatus(Q_VEIL))
AddMonsterType(UniqMonst[UMT_LACHDAN].mtype, 4);
AddMonsterType(UniqMonst[UMT_LACHDAN].mtype, PLACE_UNIQUE);
if (QuestStatus(Q_WARLORD))
AddMonsterType(UniqMonst[UMT_WARLORD].mtype, 4);
AddMonsterType(UniqMonst[UMT_WARLORD].mtype, PLACE_UNIQUE);
if (gbMaxPlayers != 1 && currlevel == quests[Q_SKELKING]._qlevel) {
AddMonsterType(MT_SKING, 4);
AddMonsterType(MT_SKING, PLACE_UNIQUE);
nt = 0;
for (i = MT_WSKELAX; i <= MT_WSKELAX + numskeltypes; i++) {
@ -279,7 +279,7 @@ void GetLevelMTypes()
}
}
}
AddMonsterType(skeltypes[random_(88, nt)], 1);
AddMonsterType(skeltypes[random_(88, nt)], PLACE_SCATTER);
}
nt = 0;
@ -296,7 +296,7 @@ void GetLevelMTypes()
if (monstdebug) {
for (i = 0; i < debugmonsttypes; i++)
AddMonsterType(DebugMonsters[i], 1);
AddMonsterType(DebugMonsters[i], PLACE_SCATTER);
} else {
while (nt > 0 && nummtypes < MAX_LVLMTYPES && monstimgtot < 4000) {
@ -311,7 +311,7 @@ void GetLevelMTypes()
if (nt != 0) {
i = random_(88, nt);
AddMonsterType(typelist[i], 1);
AddMonsterType(typelist[i], PLACE_SCATTER);
typelist[i] = typelist[--nt];
}
}
@ -319,7 +319,7 @@ void GetLevelMTypes()
} else {
if (setlvlnum == SL_SKELKING) {
AddMonsterType(MT_SKING, 4);
AddMonsterType(MT_SKING, PLACE_UNIQUE);
}
}
}
@ -687,7 +687,7 @@ void PlaceMonster(int i, int mtype, int x, int y)
InitMonster(i, rd, mtype, x, y);
}
void PlaceUniqueMonst(int uniqindex, int miniontype, int unpackfilesize)
void PlaceUniqueMonst(int uniqindex, int miniontype, int bosspacksize)
{
int xp, yp, x, y, i;
int uniqtype;
@ -698,7 +698,7 @@ void PlaceUniqueMonst(int uniqindex, int miniontype, int unpackfilesize)
MonsterStruct *Monst;
int count;
Monst = monster + nummonsters;
Monst = &monster[nummonsters];
count = 0;
Uniq = UniqMonst + uniqindex;
@ -925,7 +925,7 @@ void PlaceUniqueMonst(int uniqindex, int miniontype, int unpackfilesize)
nummonsters++;
if (Uniq->mUnqAttr & 1) {
PlaceGroup(miniontype, unpackfilesize, Uniq->mUnqAttr, nummonsters - 1);
PlaceGroup(miniontype, bosspacksize, Uniq->mUnqAttr, nummonsters - 1);
}
if (Monst->_mAi != AI_GARG) {
@ -1012,18 +1012,18 @@ void PlaceQuestMonsters()
setp = LoadFileInMem("Levels\\L4Data\\Warlord.DUN", NULL);
SetMapMonsters(setp, 2 * setpc_x, 2 * setpc_y);
mem_free_dbg(setp);
AddMonsterType(UniqMonst[UMT_WARLORD].mtype, 1);
AddMonsterType(UniqMonst[UMT_WARLORD].mtype, PLACE_SCATTER);
}
if (QuestStatus(Q_VEIL)) {
AddMonsterType(UniqMonst[UMT_LACHDAN].mtype, 1);
AddMonsterType(UniqMonst[UMT_LACHDAN].mtype, PLACE_SCATTER);
}
if (QuestStatus(Q_ZHAR) && zharlib == -1) {
quests[Q_ZHAR]._qactive = QUEST_NOTAVAIL;
}
if (currlevel == quests[Q_BETRAYER]._qlevel && gbMaxPlayers != 1) {
AddMonsterType(UniqMonst[UMT_LAZURUS].mtype, 4);
AddMonsterType(UniqMonst[UMT_RED_VEX].mtype, 4);
AddMonsterType(UniqMonst[UMT_LAZURUS].mtype, PLACE_UNIQUE);
AddMonsterType(UniqMonst[UMT_RED_VEX].mtype, PLACE_UNIQUE);
PlaceUniqueMonst(UMT_LAZURUS, 0, 0);
PlaceUniqueMonst(UMT_RED_VEX, 0, 0);
PlaceUniqueMonst(UMT_BLACKJADE, 0, 0);
@ -1192,11 +1192,11 @@ void InitMonsters()
numplacemonsters = na / 30;
if (gbMaxPlayers != 1)
numplacemonsters += numplacemonsters >> 1;
if (nummonsters + numplacemonsters > 190)
numplacemonsters = 190 - nummonsters;
if (nummonsters + numplacemonsters > MAXMONSTERS - 10)
numplacemonsters = MAXMONSTERS - 10 - nummonsters;
totalmonsters = nummonsters + numplacemonsters;
for (i = 0; i < nummtypes; i++) {
if (Monsters[i].mPlaceFlags & 1) {
if (Monsters[i].mPlaceFlags & PLACE_SCATTER) {
scattertypes[numscattypes] = i;
numscattypes++;
}
@ -1231,15 +1231,15 @@ void SetMapMonsters(BYTE *pMap, int startx, int starty)
int i, j;
int mtype;
AddMonsterType(MT_GOLEM, 2);
AddMonsterType(MT_GOLEM, PLACE_SPECIAL);
AddMonster(1, 0, 0, 0, FALSE);
AddMonster(1, 0, 0, 0, FALSE);
AddMonster(1, 0, 0, 0, FALSE);
AddMonster(1, 0, 0, 0, FALSE);
if (setlevel && setlvlnum == SL_VILEBETRAYER) {
AddMonsterType(UniqMonst[UMT_LAZURUS].mtype, 4);
AddMonsterType(UniqMonst[UMT_RED_VEX].mtype, 4);
AddMonsterType(UniqMonst[UMT_BLACKJADE].mtype, 4);
AddMonsterType(UniqMonst[UMT_LAZURUS].mtype, PLACE_UNIQUE);
AddMonsterType(UniqMonst[UMT_RED_VEX].mtype, PLACE_UNIQUE);
AddMonsterType(UniqMonst[UMT_BLACKJADE].mtype, PLACE_UNIQUE);
PlaceUniqueMonst(UMT_LAZURUS, 0, 0);
PlaceUniqueMonst(UMT_RED_VEX, 0, 0);
PlaceUniqueMonst(UMT_BLACKJADE, 0, 0);
@ -1256,7 +1256,7 @@ void SetMapMonsters(BYTE *pMap, int startx, int starty)
for (j = 0; j < rh; j++) {
for (i = 0; i < rw; i++) {
if (*lm) {
mtype = AddMonsterType(MonstConvTbl[SDL_SwapLE16(*lm) - 1], 2);
mtype = AddMonsterType(MonstConvTbl[SDL_SwapLE16(*lm) - 1], PLACE_SPECIAL);
PlaceMonster(nummonsters++, mtype, i + startx + 16, j + starty + 16);
}
lm++;
@ -1323,7 +1323,7 @@ void monster_43C785(int i)
void NewMonsterAnim(int i, AnimStruct *anim, int md)
{
MonsterStruct *Monst = monster + i;
MonsterStruct *Monst = &monster[i];
Monst->_mAnimData = anim->Data[md];
Monst->_mAnimLen = anim->Frames;
Monst->_mAnimCnt = 0;
@ -1364,7 +1364,7 @@ void M_Enemy(int i)
_menemy = -1;
best_dist = -1;
bestsameroom = 0;
Monst = monster + i;
Monst = &monster[i];
if (!(Monst->_mFlags & MFLAG_GOLEM)) {
for (pnum = 0; pnum < MAX_PLRS; pnum++) {
if (!plr[pnum].plractive || currlevel != plr[pnum].plrlevel || plr[pnum]._pLvlChanging || (plr[pnum]._pHitPoints == 0 && gbMaxPlayers != 1))
@ -1699,9 +1699,8 @@ void M_GetKnockback(int i)
monster[i]._my = monster[i]._moldy;
monster[i]._mfutx = monster[i]._mx;
monster[i]._mfuty = monster[i]._my;
// BUGFIX useless assignment
monster[i]._moldx = monster[i]._mx;
monster[i]._moldy = monster[i]._my;
monster[i]._moldx = monster[i]._mx; // CODEFIX: useless assignment
monster[i]._moldy = monster[i]._my; // CODEFIX: useless assignment
M_ClearSquares(i);
dMonster[monster[i]._mx][monster[i]._my] = i + 1;
}
@ -1746,37 +1745,38 @@ void M_StartHit(int i, int pnum, int dam)
void M_DiabloDeath(int i, BOOL sendmsg)
{
MonsterStruct *Monst, *pmonster;
MonsterStruct *Monst;
int dist;
int j, k;
int _moldx, _moldy;
Monst = monster + i;
PlaySFX(USFX_DIABLOD);
quests[Q_DIABLO]._qactive = QUEST_DONE;
if (sendmsg)
NetSendCmdQuest(TRUE, Q_DIABLO);
gbProcessPlayers = FALSE;
sgbSaveSoundOn = gbSoundOn;
gbProcessPlayers = FALSE;
#ifdef HELLFIRE
gbSoundOn = FALSE;
#endif
for (j = 0; j < nummonsters; j++) {
k = monstactive[j];
if (k == i || monster[i]._msquelch == 0)
continue;
pmonster = monster + k;
NewMonsterAnim(k, &pmonster->MType->Anims[MA_DEATH], pmonster->_mdir);
NewMonsterAnim(k, &monster[k].MType->Anims[MA_DEATH], monster[k]._mdir);
monster[k]._mmode = MM_DEATH;
monster[k]._mxoff = 0;
monster[k]._myoff = 0;
monster[k]._mVar1 = 0;
_moldx = monster[k]._moldx;
_moldy = monster[k]._moldy;
monster[k]._my = _moldy;
monster[k]._mfuty = _moldy;
monster[k]._mmode = MM_DEATH;
monster[k]._mx = _moldx;
monster[k]._mfutx = _moldx;
monster[k]._mx = monster[k]._moldx;
monster[k]._my = monster[k]._moldy;
monster[k]._mfuty = monster[k]._mx;
monster[k]._mfutx = monster[k]._my;
monster[k]._moldx = monster[k]._mx; // CODEFIX: useless assignment
monster[k]._moldy = monster[k]._my; // CODEFIX: useless assignment
M_ClearSquares(k);
dMonster[pmonster->_mx][pmonster->_my] = k + 1;
dMonster[monster[k]._mx][monster[k]._my] = k + 1;
}
AddLight(Monst->_mx, Monst->_my, 8);
DoVision(Monst->_mx, Monst->_my, 8, FALSE, TRUE);
@ -1786,12 +1786,10 @@ void M_DiabloDeath(int i, BOOL sendmsg)
dist = abs(ViewY - Monst->_my);
if (dist > 20)
dist = 20;
j = ViewX << 16;
k = ViewY << 16;
Monst->_mVar3 = j;
Monst->_mVar4 = k;
Monst->_mVar5 = (int)((j - (Monst->_mx << 16)) / (double)dist);
Monst->_mVar6 = (int)((k - (Monst->_my << 16)) / (double)dist);
Monst->_mVar3 = ViewX << 16;
Monst->_mVar4 = ViewY << 16;
Monst->_mVar5 = (int)((Monst->_mVar3 - (Monst->_mx << 16)) / (double)dist);
Monst->_mVar6 = (int)((Monst->_mVar4 - (Monst->_my << 16)) / (double)dist);
}
#ifdef HELLFIRE
@ -2217,29 +2215,51 @@ BOOL M_DoWalk(int i)
BOOL rv;
if ((DWORD)i >= MAXMONSTERS)
#ifdef HELLFIRE
return FALSE;
#else
app_fatal("M_DoWalk: Invalid monster %d", i);
#endif
if (monster[i].MType == NULL)
#ifdef HELLFIRE
return FALSE;
#else
app_fatal("M_DoWalk: Monster %d \"%s\" MType NULL", i, monster[i].mName);
#endif
rv = FALSE;
if (monster[i]._mVar8 == monster[i].MType->Anims[MA_WALK].Frames) {
dMonster[monster[i]._mx][monster[i]._my] = 0;
monster[i]._mx += monster[i]._mVar1;
monster[i]._my += monster[i]._mVar2;
dMonster[monster[i]._mx][monster[i]._my] = i + 1;
#ifdef HELLFIRE
if (!(monster[i]._mFlags & MFLAG_HIDDEN) && monster[i].mlid != 0)
#else
if (monster[i]._uniqtype != 0)
#endif
ChangeLightXY(monster[i].mlid, monster[i]._mx, monster[i]._my);
M_StartStand(i, monster[i]._mdir);
rv = TRUE;
} else if (!monster[i]._mAnimCnt) {
monster[i]._mVar8++;
monster[i]._mVar6 += monster[i]._mxvel;
monster[i]._mVar7 += monster[i]._myvel;
monster[i]._mxoff = monster[i]._mVar6 >> 4;
monster[i]._myoff = monster[i]._mVar7 >> 4;
} else {
if (monster[i]._mAnimCnt == 0) {
#ifdef HELLFIRE
if (monster[i]._mVar8 == 0 && monster[i].MType->mtype == MT_FLESTHNG)
PlayEffect(i, 3);
#endif
monster[i]._mVar8++;
monster[i]._mVar6 += monster[i]._mxvel;
monster[i]._mVar7 += monster[i]._myvel;
monster[i]._mxoff = monster[i]._mVar6 >> 4;
monster[i]._myoff = monster[i]._mVar7 >> 4;
}
rv = FALSE;
}
#ifdef HELLFIRE
if (!(monster[i]._mFlags & MFLAG_HIDDEN) && monster[i].mlid != 0)
#else
if (monster[i]._uniqtype != 0)
#endif
M_ChangeLightOffset(i);
return rv;
@ -2250,18 +2270,34 @@ BOOL M_DoWalk2(int i)
BOOL rv;
if ((DWORD)i >= MAXMONSTERS)
#ifdef HELLFIRE
return FALSE;
#else
app_fatal("M_DoWalk2: Invalid monster %d", i);
#endif
if (monster[i].MType == NULL)
#ifdef HELLFIRE
return FALSE;
#else
app_fatal("M_DoWalk2: Monster %d \"%s\" MType NULL", i, monster[i].mName);
#endif
if (monster[i]._mVar8 == monster[i].MType->Anims[MA_WALK].Frames) {
dMonster[monster[i]._mVar1][monster[i]._mVar2] = 0;
#ifdef HELLFIRE
if (!(monster[i]._mFlags & MFLAG_HIDDEN) && monster[i].mlid != 0)
#else
if (monster[i]._uniqtype != 0)
#endif
ChangeLightXY(monster[i].mlid, monster[i]._mx, monster[i]._my);
M_StartStand(i, monster[i]._mdir);
rv = TRUE;
} else {
if (!monster[i]._mAnimCnt) {
if (monster[i]._mAnimCnt == 0) {
#ifdef HELLFIRE
if (monster[i]._mVar8 == 0 && monster[i].MType->mtype == MT_FLESTHNG)
PlayEffect(i, 3);
#endif
monster[i]._mVar8++;
monster[i]._mVar6 += monster[i]._mxvel;
monster[i]._mVar7 += monster[i]._myvel;
@ -2270,7 +2306,11 @@ BOOL M_DoWalk2(int i)
}
rv = FALSE;
}
#ifdef HELLFIRE
if (!(monster[i]._mFlags & MFLAG_HIDDEN) && monster[i].mlid != 0)
#else
if (monster[i]._uniqtype != 0)
#endif
M_ChangeLightOffset(i);
return rv;
@ -2281,9 +2321,17 @@ BOOL M_DoWalk3(int i)
BOOL rv;
if ((DWORD)i >= MAXMONSTERS)
#ifdef HELLFIRE
return FALSE;
#else
app_fatal("M_DoWalk3: Invalid monster %d", i);
#endif
if (monster[i].MType == NULL)
#ifdef HELLFIRE
return FALSE;
#else
app_fatal("M_DoWalk3: Monster %d \"%s\" MType NULL", i, monster[i].mName);
#endif
if (monster[i]._mVar8 == monster[i].MType->Anims[MA_WALK].Frames) {
dMonster[monster[i]._mx][monster[i]._my] = 0;
@ -2291,12 +2339,20 @@ BOOL M_DoWalk3(int i)
monster[i]._my = monster[i]._mVar2;
dFlags[monster[i]._mVar4][monster[i]._mVar5] &= ~BFLAG_MONSTLR;
dMonster[monster[i]._mx][monster[i]._my] = i + 1;
if (monster[i]._uniqtype)
#ifdef HELLFIRE
if (!(monster[i]._mFlags & MFLAG_HIDDEN) && monster[i].mlid != 0)
#else
if (monster[i]._uniqtype != 0)
#endif
ChangeLightXY(monster[i].mlid, monster[i]._mx, monster[i]._my);
M_StartStand(i, monster[i]._mdir);
rv = TRUE;
} else {
if (!monster[i]._mAnimCnt) {
if (monster[i]._mAnimCnt == 0) {
#ifdef HELLFIRE
if (monster[i]._mVar8 == 0 && monster[i].MType->mtype == MT_FLESTHNG)
PlayEffect(i, 3);
#endif
monster[i]._mVar8++;
monster[i]._mVar6 += monster[i]._mxvel;
monster[i]._mVar7 += monster[i]._myvel;
@ -2305,7 +2361,11 @@ BOOL M_DoWalk3(int i)
}
rv = FALSE;
}
#ifdef HELLFIRE
if (monster[i]._uniqtype != 0 && !(monster[i]._mFlags & MFLAG_HIDDEN)) // BUGFIX: change uniqtype check to mlid check like it is in all other places
#else
if (monster[i]._uniqtype != 0)
#endif
M_ChangeLightOffset(i);
return rv;
@ -2569,7 +2629,7 @@ int M_DoRSpAttack(int i)
if (monster[i].MType == NULL) // BUGFIX: should check MData
app_fatal("M_DoRSpAttack: Monster %d \"%s\" MData NULL", i, monster[i].mName);
if (monster[i]._mAnimFrame == monster[i].MData->mAFNum2 && !monster[i]._mAnimCnt) {
if (monster[i]._mAnimFrame == monster[i].MData->mAFNum2 && monster[i]._mAnimCnt == 0) {
AddMissile(
monster[i]._mx,
monster[i]._my,
@ -2853,10 +2913,18 @@ void DoEnding()
if (gbIsSpawn)
return;
#ifdef HELLFIRE
if (plr[myplr]._pClass == PC_WARRIOR || plr[myplr]._pClass == PC_BARBARIAN) {
#else
if (plr[myplr]._pClass == PC_WARRIOR) {
#endif
play_movie("gendata\\DiabVic2.smk", FALSE);
} else if (plr[myplr]._pClass == PC_SORCERER) {
play_movie("gendata\\DiabVic1.smk", FALSE);
#ifdef HELLFIRE
} else if (plr[myplr]._pClass == PC_MONK) {
play_movie("gendata\\DiabVic1.smk", FALSE);
#endif
} else {
play_movie("gendata\\DiabVic3.smk", FALSE);
}
@ -2908,7 +2976,6 @@ void PrepDoEnding()
BOOL M_DoDeath(int i)
{
int var1;
int x, y;
if ((DWORD)i >= MAXMONSTERS)
@ -2925,7 +2992,6 @@ BOOL M_DoDeath(int i)
#endif
monster[i]._mVar1++;
var1 = monster[i]._mVar1;
if (monster[i].MType->mtype == MT_DIABLO) {
x = monster[i]._mx - ViewX;
if (x < 0)
@ -2942,7 +3008,7 @@ BOOL M_DoDeath(int i)
}
ViewY += y;
if (var1 == 140)
if (monster[i]._mVar1 == 140)
PrepDoEnding();
} else if (monster[i]._mAnimFrame == monster[i]._mAnimLen) {
if (monster[i]._uniqtype == 0)
@ -2986,13 +3052,20 @@ BOOL M_DoSpStand(int i)
BOOL M_DoDelay(int i)
{
int mVar2;
int oFrame;
if ((DWORD)i >= MAXMONSTERS)
#ifdef HELLFIRE
return FALSE;
#else
app_fatal("M_DoDelay: Invalid monster %d", i);
#endif
if (monster[i].MType == NULL)
#ifdef HELLFIRE
return FALSE;
#else
app_fatal("M_DoDelay: Monster %d \"%s\" MType NULL", i, monster[i].mName);
#endif
monster[i]._mAnimData = monster[i].MType->Anims[MA_STAND].Data[M_GetDir(i)];
if (monster[i]._mAi == AI_LAZURUS) {
@ -3000,10 +3073,7 @@ BOOL M_DoDelay(int i)
monster[i]._mVar2 = 8;
}
mVar2 = monster[i]._mVar2;
monster[i]._mVar2--;
if (!mVar2) {
if (monster[i]._mVar2-- == 0) {
oFrame = monster[i]._mAnimFrame;
M_StartStand(i, monster[i]._mdir);
monster[i]._mAnimFrame = oFrame;
@ -3016,7 +3086,11 @@ BOOL M_DoDelay(int i)
BOOL M_DoStone(int i)
{
if ((DWORD)i >= MAXMONSTERS)
#ifdef HELLFIRE
return FALSE;
#else
app_fatal("M_DoStone: Invalid monster %d", i);
#endif
if (!monster[i]._mhitpoints) {
dMonster[monster[i]._mx][monster[i]._my] = 0;
@ -3031,7 +3105,11 @@ void M_WalkDir(int i, int md)
int mwi;
if ((DWORD)i >= MAXMONSTERS)
#ifdef HELLFIRE
return;
#else
app_fatal("M_WalkDir: Invalid monster %d", i);
#endif
mwi = monster[i].MType->Anims[MA_WALK].Frames - 1;
switch (md) {
@ -3068,9 +3146,13 @@ void GroupUnity(int i)
BOOL clear;
if ((DWORD)i >= MAXMONSTERS)
#ifdef HELLFIRE
return;
#else
app_fatal("GroupUnity: Invalid monster %d", i);
#endif
if (monster[i].leaderflag) {
if (monster[i].leaderflag != 0) {
leader = monster[i].leader;
clear = LineClearF(CheckNoSolid, monster[i]._mx, monster[i]._my, monster[leader]._mfutx, monster[leader]._mfuty);
if (clear || monster[i].leaderflag != 1) {
@ -3095,13 +3177,11 @@ void GroupUnity(int i)
}
if (monster[leader]._mAi == AI_GARG) {
if (monster[leader]._mFlags & MFLAG_ALLOW_SPECIAL) {
monster[leader]._mmode = MM_SATTACK;
monster[leader]._mFlags &= ~MFLAG_ALLOW_SPECIAL;
monster[leader]._mmode = MM_SATTACK;
}
}
return;
}
if (monster[i]._uniqtype != 0) {
} else if (monster[i]._uniqtype != 0) {
if (UniqMonst[monster[i]._uniqtype - 1].mUnqAttr & 2) {
for (j = 0; j < nummonsters; j++) {
m = monstactive[j];
@ -3113,8 +3193,8 @@ void GroupUnity(int i)
}
if (monster[m]._mAi == AI_GARG) {
if (monster[m]._mFlags & MFLAG_ALLOW_SPECIAL) {
monster[m]._mmode = MM_SATTACK;
monster[m]._mFlags &= ~MFLAG_ALLOW_SPECIAL;
monster[m]._mmode = MM_SATTACK;
}
}
}
@ -3154,7 +3234,11 @@ BOOL M_PathWalk(int i)
(int, int, int);
if ((DWORD)i >= MAXMONSTERS)
#ifdef HELLFIRE
return FALSE;
#else
app_fatal("M_PathWalk: Invalid monster %d", i);
#endif
Check = PosOkMonst3;
if (!(monster[i]._mFlags & MFLAG_CAN_OPEN_DOOR))
@ -3206,8 +3290,8 @@ BOOL M_RoundWalk(int i, int md, int *dir)
else
md = right[right[md]];
ok = DirOK(i, md);
mdtemp = md;
ok = DirOK(i, md);
if (!ok) {
if (*dir) {
md = right[mdtemp];
@ -3233,7 +3317,11 @@ void MAI_Zombie(int i)
int md, v;
if ((DWORD)i >= MAXMONSTERS) {
#ifdef HELLFIRE
return;
#else
app_fatal("MAI_Zombie: Invalid monster %d", i);
#endif
}
Monst = &monster[i];
@ -3277,7 +3365,11 @@ void MAI_SkelSd(int i)
int mx, my, x, y, md;
if ((DWORD)i >= MAXMONSTERS)
#ifdef HELLFIRE
return;
#else
app_fatal("MAI_SkelSd: Invalid monster %d", i);
#endif
Monst = &monster[i];
if (Monst->_mmode != MM_STAND || Monst->_msquelch == 0) {
@ -3314,7 +3406,11 @@ BOOL MAI_Path(int i)
BOOL clear;
if ((DWORD)i >= MAXMONSTERS)
#ifdef HELLFIRE
return FALSE;
#else
app_fatal("MAI_Path: Invalid monster %d", i);
#endif
Monst = &monster[i];
if (Monst->MType->mtype != MT_GOLEM) {
@ -3322,7 +3418,7 @@ BOOL MAI_Path(int i)
return FALSE;
if (Monst->_mmode != MM_STAND)
return FALSE;
if (Monst->_mgoal != MGOAL_NORMAL && Monst->_mgoal != MGOAL_MOVE && Monst->_mgoal != MGOAL_SHOOT)
if (Monst->_mgoal != MGOAL_NORMAL && Monst->_mgoal != MGOAL_MOVE && Monst->_mgoal != MGOAL_ATTACK2)
return FALSE;
if (Monst->_mx == 1 && Monst->_my == 0)
return FALSE;
@ -3445,7 +3541,11 @@ void MAI_Bat(int i)
int fx, fy, xd, yd;
if ((DWORD)i >= MAXMONSTERS)
#ifdef HELLFIRE
return;
#else
app_fatal("MAI_Bat: Invalid monster %d", i);
#endif
Monst = &monster[i];
pnum = Monst->_menemy;
@ -3510,7 +3610,11 @@ void MAI_SkelBow(int i)
walking = FALSE;
if ((DWORD)i >= MAXMONSTERS)
#ifdef HELLFIRE
return;
#else
app_fatal("MAI_SkelBow: Invalid monster %d", i);
#endif
Monst = &monster[i];
if (Monst->_mmode != MM_STAND || Monst->_msquelch == 0) {
@ -3552,7 +3656,11 @@ void MAI_Fat(int i)
int mx, my, md, v;
if ((DWORD)i >= MAXMONSTERS)
#ifdef HELLFIRE
return;
#else
app_fatal("MAI_Fat: Invalid monster %d", i);
#endif
Monst = &monster[i];
if (Monst->_mmode != MM_STAND || Monst->_msquelch == 0) {
@ -3588,7 +3696,11 @@ void MAI_Sneak(int i)
int dist, v;
if ((DWORD)i >= MAXMONSTERS) {
#ifdef HELLFIRE
return;
#else
app_fatal("MAI_Sneak: Invalid monster %d", i);
#endif
}
Monst = monster + i;
@ -3602,16 +3714,23 @@ void MAI_Sneak(int i)
md = M_GetDir(i);
dist = 5 - Monst->_mint;
if (Monst->_mVar1 == MM_GOTHIT) {
Monst->_mgoalvar1 = 0;
Monst->_mgoal = MGOAL_RETREAT;
Monst->_mgoalvar1 = 0;
} else {
if (abs(mx) >= dist + 3 || abs(my) >= dist + 3 || Monst->_mgoalvar1 > 8) {
Monst->_mgoalvar1 = 0;
Monst->_mgoal = MGOAL_NORMAL;
Monst->_mgoalvar1 = 0;
}
}
#ifdef HELLFIRE
if (Monst->_mgoal == MGOAL_RETREAT && !(Monst->_mFlags & MFLAG_NO_ENEMY)) {
if (Monst->_mFlags & MFLAG_TARGETS_MONSTER)
md = GetDirection(Monst->_mx, Monst->_my, monster[Monst->_menemy]._mx, monster[Monst->_menemy]._my);
else
#else
if (Monst->_mgoal == MGOAL_RETREAT) {
if (Monst->_mFlags & MFLAG_TARGETS_MONSTER)
#endif
md = GetDirection(Monst->_mx, Monst->_my, plr[Monst->_menemy]._pownerx, plr[Monst->_menemy]._pownery);
md = opposite[md];
if (Monst->MType->mtype == MT_UNSEEN) {
@ -3654,7 +3773,11 @@ void MAI_Fireman(int i)
MonsterStruct *Monst;
if ((DWORD)i >= MAXMONSTERS)
#ifdef HELLFIRE
return;
#else
app_fatal("MAI_Fireman: Invalid monster %d", i);
#endif
Monst = &monster[i];
if (monster[i]._mmode != MM_STAND || Monst->_msquelch == 0)
@ -3671,10 +3794,10 @@ void MAI_Fireman(int i)
if (LineClear(Monst->_mx, Monst->_my, fx, fy)
&& AddMissile(Monst->_mx, Monst->_my, fx, fy, md, MIS_FIREMAN, pnum, i, 0, 0) != -1) {
Monst->_mmode = MM_CHARGE;
Monst->_mgoal = MGOAL_SHOOT;
Monst->_mgoal = MGOAL_ATTACK2;
Monst->_mgoalvar1 = 0;
}
} else if (Monst->_mgoal == MGOAL_SHOOT) {
} else if (Monst->_mgoal == MGOAL_ATTACK2) {
if (Monst->_mgoalvar1 == 3) {
Monst->_mgoal = MGOAL_NORMAL;
M_StartFadeout(i, md, TRUE);
@ -3687,7 +3810,7 @@ void MAI_Fireman(int i)
}
} else if (Monst->_mgoal == MGOAL_RETREAT) {
M_StartFadein(i, md, FALSE);
Monst->_mgoal = MGOAL_SHOOT;
Monst->_mgoal = MGOAL_ATTACK2;
}
Monst->_mdir = md;
random_(112, 100);
@ -3699,63 +3822,68 @@ void MAI_Fireman(int i)
Monst->_mgoal = MGOAL_RETREAT;
if (!M_CallWalk(i, opposite[md])) {
M_StartFadein(i, md, FALSE);
Monst->_mgoal = MGOAL_SHOOT;
Monst->_mgoal = MGOAL_ATTACK2;
}
} else if (!M_CallWalk(i, md) && (Monst->_mgoal == MGOAL_NORMAL || Monst->_mgoal == MGOAL_RETREAT)) {
M_StartFadein(i, md, FALSE);
Monst->_mgoal = MGOAL_SHOOT;
Monst->_mgoal = MGOAL_ATTACK2;
}
}
void MAI_Fallen(int i)
{
int x, y, xpos, ypos;
int m, rad, md;
int m, rad;
MonsterStruct *Monst;
if ((DWORD)i >= MAXMONSTERS) {
#if HELLFIRE
return;
#else
app_fatal("MAI_Fallen: Invalid monster %d", i);
}
if (monster[i]._mgoal == MGOAL_SHOOT) {
if (monster[i]._mgoalvar1)
monster[i]._mgoalvar1--;
else
monster[i]._mgoal = MGOAL_NORMAL;
#endif
}
Monst = &monster[i];
if (monster[i]._mmode != MM_STAND || monster[i]._msquelch == 0) {
if (Monst->_mgoal == MGOAL_ATTACK2) {
if (Monst->_mgoalvar1 != 0)
Monst->_mgoalvar1--;
else
Monst->_mgoal = MGOAL_NORMAL;
}
if (Monst->_mmode != MM_STAND || Monst->_msquelch == 0) {
return;
}
if (Monst->_mgoal == MGOAL_RETREAT) {
if (!Monst->_mgoalvar1--) {
if (Monst->_mgoalvar1-- == 0) {
Monst->_mgoal = MGOAL_NORMAL;
M_StartStand(i, opposite[Monst->_mdir]);
}
}
if (Monst->_mAnimFrame == Monst->_mAnimLen) {
if (random_(113, 4)) {
if (random_(113, 4) != 0) {
return;
}
if (!(Monst->_mFlags & MFLAG_NOHEAL)) {
if (!(monster[i]._mFlags & MFLAG_NOHEAL)) { // CODEFIX: - change to Monst-> in devilutionx
M_StartSpStand(i, Monst->_mdir);
rad = 2 * Monst->_mint + 2;
if (Monst->_mmaxhp - rad >= Monst->_mhitpoints)
Monst->_mhitpoints = rad + Monst->_mhitpoints;
if (Monst->_mmaxhp - (2 * Monst->_mint + 2) >= Monst->_mhitpoints)
Monst->_mhitpoints += 2 * Monst->_mint + 2;
else
Monst->_mhitpoints = Monst->_mmaxhp;
}
rad = 2 * Monst->_mint + 4;
for (y = -rad; y <= rad; y++) {
for (x = -rad; x <= rad; x++) {
xpos = Monst->_mx + x;
ypos = Monst->_my + y;
if (y >= 0 && y < MAXDUNY && x >= 0 && x < MAXDUNX) {
m = dMonster[x + Monst->_mx][y + Monst->_my];
m = dMonster[xpos][ypos];
if (m > 0) {
m--;
if (monster[m]._mAi == AI_FALLEN) {
monster[m]._mgoal = MGOAL_SHOOT;
monster[m]._mgoal = MGOAL_ATTACK2;
monster[m]._mgoalvar1 = 30 * Monst->_mint + 105;
}
}
@ -3763,20 +3891,16 @@ void MAI_Fallen(int i)
}
}
} else if (Monst->_mgoal == MGOAL_RETREAT) {
md = Monst->_mdir;
M_CallWalk(i, md);
} else if (Monst->_mgoal == MGOAL_SHOOT) {
M_CallWalk(i, Monst->_mdir);
} else if (Monst->_mgoal == MGOAL_ATTACK2) {
xpos = Monst->_mx - Monst->_menemyx;
ypos = Monst->_my - Monst->_menemyy;
if (abs(xpos) < 2 && abs(ypos) < 2) {
if (abs(xpos) < 2 && abs(ypos) < 2)
M_StartAttack(i);
} else {
md = M_GetDir(i);
M_CallWalk(i, md);
}
} else {
else
M_CallWalk(i, M_GetDir(i));
} else
MAI_SkelSd(i);
}
}
void MAI_Cleaver(int i)
@ -3785,7 +3909,11 @@ void MAI_Cleaver(int i)
int x, y, mx, my, md;
if ((DWORD)i >= MAXMONSTERS)
#ifdef HELLFIRE
return;
#else
app_fatal("MAI_Cleaver: Invalid monster %d", i);
#endif
Monst = &monster[i];
if (Monst->_mmode != MM_STAND || Monst->_msquelch == 0) {
@ -3817,7 +3945,11 @@ void MAI_Round(int i, BOOL special)
int dist, v;
if ((DWORD)i >= MAXMONSTERS)
#ifdef HELLFIRE
return;
#else
app_fatal("MAI_Round: Invalid monster %d", i);
#endif
Monst = monster + i;
if (Monst->_mmode == MM_STAND && Monst->_msquelch != 0) {
fy = Monst->_menemyy;
@ -3981,7 +4113,11 @@ void MAI_Scav(int i)
MonsterStruct *Monst;
if ((DWORD)i >= MAXMONSTERS)
#ifdef HELLFIRE
return;
#else
app_fatal("MAI_Scav: Invalid monster %d", i);
#endif
Monst = monster + i;
_mx = Monst->_mx;
_my = Monst->_my;
@ -3989,7 +4125,7 @@ void MAI_Scav(int i)
if (monster[i]._mmode != MM_STAND)
return;
if (Monst->_mhitpoints < (Monst->_mmaxhp >> 1) && Monst->_mgoal != MGOAL_HEALING) {
if (Monst->leaderflag) {
if (Monst->leaderflag != 0) {
monster[Monst->leader].packsize--;
Monst->leaderflag = 0;
}
@ -3998,7 +4134,7 @@ void MAI_Scav(int i)
}
if (Monst->_mgoal == MGOAL_HEALING && Monst->_mgoalvar3 != 0) {
Monst->_mgoalvar3--;
if (dDead[Monst->_mx][Monst->_my]) {
if (dDead[Monst->_mx][Monst->_my] != 0) {
M_StartEat(i);
if (!(Monst->_mFlags & MFLAG_NOHEAL))
Monst->_mhitpoints += 64;
@ -4767,7 +4903,7 @@ void MAI_SnotSpil(int i)
}
}
if (quests[Q_LTBANNER]._qvar1 == 3) {
if (Monst->_mgoal == MGOAL_NORMAL || Monst->_mgoal == MGOAL_SHOOT)
if (Monst->_mgoal == MGOAL_NORMAL || Monst->_mgoal == MGOAL_ATTACK2)
MAI_Fallen(i);
}
}

1572
Source/msg.cpp

File diff suppressed because it is too large Load Diff

110
Source/msg.h

@ -17,25 +17,13 @@ extern BYTE gbBufferMsgs;
extern int dwRecCount;
void msg_send_drop_pkt(int pnum, int reason);
void msg_send_packet(int pnum, const void *packet, DWORD dwSize);
void msg_get_next_packet();
BOOL msg_wait_resync();
void msg_free_packets();
int msg_wait_for_turns();
void run_delta_info();
void msg_pre_packet();
void DeltaExportData(int pnum);
BYTE *DeltaExportItem(BYTE *dst, TCmdPItem *src);
BYTE *DeltaExportObject(BYTE *dst, DObjectStr *src);
BYTE *DeltaExportMonster(BYTE *dst, DMonsterStr *src);
BYTE *DeltaExportJunk(BYTE *dst);
int msg_comp_level(BYTE *buffer, BYTE *end);
void delta_init();
void delta_kill_monster(int mi, BYTE x, BYTE y, BYTE bLevel);
void delta_monster_hp(int mi, int hp, BYTE bLevel);
void delta_sync_monster(const TSyncMonster *pSync, BYTE bLevel);
void delta_sync_golem(TCmdGolem *pG, int pnum, BYTE bLevel);
void delta_leave_sync(BYTE bLevel);
BOOL delta_portal_inited(int i);
BOOL delta_quest_inited(int i);
void DeltaAddItem(int ii);
@ -52,9 +40,6 @@ void NetSendCmdParam2(BOOL bHiPri, BYTE bCmd, WORD wParam1, WORD wParam2);
void NetSendCmdParam3(BOOL bHiPri, BYTE bCmd, WORD wParam1, WORD wParam2, WORD wParam3);
void NetSendCmdQuest(BOOL bHiPri, BYTE q);
void NetSendCmdGItem(BOOL bHiPri, BYTE bCmd, BYTE mast, BYTE pnum, BYTE ii);
void NetSendCmdGItem2(BOOL usonly, BYTE bCmd, BYTE mast, BYTE pnum, TCmdGItem *p);
BOOL NetSendCmdReq2(BYTE bCmd, BYTE mast, BYTE pnum, TCmdGItem *p);
void NetSendCmdExtra(TCmdGItem *p);
void NetSendCmdPItem(BOOL bHiPri, BYTE bCmd, BYTE x, BYTE y);
void NetSendCmdChItem(BOOL bHiPri, BYTE bLoc);
void NetSendCmdDelItem(BOOL bHiPri, BYTE bLoc);
@ -66,101 +51,6 @@ void NetSendCmdMonDmg(BOOL bHiPri, WORD bMon, DWORD dwDam);
void NetSendCmdString(int pmask, const char *pszStr);
void delta_close_portal(int pnum);
DWORD ParseCmd(int pnum, TCmd *pCmd);
DWORD On_DLEVEL(int pnum, TCmd *pCmd);
void DeltaImportData(BYTE cmd, DWORD recv_offset);
BYTE *DeltaImportItem(BYTE *src, TCmdPItem *dst);
BYTE *DeltaImportObject(BYTE *src, DObjectStr *dst);
BYTE *DeltaImportMonster(BYTE *src, DMonsterStr *dst);
void DeltaImportJunk(BYTE *src);
DWORD On_SYNCDATA(TCmd *pCmd, int pnum);
DWORD On_WALKXY(TCmd *pCmd, int pnum);
DWORD On_ADDSTR(TCmd *pCmd, int pnum);
DWORD On_ADDMAG(TCmd *pCmd, int pnum);
DWORD On_ADDDEX(TCmd *pCmd, int pnum);
DWORD On_ADDVIT(TCmd *pCmd, int pnum);
DWORD On_SBSPELL(TCmd *pCmd, int pnum);
void msg_errorf(const char *pszFmt, ...);
DWORD On_GOTOGETITEM(TCmd *pCmd, int pnum);
DWORD On_REQUESTGITEM(TCmd *pCmd, int pnum);
BOOL i_own_level(int nReqLevel);
DWORD On_GETITEM(TCmd *pCmd, int pnum);
BOOL delta_get_item(TCmdGItem *pI, BYTE bLevel);
DWORD On_GOTOAGETITEM(TCmd *pCmd, int pnum);
DWORD On_REQUESTAGITEM(TCmd *pCmd, int pnum);
DWORD On_AGETITEM(TCmd *pCmd, int pnum);
DWORD On_ITEMEXTRA(TCmd *pCmd, int pnum);
DWORD On_PUTITEM(TCmd *pCmd, int pnum);
void delta_put_item(TCmdPItem *pI, int x, int y, BYTE bLevel);
void check_update_plr(int pnum);
DWORD On_SYNCPUTITEM(TCmd *pCmd, int pnum);
DWORD On_RESPAWNITEM(TCmd *pCmd, int pnum);
DWORD On_ATTACKXY(TCmd *pCmd, int pnum);
DWORD On_SATTACKXY(TCmd *pCmd, int pnum);
DWORD On_RATTACKXY(TCmd *pCmd, int pnum);
DWORD On_SPELLXYD(TCmd *pCmd, int pnum);
DWORD On_SPELLXY(TCmd *pCmd, int pnum);
DWORD On_TSPELLXY(TCmd *pCmd, int pnum);
DWORD On_OPOBJXY(TCmd *pCmd, int pnum);
DWORD On_DISARMXY(TCmd *pCmd, int pnum);
DWORD On_OPOBJT(TCmd *pCmd, int pnum);
DWORD On_ATTACKID(TCmd *pCmd, int pnum);
DWORD On_ATTACKPID(TCmd *pCmd, int pnum);
DWORD On_RATTACKID(TCmd *pCmd, int pnum);
DWORD On_RATTACKPID(TCmd *pCmd, int pnum);
DWORD On_SPELLID(TCmd *pCmd, int pnum);
DWORD On_SPELLPID(TCmd *pCmd, int pnum);
DWORD On_TSPELLID(TCmd *pCmd, int pnum);
DWORD On_TSPELLPID(TCmd *pCmd, int pnum);
DWORD On_KNOCKBACK(TCmd *pCmd, int pnum);
DWORD On_RESURRECT(TCmd *pCmd, int pnum);
DWORD On_HEALOTHER(TCmd *pCmd, int pnum);
DWORD On_TALKXY(TCmd *pCmd, int pnum);
DWORD On_NEWLVL(TCmd *pCmd, int pnum);
DWORD On_WARP(TCmd *pCmd, int pnum);
DWORD On_MONSTDEATH(TCmd *pCmd, int pnum);
DWORD On_KILLGOLEM(TCmd *pCmd, int pnum);
DWORD On_AWAKEGOLEM(TCmd *pCmd, int pnum);
DWORD On_MONSTDAMAGE(TCmd *pCmd, int pnum);
DWORD On_PLRDEAD(TCmd *pCmd, int pnum);
DWORD On_PLRDAMAGE(TCmd *pCmd, int pnum);
DWORD On_OPENDOOR(TCmd *pCmd, int pnum);
void delta_sync_object(int oi, BYTE bCmd, BYTE bLevel);
DWORD On_CLOSEDOOR(TCmd *pCmd, int pnum);
DWORD On_OPERATEOBJ(TCmd *pCmd, int pnum);
DWORD On_PLROPOBJ(TCmd *pCmd, int pnum);
DWORD On_BREAKOBJ(TCmd *pCmd, int pnum);
DWORD On_CHANGEPLRITEMS(TCmd *pCmd, int pnum);
DWORD On_DELPLRITEMS(TCmd *pCmd, int pnum);
DWORD On_PLRLEVEL(TCmd *pCmd, int pnum);
DWORD On_DROPITEM(TCmd *pCmd, int pnum);
DWORD On_SEND_PLRINFO(TCmd *pCmd, int pnum);
DWORD On_ACK_PLRINFO(TCmd *pCmd, int pnum);
DWORD On_PLAYER_JOINLEVEL(TCmd *pCmd, int pnum);
DWORD On_ACTIVATEPORTAL(TCmd *pCmd, int pnum);
void delta_open_portal(int pnum, BYTE x, BYTE y, BYTE bLevel, BYTE bLType, BYTE bSetLvl);
DWORD On_DEACTIVATEPORTAL(TCmd *pCmd, int pnum);
DWORD On_RETOWN(TCmd *pCmd, int pnum);
DWORD On_SETSTR(TCmd *pCmd, int pnum);
DWORD On_SETDEX(TCmd *pCmd, int pnum);
DWORD On_SETMAG(TCmd *pCmd, int pnum);
DWORD On_SETVIT(TCmd *pCmd, int pnum);
DWORD On_STRING(TCmd *pCmd, int pnum);
DWORD On_STRING2(int pnum, TCmd *pCmd);
DWORD On_SYNCQUEST(TCmd *pCmd, int pnum);
DWORD On_ENDSHIELD(TCmd *pCmd, int pnum);
DWORD On_CHEAT_EXPERIENCE(TCmd *pCmd, int pnum);
DWORD On_CHEAT_SPELL_LEVEL(TCmd *pCmd, int pnum);
DWORD On_DEBUG(TCmd *pCmd, int pnum);
#ifndef HELLFIRE
DWORD On_NOVA(TCmd *pCmd, int pnum);
DWORD On_SETSHIELD(TCmd *pCmd, int pnum);
DWORD On_REMSHIELD(TCmd *pCmd, int pnum);
#else
DWORD On_REFLECT(TCmd *pCmd, int pnum);
DWORD On_NAKRUL(TCmd *pCmd, int pnum);
DWORD On_OPENHIVE(TCmd *pCmd, int pnum);
DWORD On_OPENCRYPT(TCmd *pCmd, int pnum);
#endif
#ifdef __cplusplus
}

540
Source/multi.cpp

@ -48,22 +48,19 @@ const int event_types[3] = {
EVENT_TYPE_PLAYER_MESSAGE
};
void multi_msg_add(BYTE *pbMsg, BYTE bLen)
static void buffer_init(TBuffer *pBuf)
{
if (pbMsg && bLen) {
tmsg_add(pbMsg, bLen);
}
pBuf->dwNextWriteOffset = 0;
pBuf->bData[0] = 0;
}
void NetSendLoPri(BYTE *pbMsg, BYTE bLen)
// Microsoft VisualC 2-11/net runtime
static int multi_check_pkt_valid(TBuffer *pBuf)
{
if (pbMsg && bLen) {
multi_copy_packet(&sgLoPriBuf, pbMsg, bLen);
multi_send_packet(pbMsg, bLen);
}
return pBuf->dwNextWriteOffset == 0;
}
void multi_copy_packet(TBuffer *buf, void *packet, BYTE size)
static void multi_copy_packet(TBuffer *buf, void *packet, BYTE size)
{
BYTE *p;
@ -79,18 +76,33 @@ void multi_copy_packet(TBuffer *buf, void *packet, BYTE size)
p[size] = 0;
}
void multi_send_packet(void *packet, BYTE dwSize)
static BYTE *multi_recv_packet(TBuffer *pBuf, BYTE *body, int *size)
{
TPkt pkt;
BYTE *src_ptr;
size_t chunk_size;
NetRecvPlrData(&pkt);
pkt.hdr.wLen = dwSize + sizeof(pkt.hdr);
memcpy(pkt.body, packet, dwSize);
if (!SNetSendMessage(myplr, &pkt.hdr, pkt.hdr.wLen))
nthread_terminate_game("SNetSendMessage0");
if (pBuf->dwNextWriteOffset != 0) {
src_ptr = pBuf->bData;
while (TRUE) {
if (*src_ptr == 0)
break;
chunk_size = *src_ptr;
if (chunk_size > *size)
break;
src_ptr++;
memcpy(body, src_ptr, chunk_size);
body += chunk_size;
src_ptr += chunk_size;
*size -= chunk_size;
}
memcpy(pBuf->bData, src_ptr, (pBuf->bData - src_ptr) + pBuf->dwNextWriteOffset + 1);
pBuf->dwNextWriteOffset += (pBuf->bData - src_ptr);
return body;
}
return body;
}
void NetRecvPlrData(TPkt *pkt)
static void NetRecvPlrData(TPkt *pkt)
{
pkt->hdr.wCheck = 'ip';
pkt->hdr.px = plr[myplr]._px;
@ -104,6 +116,32 @@ void NetRecvPlrData(TPkt *pkt)
pkt->hdr.bdex = plr[myplr]._pBaseDex;
}
void multi_msg_add(BYTE *pbMsg, BYTE bLen)
{
if (pbMsg && bLen) {
tmsg_add(pbMsg, bLen);
}
}
static void multi_send_packet(void *packet, BYTE dwSize)
{
TPkt pkt;
NetRecvPlrData(&pkt);
pkt.hdr.wLen = dwSize + sizeof(pkt.hdr);
memcpy(pkt.body, packet, dwSize);
if (!SNetSendMessage(myplr, &pkt.hdr, pkt.hdr.wLen))
nthread_terminate_game("SNetSendMessage0");
}
void NetSendLoPri(BYTE *pbMsg, BYTE bLen)
{
if (pbMsg && bLen) {
multi_copy_packet(&sgLoPriBuf, pbMsg, bLen);
multi_send_packet(pbMsg, bLen);
}
}
void NetSendHiPri(BYTE *pbMsg, BYTE bLen)
{
BYTE *hipri_body;
@ -130,32 +168,6 @@ void NetSendHiPri(BYTE *pbMsg, BYTE bLen)
}
}
BYTE *multi_recv_packet(TBuffer *pBuf, BYTE *body, int *size)
{
BYTE *src_ptr;
size_t chunk_size;
if (pBuf->dwNextWriteOffset != 0) {
src_ptr = pBuf->bData;
while (TRUE) {
if (*src_ptr == 0)
break;
chunk_size = *src_ptr;
if (chunk_size > *size)
break;
src_ptr++;
memcpy(body, src_ptr, chunk_size);
body += chunk_size;
src_ptr += chunk_size;
*size -= chunk_size;
}
memcpy(pBuf->bData, src_ptr, (pBuf->bData - src_ptr) + pBuf->dwNextWriteOffset + 1);
pBuf->dwNextWriteOffset += (pBuf->bData - src_ptr);
return body;
}
return body;
}
void multi_send_msg_packet(int pmask, BYTE *src, BYTE len)
{
DWORD v, p, t;
@ -175,34 +187,18 @@ void multi_send_msg_packet(int pmask, BYTE *src, BYTE len)
}
}
void multi_msg_countdown()
static void multi_mon_seeds()
{
int i;
DWORD l;
for (i = 0; i < MAX_PLRS; i++) {
if (player_state[i] & PS_TURN_ARRIVED) {
if (gdwMsgLenTbl[i] == 4)
multi_parse_turn(i, *(DWORD *)glpMsgTbl[i]);
}
}
}
void multi_parse_turn(int pnum, int turn)
{
DWORD absTurns;
if (turn >> 31)
multi_handle_turn_upper_bit(pnum);
absTurns = turn & 0x7FFFFFFF;
if (sgbSentThisCycle < gdwTurnsInTransit + absTurns) {
if (absTurns >= 0x7FFFFFFF)
absTurns &= 0xFFFF;
sgbSentThisCycle = absTurns + gdwTurnsInTransit;
sgdwGameLoops = 4 * absTurns * sgbNetUpdateRate;
}
sgdwGameLoops++;
l = (sgdwGameLoops >> 8) | (sgdwGameLoops << 24); // _rotr(sgdwGameLoops, 8)
for (i = 0; i < MAXMONSTERS; i++)
monster[i]._mAISeed = l + i;
}
void multi_handle_turn_upper_bit(int pnum)
static void multi_handle_turn_upper_bit(int pnum)
{
int i;
@ -218,31 +214,34 @@ void multi_handle_turn_upper_bit(int pnum)
}
}
void multi_player_left(int pnum, int reason)
static void multi_parse_turn(int pnum, int turn)
{
sgbPlayerLeftGameTbl[pnum] = TRUE;
sgdwPlayerLeftReasonTbl[pnum] = reason;
multi_clear_left_tbl();
DWORD absTurns;
if (turn >> 31)
multi_handle_turn_upper_bit(pnum);
absTurns = turn & 0x7FFFFFFF;
if (sgbSentThisCycle < gdwTurnsInTransit + absTurns) {
if (absTurns >= 0x7FFFFFFF)
absTurns &= 0xFFFF;
sgbSentThisCycle = absTurns + gdwTurnsInTransit;
sgdwGameLoops = 4 * absTurns * sgbNetUpdateRate;
}
}
void multi_clear_left_tbl()
void multi_msg_countdown()
{
int i;
for (i = 0; i < MAX_PLRS; i++) {
if (sgbPlayerLeftGameTbl[i]) {
if (gbBufferMsgs == 1)
msg_send_drop_pkt(i, sgdwPlayerLeftReasonTbl[i]);
else
multi_player_left_msg(i, 1);
sgbPlayerLeftGameTbl[i] = FALSE;
sgdwPlayerLeftReasonTbl[i] = 0;
if (player_state[i] & PS_TURN_ARRIVED) {
if (gdwMsgLenTbl[i] == 4)
multi_parse_turn(i, *(DWORD *)glpMsgTbl[i]);
}
}
}
void multi_player_left_msg(int pnum, int left)
static void multi_player_left_msg(int pnum, int left)
{
const char *pszFmt;
@ -271,69 +270,48 @@ void multi_player_left_msg(int pnum, int left)
}
}
void multi_net_ping()
{
sgbTimeout = TRUE;
sglTimeoutStart = SDL_GetTicks();
}
int multi_handle_delta()
static void multi_clear_left_tbl()
{
int i;
BOOL received;
if (gbGameDestroyed) {
gbRunGame = FALSE;
return FALSE;
}
for (i = 0; i < MAX_PLRS; i++) {
if (sgbSendDeltaTbl[i]) {
sgbSendDeltaTbl[i] = FALSE;
DeltaExportData(i);
}
}
sgbSentThisCycle = nthread_send_and_recv_turn(sgbSentThisCycle, 1);
if (!nthread_recv_turns(&received)) {
multi_begin_timeout();
return FALSE;
}
if (sgbPlayerLeftGameTbl[i]) {
if (gbBufferMsgs == 1)
msg_send_drop_pkt(i, sgdwPlayerLeftReasonTbl[i]);
else
multi_player_left_msg(i, 1);
sgbTimeout = FALSE;
if (received) {
if (!gbShouldValidatePackage) {
NetSendHiPri(0, 0);
gbShouldValidatePackage = FALSE;
} else {
gbShouldValidatePackage = FALSE;
if (!multi_check_pkt_valid(&sgHiPriBuf))
NetSendHiPri(0, 0);
sgbPlayerLeftGameTbl[i] = FALSE;
sgdwPlayerLeftReasonTbl[i] = 0;
}
}
multi_mon_seeds();
}
return TRUE;
void multi_player_left(int pnum, int reason)
{
sgbPlayerLeftGameTbl[pnum] = TRUE;
sgdwPlayerLeftReasonTbl[pnum] = reason;
multi_clear_left_tbl();
}
// Microsoft VisualC 2-11/net runtime
int multi_check_pkt_valid(TBuffer *pBuf)
void multi_net_ping()
{
return pBuf->dwNextWriteOffset == 0;
sgbTimeout = TRUE;
sglTimeoutStart = SDL_GetTicks();
}
void multi_mon_seeds()
static void multi_check_drop_player()
{
int i;
DWORD l;
sgdwGameLoops++;
l = (sgdwGameLoops >> 8) | (sgdwGameLoops << 24); // _rotr(sgdwGameLoops, 8)
for (i = 0; i < MAXMONSTERS; i++)
monster[i]._mAISeed = l + i;
for (i = 0; i < MAX_PLRS; i++) {
if (!(player_state[i] & PS_ACTIVE) && player_state[i] & PS_CONNECTED) {
SNetDropPlayer(i, LEAVE_DROP);
}
}
}
void multi_begin_timeout()
static void multi_begin_timeout()
{
int i, nTicks, nState, nLowestActive, nLowestPlayer;
BYTE bGroupPlayers, bGroupCount;
@ -394,14 +372,66 @@ void multi_begin_timeout()
}
}
void multi_check_drop_player()
int multi_handle_delta()
{
int i;
BOOL received;
if (gbGameDestroyed) {
gbRunGame = FALSE;
return FALSE;
}
for (i = 0; i < MAX_PLRS; i++) {
if (!(player_state[i] & PS_ACTIVE) && player_state[i] & PS_CONNECTED) {
SNetDropPlayer(i, LEAVE_DROP);
if (sgbSendDeltaTbl[i]) {
sgbSendDeltaTbl[i] = FALSE;
DeltaExportData(i);
}
}
sgbSentThisCycle = nthread_send_and_recv_turn(sgbSentThisCycle, 1);
if (!nthread_recv_turns(&received)) {
multi_begin_timeout();
return FALSE;
}
sgbTimeout = FALSE;
if (received) {
if (!gbShouldValidatePackage) {
NetSendHiPri(0, 0);
gbShouldValidatePackage = FALSE;
} else {
gbShouldValidatePackage = FALSE;
if (!multi_check_pkt_valid(&sgHiPriBuf))
NetSendHiPri(0, 0);
}
}
multi_mon_seeds();
return TRUE;
}
static void multi_handle_all_packets(int pnum, BYTE *pData, int nSize)
{
int nLen;
while (nSize != 0) {
nLen = ParseCmd(pnum, (TCmd *)pData);
if (nLen == 0) {
break;
}
pData += nLen;
nSize -= nLen;
}
}
static void multi_process_tmsgs()
{
int cnt;
TPkt pkt;
while (cnt = tmsg_get((BYTE *)&pkt, 512)) {
multi_handle_all_packets(myplr, (BYTE *)&pkt, cnt);
}
}
@ -476,30 +506,6 @@ void multi_process_network_packets()
nthread_terminate_game("SNetReceiveMsg");
}
void multi_handle_all_packets(int pnum, BYTE *pData, int nSize)
{
int nLen;
while (nSize != 0) {
nLen = ParseCmd(pnum, (TCmd *)pData);
if (nLen == 0) {
break;
}
pData += nLen;
nSize -= nLen;
}
}
void multi_process_tmsgs()
{
int cnt;
TPkt pkt;
while (cnt = tmsg_get((BYTE *)&pkt, 512)) {
multi_handle_all_packets(myplr, (BYTE *)&pkt, cnt);
}
}
void multi_send_zero_packet(int pnum, BYTE bCmd, BYTE *pbSrc, DWORD dwLen)
{
DWORD dwOffset, dwBody, dwMsg;
@ -565,41 +571,94 @@ void multi_send_zero_packet(int pnum, BYTE bCmd, BYTE *pbSrc, DWORD dwLen)
}
}
void NetClose()
static void multi_send_pinfo(int pnum, char cmd)
{
if (!sgbNetInited) {
return;
}
PkPlayerStruct pkplr;
sgbNetInited = FALSE;
nthread_cleanup();
dthread_cleanup();
tmsg_cleanup();
multi_event_handler(FALSE);
SNetLeaveGame(3);
if (gbMaxPlayers > 1)
SDL_Delay(2000);
PackPlayer(&pkplr, myplr, TRUE);
dthread_send_delta(pnum, cmd, &pkplr, sizeof(pkplr));
}
void multi_event_handler(BOOL add)
static int InitLevelType(int l)
{
DWORD i;
BOOL(STORMAPI * fn)
(int, SEVTHANDLER);
if (l == 0)
return DTYPE_TOWN;
if (l >= 1 && l <= 4)
return DTYPE_CATHEDRAL;
if (l >= 5 && l <= 8)
return DTYPE_CATACOMBS;
if (l >= 9 && l <= 12)
return DTYPE_CAVES;
if (add)
fn = SNetRegisterEventHandler;
else
fn = SNetUnregisterEventHandler;
#ifdef HELLFIRE
if (l >= 13 && l <= 16)
return DTYPE_HELL;
if (l >= 21 && l <= 24)
return DTYPE_CATHEDRAL; // Crypt
if (l >= 17 && l <= 20)
return DTYPE_CAVES; // Hive
for (i = 0; i < 3; i++) {
if (!fn(event_types[i], multi_handle_events) && add) {
app_fatal("SNetRegisterEventHandler:\n%s", TraceLastError());
return DTYPE_CATHEDRAL;
#else
return DTYPE_HELL;
#endif
}
static void SetupLocalCoords()
{
int x, y;
if (!leveldebug || gbMaxPlayers > 1) {
currlevel = 0;
leveltype = DTYPE_TOWN;
setlevel = FALSE;
}
x = 75;
y = 68;
#ifdef _DEBUG
if (debug_mode_key_inverted_v || debug_mode_key_d) {
x = 49;
y = 23;
}
#endif
x += plrxoff[myplr];
y += plryoff[myplr];
plr[myplr]._px = x;
plr[myplr]._py = y;
plr[myplr]._pfutx = x;
plr[myplr]._pfuty = y;
plr[myplr]._ptargx = x;
plr[myplr]._ptargy = y;
plr[myplr].plrlevel = currlevel;
plr[myplr]._pLvlChanging = TRUE;
plr[myplr].pLvlLoad = 0;
plr[myplr]._pmode = PM_NEWLVL;
plr[myplr].destAction = ACTION_NONE;
}
static BOOL multi_upgrade(BOOL *pfExitProgram)
{
BOOL result;
int status;
SNetPerformUpgrade((LPDWORD)&status);
result = TRUE;
if (status && status != 1) {
if (status != 2) {
if (status == -1) {
DrawDlg("Network upgrade failed");
}
} else {
*pfExitProgram = 1;
}
result = FALSE;
}
return result;
}
void multi_handle_events(_SNETEVENT *pEvt)
static void multi_handle_events(_SNETEVENT *pEvt)
{
DWORD LeftReason;
_gamedata *gameData;
@ -635,6 +694,40 @@ void multi_handle_events(_SNETEVENT *pEvt)
}
}
static void multi_event_handler(BOOL add)
{
DWORD i;
BOOL(STORMAPI * fn)
(int, SEVTHANDLER);
if (add)
fn = SNetRegisterEventHandler;
else
fn = SNetUnregisterEventHandler;
for (i = 0; i < 3; i++) {
if (!fn(event_types[i], multi_handle_events) && add) {
app_fatal("SNetRegisterEventHandler:\n%s", TraceLastError());
}
}
}
void NetClose()
{
if (!sgbNetInited) {
return;
}
sgbNetInited = FALSE;
nthread_cleanup();
dthread_cleanup();
tmsg_cleanup();
multi_event_handler(FALSE);
SNetLeaveGame(3);
if (gbMaxPlayers > 1)
SDL_Delay(2000);
}
BOOL NetInit(BOOL bSinglePlayer, BOOL *pfExitProgram)
{
int i;
@ -738,77 +831,6 @@ BOOL NetInit(BOOL bSinglePlayer, BOOL *pfExitProgram)
return TRUE;
}
void buffer_init(TBuffer *pBuf)
{
pBuf->dwNextWriteOffset = 0;
pBuf->bData[0] = 0;
}
void multi_send_pinfo(int pnum, char cmd)
{
PkPlayerStruct pkplr;
PackPlayer(&pkplr, myplr, TRUE);
dthread_send_delta(pnum, cmd, &pkplr, sizeof(pkplr));
}
int InitLevelType(int l)
{
if (l == 0)
return DTYPE_TOWN;
if (l >= 1 && l <= 4)
return DTYPE_CATHEDRAL;
if (l >= 5 && l <= 8)
return DTYPE_CATACOMBS;
if (l >= 9 && l <= 12)
return DTYPE_CAVES;
#ifdef HELLFIRE
if (l >= 13 && l <= 16)
return DTYPE_HELL;
if (l >= 21 && l <= 24)
return DTYPE_CATHEDRAL; // Crypt
if (l >= 17 && l <= 20)
return DTYPE_CAVES; // Hive
return DTYPE_CATHEDRAL;
#else
return DTYPE_HELL;
#endif
}
void SetupLocalCoords()
{
int x, y;
if (!leveldebug || gbMaxPlayers > 1) {
currlevel = 0;
leveltype = DTYPE_TOWN;
setlevel = FALSE;
}
x = 75;
y = 68;
#ifdef _DEBUG
if (debug_mode_key_inverted_v || debug_mode_key_d) {
x = 49;
y = 23;
}
#endif
x += plrxoff[myplr];
y += plryoff[myplr];
plr[myplr]._px = x;
plr[myplr]._py = y;
plr[myplr]._pfutx = x;
plr[myplr]._pfuty = y;
plr[myplr]._ptargx = x;
plr[myplr]._ptargy = y;
plr[myplr].plrlevel = currlevel;
plr[myplr]._pLvlChanging = TRUE;
plr[myplr].pLvlLoad = 0;
plr[myplr]._pmode = PM_NEWLVL;
plr[myplr].destAction = ACTION_NONE;
}
BOOL multi_init_single(_SNETPROGRAMDATA *client_info, _SNETPLAYERDATA *user_info, _SNETUIDATA *ui_info)
{
int unused;
@ -868,28 +890,6 @@ BOOL multi_init_multi(_SNETPROGRAMDATA *client_info, _SNETPLAYERDATA *user_info,
}
}
BOOL multi_upgrade(BOOL *pfExitProgram)
{
BOOL result;
int status;
SNetPerformUpgrade((LPDWORD)&status);
result = TRUE;
if (status && status != 1) {
if (status != 2) {
if (status == -1) {
DrawDlg("Network upgrade failed");
}
} else {
*pfExitProgram = 1;
}
result = FALSE;
}
return result;
}
void recv_plrinfo(int pnum, TCmdPlrInfoHdr *p, BOOL recv)
{
const char *szEvent;

27
Source/multi.h

@ -15,8 +15,6 @@ extern "C" {
extern BOOLEAN gbSomebodyWonGameKludge;
extern char szPlayerDescript[128];
extern WORD sgwPackPlrOffsetTbl[MAX_PLRS];
extern PkPlayerStruct netplr[MAX_PLRS];
extern BOOL gbShouldValidatePackage;
extern BYTE gbActivePlayers;
extern BOOLEAN gbGameDestroyed;
extern BOOLEAN gbSelectProvider;
@ -27,45 +25,20 @@ extern int player_state[MAX_PLRS];
void multi_msg_add(BYTE *pbMsg, BYTE bLen);
void NetSendLoPri(BYTE *pbMsg, BYTE bLen);
void multi_copy_packet(TBuffer *pBuf, void *packet, BYTE size);
void multi_send_packet(void *packet, BYTE dwSize);
void NetRecvPlrData(TPkt *pkt);
void NetSendHiPri(BYTE *pbMsg, BYTE bLen);
BYTE *multi_recv_packet(TBuffer *pBuf, BYTE *body, int *size);
void multi_send_msg_packet(int pmask, BYTE *src, BYTE len);
void multi_msg_countdown();
void multi_parse_turn(int pnum, int turn);
void multi_handle_turn_upper_bit(int pnum);
void multi_player_left(int pnum, int reason);
void multi_clear_left_tbl();
void multi_player_left_msg(int pnum, int left);
void multi_net_ping();
int multi_handle_delta();
int multi_check_pkt_valid(TBuffer *pBuf);
void multi_mon_seeds();
void multi_begin_timeout();
void multi_check_drop_player();
void multi_process_network_packets();
void multi_handle_all_packets(int pnum, BYTE *pData, int nSize);
void multi_process_tmsgs();
void multi_send_zero_packet(int pnum, BYTE bCmd, BYTE *pbSrc, DWORD dwLen);
void NetClose();
void multi_event_handler(BOOL add);
void multi_handle_events(_SNETEVENT *pEvt);
BOOL NetInit(BOOL bSinglePlayer, BOOL *pfExitProgram);
void buffer_init(TBuffer *pBuf);
void multi_send_pinfo(int pnum, char cmd);
int InitLevelType(int l);
void SetupLocalCoords();
BOOL multi_init_single(_SNETPROGRAMDATA *client_info, _SNETPLAYERDATA *user_info, _SNETUIDATA *ui_info);
BOOL multi_init_multi(_SNETPROGRAMDATA *client_info, _SNETPLAYERDATA *user_info, _SNETUIDATA *ui_info, BOOL *pfExitProgram);
BOOL multi_upgrade(BOOL *pfExitProgram);
void recv_plrinfo(int pnum, TCmdPlrInfoHdr *p, BOOL recv);
/* rdata */
extern const int event_types[3];
#ifdef __cplusplus
}
#endif

52
Source/nthread.cpp

@ -109,6 +109,32 @@ BOOL nthread_recv_turns(BOOL *pfSendAsync)
}
}
static unsigned int nthread_handler(void *data)
{
int delta;
BOOL received;
if (nthread_should_run) {
while (1) {
sgMemCrit.Enter();
if (!nthread_should_run)
break;
nthread_send_and_recv_turn(0, 0);
if (nthread_recv_turns(&received))
delta = last_tick - SDL_GetTicks();
else
delta = tick_delay;
sgMemCrit.Leave();
if (delta > 0)
SDL_Delay(delta);
if (!nthread_should_run)
return 0;
}
sgMemCrit.Leave();
}
return 0;
}
void nthread_set_turn_upper_bit()
{
turn_upper_bit = 0x80000000;
@ -169,32 +195,6 @@ void nthread_start(BOOL set_turn_upper_bit)
}
}
unsigned int nthread_handler(void *data)
{
int delta;
BOOL received;
if (nthread_should_run) {
while (1) {
sgMemCrit.Enter();
if (!nthread_should_run)
break;
nthread_send_and_recv_turn(0, 0);
if (nthread_recv_turns(&received))
delta = last_tick - SDL_GetTicks();
else
delta = tick_delay;
sgMemCrit.Leave();
if (delta > 0)
SDL_Delay(delta);
if (!nthread_should_run)
return 0;
}
sgMemCrit.Leave();
}
return 0;
}
void nthread_cleanup()
{
nthread_should_run = FALSE;

6
Source/nthread.h

@ -15,27 +15,21 @@ extern "C" {
extern BYTE sgbNetUpdateRate;
extern DWORD gdwMsgLenTbl[MAX_PLRS];
extern DWORD gdwDeltaBytesSec;
extern BOOLEAN nthread_should_run;
extern DWORD gdwTurnsInTransit;
extern uintptr_t glpMsgTbl[MAX_PLRS];
extern SDL_threadID glpNThreadId;
extern int turn_upper_bit;
extern BOOLEAN sgbThreadIsRunning;
extern DWORD gdwLargestMsgSize;
extern DWORD gdwNormalMsgSize;
extern int last_tick;
void nthread_terminate_game(const char *pszFcn);
DWORD nthread_send_and_recv_turn(DWORD cur_turn, int turn_delta);
BOOL nthread_recv_turns(BOOL *pfSendAsync);
void nthread_set_turn_upper_bit();
void nthread_start(BOOL set_turn_upper_bit);
unsigned int nthread_handler(void *data);
void nthread_cleanup();
void nthread_ignore_mutex(BOOL bStart);
BOOL nthread_has_500ms_passed(BOOL unused);
/* rdata */
#ifdef __cplusplus
}
#endif

48
Source/objects.cpp

@ -297,6 +297,17 @@ DIABOOL RndLocOk(int xp, int yp)
return FALSE;
}
static DIABOOL WallTrapLocOkK(int xp, int yp)
{
if (dFlags[xp][yp] & BFLAG_POPULATED)
return FALSE;
if (nTrapTable[dPiece[xp][yp]] != FALSE)
return TRUE;
else
return FALSE;
}
void InitRndLocObj(int min, int max, int objtype)
{
int i, xp, yp, numobjs;
@ -603,7 +614,7 @@ void AddL3Objs(int x1, int y1, int x2, int y2)
}
}
DIABOOL WallTrapLocOk(int xp, int yp)
DIABOOL TorchLocOK(int xp, int yp)
{
if (dFlags[xp][yp] & BFLAG_POPULATED)
return FALSE;
@ -616,7 +627,7 @@ void AddL2Torches()
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++) {
if (!WallTrapLocOk(i, j))
if (!TorchLocOK(i, j))
continue;
pn = dPiece[i][j];
@ -635,17 +646,6 @@ void AddL2Torches()
}
}
DIABOOL TorchLocOK(int xp, int yp)
{
if (dFlags[xp][yp] & BFLAG_POPULATED)
return FALSE;
if (nTrapTable[dPiece[xp][yp]] != FALSE)
return TRUE;
else
return FALSE;
}
void AddObjTraps()
{
char oi_trap, oi;
@ -675,7 +675,7 @@ void AddObjTraps()
while (!nSolidTable[dPiece[xp][j]])
xp--;
if (!TorchLocOK(xp, j) || i - xp <= 1)
if (!WallTrapLocOkK(xp, j) || i - xp <= 1)
continue;
AddObject(OBJ_TRAPL, xp, j);
@ -688,7 +688,7 @@ void AddObjTraps()
while (!nSolidTable[dPiece[i][yp]])
yp--;
if (!TorchLocOK(i, yp) || j - yp <= 1)
if (!WallTrapLocOkK(i, yp) || j - yp <= 1)
continue;
AddObject(OBJ_TRAPR, i, yp);
@ -1652,7 +1652,7 @@ void objects_44D8C5(int ot, int v2, int ox, int oy)
return;
oi = objectavail[0];
objectavail[0] = objectavail[126 - nobjects];
objectavail[0] = objectavail[MAXOBJECTS - 1 - nobjects];
objectactive[nobjects] = oi;
dObject[ox][oy] = oi + 1;
SetupObject(oi, ox, oy, ot);
@ -1739,7 +1739,7 @@ void AddObject(int ot, int ox, int oy)
return;
oi = objectavail[0];
objectavail[0] = objectavail[126 - nobjects];
objectavail[0] = objectavail[MAXOBJECTS - 1 - nobjects];
objectactive[nobjects] = oi;
dObject[ox][oy] = oi + 1;
SetupObject(oi, ox, oy, ot);
@ -3076,12 +3076,12 @@ void OperateBookLever(int pnum, int i)
x = 2 * setpc_x + 16;
y = 2 * setpc_y + 16;
if (object[i]._oSelFlag != 0 && !qtextflag) {
if (object[i]._otype == OBJ_BLINDBOOK && !quests[Q_BLIND]._qvar1) {
if (object[i]._otype == OBJ_BLINDBOOK && quests[Q_BLIND]._qvar1 == 0) {
quests[Q_BLIND]._qactive = QUEST_ACTIVE;
quests[Q_BLIND]._qlog = TRUE;
quests[Q_BLIND]._qvar1 = 1;
}
if (object[i]._otype == OBJ_BLOODBOOK && !quests[Q_BLOOD]._qvar1) {
if (object[i]._otype == OBJ_BLOODBOOK && quests[Q_BLOOD]._qvar1 == 0) {
quests[Q_BLOOD]._qactive = QUEST_ACTIVE;
quests[Q_BLOOD]._qlog = TRUE;
quests[Q_BLOOD]._qvar1 = 1;
@ -3090,7 +3090,7 @@ void OperateBookLever(int pnum, int i)
SpawnQuestItem(IDI_BLDSTONE, 2 * setpc_x + 25, 2 * setpc_y + 33, 0, 1);
}
object[i]._otype = object[i]._otype;
if (object[i]._otype == OBJ_STEELTOME && !quests[Q_WARLORD]._qvar1) {
if (object[i]._otype == OBJ_STEELTOME && quests[Q_WARLORD]._qvar1 == 0) {
quests[Q_WARLORD]._qactive = QUEST_ACTIVE;
quests[Q_WARLORD]._qlog = TRUE;
quests[Q_WARLORD]._qvar1 = 1;
@ -3099,7 +3099,7 @@ void OperateBookLever(int pnum, int i)
if (object[i]._otype != OBJ_BLOODBOOK)
ObjChangeMap(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4);
if (object[i]._otype == OBJ_BLINDBOOK) {
CreateItem(3, x + 5, y + 5);
CreateItem(UITEM_OPTAMULET, x + 5, y + 5);
tren = TransVal;
TransVal = 9;
DRLG_MRectTrans(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4);
@ -3419,7 +3419,7 @@ void OperatePedistal(int pnum, int i)
mem = LoadFileInMem("Levels\\L2Data\\Blood2.DUN", NULL);
LoadMapObjs(mem, 2 * setpc_x, 2 * setpc_y);
mem_free_dbg(mem);
CreateItem(7, 2 * setpc_x + 25, 2 * setpc_y + 19);
CreateItem(UITEM_ARMOFVAL, 2 * setpc_x + 25, 2 * setpc_y + 19);
object[i]._oSelFlag = 0;
}
}
@ -4280,7 +4280,7 @@ void OperateBookCase(int pnum, int i, DIABOOL sendmsg)
&& monster[MAX_PLRS]._mhitpoints) {
monster[MAX_PLRS].mtalkmsg = TEXT_ZHAR2;
M_StartStand(0, monster[MAX_PLRS]._mdir);
monster[MAX_PLRS]._mgoal = MGOAL_SHOOT;
monster[MAX_PLRS]._mgoal = MGOAL_ATTACK2;
monster[MAX_PLRS]._mmode = MM_TALK;
}
if (pnum == myplr)
@ -4543,7 +4543,7 @@ void OperateStoryBook(int pnum, int i)
object[i]._oAnimFrame = object[i]._oVar4;
PlaySfxLoc(IS_ISCROL, object[i]._ox, object[i]._oy);
#ifdef HELLFIRE
if (object[i]._oVar8 && currlevel == 24) {
if (object[i]._oVar8 != 0 && currlevel == 24) {
if (IsUberLeverActivated != 1 && quests[Q_NAKRUL]._qactive != 3 && objects_lv_24_454B04(object[i]._oVar8)) {
NetSendCmd(FALSE, CMD_NAKRUL);
return;

134
Source/objects.h

@ -12,86 +12,20 @@ DEVILUTION_BEGIN_NAMESPACE
extern "C" {
#endif
extern int trapid;
extern int trapdir;
extern BYTE *pObjCels[40];
extern char ObjFileList[40];
extern int objectactive[MAXOBJECTS];
extern int nobjects;
extern int leverid;
extern int objectavail[MAXOBJECTS];
extern ObjectStruct object[MAXOBJECTS];
extern BOOL InitObjFlag;
extern int numobjfiles;
void InitObjectGFX();
void FreeObjectGFX();
DIABOOL RndLocOk(int xp, int yp);
void InitRndLocObj(int min, int max, int objtype);
void InitRndLocBigObj(int min, int max, int objtype);
void InitRndLocObj5x5(int min, int max, int objtype);
void ClrAllObjects();
void AddTortures();
void AddCandles();
void AddBookLever(int lx1, int ly1, int lx2, int ly2, int x1, int y1, int x2, int y2, int msg);
void InitRndBarrels();
void AddL1Objs(int x1, int y1, int x2, int y2);
#ifdef HELLFIRE
void add_crypt_objs(int x1, int y1, int x2, int y2);
#endif
void AddL2Objs(int x1, int y1, int x2, int y2);
void AddL3Objs(int x1, int y1, int x2, int y2);
DIABOOL WallTrapLocOk(int xp, int yp);
void AddL2Torches();
DIABOOL TorchLocOK(int xp, int yp);
void AddObjTraps();
void AddChestTraps();
void LoadMapObjects(BYTE *pMap, int startx, int starty, int x1, int y1, int w, int h, int leveridx);
void LoadMapObjs(BYTE *pMap, int startx, int starty);
void AddDiabObjs();
#ifdef HELLFIRE
void objects_add_lv22(int s);
void objects_add_lv24();
#endif
void AddStoryBooks();
void AddHookedBodies(int freq);
void AddL4Goodies();
void AddLazStand();
void InitObjects();
void SetMapObjects(BYTE *pMap, int startx, int starty);
void DeleteObject_(int oi, int i);
void SetupObject(int i, int x, int y, int ot);
void SetObjMapRange(int i, int x1, int y1, int x2, int y2, int v);
void SetBookMsg(int i, int msg);
void AddL1Door(int i, int x, int y, int ot);
void AddSCambBook(int i);
void AddChest(int i, int t);
void AddL2Door(int i, int x, int y, int ot);
void AddL3Door(int i, int x, int y, int ot);
void AddSarc(int i);
void AddFlameTrap(int i);
void AddFlameLvr(int i);
void AddTrap(int i, int ot);
void AddObjLight(int i, int r);
void AddBarrel(int i, int t);
void AddShrine(int i);
void AddBookcase(int i);
void AddPurifyingFountain(int i);
void AddArmorStand(int i);
void AddGoatShrine(int i);
void AddCauldron(int i);
void AddMurkyFountain(int i);
void AddTearFountain(int i);
void AddDecap(int i);
void AddVilebook(int i);
void AddMagicCircle(int i);
void AddBrnCross(int i);
void AddBookstand(int i);
void AddBloodFtn(int i);
void AddPedistal(int i);
void AddStoryBook(int i);
void AddWeaponRack(int i);
void AddTorturedBody(int i);
void GetRndObjLoc(int randarea, int *xx, int *yy);
void AddMushPatch();
void AddSlainHero();
@ -101,76 +35,19 @@ void objects_44DA68(int a1, int a2);
void objects_454AF0(int a1, int a2, int a3);
#endif
void AddObject(int ot, int ox, int oy);
void Obj_Light(int i, int lr);
void Obj_Circle(int i);
void Obj_StopAnim(int i);
void Obj_Door(int i);
void Obj_Sarc(int i);
void ActivateTrapLine(int ttype, int tid);
void Obj_FlameTrap(int i);
void Obj_Trap(int i);
void Obj_BCrossDamage(int i);
void ProcessObjects();
void ObjSetMicro(int dx, int dy, int pn);
void objects_set_door_piece(int x, int y);
void ObjSetMini(int x, int y, int v);
void ObjL1Special(int x1, int y1, int x2, int y2);
void ObjL2Special(int x1, int y1, int x2, int y2);
void DoorSet(int oi, int dx, int dy);
void RedoPlayerVision();
void OperateL1RDoor(int pnum, int oi, DIABOOL sendflag);
void OperateL1LDoor(int pnum, int oi, DIABOOL sendflag);
void OperateL2RDoor(int pnum, int oi, DIABOOL sendflag);
void OperateL2LDoor(int pnum, int oi, BOOL sendflag);
void OperateL3RDoor(int pnum, int oi, DIABOOL sendflag);
void OperateL3LDoor(int pnum, int oi, DIABOOL sendflag);
void MonstCheckDoors(int m);
void ObjChangeMap(int x1, int y1, int x2, int y2);
void ObjChangeMapResync(int x1, int y1, int x2, int y2);
void OperateL1Door(int pnum, int i, DIABOOL sendflag);
void OperateLever(int pnum, int i);
void OperateBook(int pnum, int i);
void OperateBookLever(int pnum, int i);
void OperateSChambBk(int pnum, int i);
void OperateChest(int pnum, int i, DIABOOL sendmsg);
void OperateMushPatch(int pnum, int i);
void OperateInnSignChest(int pnum, int i);
void OperateSlainHero(int pnum, int i, DIABOOL sendmsg);
void OperateTrapLvr(int i);
void OperateSarc(int pnum, int i, DIABOOL sendmsg);
void OperateL2Door(int pnum, int i, DIABOOL sendflag);
void OperateL3Door(int pnum, int i, DIABOOL sendflag);
void OperatePedistal(int pnum, int i);
void TryDisarm(int pnum, int i);
int ItemMiscIdIdx(int imiscid);
void OperateShrine(int pnum, int i, int sType);
void OperateSkelBook(int pnum, int i, DIABOOL sendmsg);
void OperateBookCase(int pnum, int i, DIABOOL sendmsg);
void OperateDecap(int pnum, int i, DIABOOL sendmsg);
void OperateArmorStand(int pnum, int i, DIABOOL sendmsg);
int FindValidShrine(int i);
void OperateGoatShrine(int pnum, int i, int sType);
void OperateCauldron(int pnum, int i, int sType);
DIABOOL OperateFountains(int pnum, int i);
void OperateWeaponRack(int pnum, int i, DIABOOL sendmsg);
void OperateStoryBook(int pnum, int i);
void OperateLazStand(int pnum, int i);
void OperateObject(int pnum, int i, BOOL TeleFlag);
void SyncOpL1Door(int pnum, int cmd, int i);
void SyncOpL2Door(int pnum, int cmd, int i);
void SyncOpL3Door(int pnum, int cmd, int i);
void SyncOpObject(int pnum, int cmd, int i);
void BreakCrux(int i);
void BreakBarrel(int pnum, int i, int dam, BOOL forcebreak, BOOL sendmsg);
void BreakObject(int pnum, int oi);
void SyncBreakObj(int pnum, int oi);
void SyncL1Doors(int i);
void SyncCrux(int i);
void SyncLever(int i);
void SyncQSTLever(int i);
void SyncPedistal(int i);
void SyncL2Doors(int i);
void SyncL3Doors(int i);
void SyncObjectAnim(int o);
void GetObjectStr(int i);
void operate_lv24_lever();
@ -178,17 +55,6 @@ void objects_454BA8();
void objects_rnd_454BEA();
DIABOOL objects_lv_24_454B04(int s);
/* rdata */
extern int bxadd[8];
extern int byadd[8];
extern const char *const shrinestrs[NUM_SHRINETYPE];
extern char shrinemin[NUM_SHRINETYPE];
extern char shrinemax[NUM_SHRINETYPE];
extern BYTE shrineavail[NUM_SHRINETYPE];
extern const char *const StoryBookName[];
extern int StoryText[3][3];
#ifdef __cplusplus
}
#endif

1
Source/pack.h

@ -13,7 +13,6 @@ extern "C" {
#endif
void PackPlayer(PkPlayerStruct *pPack, int pnum, BOOL manashield);
void VerifyGoldSeeds(PlayerStruct *pPlayer);
void UnPackPlayer(PkPlayerStruct *pPack, int pnum, BOOL killok);
#ifdef HELLFIRE
void PackItem(PkItemStruct *id, ItemStruct *is);

9
Source/palette.h

@ -39,15 +39,6 @@ void palette_update_quest_palette(int n);
BOOL palette_get_color_cycling();
BOOL palette_set_color_cycling(BOOL enabled);
/* rdata */
/* data */
extern int gamma_correction;
#ifndef HELLFIRE
extern BOOL color_cycling_enabled;
#endif
#ifdef __cplusplus
}
#endif

14
Source/path.h

@ -12,18 +12,8 @@ DEVILUTION_BEGIN_NAMESPACE
extern "C" {
#endif
extern PATHNODE path_nodes[MAXPATHNODES];
extern int gdwCurPathStep;
extern int gdwCurNodes;
extern int pnode_vals[MAX_PATH_LENGTH];
extern PATHNODE *pnode_ptr;
extern PATHNODE *pnode_tblptr[MAXPATHNODES];
extern PATHNODE *path_2_nodes;
extern PATHNODE path_unusednodes[MAXPATHNODES];
int FindPath(BOOL (*PosOk)(int, int, int), int PosOkArg, int sx, int sy, int dx, int dy, char *path);
int path_get_h_cost(int sx, int sy, int dx, int dy);
int path_check_equal(PATHNODE *pPath, int dx, int dy);
PATHNODE *GetNextPath();
BOOL path_solid_pieces(PATHNODE *pPath, int dx, int dy);
BOOL path_get_path(BOOL (*PosOk)(int, int, int), int PosOkArg, PATHNODE *pPath, int x, int y);
@ -40,10 +30,6 @@ PATHNODE *path_new_step();
extern const char pathxdir[8];
extern const char pathydir[8];
/* data */
extern char path_directions[9];
#ifdef __cplusplus
}
#endif

272
Source/pfile.cpp

@ -61,20 +61,7 @@ std::string GetSavePath(DWORD save_num)
static char hero_names[MAX_CHARACTERS][PLR_NAME_LEN];
BOOL gbValidSaveFile;
void pfile_write_hero()
{
DWORD save_num;
PkPlayerStruct pkplr;
save_num = pfile_get_save_num_from_name(plr[myplr]._pName);
if (pfile_open_archive(TRUE, save_num)) {
PackPlayer(&pkplr, myplr, gbMaxPlayers == 1);
pfile_encode_hero(&pkplr);
pfile_flush(gbMaxPlayers == 1, save_num);
}
}
DWORD pfile_get_save_num_from_name(const char *name)
static DWORD pfile_get_save_num_from_name(const char *name)
{
DWORD i;
@ -86,7 +73,48 @@ DWORD pfile_get_save_num_from_name(const char *name)
return i;
}
void pfile_encode_hero(const PkPlayerStruct *pPack)
static BOOL pfile_read_hero(HANDLE archive, PkPlayerStruct *pPack)
{
HANDLE file;
DWORD dwlen;
BYTE *buf;
if (!SFileOpenFileEx(archive, "hero", 0, &file)) {
return FALSE;
} else {
BOOL ret = FALSE;
const char *password;
if (gbIsSpawn) {
password = PASSWORD_SPAWN_SINGLE;
if (gbMaxPlayers > 1)
password = PASSWORD_SPAWN_MULTI;
} else {
password = PASSWORD_SINGLE;
if (gbMaxPlayers > 1)
password = PASSWORD_MULTI;
}
dwlen = SFileGetFileSize(file, NULL);
if (dwlen) {
DWORD read;
buf = DiabloAllocPtr(dwlen);
if (SFileReadFile(file, buf, dwlen, &read, NULL)) {
read = codec_decode(buf, dwlen, password);
if (read == sizeof(*pPack)) {
memcpy(pPack, buf, sizeof(*pPack));
ret = TRUE;
}
}
if (buf)
mem_free_dbg(buf);
}
SFileCloseFile(file);
return ret;
}
}
static void pfile_encode_hero(const PkPlayerStruct *pPack)
{
BYTE *packed;
DWORD packed_len;
@ -110,7 +138,7 @@ void pfile_encode_hero(const PkPlayerStruct *pPack)
mem_free_dbg(packed);
}
BOOL pfile_open_archive(BOOL update, DWORD save_num)
static BOOL pfile_open_archive(BOOL update, DWORD save_num)
{
if (OpenMPQ(GetSavePath(save_num).c_str(), save_num))
return TRUE;
@ -118,11 +146,41 @@ BOOL pfile_open_archive(BOOL update, DWORD save_num)
return FALSE;
}
void pfile_flush(BOOL is_single_player, DWORD save_num)
static void pfile_flush(BOOL is_single_player, DWORD save_num)
{
mpqapi_flush_and_close(GetSavePath(save_num).c_str(), is_single_player, save_num);
}
/**
* @param showFixedMsg Display a dialog if a save file was corrected (deprecated)
*/
static HANDLE pfile_open_save_archive(BOOL *showFixedMsg, DWORD save_num)
{
HANDLE archive;
if (SFileOpenArchive(GetSavePath(save_num).c_str(), 0x7000, FS_PC, &archive))
return archive;
return NULL;
}
static void pfile_SFileCloseArchive(HANDLE hsArchive)
{
SFileCloseArchive(hsArchive);
}
void pfile_write_hero()
{
DWORD save_num;
PkPlayerStruct pkplr;
save_num = pfile_get_save_num_from_name(plr[myplr]._pName);
if (pfile_open_archive(TRUE, save_num)) {
PackPlayer(&pkplr, myplr, gbMaxPlayers == 1);
pfile_encode_hero(&pkplr);
pfile_flush(gbMaxPlayers == 1, save_num);
}
}
BOOL pfile_create_player_description(char *dst, DWORD len)
{
char desc[128];
@ -178,24 +236,28 @@ void pfile_flush_W()
pfile_flush(TRUE, pfile_get_save_num_from_name(plr[myplr]._pName));
}
void game_2_ui_player(const PlayerStruct *p, _uiheroinfo *heroinfo, BOOL bHasSaveFile)
static char pfile_get_player_class(unsigned int player_class_nr)
{
memset(heroinfo, 0, sizeof(*heroinfo));
strncpy(heroinfo->name, p->_pName, sizeof(heroinfo->name) - 1);
heroinfo->name[sizeof(heroinfo->name) - 1] = '\0';
heroinfo->level = p->_pLevel;
heroinfo->heroclass = game_2_ui_class(p);
heroinfo->strength = p->_pStrength;
heroinfo->magic = p->_pMagic;
heroinfo->dexterity = p->_pDexterity;
heroinfo->vitality = p->_pVitality;
heroinfo->gold = p->_pGold;
heroinfo->hassaved = bHasSaveFile;
heroinfo->herorank = p->pDiabloKillLevel;
heroinfo->spawned = gbIsSpawn;
char pc_class;
if (player_class_nr == UI_WARRIOR)
pc_class = PC_WARRIOR;
else if (player_class_nr == UI_ROGUE)
pc_class = PC_ROGUE;
#ifdef HELLFIRE
else if (player_class_nr == 3)
pc_class = PC_MONK;
else if (player_class_nr == 4)
pc_class = PC_BARD;
else if (player_class_nr == 5)
pc_class = PC_BARBARIAN;
#endif
else
pc_class = PC_SORCERER;
return pc_class;
}
BYTE game_2_ui_class(const PlayerStruct *p)
static BYTE game_2_ui_class(const PlayerStruct *p) // game_2_ui_class
{
BYTE uiclass;
if (p->_pClass == PC_WARRIOR)
@ -216,6 +278,23 @@ BYTE game_2_ui_class(const PlayerStruct *p)
return uiclass;
}
void game_2_ui_player(const PlayerStruct *p, _uiheroinfo *heroinfo, BOOL bHasSaveFile)
{
memset(heroinfo, 0, sizeof(*heroinfo));
strncpy(heroinfo->name, p->_pName, sizeof(heroinfo->name) - 1);
heroinfo->name[sizeof(heroinfo->name) - 1] = '\0';
heroinfo->level = p->_pLevel;
heroinfo->heroclass = game_2_ui_class(p);
heroinfo->strength = p->_pStrength;
heroinfo->magic = p->_pMagic;
heroinfo->dexterity = p->_pDexterity;
heroinfo->vitality = p->_pVitality;
heroinfo->gold = p->_pGold;
heroinfo->hassaved = bHasSaveFile;
heroinfo->herorank = p->pDiabloKillLevel;
heroinfo->spawned = gbIsSpawn;
}
BOOL pfile_ui_set_hero_infos(BOOL(*ui_add_hero_info)(_uiheroinfo *))
{
DWORD i;
@ -242,64 +321,6 @@ BOOL pfile_ui_set_hero_infos(BOOL(*ui_add_hero_info)(_uiheroinfo *))
return TRUE;
}
BOOL pfile_read_hero(HANDLE archive, PkPlayerStruct *pPack)
{
HANDLE file;
DWORD dwlen;
BYTE *buf;
if (!SFileOpenFileEx(archive, "hero", 0, &file)) {
return FALSE;
} else {
BOOL ret = FALSE;
const char *password;
if (gbIsSpawn) {
password = PASSWORD_SPAWN_SINGLE;
if (gbMaxPlayers > 1)
password = PASSWORD_SPAWN_MULTI;
} else {
password = PASSWORD_SINGLE;
if (gbMaxPlayers > 1)
password = PASSWORD_MULTI;
}
dwlen = SFileGetFileSize(file, NULL);
if (dwlen) {
DWORD read;
buf = DiabloAllocPtr(dwlen);
if (SFileReadFile(file, buf, dwlen, &read, NULL)) {
read = codec_decode(buf, dwlen, password);
if (read == sizeof(*pPack)) {
memcpy(pPack, buf, sizeof(*pPack));
ret = TRUE;
}
}
if (buf)
mem_free_dbg(buf);
}
SFileCloseFile(file);
return ret;
}
}
/**
* @param showFixedMsg Display a dialog if a save file was corrected (deprecated)
*/
HANDLE pfile_open_save_archive(BOOL *showFixedMsg, DWORD save_num)
{
HANDLE archive;
if (SFileOpenArchive(GetSavePath(save_num).c_str(), 0x7000, FS_PC, &archive))
return archive;
return NULL;
}
void pfile_SFileCloseArchive(HANDLE hsArchive)
{
SFileCloseArchive(hsArchive);
}
BOOL pfile_archive_contains_game(HANDLE hsArchive, DWORD save_num)
{
HANDLE file;
@ -326,27 +347,6 @@ BOOL pfile_ui_set_class_stats(unsigned int player_class_nr, _uidefaultstats *cla
return TRUE;
}
char pfile_get_player_class(unsigned int player_class_nr)
{
char pc_class;
if (player_class_nr == UI_WARRIOR)
pc_class = PC_WARRIOR;
else if (player_class_nr == UI_ROGUE)
pc_class = PC_ROGUE;
#ifdef HELLFIRE
else if (player_class_nr == 3)
pc_class = PC_MONK;
else if (player_class_nr == 4)
pc_class = PC_BARD;
else if (player_class_nr == 5)
pc_class = PC_BARBARIAN;
#endif
else
pc_class = PC_SORCERER;
return pc_class;
}
BOOL pfile_ui_save_create(_uiheroinfo *heroinfo)
{
DWORD save_num;
@ -470,18 +470,23 @@ void pfile_get_game_name(char *dst)
strcpy(dst, "game");
}
void pfile_remove_temp_files()
static BOOL GetPermSaveNames(DWORD dwIndex, char *szPerm)
{
if (gbMaxPlayers <= 1) {
DWORD save_num = pfile_get_save_num_from_name(plr[myplr]._pName);
if (!pfile_open_archive(FALSE, save_num))
app_fatal("Unable to write to save file archive");
mpqapi_remove_hash_entries(GetTempSaveNames);
pfile_flush(TRUE, save_num);
}
const char *fmt;
if (dwIndex < 17)
fmt = "perml%02d";
else if (dwIndex < 34) {
dwIndex -= 17;
fmt = "perms%02d";
} else
return FALSE;
sprintf(szPerm, fmt, dwIndex);
return TRUE;
}
BOOL GetTempSaveNames(DWORD dwIndex, char *szTemp)
static BOOL GetTempSaveNames(DWORD dwIndex, char *szTemp)
{
const char *fmt;
@ -497,6 +502,17 @@ BOOL GetTempSaveNames(DWORD dwIndex, char *szTemp)
return TRUE;
}
void pfile_remove_temp_files()
{
if (gbMaxPlayers <= 1) {
DWORD save_num = pfile_get_save_num_from_name(plr[myplr]._pName);
if (!pfile_open_archive(FALSE, save_num))
app_fatal("Unable to write to save file archive");
mpqapi_remove_hash_entries(GetTempSaveNames);
pfile_flush(TRUE, save_num);
}
}
void pfile_rename_temp_to_perm()
{
DWORD dwChar, dwIndex;
@ -525,22 +541,6 @@ void pfile_rename_temp_to_perm()
pfile_flush(TRUE, dwChar);
}
BOOL GetPermSaveNames(DWORD dwIndex, char *szPerm)
{
const char *fmt;
if (dwIndex < 17)
fmt = "perml%02d";
else if (dwIndex < 34) {
dwIndex -= 17;
fmt = "perms%02d";
} else
return FALSE;
sprintf(szPerm, fmt, dwIndex);
return TRUE;
}
void pfile_write_save_file(const char *pszName, BYTE *pbData, DWORD dwLen, DWORD qwLen)
{
DWORD save_num;

13
Source/pfile.h

@ -15,25 +15,15 @@ extern "C" {
extern BOOL gbValidSaveFile;
void pfile_init_save_directory();
void pfile_check_available_space(char *pszDir);
void pfile_write_hero();
DWORD pfile_get_save_num_from_name(const char *name);
void pfile_encode_hero(const PkPlayerStruct *pPack);
BOOL pfile_open_archive(BOOL update, DWORD save_num);
void pfile_flush(BOOL is_single_player, DWORD save_num);
BOOL pfile_create_player_description(char *dst, DWORD len);
BOOL pfile_rename_hero(const char *name_1, const char *name_2);
void pfile_flush_W();
void game_2_ui_player(const PlayerStruct *p, _uiheroinfo *heroinfo, BOOL bHasSaveFile);
BYTE game_2_ui_class(const PlayerStruct *p);
BOOL pfile_ui_set_hero_infos(BOOL(*ui_add_hero_info)(_uiheroinfo *));
char *GetSaveDirectory(char *dst, int dst_size, DWORD save_num);
BOOL pfile_read_hero(HANDLE archive, PkPlayerStruct *pPack);
HANDLE pfile_open_save_archive(BOOL *showFixedMsg, DWORD save_num);
void pfile_SFileCloseArchive(HANDLE hsArchive);
BOOL pfile_archive_contains_game(HANDLE hsArchive, DWORD save_num);
BOOL pfile_ui_set_class_stats(unsigned int player_class_nr, _uidefaultstats *class_stats);
char pfile_get_player_class(unsigned int player_class_nr);
BOOL pfile_ui_save_create(_uiheroinfo *heroinfo);
BOOL pfile_get_file_name(DWORD lvl, char *dst);
BOOL pfile_delete_save(_uiheroinfo *hero_info);
@ -42,14 +32,11 @@ void GetTempLevelNames(char *szTemp);
void GetPermLevelNames(char *szPerm);
void pfile_get_game_name(char *dst);
void pfile_remove_temp_files();
BOOL GetTempSaveNames(DWORD dwIndex, char *szTemp);
void pfile_rename_temp_to_perm();
BOOL GetPermSaveNames(DWORD dwIndex, char *szPerm);
void pfile_write_save_file(const char *pszName, BYTE *pbData, DWORD dwLen, DWORD qwLen);
BYTE *pfile_read(const char *pszName, DWORD *pdwLen);
void pfile_update(BOOL force_save);
/* rdata */
#ifdef __cplusplus
}
#endif

4
Source/quests.cpp

@ -791,7 +791,7 @@ void ResyncQuests()
}
}
if (currlevel == quests[Q_MUSHROOM]._qlevel) {
if (quests[Q_MUSHROOM]._qactive == QUEST_INIT && !quests[Q_MUSHROOM]._qvar1) {
if (quests[Q_MUSHROOM]._qactive == QUEST_INIT && quests[Q_MUSHROOM]._qvar1 == 0) {
SpawnQuestItem(IDI_FUNGALTM, 0, 0, 5, 1);
quests[Q_MUSHROOM]._qvar1 = QS_TOMESPAWNED;
} else {
@ -805,7 +805,7 @@ void ResyncQuests()
}
}
}
if (currlevel == quests[Q_VEIL]._qlevel + 1 && quests[Q_VEIL]._qactive == QUEST_ACTIVE && !quests[Q_VEIL]._qvar1) {
if (currlevel == quests[Q_VEIL]._qlevel + 1 && quests[Q_VEIL]._qactive == QUEST_ACTIVE && quests[Q_VEIL]._qvar1 == 0) {
quests[Q_VEIL]._qvar1 = 1;
SpawnQuestItem(IDI_GLDNELIX, 0, 0, 5, 1);
}

2
Source/themes.cpp

@ -503,7 +503,7 @@ void PlaceThemeMonsts(int t, int f)
numscattypes = 0;
for (i = 0; i < nummtypes; i++) {
if (Monsters[i].mPlaceFlags & 1) {
if (Monsters[i].mPlaceFlags & PLACE_SCATTER) {
scattertypes[numscattypes] = i;
numscattypes++;
}

8
enums.h

@ -1785,7 +1785,7 @@ typedef enum monster_goal {
MGOAL_RETREAT = 2,
MGOAL_HEALING = 3,
MGOAL_MOVE = 4,
MGOAL_SHOOT = 5,
MGOAL_ATTACK2 = 5,
MGOAL_INQUIRING = 6,
MGOAL_TALKING = 7,
} monster_goal;
@ -2237,6 +2237,12 @@ typedef enum clicktype {
CLICK_RIGHT = 2,
} clicktype;
typedef enum placeflag {
PLACE_SCATTER = 1,
PLACE_SPECIAL = 2,
PLACE_UNIQUE = 4,
} placeflag;
/*
First 5 bits store level
6th bit stores onlygood flag

Loading…
Cancel
Save