Browse Source

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

pull/977/head
Anders Jenbo 5 years ago
parent
commit
ccd0e7fd23
  1. 8
      Source/control.cpp
  2. 2
      Source/items.cpp
  3. 8
      Source/loadsave.cpp
  4. 10
      Source/missiles.cpp
  5. 410
      Source/monster.cpp
  6. 16
      Source/monster.h
  7. 6
      Source/pack.cpp
  8. 2
      Source/player.cpp
  9. 4
      structs.h

8
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;

2
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];

8
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);

10
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);
}

410
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) {

16
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);

6
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;

2
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);

4
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;

Loading…
Cancel
Save