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