diff --git a/Source/control.cpp b/Source/control.cpp index 1ded64ab1..cb8d0dca5 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -1886,6 +1886,14 @@ void DrawSpellBook() if (gbIsHellfire && sbooktab < 5) CelDraw(RIGHT_PANEL_X + 61 * sbooktab + 7, 348 + SCREEN_Y, pSBkBtnCel, sbooktab + 1, 61); else if (gbIsHellfire && sbooktab < 4) + // BUGFIX: rendering of page 3 and page 4 buttons are both off-by-one pixel. + // The fix would look as follows: + // + // int sx = RIGHT_PANEL_X + 76 * sbooktab + 7; + // if (sbooktab == 2 || sbooktab == 3) { + // sx++; + // } + // CelDraw(sx, 348 + SCREEN_Y, pSBkBtnCel, sbooktab + 1, 76); CelDraw(RIGHT_PANEL_X + 76 * sbooktab + 7, 348 + SCREEN_Y, pSBkBtnCel, sbooktab + 1, 76); spl = plr[myplr]._pMemSpells | plr[myplr]._pISpells | plr[myplr]._pAblSpells; diff --git a/Source/items.cpp b/Source/items.cpp index 660a6af2f..576347d05 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -2935,7 +2935,7 @@ void CreateTypeItem(int x, int y, BOOL onlygood, int itype, int imisc, BOOL send if (itype != ITYPE_GOLD) idx = RndTypeItems(itype, imisc, curlv); else - idx = 0; + idx = IDI_GOLD; if (numitems < MAXITEMS) { ii = itemavail[0]; diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index 045724d6e..8320fa9e1 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -383,13 +383,13 @@ static void LoadPlayer(int i) } CopyChar(tbuff, &pPlayer->pManaShield); if (gbIsHellfireSaveGame) { - CopyChar(tbuff, &pPlayer->pOriginalCathedral); + CopyChar(tbuff, &pPlayer->pOriginalCathedral); } else { - tbuff += 1; + tbuff += 1; pPlayer->pOriginalCathedral = true; } CopyBytes(tbuff, 2, &pPlayer->bReserved); - CopyShort(tbuff, &pPlayer->wReflection); + CopyShort(tbuff, &pPlayer->wReflections); CopyShorts(tbuff, 7, &pPlayer->wReserved); CopyInt(tbuff, &pPlayer->pDiabloKillLevel); @@ -1242,7 +1242,7 @@ static void SavePlayer(int i) CopyChar(&pPlayer->pManaShield, tbuff); CopyChar(&pPlayer->pOriginalCathedral, tbuff); CopyBytes(&pPlayer->bReserved, 2, tbuff); - CopyShort(&pPlayer->wReflection, tbuff); + CopyShort(&pPlayer->wReflections, tbuff); CopyShorts(&pPlayer->wReserved, 7, tbuff); CopyInt(&pPlayer->pDiabloKillLevel, tbuff); diff --git a/Source/missiles.cpp b/Source/missiles.cpp index abdac750d..4f28968f1 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -1259,8 +1259,8 @@ void InitMissileGFX() int mi; for (mi = 0; misfiledata[mi].mAnimFAmt; mi++) { - if (!gbIsHellfire && mi > MFILE_SCBSEXPD) - break; + if (!gbIsHellfire && mi > MFILE_SCBSEXPD) + break; if (!(misfiledata[mi].mFlags & MFLAG_HIDDEN)) LoadMissileGFX(mi); } @@ -1362,7 +1362,7 @@ void InitMissiles() } } #ifdef HELLFIRE - plr[myplr].wReflection = FALSE; + plr[myplr].wReflections = 0; #endif } @@ -1503,7 +1503,7 @@ void missiles_reflection(int mi, int sx, int sy, int dx, int dy, int midir, char lvl = missile[mi]._mispllvl; else lvl = 2; - plr[id].wReflection += lvl * plr[id]._pLevel; + plr[id].wReflections += lvl * plr[id]._pLevel; UseMana(id, SPL_REFLECT); } missile[mi]._mirange = 0; @@ -4285,7 +4285,7 @@ void mi_reflect(int i) } if (src != myplr && currlevel != plr[src].plrlevel) missile[i]._miDelFlag = TRUE; - if ((WORD)plr[src].wReflection <= 0) { + if (plr[src].wReflections <= 0) { missile[i]._miDelFlag = TRUE; NetSendCmd(TRUE, CMD_REFLECT); } diff --git a/Source/monster.cpp b/Source/monster.cpp index 0c7220941..6583f22a2 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -114,14 +114,14 @@ void (*AiProc[])(int i) = { &MAI_Lazhelp, &MAI_Lachdanan, &MAI_Warlord, - &mai_ranged_441680, - &mai_ranged_44168B, - &mai_horkdemon, - &mai_ranged_441649, - &mai_ranged_441654, - &mai_ranged_44165F, - &mai_ranged_44166A, - &mai_roundranged_441EA0 + &MAI_Firebat, + &MAI_Torchant, + &MAI_HorkDemon, + &MAI_Lich, + &MAI_ArchLich, + &MAI_Psychorb, + &MAI_Necromorb, + &MAI_BoneDemon }; void InitMonsterTRN(int monst, BOOL special) @@ -1316,7 +1316,7 @@ void M_Enemy(int i) int mi, pnum; int dist, best_dist; int _menemy; - BOOL sameroom, bestsameroom; + DIABOOL sameroom, bestsameroom; MonsterStruct *Monst; BYTE enemyx, enemyy; @@ -1324,14 +1324,28 @@ void M_Enemy(int i) best_dist = -1; bestsameroom = 0; Monst = &monster[i]; - if (!(Monst->_mFlags & MFLAG_GOLEM)) { + if ( +#ifdef HELLFIRE + Monst->_mFlags & MFLAG_BERSERK || +#endif + !(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)) + if (!plr[pnum].plractive || currlevel != plr[pnum].plrlevel || plr[pnum]._pLvlChanging +#ifdef HELLFIRE + || ((plr[pnum]._pHitPoints >> 6) == 0) +#else + || (plr[pnum]._pHitPoints == 0 && gbMaxPlayers != 1) +#endif + ) continue; +#ifdef HELLFIRE + sameroom = (dTransVal[Monst->_mx][Monst->_my] == dTransVal[plr[pnum]._px][plr[pnum]._py]); +#else if (dTransVal[Monst->_mx][Monst->_my] == dTransVal[plr[pnum]._px][plr[pnum]._py]) sameroom = TRUE; else sameroom = FALSE; +#endif if (abs(Monst->_mx - plr[pnum]._px) > abs(Monst->_my - plr[pnum]._py)) dist = Monst->_mx - plr[pnum]._px; else @@ -1353,13 +1367,25 @@ void M_Enemy(int i) mi = monstactive[j]; if (mi == i) continue; +#ifdef HELLFIRE + if (!((monster[mi]._mhitpoints >> 6) > 0)) + continue; +#endif if (monster[mi]._mx == 1 && monster[mi]._my == 0) continue; if (M_Talker(mi) && monster[mi].mtalkmsg) continue; - if (!(Monst->_mFlags & MFLAG_GOLEM) - && ((abs(monster[mi]._mx - Monst->_mx) >= 2 || abs(monster[mi]._my - Monst->_my) >= 2) && !M_Ranged(i) - || (!(Monst->_mFlags & MFLAG_GOLEM) && !(monster[mi]._mFlags & MFLAG_GOLEM)))) { + if ((!(Monst->_mFlags & MFLAG_GOLEM) +#ifdef HELLFIRE + && !(Monst->_mFlags & MFLAG_BERSERK) +#endif + && (abs(monster[mi]._mx - Monst->_mx) >= 2 || abs(monster[mi]._my - Monst->_my) >= 2) + && !M_Ranged(i)) + || (!(Monst->_mFlags & MFLAG_GOLEM) +#ifdef HELLFIRE + && !(Monst->_mFlags & MFLAG_BERSERK) +#endif + && !(monster[mi]._mFlags & MFLAG_GOLEM))) { continue; } sameroom = dTransVal[Monst->_mx][Monst->_my] == dTransVal[monster[mi]._mx][monster[mi]._my]; @@ -1676,16 +1702,24 @@ void M_StartHit(int i, int pnum, int dam) PlayEffect(i, 1); if (monster[i].MType->mtype >= MT_SNEAK && monster[i].MType->mtype <= MT_ILLWEAV || dam >> 6 >= monster[i].mLevel + 3) { if (pnum >= 0) { - monster[i]._mFlags &= ~MFLAG_TARGETS_MONSTER; monster[i]._menemy = pnum; monster[i]._menemyx = plr[pnum]._pfutx; monster[i]._menemyy = plr[pnum]._pfuty; + monster[i]._mFlags &= ~MFLAG_TARGETS_MONSTER; monster[i]._mdir = M_GetDir(i); } if (monster[i].MType->mtype == MT_BLINK) { M_Teleport(i); - } else if (monster[i].MType->mtype >= MT_NSCAV && monster[i].MType->mtype <= MT_YSCAV) { + } else if ((monster[i].MType->mtype >= MT_NSCAV && monster[i].MType->mtype <= MT_YSCAV) +#ifdef HELLFIRE + || monster[i].MType->mtype == MT_GRAVEDIG +#endif + ) { monster[i]._mgoal = MGOAL_NORMAL; +#ifdef HELLFIRE + monster[i]._mgoalvar1 = 0; + monster[i]._mgoalvar2 = 0; +#endif } if (monster[i]._mmode != MM_STONE) { NewMonsterAnim(i, &monster[i].MType->Anims[MA_GOTHIT], monster[i]._mdir); @@ -1791,11 +1825,19 @@ void SpawnLoot(int i, BOOL sendmsg) void M2MStartHit(int mid, int i, int dam) { if ((DWORD)mid >= MAXMONSTERS) { +#ifdef HELLFIRE + return; +#else app_fatal("Invalid monster %d getting hit by monster", mid); +#endif } if (monster[mid].MType == NULL) { +#ifdef HELLFIRE + return; +#else app_fatal("Monster %d \"%s\" getting hit by monster: MType NULL", mid, monster[mid].mName); +#endif } if (i >= 0) @@ -1811,8 +1853,16 @@ void M2MStartHit(int mid, int i, int dam) if (monster[mid].MType->mtype == MT_BLINK) { M_Teleport(mid); - } else if (monster[mid].MType->mtype >= MT_NSCAV && monster[mid].MType->mtype <= MT_YSCAV) { + } else if (monster[mid].MType->mtype >= MT_NSCAV && monster[mid].MType->mtype <= MT_YSCAV +#ifdef HELLFIRE + || monster[mid].MType->mtype == MT_GRAVEDIG +#endif + ) { monster[mid]._mgoal = MGOAL_NORMAL; +#ifdef HELLFIRE + monster[mid]._mgoalvar1 = 0; + monster[mid]._mgoalvar2 = 0; +#endif } if (monster[mid]._mmode != MM_STONE) { @@ -1897,13 +1947,26 @@ void M2MStartKill(int i, int mid) int md; if ((DWORD)i >= MAXMONSTERS) { +#ifdef HELLFIRE + return; +#else app_fatal("M2MStartKill: Invalid monster (attacker) %d", i); +#endif } +#ifdef HELLFIRE + if ((DWORD)mid >= MAXMONSTERS) { + return; +#else if ((DWORD)i >= MAXMONSTERS) { /// BUGFIX: should check `mid` app_fatal("M2MStartKill: Invalid monster (killed) %d", mid); +#endif } if (monster[i].MType == NULL) +#ifdef HELLFIRE + return; +#else app_fatal("M2MStartKill: Monster %d \"%s\" MType NULL", mid, monster[mid].mName); +#endif delta_kill_monster(mid, monster[mid]._mx, monster[mid]._my, currlevel); NetSendCmdLocParam1(FALSE, CMD_MONSTDEATH, monster[mid]._mx, monster[mid]._my, mid); @@ -1916,14 +1979,20 @@ void M2MStartKill(int i, int mid) monster[mid]._mhitpoints = 0; SetRndSeed(monster[mid]._mRndSeed); +#ifdef HELLFIRE + SpawnLoot(mid, TRUE); +#else if (mid >= MAX_PLRS) SpawnItem(mid, monster[mid]._mx, monster[mid]._my, TRUE); +#endif if (monster[mid].MType->mtype == MT_DIABLO) M_DiabloDeath(mid, TRUE); else +#ifndef HELLFIRE PlayEffect(i, 2); +#endif PlayEffect(mid, 2); md = (monster[i]._mdir - 4) & 7; @@ -1945,6 +2014,10 @@ void M2MStartKill(int i, int mid) M_FallenFear(monster[mid]._mx, monster[mid]._my); if (monster[mid].MType->mtype >= MT_NACID && monster[mid].MType->mtype <= MT_XACID) AddMissile(monster[mid]._mx, monster[mid]._my, 0, 0, 0, MIS_ACIDPUD, TARGET_PLAYERS, mid, monster[mid]._mint + 1, 0); + +#ifdef HELLFIRE + M_StartStand(i, monster[i]._mdir); +#endif } void M_StartKill(int i, int pnum) @@ -2321,10 +2394,18 @@ void M_TryM2MHit(int i, int mid, int hper, int mind, int maxd) BOOL ret; if ((DWORD)mid >= MAXMONSTERS) { +#ifdef HELLFIRE + return; +#else app_fatal("M_TryM2MHit: Invalid monster %d", mid); +#endif } if (monster[mid].MType == NULL) +#ifdef HELLFIRE + return; +#else app_fatal("M_TryM2MHit: Monster %d \"%s\" MType NULL", mid, monster[mid].mName); +#endif if (monster[mid]._mhitpoints >> 6 > 0 && (monster[mid].MType->mtype != MT_ILLWEAV || monster[mid]._mgoal != MGOAL_RETREAT)) { int hit = random_(4, 100); if (monster[mid]._mmode == MM_STONE) @@ -2358,12 +2439,20 @@ void M_TryH2HHit(int i, int pnum, int Hit, int MinDam, int MaxDam) int blk, blkper; int dam, mdam; int newx, newy; - int j, misnum, ms_num, cur_ms_num, new_hp; + int j, misnum, ms_num, cur_ms_num, new_hp, dir, ac; if ((DWORD)i >= MAXMONSTERS) +#ifdef HELLFIRE + return; +#else app_fatal("M_TryH2HHit: Invalid monster %d", i); +#endif if (monster[i].MType == NULL) +#ifdef HELLFIRE + return; +#else app_fatal("M_TryH2HHit: Monster %d \"%s\" MType NULL", i, monster[i].mName); +#endif if (monster[i]._mFlags & MFLAG_TARGETS_MONSTER) { M_TryM2MHit(i, pnum, Hit, MinDam, MaxDam); return; @@ -2379,12 +2468,18 @@ void M_TryH2HHit(int i, int pnum, int Hit, int MinDam, int MaxDam) #ifdef _DEBUG if (debug_mode_dollar_sign || debug_mode_key_inverted_v) hper = 1000; +#endif + ac = plr[pnum]._pIBonusAC + plr[pnum]._pIAC; +#ifdef HELLFIRE + if (plr[pnum].pDamAcFlags & 0x20 && monster[i].MData->mMonstClass == MC_DEMON) + ac += 40; + if (plr[pnum].pDamAcFlags & 0x40 && monster[i].MData->mMonstClass == MC_UNDEAD) + ac += 20; #endif hit = Hit + 2 * (monster[i].mLevel - plr[pnum]._pLevel) + 30 - - plr[pnum]._pIBonusAC - - plr[pnum]._pIAC + - ac - plr[pnum]._pDexterity / 5; if (hit < 15) hit = 15; @@ -2410,7 +2505,26 @@ void M_TryH2HHit(int i, int pnum, int Hit, int MinDam, int MaxDam) if (hper >= hit) return; if (blkper < blk) { - StartPlrBlock(pnum, GetDirection(plr[pnum]._px, plr[pnum]._py, monster[i]._mx, monster[i]._my)); + dir = GetDirection(plr[pnum]._px, plr[pnum]._py, monster[i]._mx, monster[i]._my); + StartPlrBlock(pnum, dir); +#ifdef HELLFIRE + if (pnum == myplr && plr[pnum].wReflections > 0) { + plr[pnum].wReflections--; + dam = random_(99, (MaxDam - MinDam + 1) << 6) + (MinDam << 6); + dam += plr[pnum]._pIGetHit << 6; + if (dam < 64) + dam = 64; + mdam = dam * (0.01 * (random_(100, 10) + 20)); + monster[i]._mhitpoints -= mdam; + dam -= mdam; + if (dam < 0) + dam = 0; + if (monster[i]._mhitpoints >> 6 <= 0) + M_StartKill(i, pnum); + else + M_StartHit(i, pnum, mdam); + } +#endif return; } if (monster[i].MType->mtype == MT_YZOMBIE && pnum == myplr) { @@ -2426,20 +2540,21 @@ void M_TryH2HHit(int i, int pnum, int Hit, int MinDam, int MaxDam) ms_num = misnum; } if (plr[pnum]._pMaxHP > 64) { - if (plr[pnum]._pMaxHPBase > 64) { - new_hp = plr[pnum]._pMaxHP - 64; - plr[pnum]._pMaxHP = new_hp; - if (plr[pnum]._pHitPoints > new_hp) { - plr[pnum]._pHitPoints = new_hp; +#ifndef HELLFIRE + if (plr[pnum]._pMaxHPBase > 64) +#endif + { + plr[pnum]._pMaxHP -= 64; + if (plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) { + plr[pnum]._pHitPoints = plr[pnum]._pMaxHP; if (cur_ms_num >= 0) - missile[cur_ms_num]._miVar1 = new_hp; + missile[cur_ms_num]._miVar1 = plr[pnum]._pHitPoints; } - new_hp = plr[pnum]._pMaxHPBase - 64; - plr[pnum]._pMaxHPBase = new_hp; - if (plr[pnum]._pHPBase > new_hp) { - plr[pnum]._pHPBase = new_hp; + plr[pnum]._pMaxHPBase -= 64; + if (plr[pnum]._pHPBase > plr[pnum]._pMaxHPBase) { + plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase; if (cur_ms_num >= 0) - missile[cur_ms_num]._miVar2 = new_hp; + missile[cur_ms_num]._miVar2 = plr[pnum]._pHPBase; } } } @@ -2449,6 +2564,20 @@ void M_TryH2HHit(int i, int pnum, int Hit, int MinDam, int MaxDam) if (dam < 64) dam = 64; if (pnum == myplr) { +#ifdef HELLFIRE + if (plr[pnum].wReflections > 0) { + plr[pnum].wReflections--; + mdam = dam * (0.01 * (random_(100, 10) + 20)); + monster[i]._mhitpoints -= mdam; + dam -= mdam; + if (dam < 0) + dam = 0; + if (monster[i]._mhitpoints >> 6 <= 0) + M_StartKill(i, pnum); + else + M_StartHit(i, pnum, mdam); + } +#endif plr[pnum]._pHitPoints -= dam; plr[pnum]._pHPBase -= dam; } @@ -2468,6 +2597,9 @@ void M_TryH2HHit(int i, int pnum, int Hit, int MinDam, int MaxDam) } if (plr[pnum]._pHitPoints >> 6 <= 0) { SyncPlrKill(pnum, 0); +#ifdef HELLFIRE + M_StartStand(i, monster[i]._mdir); +#endif return; } StartPlrHit(pnum, dam, FALSE); @@ -4099,22 +4231,22 @@ void MAI_Succ(int i) MAI_Ranged(i, MIS_FLARE, FALSE); } -void mai_ranged_441649(int i) +void MAI_Lich(int i) { MAI_Ranged(i, MIS_LICH, FALSE); } -void mai_ranged_441654(int i) +void MAI_ArchLich(int i) { MAI_Ranged(i, MIS_ARCHLICH, FALSE); } -void mai_ranged_44165F(int i) +void MAI_Psychorb(int i) { MAI_Ranged(i, MIS_PSYCHORB, FALSE); } -void mai_ranged_44166A(int i) +void MAI_Necromorb(int i) { MAI_Ranged(i, MIS_NECROMORB, FALSE); } @@ -4124,12 +4256,12 @@ void MAI_AcidUniq(int i) MAI_Ranged(i, MIS_ACID, TRUE); } -void mai_ranged_441680(int i) +void MAI_Firebat(int i) { MAI_Ranged(i, MIS_FIREBOLT, FALSE); } -void mai_ranged_44168B(int i) +void MAI_Torchant(int i) { MAI_Ranged(i, MIS_FIREBALL, FALSE); } @@ -4138,7 +4270,6 @@ void MAI_Scav(int i) { BOOL done; int x, y; - int _mx, _my; MonsterStruct *Monst; if ((DWORD)i >= MAXMONSTERS) @@ -4148,8 +4279,6 @@ void MAI_Scav(int i) app_fatal("MAI_Scav: Invalid monster %d", i); #endif Monst = &monster[i]; - _mx = Monst->_mx; - _my = Monst->_my; done = FALSE; if (monster[i]._mmode != MM_STAND) return; @@ -4165,9 +4294,25 @@ void MAI_Scav(int i) Monst->_mgoalvar3--; if (dDead[Monst->_mx][Monst->_my] != 0) { M_StartEat(i); - if (!(Monst->_mFlags & MFLAG_NOHEAL)) + if (!(Monst->_mFlags & MFLAG_NOHEAL)) { +#ifdef HELLFIRE + int mMaxHP = Monst->MType->mMaxHP << 6; + if (gbMaxPlayers == 1) + mMaxHP >>= 1; + Monst->_mhitpoints += mMaxHP >> 3; + if (Monst->_mhitpoints > mMaxHP) + Monst->_mhitpoints = mMaxHP; + if (Monst->_mmaxhp < Monst->_mhitpoints) + Monst->_mmaxhp = Monst->_mhitpoints; + if (Monst->_mgoalvar3 <= 0 || Monst->_mhitpoints == mMaxHP) + dDead[Monst->_mx][Monst->_my] = 0; + } + if (Monst->_mhitpoints == Monst->_mmaxhp) { +#else Monst->_mhitpoints += 64; + } if (Monst->_mhitpoints >= (Monst->_mmaxhp >> 1) + (Monst->_mmaxhp >> 2)) { +#endif Monst->_mgoal = MGOAL_NORMAL; Monst->_mgoalvar1 = 0; Monst->_mgoalvar2 = 0; @@ -4222,7 +4367,11 @@ void MAI_Scav(int i) } } } +#ifdef HELLFIRE + else +#else if (Monst->_mmode == MM_STAND) +#endif MAI_SkelSd(i); } @@ -4232,7 +4381,11 @@ void MAI_Garg(int i) int mx, my, dx, dy, md; if ((DWORD)i >= MAXMONSTERS) +#ifdef HELLFIRE + return; +#else app_fatal("MAI_Garg: Invalid monster %d", i); +#endif Monst = &monster[i]; dx = Monst->_mx - Monst->_lastx; @@ -4252,8 +4405,11 @@ void MAI_Garg(int i) return; } - if (Monst->_mhitpoints < (Monst->_mmaxhp >> 1) && !(Monst->_mFlags & MFLAG_NOHEAL)) - Monst->_mgoal = MGOAL_RETREAT; + if (Monst->_mhitpoints < (Monst->_mmaxhp >> 1)) +#ifndef HELLFIRE + if (!(Monst->_mFlags & MFLAG_NOHEAL)) +#endif + Monst->_mgoal = MGOAL_RETREAT; if (Monst->_mgoal == MGOAL_RETREAT) { if (abs(dx) >= Monst->_mint + 2 || abs(dy) >= Monst->_mint + 2) { Monst->_mgoal = MGOAL_NORMAL; @@ -4344,7 +4500,7 @@ void MAI_Storm(int i) MAI_RoundRanged(i, MIS_LIGHTCTRL2, TRUE, 4, 0); } -void mai_roundranged_441EA0(int i) +void MAI_BoneDemon(int i) { MAI_RoundRanged(i, MIS_BONEDEMON, TRUE, 4, 0); } @@ -4366,7 +4522,11 @@ void MAI_RR2(int i, int mistype, int dam) int dist, v, md; if ((DWORD)i >= MAXMONSTERS) +#ifdef HELLFIRE + return; +#else app_fatal("MAI_RR2: Invalid monster %d", i); +#endif Monst = &monster[i]; mx = Monst->_mx - Monst->_menemyx; @@ -4447,7 +4607,11 @@ void MAI_Golum(int i) BOOL have_enemy, ok; if ((DWORD)i >= MAXMONSTERS) +#ifdef HELLFIRE + return; +#else app_fatal("MAI_Golum: Invalid monster %d", i); +#endif Monst = &monster[i]; if (Monst->_mx == 1 && Monst->_my == 0) { @@ -4477,10 +4641,7 @@ void MAI_Golum(int i) _mey = my - monster[_menemy]._mfuty; md = GetDirection(mx, my, monster[_menemy]._mx, monster[_menemy]._my); monster[i]._mdir = md; - if (abs(_mex) >= 2 || abs(_mey) >= 2) { - if (have_enemy && MAI_Path(i)) - return; - } else if (have_enemy) { + if (abs(_mex) < 2 && abs(_mey) < 2 && have_enemy) { _menemy = monster[i]._menemy; monster[i]._menemyx = monster[_menemy]._mx; monster[i]._menemyy = monster[_menemy]._my; @@ -4500,22 +4661,24 @@ void MAI_Golum(int i) return; } + if (have_enemy && MAI_Path(i)) + return; + monster[i]._pathcount++; if (monster[i]._pathcount > 8) monster[i]._pathcount = 5; ok = M_CallWalk(i, plr[i]._pdir); - if (!ok) { - md = (md - 1) & 7; - for (j = 0; j < 8 && !ok; j++) { - md = (md + 1) & 7; - ok = DirOK(i, md); - } - if (!ok) { - return; - } - M_WalkDir(i, md); + if (ok) + return; + + md = (md - 1) & 7; + for (j = 0; j < 8 && !ok; j++) { + md = (md + 1) & 7; + ok = DirOK(i, md); } + if (ok) + M_WalkDir(i, md); } void MAI_SkelKing(int i) @@ -4525,7 +4688,11 @@ void MAI_SkelKing(int i) int dist, v, md; if ((DWORD)i >= MAXMONSTERS) +#ifdef HELLFIRE + return; +#else app_fatal("MAI_SkelKing: Invalid monster %d", i); +#endif Monst = &monster[i]; if (Monst->_mmode == MM_STAND && Monst->_msquelch != 0) { fx = Monst->_menemyx; @@ -4593,7 +4760,11 @@ void MAI_Rhino(int i) int v, dist, md; if ((DWORD)i >= MAXMONSTERS) +#ifdef HELLFIRE + return; +#else app_fatal("MAI_Rhino: Invalid monster %d", i); +#endif Monst = &monster[i]; if (Monst->_mmode == MM_STAND && Monst->_msquelch != 0) { fx = Monst->_menemyx; @@ -4631,8 +4802,8 @@ void MAI_Rhino(int i) if (AddMissile(Monst->_mx, Monst->_my, fx, fy, md, MIS_RHINO, Monst->_menemy, i, 0, 0) != -1) { if (Monst->MData->snd_special) PlayEffect(i, 3); - Monst->_mmode = MM_CHARGE; dMonster[Monst->_mx][Monst->_my] = -1 - i; + Monst->_mmode = MM_CHARGE; } } else { if (abs(mx) >= 2 || abs(my) >= 2) { @@ -4656,7 +4827,7 @@ void MAI_Rhino(int i) } } -void mai_horkdemon(int i) +void MAI_HorkDemon(int i) { MonsterStruct *Monst; int fx, fy, mx, my, md, v, dist; @@ -4734,7 +4905,11 @@ void MAI_Counselor(int i) MonsterStruct *Monst; if ((DWORD)i >= MAXMONSTERS) +#ifdef HELLFIRE + return; +#else app_fatal("MAI_Counselor: Invalid monster %d", i); +#endif if (monster[i]._mmode == MM_STAND && monster[i]._msquelch != 0) { Monst = &monster[i]; fx = Monst->_menemyx; @@ -4849,11 +5024,15 @@ void MAI_Garbud(int i) void MAI_Zhar(int i) { - int mx, my, _mx, _my, md; + int mx, my, md; MonsterStruct *Monst; if ((DWORD)i >= MAXMONSTERS) +#ifdef HELLFIRE + return; +#else app_fatal("MAI_Zhar: Invalid monster %d", i); +#endif Monst = &monster[i]; if (monster[i]._mmode != MM_STAND) { @@ -4869,12 +5048,6 @@ void MAI_Zhar(int i) } if (dFlags[mx][my] & BFLAG_VISIBLE) { - _mx = Monst->_mx - Monst->_menemyx; - _my = Monst->_my - Monst->_menemyy; - if (abs(_mx) > abs(_my)) - abs(_mx); - else - abs(_my); if (Monst->mtalkmsg == TEXT_ZHAR2) { if (!effect_is_playing(USFX_ZHAR2) && Monst->_mgoal == MGOAL_TALKING) { Monst->_msquelch = UCHAR_MAX; @@ -4899,7 +5072,11 @@ void MAI_SnotSpil(int i) MonsterStruct *Monst; if ((DWORD)i >= MAXMONSTERS) +#ifdef HELLFIRE + return; +#else app_fatal("MAI_SnotSpil: Invalid monster %d", i); +#endif Monst = &monster[i]; if (monster[i]._mmode != MM_STAND) { @@ -4949,7 +5126,11 @@ void MAI_Lazurus(int i) MonsterStruct *Monst; if ((DWORD)i >= MAXMONSTERS) +#ifdef HELLFIRE + return; +#else app_fatal("MAI_Lazurus: Invalid monster %d", i); +#endif Monst = &monster[i]; if (monster[i]._mmode != MM_STAND) { @@ -4961,7 +5142,7 @@ void MAI_Lazurus(int i) md = M_GetDir(i); if (dFlags[mx][my] & BFLAG_VISIBLE) { if (gbMaxPlayers == 1) { - if (Monst->mtalkmsg == TEXT_VILE13 && Monst->_mgoal == MGOAL_INQUIRING && plr[myplr]._px == TEXT_VILE13 && plr[myplr]._py == 46) { + if (Monst->mtalkmsg == TEXT_VILE13 && Monst->_mgoal == MGOAL_INQUIRING && plr[myplr]._px == 35 && plr[myplr]._py == 46) { PlayInGameMovie("gendata\\fprst3.smk"); Monst->_mmode = MM_TALK; quests[Q_BETRAYER]._qvar1 = 5; @@ -4970,10 +5151,10 @@ void MAI_Lazurus(int i) if (Monst->mtalkmsg == TEXT_VILE13 && !effect_is_playing(USFX_LAZ1) && Monst->_mgoal == MGOAL_TALKING) { ObjChangeMapResync(1, 18, 20, 24); RedoPlayerVision(); - Monst->_msquelch = UCHAR_MAX; - Monst->mtalkmsg = 0; quests[Q_BETRAYER]._qvar1 = 6; Monst->_mgoal = MGOAL_NORMAL; + Monst->_msquelch = UCHAR_MAX; + Monst->mtalkmsg = 0; } } @@ -4983,7 +5164,9 @@ void MAI_Lazurus(int i) } if (Monst->_mgoal == MGOAL_NORMAL || Monst->_mgoal == MGOAL_RETREAT || Monst->_mgoal == MGOAL_MOVE) { +#ifndef HELLFIRE Monst->mtalkmsg = 0; +#endif MAI_Counselor(i); } @@ -5000,7 +5183,11 @@ void MAI_Lazhelp(int i) MonsterStruct *Monst; if ((DWORD)i >= MAXMONSTERS) +#ifdef HELLFIRE + return; +#else app_fatal("MAI_Lazhelp: Invalid monster %d", i); +#endif if (monster[i]._mmode != MM_STAND) return; @@ -5014,8 +5201,8 @@ void MAI_Lazhelp(int i) if (quests[Q_BETRAYER]._qvar1 <= 5) { Monst->_mgoal = MGOAL_INQUIRING; } else { - Monst->mtalkmsg = 0; Monst->_mgoal = MGOAL_NORMAL; + Monst->mtalkmsg = 0; } } else Monst->_mgoal = MGOAL_NORMAL; @@ -5324,7 +5511,11 @@ BOOL DirOK(int i, int mdir) int mcount, mi; if ((DWORD)i >= MAXMONSTERS) +#ifdef HELLFIRE + return FALSE; +#else app_fatal("DirOK: Invalid monster %d", i); +#endif fx = monster[i]._mx + offset_x[mdir]; fy = monster[i]._my + offset_y[mdir]; if (fy < 0 || fy >= MAXDUNY || fx < 0 || fx >= MAXDUNX || !PosOkMonst(i, fx, fy)) @@ -5332,16 +5523,13 @@ BOOL DirOK(int i, int mdir) if (mdir == DIR_E) { if (SolidLoc(fx, fy + 1) || dFlags[fx][fy + 1] & BFLAG_MONSTLR) return FALSE; - } - if (mdir == DIR_W) { + } else if (mdir == DIR_W) { if (SolidLoc(fx + 1, fy) || dFlags[fx + 1][fy] & BFLAG_MONSTLR) return FALSE; - } - if (mdir == DIR_N) { + } else if (mdir == DIR_N) { if (SolidLoc(fx + 1, fy) || SolidLoc(fx, fy + 1)) return FALSE; - } - if (mdir == DIR_S) + } else if (mdir == DIR_S) if (SolidLoc(fx - 1, fy) || SolidLoc(fx, fy - 1)) return FALSE; if (monster[i].leaderflag == 1) { @@ -5392,6 +5580,7 @@ BOOL LineClearF(BOOL (*Clear)(int, int), int x1, int y1, int x2, int y2) int d; int xincD, yincD, dincD, dincH; int tmp; + BOOL done = FALSE; xorg = x1; yorg = y1; @@ -5410,16 +5599,16 @@ BOOL LineClearF(BOOL (*Clear)(int, int), int x1, int y1, int x2, int y2) } if (dy > 0) { d = 2 * dy - dx; - dincH = 2 * (dy - dx); dincD = 2 * dy; + dincH = 2 * (dy - dx); yincD = 1; } else { d = 2 * dy + dx; - dincH = 2 * (dx + dy); dincD = 2 * dy; + dincH = 2 * (dx + dy); yincD = -1; } - while (x1 != x2 || y1 != y2) { + while (!done && (x1 != x2 || y1 != y2)) { if ((d <= 0) ^ (yincD < 0)) { d += dincD; } else { @@ -5427,8 +5616,7 @@ BOOL LineClearF(BOOL (*Clear)(int, int), int x1, int y1, int x2, int y2) y1 += yincD; } x1++; - if ((x1 != xorg || y1 != yorg) && !Clear(x1, y1)) - break; + done = ((x1 != xorg || y1 != yorg) && !Clear(x1, y1)); } } else { if (dy < 0) { @@ -5443,16 +5631,16 @@ BOOL LineClearF(BOOL (*Clear)(int, int), int x1, int y1, int x2, int y2) } if (dx > 0) { d = 2 * dx - dy; - dincH = 2 * (dx - dy); dincD = 2 * dx; + dincH = 2 * (dx - dy); xincD = 1; } else { d = 2 * dx + dy; - dincH = 2 * (dy + dx); dincD = 2 * dx; + dincH = 2 * (dy + dx); xincD = -1; } - while (y1 != y2 || x1 != x2) { + while (!done && (y1 != y2 || x1 != x2)) { if ((d <= 0) ^ (xincD < 0)) { d += dincD; } else { @@ -5460,8 +5648,7 @@ BOOL LineClearF(BOOL (*Clear)(int, int), int x1, int y1, int x2, int y2) x1 += xincD; } y1++; - if ((y1 != yorg || x1 != xorg) && !Clear(x1, y1)) - break; + done = ((y1 != yorg || x1 != xorg) && !Clear(x1, y1)); } } return x1 == x2 && y1 == y2; @@ -5474,11 +5661,12 @@ BOOL LineClear(int x1, int y1, int x2, int y2) BOOL LineClearF1(BOOL (*Clear)(int, int, int), int monst, int x1, int y1, int x2, int y2) { - int xorg, yorg; int dx, dy; int d; + int xorg, yorg; int xincD, yincD, dincD, dincH; int tmp; + BOOL done = FALSE; xorg = x1; yorg = y1; @@ -5497,16 +5685,16 @@ BOOL LineClearF1(BOOL (*Clear)(int, int, int), int monst, int x1, int y1, int x2 } if (dy > 0) { d = 2 * dy - dx; - dincH = 2 * (dy - dx); dincD = 2 * dy; + dincH = 2 * (dy - dx); yincD = 1; } else { d = 2 * dy + dx; - dincH = 2 * (dx + dy); dincD = 2 * dy; + dincH = 2 * (dx + dy); yincD = -1; } - while (x1 != x2 || y1 != y2) { + while (!done && (x1 != x2 || y1 != y2)) { if ((d <= 0) ^ (yincD < 0)) { d += dincD; } else { @@ -5514,8 +5702,7 @@ BOOL LineClearF1(BOOL (*Clear)(int, int, int), int monst, int x1, int y1, int x2 y1 += yincD; } x1++; - if ((x1 != xorg || y1 != yorg) && !Clear(monst, x1, y1)) - break; + done = ((x1 != xorg || y1 != yorg) && !Clear(monst, x1, y1)); } } else { if (dy < 0) { @@ -5530,16 +5717,16 @@ BOOL LineClearF1(BOOL (*Clear)(int, int, int), int monst, int x1, int y1, int x2 } if (dx > 0) { d = 2 * dx - dy; - dincH = 2 * (dx - dy); dincD = 2 * dx; + dincH = 2 * (dx - dy); xincD = 1; } else { d = 2 * dx + dy; - dincH = 2 * (dy + dx); dincD = 2 * dx; + dincH = 2 * (dy + dx); xincD = -1; } - while (y1 != y2 || x1 != x2) { + while (!done && (y1 != y2 || x1 != x2)) { if ((d <= 0) ^ (xincD < 0)) { d += dincD; } else { @@ -5547,8 +5734,7 @@ BOOL LineClearF1(BOOL (*Clear)(int, int, int), int monst, int x1, int y1, int x2 x1 += xincD; } y1++; - if ((y1 != yorg || x1 != xorg) && !Clear(monst, x1, y1)) - break; + done = ((y1 != yorg || x1 != xorg) && !Clear(monst, x1, y1)); } } return x1 == x2 && y1 == y2; @@ -5679,6 +5865,15 @@ void PrintMonstHistory(int mt) minHP = 1; if (maxHP < 1) maxHP = 1; +#ifdef HELLFIRE + if (gnDifficulty == DIFF_NIGHTMARE) { + minHP = 3 * minHP + (gbMaxPlayers == 1 ? 50 : 100); + maxHP = 3 * maxHP + (gbMaxPlayers == 1 ? 50 : 100); + } else if (gnDifficulty == DIFF_HELL) { + minHP = 4 * minHP + (gbMaxPlayers == 1 ? 100 : 200); + maxHP = 4 * maxHP + (gbMaxPlayers == 1 ? 100 : 200); + } +#else if (gnDifficulty == DIFF_NIGHTMARE) { minHP = 3 * minHP + 1; maxHP = 3 * maxHP + 1; @@ -5687,6 +5882,7 @@ void PrintMonstHistory(int mt) minHP = 4 * minHP + 3; maxHP = 4 * maxHP + 3; } +#endif sprintf(tempstr, "Hit Points: %i-%i", minHP, maxHP); AddPanelString(tempstr, TRUE); } @@ -5761,13 +5957,21 @@ void MissToMonst(int i, int x, int y) MonsterStruct *Monst; if ((DWORD)i >= MAXMISSILES) +#ifdef HELLFIRE + return; +#else app_fatal("MissToMonst: Invalid missile %d", i); +#endif Miss = &missile[i]; m = Miss->_misource; if ((DWORD)m >= MAXMONSTERS) +#ifdef HELLFIRE + return; +#else app_fatal("MissToMonst: Invalid monster %d", m); +#endif Monst = &monster[m]; oldx = Miss->_mix; @@ -6203,7 +6407,11 @@ void TalktoMonster(int i) void SpawnGolum(int i, int x, int y, int mi) { if ((DWORD)i >= MAXMONSTERS) +#ifdef HELLFIRE + return; +#else app_fatal("SpawnGolum: Invalid monster %d", i); +#endif dMonster[x][y] = i + 1; monster[i]._mx = x; @@ -6213,13 +6421,13 @@ void SpawnGolum(int i, int x, int y, int mi) monster[i]._moldx = x; monster[i]._moldy = y; monster[i]._pathcount = 0; - monster[i]._mFlags |= MFLAG_GOLEM; - monster[i].mArmorClass = 25; monster[i]._mmaxhp = 2 * (320 * missile[mi]._mispllvl + plr[i]._pMaxMana / 3); monster[i]._mhitpoints = monster[i]._mmaxhp; + monster[i].mArmorClass = 25; monster[i].mHit = 5 * (missile[mi]._mispllvl + 8) + 2 * plr[i]._pLevel; monster[i].mMinDamage = 2 * (missile[mi]._mispllvl + 4); monster[i].mMaxDamage = 2 * (missile[mi]._mispllvl + 8); + monster[i]._mFlags |= MFLAG_GOLEM; M_StartSpStand(i, 0); M_Enemy(i); if (i == myplr) { diff --git a/Source/monster.h b/Source/monster.h index d09801abb..cb32a35f9 100644 --- a/Source/monster.h +++ b/Source/monster.h @@ -65,26 +65,26 @@ void MAI_GoatMc(int i); void MAI_Ranged(int i, int missile_type, BOOL special); void MAI_GoatBow(int i); void MAI_Succ(int i); -void mai_ranged_441649(int i); -void mai_ranged_441654(int i); -void mai_ranged_44165F(int i); -void mai_ranged_44166A(int i); +void MAI_Lich(int i); +void MAI_ArchLich(int i); +void MAI_Psychorb(int i); +void MAI_Necromorb(int i); void MAI_AcidUniq(int i); -void mai_ranged_441680(int i); -void mai_ranged_44168B(int i); +void MAI_Firebat(int i); +void MAI_Torchant(int i); void MAI_Scav(int i); void MAI_Garg(int i); void MAI_RoundRanged(int i, int missile_type, BOOL checkdoors, int dam, int lessmissiles); void MAI_Magma(int i); void MAI_Storm(int i); -void mai_roundranged_441EA0(int i); +void MAI_BoneDemon(int i); void MAI_Acid(int i); void MAI_Diablo(int i); void MAI_Mega(int i); void MAI_Golum(int i); void MAI_SkelKing(int i); void MAI_Rhino(int i); -void mai_horkdemon(int i); +void MAI_HorkDemon(int i); void MAI_Counselor(int i); void MAI_Garbud(int i); void MAI_Zhar(int i); diff --git a/Source/pack.cpp b/Source/pack.cpp index 9b51a096f..78fd94ba9 100644 --- a/Source/pack.cpp +++ b/Source/pack.cpp @@ -74,7 +74,7 @@ void PackPlayer(PkPlayerStruct *pPack, int pnum, BOOL manashield) pPack->pMaxManaBase = SwapLE32(pPlayer->_pMaxManaBase); pPack->pMemSpells = SDL_SwapLE64(pPlayer->_pMemSpells); - for (i = 0; i < 37; i++) // Should be MAX_SPELLS but set to 36 to make save games compatible + for (i = 0; i < 37; i++) // Should be MAX_SPELLS but set to 37 to make save games compatible pPack->pSplLvl[i] = pPlayer->_pSplLvl[i]; for (i = 37; i < 47; i++) pPack->pSplLvl2[i - 37] = pPlayer->_pSplLvl[i]; @@ -110,7 +110,7 @@ void PackPlayer(PkPlayerStruct *pPack, int pnum, BOOL manashield) pi++; } - pPack->wReflection = SwapLE16(pPlayer->wReflection); + pPack->wReflections = SwapLE16(pPlayer->wReflections); pPack->pDifficulty = SwapLE32(pPlayer->pDifficulty); pPack->pDamAcFlags = SwapLE32(pPlayer->pDamAcFlags); pPack->pDiabloKillLevel = SwapLE32(pPlayer->pDiabloKillLevel); @@ -270,7 +270,7 @@ void UnPackPlayer(PkPlayerStruct *pPack, int pnum, BOOL killok) } CalcPlrInv(pnum, FALSE); - pPlayer->wReflection = SwapLE16(pPack->wReflection); + pPlayer->wReflections = SwapLE16(pPack->wReflections); pPlayer->pTownWarps = 0; pPlayer->pDungMsgs = 0; pPlayer->pDungMsgs2 = 0; diff --git a/Source/player.cpp b/Source/player.cpp index 527a94bdd..efbd00f0a 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -850,7 +850,7 @@ void CreatePlayer(int pnum, char c) plr[pnum].pBattleNet = FALSE; plr[pnum].pManaShield = FALSE; plr[pnum].pDamAcFlags = 0; - plr[pnum].wReflection = 0; + plr[pnum].wReflections = 0; InitDungMsgs(pnum); CreatePlrItems(pnum); diff --git a/structs.h b/structs.h index 4f0cf8514..48fa8a139 100644 --- a/structs.h +++ b/structs.h @@ -346,7 +346,7 @@ typedef struct PlayerStruct { unsigned char pDungMsgs2; BOOLEAN pOriginalCathedral; char bReserved[2]; - short wReflection; + WORD wReflections; short wReserved[7]; DWORD pDiabloKillLevel; int pDifficulty; @@ -1456,7 +1456,7 @@ typedef struct PkPlayerStruct { BOOLEAN pManaShield; unsigned char pDungMsgs2; char bReserved[2]; - short wReflection; + WORD wReflections; short wReserved2; char pSplLvl2[10]; // Hellfire spells short wReserved8;