Devilution
Diablo devolved - magic behind the 1996 computer game
|
Go to the documentation of this file.
7 #include "../3rdParty/Storm/Source/storm.h"
26 const char plr2monst[9] = { 0, 5, 3, 7, 1, 4, 6, 0, 2 };
58 int left[8] = { 7, 0, 1, 2, 3, 4, 5, 6 };
59 int right[8] = { 1, 2, 3, 4, 5, 6, 7, 0 };
61 int offset_x[8] = { 1, 0, -1, -1, -1, 0, 1, 1 };
62 int offset_y[8] = { 1, 1, 1, 0, -1, -1, -1, 0 };
65 int rnd5[4] = { 5, 10, 15, 20 };
66 int rnd10[4] = { 10, 15, 20, 30 };
67 int rnd20[4] = { 20, 30, 40, 50 };
68 int rnd60[4] = { 60, 70, 80, 90 };
111 for (i = 0; i < 256; i++) {
119 for (i = 0; i < n; i++) {
121 for (j = 0; j < 8; j++) {
159 for (i = 0; i <
nummtypes && !done; i++) {
189 const int numskeltypes = 19;
259 for (i = 0; i < nt;) {
261 typelist[i] = typelist[--nt];
271 typelist[i] = typelist[--nt];
291 for (anim = 0; anim < 6; anim++) {
300 for (i = 0; i < 8; i++) {
304 for (i = 0; i < 8; i++) {
494 Monst->
mName =
"Invalid Monster";
575 for (uniqtype = 0; uniqtype <
nummtypes; uniqtype++) {
585 for (x = xp - 3; x < xp + 3; x++) {
586 for (y = yp - 3; y < yp + 3; y++) {
616 if (i ==
zharlib && zharflag == TRUE) {
656 for (yp = 0; yp <
MAXDUNY && !done; yp++) {
657 for (xp = 0; xp <
MAXDUNX && !done; xp++) {
658 done =
dPiece[xp][yp] == 367;
716 Monst->
mExp = 2 * (Monst->
mExp + 1000);
727 Monst->
mExp = 4 * (Monst->
mExp + 1000);
734 sprintf(filestr,
"Monsters\\Monsters\\%s.TRN", Uniq->
mTrnName);
774 for (skeltype = 0; skeltype <
nummtypes; skeltype++) {
834 int placed, try1, try2, j;
839 for (try1 = 0; try1 < 10; try1++) {
852 x1 = xp =
random_(93, 80) + 16;
853 y1 = yp =
random_(93, 80) + 16;
865 || (leaderf & 2) && ((abs(xp - x1) >= 4) || (abs(yp - y1) >= 4))) {
909 lpSetPiece =
LoadFileInMem(
"Levels\\L4Data\\diab1.DUN", NULL);
912 lpSetPiece =
LoadFileInMem(
"Levels\\L4Data\\diab2a.DUN", NULL);
915 lpSetPiece =
LoadFileInMem(
"Levels\\L4Data\\diab3a.DUN", NULL);
918 lpSetPiece =
LoadFileInMem(
"Levels\\L4Data\\diab4a.DUN", NULL);
928 int numplacemonsters;
949 for (i = 0; i < nt; i++) {
950 for (s = -2; s < 2; s++) {
951 for (t = -2; t < 2; t++)
963 for (s = 16; s < 96; s++)
964 for (t = 16; t < 96; t++)
967 numplacemonsters = na / 30;
969 numplacemonsters += numplacemonsters >> 1;
975 scattertypes[numscattypes] = i;
980 mtype = scattertypes[
random_(95, numscattypes)];
990 for (i = 0; i < nt; i++) {
991 for (s = -2; s < 2; s++) {
992 for (t = -2; t < 2; t++)
1050 rw = SDL_SwapLE16(*lm);
1052 rh = SDL_SwapLE16(*lm);
1053 lm += (rw * rh + 1);
1058 for (j = 0; j < rh; j++) {
1059 for (i = 0; i < rw; i++) {
1127 int dist, best_dist;
1129 BOOL sameroom, bestsameroom;
1131 BYTE enemyx, enemyy;
1138 for (pnum = 0; pnum <
MAX_PLRS; pnum++) {
1150 if ((sameroom && !bestsameroom)
1151 || ((sameroom || !bestsameroom) && dist < best_dist)
1152 || (_menemy == -1)) {
1158 bestsameroom = sameroom;
1181 if ((sameroom && !bestsameroom)
1182 || ((sameroom || !bestsameroom) && dist < best_dist)
1183 || (_menemy == -1)) {
1189 bestsameroom = sameroom;
1192 if (_menemy != -1) {
1252 void M_StartWalk(
int i,
int xvel,
int yvel,
int xadd,
int yadd,
int EndDir)
1275 void M_StartWalk2(
int i,
int xvel,
int yvel,
int xoff,
int yoff,
int xadd,
int yadd,
int EndDir)
1290 if (
monster[i]._uniqtype != 0)
1305 void M_StartWalk3(
int i,
int xvel,
int yvel,
int xoff,
int yoff,
int xadd,
int yadd,
int mapx,
int mapy,
int EndDir)
1312 if (
monster[i]._uniqtype != 0)
1414 int x, y, mx, my, m1, m2;
1421 for (y = my - 1; y <= my + 1; y++) {
1423 for (x = mx - 1; x <= mx + 1; x++) {
1463 if (pnum ==
myplr) {
1514 if (k == i ||
monster[i]._msquelch == 0)
1544 Monst->
_mVar5 = (int)((j - (Monst->
_mx << 16)) / (double)dist);
1545 Monst->
_mVar6 = (int)((k - (Monst->
_my << 16)) / (
double)dist);
1551 app_fatal(
"Invalid monster %d getting hit by monster", mid);
1554 if (
monster[mid].MType == NULL) {
1555 app_fatal(
"Monster %d \"%s\" getting hit by monster: MType NULL", mid,
monster[mid].mName);
1598 app_fatal(
"MonstStartKill: Invalid monster %d", i);
1601 app_fatal(
"MonstStartKill: Monster %d \"%s\" MType NULL", i,
monster[i].mName);
1606 if (pnum < MAX_PLRS && i >
MAX_PLRS)
1648 app_fatal(
"M2MStartKill: Invalid monster (attacker) %d", i);
1651 app_fatal(
"M2MStartKill: Invalid monster (killed) %d", mid);
1654 app_fatal(
"M2MStartKill: Monster %d \"%s\" MType NULL", mid,
monster[mid].mName);
1701 app_fatal(
"M_StartKill: Invalid monster %d", i);
1704 if (
myplr == pnum) {
1719 app_fatal(
"M_SyncStartKill: Invalid monster %d", i);
1744 app_fatal(
"M_StartFadein: Invalid monster %d", i);
1746 app_fatal(
"M_StartFadein: Monster %d \"%s\" MType NULL", i,
monster[i].mName);
1767 app_fatal(
"M_StartFadeout: Invalid monster %d", i);
1769 app_fatal(
"M_StartFadeout: Monster %d \"%s\" MType NULL", i,
monster[i].mName);
1791 app_fatal(
"M_StartHeal: Invalid monster %d", i);
1793 app_fatal(
"M_StartHeal: Monster %d \"%s\" MType NULL", i,
monster[i].mName);
1805 int lx, ly, _mxoff, _myoff, sign;
1808 app_fatal(
"M_ChangeLightOffset: Invalid monster %d", monst);
1820 _mxoff = sign * (lx >> 3);
1828 _myoff *= (ly >> 3);
1837 app_fatal(
"M_DoStand: Invalid monster %d", i);
1860 app_fatal(
"M_DoWalk: Invalid monster %d", i);
1870 if (
monster[i]._uniqtype != 0)
1874 }
else if (!
monster[i]._mAnimCnt) {
1882 if (
monster[i]._uniqtype != 0)
1893 app_fatal(
"M_DoWalk2: Invalid monster %d", i);
1899 if (
monster[i]._uniqtype != 0)
1913 if (
monster[i]._uniqtype != 0)
1924 app_fatal(
"M_DoWalk3: Invalid monster %d", i);
1948 if (
monster[i]._uniqtype != 0)
1959 app_fatal(
"M_TryM2MHit: Invalid monster %d", mid);
1961 if (
monster[mid].MType == NULL)
1962 app_fatal(
"M_TryM2MHit: Monster %d \"%s\" MType NULL", mid,
monster[mid].mName);
1968 int dam = (mind +
random_(5, maxd - mind + 1)) << 6;
1970 if (
monster[mid]._mhitpoints >> 6 <= 0) {
1996 int j, misnum, ms_num, cur_ms_num, new_hp;
1999 app_fatal(
"M_TryH2HHit: Invalid monster %d", i);
2001 app_fatal(
"M_TryH2HHit: Monster %d \"%s\" MType NULL", i,
monster[i].mName);
2006 if (
plr[pnum]._pHitPoints >> 6 <= 0 ||
plr[pnum]._pInvincible ||
plr[pnum]._pSpellFlags & 1)
2010 if (dx >= 2 || dy >= 2)
2015 if (debug_mode_dollar_sign || debug_mode_key_inverted_v)
2021 -
plr[pnum]._pIBonusAC
2023 -
plr[pnum]._pDexterity / 5;
2040 + (
plr[pnum]._pLevel << 1);
2058 if (
missile[misnum]._misource == pnum)
2059 cur_ms_num = misnum;
2063 if (
plr[pnum]._pMaxHP > 64) {
2064 if (
plr[pnum]._pMaxHPBase > 64) {
2067 if (
plr[pnum]._pHitPoints > new_hp) {
2069 if (cur_ms_num >= 0)
2074 if (
plr[pnum]._pHPBase > new_hp) {
2076 if (cur_ms_num >= 0)
2082 dam = (MinDam << 6) +
random_(99, (MaxDam - MinDam + 1) << 6);
2086 if (pnum ==
myplr) {
2091 mdam = (
random_(99, 3) + 1) << 6;
2093 if (
monster[i]._mhitpoints >> 6 <= 0)
2100 if (
plr[pnum]._pHitPoints >
plr[pnum]._pMaxHP) {
2104 if (
plr[pnum]._pHitPoints >> 6 <= 0) {
2119 dPlayer[newx][newy] = pnum + 1;
2130 app_fatal(
"M_DoAttack: Invalid monster %d", i);
2133 if (Monst->
MType == NULL)
2134 app_fatal(
"M_DoAttack: Monster %d \"%s\" MType NULL", i, Monst->
mName);
2135 if (Monst->
MType == NULL)
2136 app_fatal(
"M_DoAttack: Monster %d \"%s\" MData NULL", i, Monst->
mName);
2163 int multimissiles, mi;
2166 app_fatal(
"M_DoRAttack: Invalid monster %d", i);
2168 app_fatal(
"M_DoRAttack: Monster %d \"%s\" MType NULL", i,
monster[i].mName);
2170 app_fatal(
"M_DoRAttack: Monster %d \"%s\" MData NULL", i,
monster[i].mName);
2173 if (
monster[i]._mVar1 != -1) {
2178 for (mi = 0; mi < multimissiles; mi++) {
2206 app_fatal(
"M_DoRSpAttack: Invalid monster %d", i);
2208 app_fatal(
"M_DoRSpAttack: Monster %d \"%s\" MType NULL", i,
monster[i].mName);
2210 app_fatal(
"M_DoRSpAttack: Monster %d \"%s\" MData NULL", i,
monster[i].mName);
2232 }
else if (
monster[i]._mVar2 == 15) {
2248 app_fatal(
"M_DoSAttack: Invalid monster %d", i);
2250 app_fatal(
"M_DoSAttack: Monster %d \"%s\" MType NULL", i,
monster[i].mName);
2252 app_fatal(
"M_DoSAttack: Monster %d \"%s\" MData NULL", i,
monster[i].mName);
2268 app_fatal(
"M_DoFadein: Invalid monster %d", i);
2286 app_fatal(
"M_DoFadeout: Invalid monster %d", i);
2311 app_fatal(
"M_DoHeal: Invalid monster %d", i);
2339 app_fatal(
"M_DoTalk: Invalid monster %d", i);
2406 int k, j, x, y, _mx, _my, rx, ry;
2409 app_fatal(
"M_Teleport: Invalid monster %d", i);
2420 for (j = -1; j <= 1 && !tren; j++) {
2421 for (k = -1; k < 1 && !tren; k++) {
2422 if (j != 0 || k != 0) {
2425 if (y >= 0 && y < MAXDUNY && x >= 0 && x < MAXDUNX && x != Monst->_mx && y != Monst->
_my) {
2447 app_fatal(
"M_DoGotHit: Invalid monster %d", i);
2450 app_fatal(
"M_DoGotHit: Monster %d \"%s\" MType NULL", i,
monster[i].mName);
2465 app_fatal(
"M_UpdateLeader: Invalid monster %d", i);
2473 if (
monster[i].leaderflag == 1) {
2484 SNetLeaveGame(0x40000004);
2522 int newKillLevel, i;
2532 if (*killLevel > newKillLevel)
2533 newKillLevel = *killLevel;
2540 if (
plr[i]._pHitPoints >> 6 == 0)
2542 if (
plr[i]._pMana >> 6 == 0)
2554 app_fatal(
"M_DoDeath: Invalid monster %d", i);
2579 if (
monster[i]._uniqtype == 0)
2595 app_fatal(
"M_DoSpStand: Invalid monster %d", i);
2597 app_fatal(
"M_DoSpStand: Monster %d \"%s\" MType NULL", i,
monster[i].mName);
2616 app_fatal(
"M_DoDelay: Invalid monster %d", i);
2642 app_fatal(
"M_DoStone: Invalid monster %d", i);
2644 if (!
monster[i]._mhitpoints) {
2657 app_fatal(
"M_WalkDir: Invalid monster %d", i);
2694 app_fatal(
"GroupUnity: Invalid monster %d", i);
2699 if (clear ||
monster[i].leaderflag != 1) {
2713 if (
monster[i].leaderflag == 1) {
2727 if (
monster[i]._uniqtype != 0) {
2780 app_fatal(
"M_PathWalk: Invalid monster %d", i);
2859 app_fatal(
"MAI_Zombie: Invalid monster %d", i);
2877 if (abs(mx) >= 2 || abs(my) >= 2) {
2878 if (v < 2 * Monst->_mint + 10) {
2879 if (abs(mx) >= 2 * Monst->
_mint + 4 || abs(my) >= 2 * Monst->
_mint + 4) {
2889 }
else if (v < 2 * Monst->_mint + 10) {
2900 int mx, my, x, y, md;
2903 app_fatal(
"MAI_SkelSd: Invalid monster %d", i);
2916 if (abs(x) >= 2 || abs(y) >= 2) {
2940 app_fatal(
"MAI_Path: Invalid monster %d", i);
2950 if (Monst->
_mx == 1 && Monst->
_my == 0)
2980 int fx, fy, mx, my, md;
2985 app_fatal(
"MAI_Snake: Invalid monster %d", i);
2987 char pattern[6] = { 1, 1, 0, -1, -1, 0 };
2994 mx = Monst->
_mx - fx;
2995 my = Monst->
_my - fy;
2998 if (abs(mx) >= 2 || abs(my) >= 2) {
3031 }
else if (md == 4) {
3067 app_fatal(
"MAI_Bat: Invalid monster %d", i);
3097 && (abs(xd) >= 5 || abs(yd) >= 5)
3098 && v < 4 * Monst->_mint + 33
3104 }
else if (abs(xd) >= 2 || abs(yd) >= 2) {
3105 if (Monst->
_mVar2 > 20 && v < Monst->_mint + 13
3108 && v < Monst->
_mint + 63) {
3111 }
else if (v < 4 * Monst->_mint + 8) {
3116 AddMissile(Monst->
_menemyx, Monst->
_menemyy, Monst->
_menemyx + 1, 0, -1,
MIS_LIGHTNING, 1, i,
random_(109, 10) + 1, 0);
3132 app_fatal(
"MAI_SkelBow: Invalid monster %d", i);
3146 if (abs(mx) < 4 && abs(my) < 4) {
3147 if (Monst->
_mVar2 > 20 && v < 2 * Monst->_mint + 13
3150 && v < 2 * Monst->_mint + 63) {
3174 app_fatal(
"MAI_Fat: Invalid monster %d", i);
3186 if (abs(mx) >= 2 || abs(my) >= 2) {
3187 if (Monst->
_mVar2 > 20 && v < 4 * Monst->_mint + 20
3190 && v < 4 * Monst->_mint + 70) {
3193 }
else if (v < 4 * Monst->_mint + 15) {
3195 }
else if (v < 4 * Monst->_mint + 20) {
3210 app_fatal(
"MAI_Sneak: Invalid monster %d", i);
3222 dist = 5 - Monst->
_mint;
3227 if (abs(mx) >= dist + 3 || abs(my) >= dist + 3 || Monst->
_mgoalvar1 > 8) {
3259 if (abs(mx) >= 2 || abs(my) >= 2 || v >= 4 * Monst->
_mint + 10)
3276 app_fatal(
"MAI_Fireman: Invalid monster %d", i);
3331 int x, y, xpos, ypos;
3336 app_fatal(
"MAI_Fallen: Invalid monster %d", i);
3363 rad = 2 * Monst->
_mint + 2;
3369 rad = 2 * Monst->
_mint + 4;
3370 for (y = -rad; y <= rad; y++) {
3371 for (x = -rad; x <= rad; x++) {
3372 if (y >= 0 && y < MAXDUNY && x >= 0 && x <
MAXDUNX) {
3390 if (abs(xpos) < 2 && abs(ypos) < 2) {
3404 int x, y, mx, my, md;
3407 app_fatal(
"MAI_Cleaver: Invalid monster %d", i);
3422 if (abs(x) >= 2 || abs(y) >= 2)
3439 app_fatal(
"MAI_Round: Invalid monster %d", i);
3444 mx = Monst->
_mx - fx;
3445 my = Monst->
_my - fy;
3457 if (abs(mx) > abs(my))
3470 if (abs(mx) >= 2 || abs(my) >= 2) {
3471 if (Monst->
_mVar2 > 20 && v < 2 * Monst->_mint + 28
3474 && v < 2 * Monst->_mint + 78) {
3477 }
else if (v < 2 * Monst->_mint + 23) {
3502 app_fatal(
"MAI_Ranged: Invalid monster %d", i);
3512 mx = Monst->
_mx - fx;
3513 my = Monst->
_my - fy;
3520 }
else if (abs(mx) < 4 && abs(my) < 4) {
3565 app_fatal(
"MAI_Scav: Invalid monster %d", i);
3594 for (y = -4; y <= 4 && !done; y++) {
3595 for (x = -4; x <= 4 && !done; x++) {
3611 for (y = 4; y >= -4 && !done; y--) {
3612 for (x = 4; x >= -4 && !done; x--) {
3648 int mx, my, dx, dy, md;
3651 app_fatal(
"MAI_Garg: Invalid monster %d", i);
3661 if (abs(mx) < Monst->
_mint + 2 && abs(my) < Monst->
_mint + 2) {
3674 if (abs(dx) >= Monst->
_mint + 2 || abs(dy) >= Monst->
_mint + 2) {
3692 app_fatal(
"MAI_RoundRanged: Invalid monster %d", i);
3697 mx = Monst->
_mx - fx;
3698 my = Monst->
_my - fy;
3700 if (checkdoors && Monst->
_msquelch < UCHAR_MAX)
3704 if (Monst->
_mgoal ==
MGOAL_MOVE || ((abs(mx) >= 3 || abs(my) >= 3) &&
random_(122, 4 << lessmissiles) == 0)) {
3710 if (abs(mx) > abs(my)) {
3717 }
else if (v<500 * (Monst->
_mint + 1)>> lessmissiles
3728 if (((abs(mx) >= 3 || abs(my) >= 3) && v < ((500 * (Monst->
_mint + 2)) >> lessmissiles)
3729 || v < ((500 * (Monst->
_mint + 1)) >> lessmissiles))
3732 }
else if (abs(mx) >= 2 || abs(my) >= 2) {
3734 if (v < 1000 * (Monst->
_mint + 5)
3738 }
else if (v < 1000 * (Monst->
_mint + 6)) {
3776 app_fatal(
"MAI_RR2: Invalid monster %d", i);
3781 if (abs(mx) >= 5 || abs(my) >= 5) {
3789 mx = Monst->
_mx - fx;
3790 my = Monst->
_my - fy;
3803 if (abs(mx) > abs(my)) {
3809 if (v < 5 * (Monst->
_mint + 16))
3817 if (((abs(mx) >= 3 || abs(my) >= 3) && v < 5 * (Monst->
_mint + 2) || v < 5 * (Monst->
_mint + 1) || Monst->
_mgoalvar3 == 4) &&
LineClear(Monst->
_mx, Monst->
_my, fx, fy)) {
3819 }
else if (abs(mx) >= 2 || abs(my) >= 2) {
3821 if (v < 2 * (5 * Monst->
_mint + 25)
3824 && v < 2 * (5 * Monst->
_mint + 40)) {
3851 int mx, my, _mex, _mey;
3852 int md, j, k, _menemy;
3854 BOOL have_enemy, ok;
3857 app_fatal(
"MAI_Golum: Invalid monster %d", i);
3860 if (Monst->
_mx == 1 && Monst->
_my == 0) {
3887 if (abs(_mex) >= 2 || abs(_mey) >= 2) {
3890 }
else if (have_enemy) {
3894 if (
monster[_menemy]._msquelch == 0) {
3898 for (j = 0; j < 5; j++) {
3899 for (k = 0; k < 5; k++) {
3911 if (
monster[i]._pathcount > 8)
3917 for (j = 0; j < 8 && !ok; j++) {
3931 int mx, my, fx, fy, nx, ny;
3935 app_fatal(
"MAI_SkelKing: Invalid monster %d", i);
3940 mx = Monst->
_mx - fx;
3941 my = Monst->
_my - fy;
3953 if (abs(mx) > abs(my)) {
3968 && ((abs(mx) >= 3 || abs(my) >= 3) && v < 4 * Monst->_mint + 35 || v < 6)
3977 if (abs(mx) >= 2 || abs(my) >= 2) {
3979 if (v >= Monst->
_mint + 25
3985 }
else if (v < Monst->_mint + 20) {
4003 app_fatal(
"MAI_Rhino: Invalid monster %d", i);
4008 mx = Monst->
_mx - fx;
4009 my = Monst->
_my - fy;
4014 if (abs(mx) >= 2 || abs(my) >= 2) {
4021 if (abs(mx) > abs(my)) {
4035 if ((abs(mx) >= 5 || abs(my) >= 5)
4036 && v < 2 * Monst->_mint + 43
4045 if (abs(mx) >= 2 || abs(my) >= 2) {
4047 if (v >= 2 * Monst->
_mint + 33
4050 || v >= 2 * Monst->
_mint + 83)) {
4055 }
else if (v < 2 * Monst->_mint + 28) {
4073 app_fatal(
"MAI_Counselor: Invalid monster %d", i);
4078 mx = Monst->
_mx - fx;
4079 my = Monst->
_my - fy;
4092 if (abs(mx) > abs(my))
4108 if (abs(mx) >= 2 || abs(my) >= 2) {
4111 }
else if (
random_(124, 100) < 30) {
4144 app_fatal(
"MAI_Garbud: Invalid monster %d", i);
4186 int mx, my, _mx, _my, md;
4190 app_fatal(
"MAI_Zhar: Invalid monster %d", i);
4208 if (abs(_mx) > abs(_my))
4238 app_fatal(
"MAI_SnotSpil: Invalid monster %d", i);
4290 app_fatal(
"MAI_Lazurus: Invalid monster %d", i);
4343 app_fatal(
"MAI_Lazhelp: Invalid monster %d", i);
4376 app_fatal(
"MAI_Lachdanan: Invalid monster %d", i);
4415 app_fatal(
"MAI_Warlord: Invalid monster %d", i);
4474 int i, mi, mx, my, _menemy;
4508 app_fatal(
"Illegal enemy monster %d for monster \"%s\"", _menemy, Monst->
mName);
4517 app_fatal(
"Illegal enemy player %d for monster \"%s\"", _menemy, Monst->
mName);
4624 for (j = 0; j < 6; j++) {
4641 app_fatal(
"DirOK: Invalid monster %d", i);
4646 if (mdir ==
DIR_E) {
4650 if (mdir ==
DIR_W) {
4654 if (mdir ==
DIR_N) {
4661 if (
monster[i].leaderflag == 1) {
4671 for (x = fx - 3; x <= fx + 3; x++) {
4672 for (y = fy - 3; y <= fy + 3; y++) {
4680 if (
monster[mi].leaderflag == 1
4701 BOOL
LineClearF(BOOL (*Clear)(
int,
int),
int x1,
int y1,
int x2,
int y2)
4706 int xincD, yincD, dincD, dincH;
4713 if (abs(dx) > abs(dy)) {
4726 dincH = 2 * (dy - dx);
4731 dincH = 2 * (dx + dy);
4735 while (x1 != x2 || y1 != y2) {
4736 if ((d <= 0) ^ (yincD < 0)) {
4743 if ((x1 != xorg || y1 != yorg) && !Clear(x1, y1))
4759 dincH = 2 * (dx - dy);
4764 dincH = 2 * (dy + dx);
4768 while (y1 != y2 || x1 != x2) {
4769 if ((d <= 0) ^ (xincD < 0)) {
4776 if ((y1 != yorg || x1 != xorg) && !Clear(x1, y1))
4780 return x1 == x2 && y1 == y2;
4788 BOOL
LineClearF1(BOOL (*Clear)(
int,
int,
int),
int monst,
int x1,
int y1,
int x2,
int y2)
4793 int xincD, yincD, dincD, dincH;
4800 if (abs(dx) > abs(dy)) {
4813 dincH = 2 * (dy - dx);
4818 dincH = 2 * (dx + dy);
4822 while (x1 != x2 || y1 != y2) {
4823 if ((d <= 0) ^ (yincD < 0)) {
4830 if ((x1 != xorg || y1 != yorg) && !Clear(monst, x1, y1))
4846 dincH = 2 * (dx - dy);
4851 dincH = 2 * (dy + dx);
4855 while (y1 != y2 || x1 != x2) {
4856 if ((d <= 0) ^ (xincD < 0)) {
4863 if ((y1 != yorg || x1 != xorg) && !Clear(monst, x1, y1))
4867 return x1 == x2 && y1 == y2;
4877 app_fatal(
"SyncMonsterAnim: Invalid monster %d", i);
4881 Monst->
MData = MData;
4940 int i, mi, rundist, aitype;
4946 switch (
monster[mi].MType->mtype) {
4967 && abs(x -
monster[mi]._mx) < 5
4968 && abs(y -
monster[mi]._my) < 5
4969 &&
monster[mi]._mhitpoints >> 6 > 0) {
4979 int minHP, maxHP, res;
4995 minHP = 3 * minHP + 1;
4996 maxHP = 3 * maxHP + 1;
4999 minHP = 4 * minHP + 3;
5000 maxHP = 4 * maxHP + 3;
5002 sprintf(
tempstr,
"Hit Points : %i-%i", minHP, maxHP);
5012 strcpy(
tempstr,
"No magic resistance");
5016 strcpy(
tempstr,
"Resists : ");
5022 strcat(
tempstr,
"Lightning ");
5033 strcat(
tempstr,
"Lightning ");
5048 strcpy(
tempstr,
"No resistances");
5050 strcpy(
tempstr,
"No Immunities");
5053 strcpy(
tempstr,
"Some Magic Resistances");
5055 strcpy(
tempstr,
"No resistances");
5058 strcpy(
tempstr,
"Some Magic Immunities");
5060 strcpy(
tempstr,
"No Immunities");
5076 app_fatal(
"MissToMonst: Invalid missile %d", i);
5082 app_fatal(
"MissToMonst: Invalid monster %d", m);
5102 pnum =
dPlayer[oldx][oldy] - 1;
5103 if (
dPlayer[oldx][oldy] > 0) {
5107 if (
plr[pnum]._pmode != 7 &&
plr[pnum]._pmode != 8)
5116 dPlayer[newx][newy] = pnum + 1;
5154 if (
object[oi]._oSolidFlag)
5158 if (ret &&
dMissile[x][y] && i >= 0) {
5186 if (
object[oi]._oSolidFlag)
5190 if (ret &&
dMissile[x][y] && i >= 0) {
5211 int j, oi, objtype, mi;
5212 BOOL ret, fire, isdoor;
5218 if (ret &&
dObject[x][y] != 0) {
5220 objtype =
object[oi]._otype;
5224 if (
object[oi]._oSolidFlag && !isdoor) {
5231 if (ret &&
dMissile[x][y] != 0 && i >= 0) {
5268 int i, j, skeltypes, skel;
5279 for (i = 0; i <
nummtypes && j <= skeltypes; i++) {
5307 int dx, dy, xx, yy, dir, j, k, rs;
5322 for (j = y - 1; j <= y + 1; j++) {
5324 for (k = x - 1; k <= x + 1; k++) {
5326 savail |= monstok[xx][yy];
5339 if (monstok[xx][yy])
5362 int i, j, skeltypes, skel;
5374 for (i = 0; i <
nummtypes && j <= skeltypes; i++) {
5394 app_fatal(
"TalktoMonster: Invalid monster %d", i);
5419 app_fatal(
"SpawnGolum: Invalid monster %d", i);
5452 app_fatal(
"CanTalkToMonst: Invalid monster %d", m);
5465 app_fatal(
"CheckMonsterHit: Invalid monster %d", m);
unsigned char mArmorClass
BOOL LineClear(int x1, int y1, int x2, int y2)
void PlaceQuestMonsters()
void M_DiabloDeath(int i, BOOL sendmsg)
void SyncMonsterAnim(int i)
int AddLight(int x, int y, int r)
void AddDead(int dx, int dy, char dv, int ddir)
BOOL PosOkPlayer(int pnum, int x, int y)
QuestStruct quests[MAXQUESTS]
UniqMonstStruct UniqMonst[]
void StartPlrHit(int pnum, int dam, BOOL forcehit)
void MAI_Ranged(int i, int missile_type, BOOL special)
void play_movie(char *pszMovie, BOOL user_can_close)
CMonster Monsters[MAX_LVLMTYPES]
void NetSendCmdLocParam1(BOOL bHiPri, BYTE bCmd, BYTE x, BYTE y, WORD wParam1)
void M_UpdateLeader(int i)
int AddMonster(int x, int y, int dir, int mtype, BOOL InMap)
void SetRndSeed(int s)
Set the RNG seed.
void M_GetKnockback(int i)
void MonstCheckDoors(int m)
void M_StartSpAttack(int i)
BOOL effect_is_playing(int nSFX)
BYTE * CelGetFrameStart(BYTE *pCelBuff, int nCel)
void ChangeLightOff(int i, int x, int y)
unsigned char mMaxDamage2
void PlayEffect(int i, int mode)
void PlaceMonster(int i, int mtype, int x, int y)
void Cl2ApplyTrans(BYTE *p, BYTE *ttbl, int nCel)
Apply the color swaps to a CL2 sprite.
void FixPlrWalkTags(int pnum)
BOOL CheckNoSolid(int x, int y)
void M_TryH2HHit(int i, int pnum, int Hit, int MinDam, int MaxDam)
BOOL M_CallWalk(int i, int md)
void MAI_RR2(int i, int mistype, int dam)
void music_start(int nTrack)
void MAI_Counselor(int i)
int GetDirection(int x1, int y1, int x2, int y2)
Calculate the best fit direction between two points.
void FixPlayerLocation(int pnum, int bDir)
BOOL MonstPlace(int xp, int yp)
void M_TryM2MHit(int i, int mid, int hper, int mind, int maxd)
BOOL M_CallWalk2(int i, int md)
MissileStruct missile[MAXMISSILES]
void M_StartWalk3(int i, int xvel, int yvel, int xoff, int yoff, int xadd, int yadd, int mapx, int mapy, int EndDir)
BOOL PosOkMonst(int i, int x, int y)
void PlayInGameMovie(char *pszMovie)
Fade to black and play a video.
BOOL CanTalkToMonst(int m)
void MonstStartKill(int i, int pnum, BOOL sendmsg)
unsigned char mMinDamage2
void CheckQuestKill(int m, BOOL sendmsg)
void ChangeLightXY(int i, int x, int y)
BOOL PosOkMissile(int x, int y)
void delta_kill_monster(int mi, BYTE x, BYTE y, BYTE bLevel)
void SyncPlrKill(int pnum, int earflag)
void SpawnUnique(int uid, int x, int y)
void InitMonster(int i, int rd, int mtype, int x, int y)
char dObject[MAXDUNX][MAXDUNY]
void InitMonsterGFX(int monst)
BOOL loop_movie
Should the movie play in a loop.
BOOL SolidLoc(int x, int y)
void DeleteMonster(int i)
DWORD LoadFileWithMem(const char *pszName, void *p)
Load a file in to the given buffer.
BYTE gbMaxPlayers
Specifies the maximum number of players in a game, where 1 represents a single player game and 4 repr...
void NetSendCmdQuest(BOOL bHiPri, BYTE q)
void SetPlayerOld(int pnum)
int AddMissile(int sx, int sy, int dx, int dy, int midir, int mitype, char micaster, int id, int midam, int spllvl)
void SpawnItem(int m, int x, int y, BOOL sendmsg)
void M_StartKill(int i, int pnum)
void NewMonsterAnim(int i, AnimStruct *anim, int md)
char dLight[MAXDUNX][MAXDUNY]
int sound_get_or_set_music_volume(int volume)
int dPiece[MAXDUNX][MAXDUNY]
BOOL CheckMonsterHit(int m, BOOL *ret)
BOOLEAN nSolidTable[2049]
List of path blocking dPieces.
void DRLG_MRectTrans(int x1, int y1, int x2, int y2)
void M_SyncStartKill(int i, int x, int y, int pnum)
void MissToMonst(int i, int x, int y)
void AddPlrMonstExper(int lvl, int exp, char pmask)
void ObjChangeMapResync(int x1, int y1, int x2, int y2)
unsigned char mArmorClass
void app_fatal(const char *pszFmt,...)
#define DEVILUTION_END_NAMESPACE
BOOLEAN nMissileTable[2049]
List of missile blocking dPieces.
void PrintMonstHistory(int mt)
MonsterStruct monster[MAXMONSTERS]
BOOL PosOkMonst2(int i, int x, int y)
void AddPanelString(char *str, BOOL just)
void SpawnGolum(int i, int x, int y, int mi)
void PrintUniqueHistory()
TriggerStruct trigs[MAXTRIGGERS]
void M_WalkDir(int i, int md)
THEME_LOC themeLoc[MAXTHEMES]
BYTE MonstAvailTbl[]
0 = Never avalible 1 = Avalible in retail and shareware 2 = avalible in retail only
BYTE * LoadFileInMem(char *pszName, DWORD *pdwFileLen)
Load a file in to a buffer.
void M_StartSpStand(int i, int md)
void RemoveInvItem(int pnum, int iv)
void M_StartWalk(int i, int xvel, int yvel, int xadd, int yadd, int EndDir)
unsigned char mMinDamage2
char dMissile[MAXDUNX][MAXDUNY]
void M_StartRSpAttack(int i, int missile_type, int dam)
void M_StartStand(int i, int md)
int AddMonsterType(int type, int placeflag)
void TalktoMonster(int i)
void decode_enemy(int m, int enemy)
void CreateTypeItem(int x, int y, BOOL onlygood, int itype, int imisc, BOOL sendmsg, BOOL delta)
DEVILUTION_BEGIN_NAMESPACE int missileactive[MAXMISSILES]
BOOL M_DumbWalk(int i, int md)
int GetRndSeed()
Get the current RNG seed.
void M_ChangeLightOffset(int monst)
void M_StartAttack(int i)
void MAI_Round(int i, BOOL special)
void M_StartRAttack(int i, int missile_type, int dam)
BOOL M_RoundWalk(int i, int md, int *dir)
void M2MStartKill(int i, int mid)
void StartPlrBlock(int pnum, int dir)
void MAI_Lachdanan(int i)
int monstkills[MAXMONSTERS]
void M_ClearSquares(int i)
int monstactive[MAXMONSTERS]
void DoVision(int nXPos, int nYPos, int nRadius, BOOL doautomap, BOOL visible)
int FindPath(BOOL(*PosOk)(int, int, int), int PosOkArg, int sx, int sy, int dx, int dy, char *path)
find the shortest path from (sx,sy) to (dx,dy), using PosOk(PosOkArg,x,y) to check that each step is ...
void PlaceGroup(int mtype, int num, int leaderf, int leader)
void M_StartFadeout(int i, int md, BOOL backwards)
void M_StartDelay(int i, int len)
char dTransVal[MAXDUNX][MAXDUNY]
void SetMapMonsters(BYTE *pMap, int startx, int starty)
BOOL PosOkMonst3(int i, int x, int y)
unsigned char mPlaceFlags
ItemStruct * PlrHasItem(int pnum, int item, int *i)
void M_StartHit(int i, int pnum, int dam)
const DEVILUTION_BEGIN_NAMESPACE TextDataStruct alltext[]
Contains the data related to each speech ID.
void delta_monster_hp(int mi, int hp, BYTE bLevel)
void M_FallenFear(int x, int y)
int random_(BYTE idx, int v)
Main RNG function.
void mem_free_dbg(void *p)
Multithreaded safe memfree.
BOOL DirOK(int i, int mdir)
int M_SpawnSkel(int x, int y, int dir)
void LoadMissileGFX(BYTE mi)
BOOL SpawnSkeleton(int ii, int x, int y)
void M_StartFadein(int i, int md, BOOL backwards)
int dMonster[MAXDUNX][MAXDUNY]
void NetSendCmdParam2(BOOL bHiPri, BYTE bCmd, WORD wParam1, WORD wParam2)
void ObjChangeMap(int x1, int y1, int x2, int y2)
unsigned short mMagicRes2
char dPlayer[MAXDUNX][MAXDUNY]
void NetSendCmdGolem(BYTE mx, BYTE my, BYTE dir, BYTE menemy, int hp, BYTE cl)
DEVILUTION_BEGIN_NAMESPACE int diabquad1x
char dFlags[MAXDUNX][MAXDUNY]
void InitMonsterSND(int monst)
void PlaceUniqueMonst(int uniqindex, int miniontype, int unpackfilesize)
unsigned char * _mAnimData
void ActivateSpawn(int i, int x, int y, int dir)
DEVILUTION_BEGIN_NAMESPACE MonsterData monsterdata[]
void M2MStartHit(int mid, int i, int dam)
DEVILUTION_BEGIN_NAMESPACE int MissileFileFlag
Tracks which missile files are already loaded.
BOOL LineClearF(BOOL(*Clear)(int, int), int x1, int y1, int x2, int y2)
char dDead[MAXDUNX][MAXDUNY]
PlayerStruct plr[MAX_PLRS]
void InitMonsterTRN(int monst, BOOL special)
BOOL LineClearF1(BOOL(*Clear)(int, int, int), int monst, int x1, int y1, int x2, int y2)
void MAI_RoundRanged(int i, int missile_type, BOOL checkdoors, int dam, int lessmissiles)
void DoUnVision(int nXPos, int nYPos, int nRadius)
void M_StartWalk2(int i, int xvel, int yvel, int xoff, int yoff, int xadd, int yadd, int EndDir)
unsigned char mMaxDamage2