mirror of
https://github.com/jmarshall23/Hellfire.git
synced 2026-08-11 23:40:51 +02:00
6890 lines
202 KiB
Plaintext
6890 lines
202 KiB
Plaintext
/*-----------------------------------------------------------------------**
|
|
** Diablo
|
|
**
|
|
** Missiles file
|
|
**
|
|
** (C)1995 Condor, Inc. All rights reserved.
|
|
**
|
|
**-----------------------------------------------------------------------**
|
|
** $Header: /Diablo/MISSILES.CPP 3 2/25/97 2:27p Jmcreynolds $
|
|
**-----------------------------------------------------------------------**
|
|
**
|
|
** File Routines
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
#include "diablo.h"
|
|
#pragma hdrstop
|
|
#include <math.h>
|
|
#include <limits>
|
|
#include "sound.h"
|
|
#include "missiles.h"
|
|
#include "misdat.h"
|
|
#include "engine.h"
|
|
#include "gendung.h"
|
|
#include "lighting.h"
|
|
#include "items.h"
|
|
#include "player.h"
|
|
#include "monster.h"
|
|
#include "monstdat.h"
|
|
#include "monstint.h"
|
|
#include "control.h"
|
|
#include "objects.h"
|
|
#include "objdat.h"
|
|
#include "spells.h"
|
|
#include "cursor.h"
|
|
#include "dead.h"
|
|
#include "effects.h"
|
|
#include "palette.h"
|
|
#include "inv.h"
|
|
#include "msg.h"
|
|
#include "quests.h"
|
|
#include "itemdat.h"
|
|
#include "multi.h"
|
|
#include "trigs.h"
|
|
#include "scrollrt.h"
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** Constants
|
|
**-----------------------------------------------------------------------*/
|
|
#if RLE_DRAW
|
|
#define CEL_EXT ".CL2"
|
|
#else
|
|
#define CEL_EXT ".CEL"
|
|
#endif
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** Global Variables
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
MissileStruct missile[MAXMISSILES];
|
|
int nummissiles;
|
|
|
|
static int missilevars[MAXMISSILES][3]; //0 missile num; 1 var1; 2 var2
|
|
static int nummissilevars;
|
|
|
|
int missileactive[MAXMISSILES];
|
|
int missileavail[MAXMISSILES];
|
|
|
|
int XDirAdd[8] = { 1, 0, -1, -1, -1, 0, 1, 1 };
|
|
int YDirAdd[8] = { 1, 1, 1, 0, -1, -1, -1, 0 };
|
|
|
|
// Indexes into the CrawlTable.
|
|
static int const CrawlNum[19] = { 0, 3, 12, 45, 94, 159, 240, 337, 450, 579, 724,
|
|
885, 1062, 1255, 1464, 1689, 1930, 2187, 2460 };
|
|
|
|
BOOL ManashieldFlag;
|
|
BOOL MissilePreFlag;
|
|
|
|
typedef BOOL (*CHECKFUNC)(int x, int y);
|
|
|
|
static void GetMissilePos(int i);
|
|
|
|
/*-----------------------------------------------------------------------**
|
|
**----------------------- General use routines --------------------------**
|
|
**-----------------------------------------------------------------------*/
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void GetDamageAmt(int i, int * mind, int * maxd)
|
|
{
|
|
int k, sl;
|
|
|
|
app_assert(myplr < MAX_PLRS);
|
|
app_assert(i < 64);
|
|
sl = plr[myplr]._pSplLvl[i] + plr[myplr]._pISplLvlAdd;
|
|
|
|
switch (i) {
|
|
case SPL_FIREBOLT:
|
|
*mind = 1 + (plr[myplr]._pMagic >> 3) + sl;
|
|
*maxd = 10 + (plr[myplr]._pMagic >> 3) + sl;
|
|
break;
|
|
case SPL_HEAL:
|
|
*mind = 1 + plr[myplr]._pLevel + sl;
|
|
if (plr[myplr]._pClass == CLASS_WARRIOR) *mind = *mind << 1;
|
|
else if (plr[myplr]._pClass == CLASS_ROGUE ||
|
|
plr[myplr]._pClass == CLASS_BARD) *mind += (*mind >> 1);
|
|
*maxd = 10;
|
|
for (k = 0; k < plr[myplr]._pLevel; ++k) *maxd += 4;
|
|
for (k = 0; k < sl; ++k) *maxd += 6;
|
|
if (plr[myplr]._pClass == CLASS_WARRIOR) *maxd = *maxd << 1;
|
|
else if (plr[myplr]._pClass == CLASS_ROGUE ||
|
|
plr[myplr]._pClass == CLASS_BARD) *maxd += (*maxd >> 1);
|
|
*mind = -1;
|
|
*maxd = -1;
|
|
break;
|
|
case SPL_LIGHTNING:
|
|
*mind = 2;
|
|
*maxd = plr[myplr]._pLevel + 2;
|
|
break;
|
|
case SPL_FLASH:
|
|
*mind = plr[myplr]._pLevel;
|
|
for (k = sl; k > 0; --k) *mind += (*mind >> 3);
|
|
*mind += *mind >> 1;
|
|
*maxd = *mind << 1; // this is not actual(below is) - its a kludge to make it seem acurate text wise
|
|
/**maxd = 0;
|
|
for (k = 0; k <= plr[myplr]._pLevel; ++k) *maxd += 20;
|
|
for (k = sl; k > 0; --k) *maxd += (*maxd >> 3);
|
|
*maxd += *maxd >> 1;*/
|
|
break;
|
|
case SPL_IDENTIFY:
|
|
case SPL_TOWN:
|
|
case SPL_STONE:
|
|
case SPL_INFRA:
|
|
case SPL_PHASE:
|
|
case SPL_MANASHLD:
|
|
case SPL_DOOM:
|
|
case SPL_BLOODR:
|
|
case SPL_INVIS:
|
|
case SPL_BLOODB:
|
|
case SPL_TELE:
|
|
case SPL_ETHER:
|
|
case SPL_REPAIR:
|
|
case SPL_RECHARGE:
|
|
case SPL_DISARM:
|
|
case SPL_RESURRECT:
|
|
case SPL_TELEKINESIS:
|
|
case SPL_BONESPIRIT:
|
|
*mind = -1;
|
|
*maxd = -1;
|
|
break;
|
|
case SPL_WALL:
|
|
*mind = ((2 + plr[myplr]._pLevel) << 2) >> 1;
|
|
*maxd = ((20 + plr[myplr]._pLevel) << 2) >> 1;
|
|
break;
|
|
case SPL_FIREBALL:
|
|
*mind = (2 + plr[myplr]._pLevel) << 1;
|
|
for (k = sl; k > 0; --k) *mind += (*mind >> 3);
|
|
*maxd = (20 + plr[myplr]._pLevel) << 1;
|
|
for (k = sl; k > 0; --k) *maxd += (*maxd >> 3);
|
|
break;
|
|
case SPL_GUARDIAN:
|
|
*mind = 1 + (plr[myplr]._pLevel >> 1);
|
|
for (k = sl; k > 0; --k) *mind += (*mind >> 3);
|
|
*maxd = 10 + (plr[myplr]._pLevel >> 1);
|
|
for (k = sl; k > 0; --k) *maxd += (*maxd >> 3);
|
|
break;
|
|
case SPL_CHAIN:
|
|
// this is not actual - its a kludge to make it seem acurate text wise
|
|
*mind = 2 << 1;
|
|
*maxd = (plr[myplr]._pLevel + 2) << 1;
|
|
break;
|
|
case SPL_WAVE:
|
|
// this is not actual - its a kludge to make it seem acurate text wise
|
|
*mind = ((1 + plr[myplr]._pLevel) << 2) + ((1 + plr[myplr]._pLevel) << 1);
|
|
*maxd = ((10 + plr[myplr]._pLevel) << 2) + ((10 + plr[myplr]._pLevel) << 1);
|
|
break;
|
|
case SPL_NOVA:
|
|
// this is not actual - its a kludge to make it seem acurate text wise
|
|
*mind = (5 + plr[myplr]._pLevel) >> 1;
|
|
for (k = sl; k > 0; --k) *mind += (*mind >> 3);
|
|
*mind = (*mind << 2) + *mind;
|
|
*maxd = (30 + plr[myplr]._pLevel) >> 1;
|
|
for (k = sl; k > 0; --k) *maxd += (*maxd >> 3);
|
|
*maxd = (*maxd << 2) + *maxd;
|
|
break;
|
|
case SPL_FLAME:
|
|
*mind = 2;
|
|
*mind += *mind >> 1;
|
|
*maxd = (plr[myplr]._pLevel + 4);
|
|
*maxd += *maxd >> 1;
|
|
break;
|
|
case SPL_GOLEM:
|
|
*mind = 11;
|
|
*maxd = 17;
|
|
break;
|
|
case SPL_APOCA:
|
|
*mind = 0;
|
|
for (k = 0; k < plr[myplr]._pLevel; ++k) *mind += 1;
|
|
*maxd = 0;
|
|
for (k = 0; k < plr[myplr]._pLevel; ++k) *maxd += 6;
|
|
break;
|
|
case SPL_ELEMENT:
|
|
*mind = (2 + plr[myplr]._pLevel) << 1;
|
|
for (k = sl; k > 0; --k) *mind += (*mind >> 3);
|
|
*maxd = (20 + plr[myplr]._pLevel) << 1;
|
|
for (k = sl; k > 0; --k) *maxd += (*maxd >> 3);
|
|
break;
|
|
case SPL_CBOLT:
|
|
*mind = 1;
|
|
*maxd = 1 + (plr[myplr]._pMagic >> 2);
|
|
break;
|
|
case SPL_HBOLT:
|
|
*mind = 9 + plr[myplr]._pLevel;
|
|
*maxd = 18 + plr[myplr]._pLevel;
|
|
break;
|
|
case SPL_HEALOTHER:
|
|
*mind = 1 + plr[myplr]._pLevel + sl;
|
|
if (plr[myplr]._pClass == CLASS_WARRIOR) *mind = *mind << 1;
|
|
if (plr[myplr]._pClass == CLASS_ROGUE ||
|
|
plr[myplr]._pClass == CLASS_BARD ) *mind += (*mind >> 1);
|
|
*maxd = 10;
|
|
for (k = 0; k < plr[myplr]._pLevel; ++k) *maxd += 4;
|
|
for (k = 0; k < sl; ++k) *maxd += 6;
|
|
if (plr[myplr]._pClass == CLASS_WARRIOR) *maxd = *maxd << 1;
|
|
if (plr[myplr]._pClass == CLASS_ROGUE ||
|
|
plr[myplr]._pClass == CLASS_BARD ) *maxd += (*maxd >> 1);
|
|
*mind = -1;
|
|
*maxd = -1;
|
|
break;
|
|
case SPL_BSTAR:
|
|
*mind = ((plr[myplr]._pMagic>>1)-(plr[myplr]._pMagic>>3)) + (sl << 1) + sl;
|
|
*maxd = *mind;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
int CheckBlock(int fx, int fy, int tx, int ty)
|
|
{
|
|
int pn, dir, coll;
|
|
|
|
coll = 0;
|
|
|
|
while ((fx != tx) || (fy != ty)) {
|
|
dir = GetDirection(fx, fy, tx, ty);
|
|
fx += XDirAdd[dir];
|
|
fy += YDirAdd[dir];
|
|
app_assert(fx < MAXDUNX);
|
|
app_assert(fy < MAXDUNY);
|
|
pn = dPiece[fx][fy];
|
|
app_assert(pn <= MAXTILES);
|
|
if (nSolidTable[pn]) coll = 1;
|
|
}
|
|
|
|
return coll;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
int FindClosest(int sx, int sy, int rad)
|
|
{
|
|
int cr, cidx, cent, cne, mid, tx, ty;
|
|
|
|
if (rad > 19) rad = 19;
|
|
|
|
for (cr = 1; cr < rad; ++cr) {
|
|
cidx = CrawlNum[cr];
|
|
cent = cidx + 1;
|
|
for (cne = CrawlTable[cidx]; cne > 0; --cne) {
|
|
tx = sx + CrawlTable[cent];
|
|
ty = sy + CrawlTable[(cent + 1)];
|
|
if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
mid = dMonster[tx][ty];
|
|
if ((mid > 0) && (CheckBlock(sx, sy, tx, ty) == 0))
|
|
return (mid - 1);
|
|
}
|
|
cent += 2;
|
|
}
|
|
}
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
static bool SetMissileLocation(int i, int *sx, int *sy, int rad)
|
|
{
|
|
bool success = false;
|
|
|
|
if (rad > 19) rad = 19;
|
|
|
|
for (int cr = 1; cr < rad && !success; ++cr) {
|
|
int const cidx = CrawlNum[cr];
|
|
int cent = cidx + 1;
|
|
for (int cne = CrawlTable[cidx]; cne > 0; --cne, cent += 2) {
|
|
int const tx = *sx + CrawlTable[cent];
|
|
int const ty = *sy + CrawlTable[(cent + 1)];
|
|
if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
int const pn = dPiece[tx][ty];
|
|
if (!nSolidTable[pn] && dObject[tx][ty] == 0) {
|
|
missile[i]._mix = tx;
|
|
missile[i]._miy = ty;
|
|
*sx = tx;
|
|
*sy = ty;
|
|
success = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (success);
|
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
int GetSpellLevel(int id, int sn)
|
|
{
|
|
int rv;
|
|
|
|
app_assert(id < MAX_PLRS);
|
|
app_assert(sn < 64);
|
|
if (id == myplr)
|
|
rv = plr[id]._pSplLvl[sn] + plr[id]._pISplLvlAdd;
|
|
else
|
|
rv = 1;
|
|
if (rv < 0 ) rv = 0;
|
|
return (rv);
|
|
}
|
|
|
|
#if 0 // UNUSED
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void RndBlood(int x, int y, int type, int dam, int hp)
|
|
{
|
|
int pct, str;
|
|
|
|
app_assert(hp != 0);
|
|
str = 0;
|
|
pct = (dam * 100) / hp;
|
|
if (pct > 65) str = 1;
|
|
if (pct > 80) str = 2;
|
|
if (pct > 90) str = 3;
|
|
str = 1;
|
|
|
|
//AddMissile(x, y, str, 0, 0, type, 0, myplr, 0);
|
|
}
|
|
#endif
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
static int GetDirection8(int x1, int y1, int x2, int y2)
|
|
{
|
|
BYTE const Dirs[16][16] = {
|
|
{ 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0
|
|
{ 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1
|
|
{ 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 2
|
|
{ 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, // 3
|
|
{ 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, // 4
|
|
{ 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 }, // 5
|
|
{ 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 6
|
|
{ 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 7
|
|
{ 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 8
|
|
{ 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 9
|
|
{ 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 10
|
|
{ 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 11
|
|
{ 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 12
|
|
{ 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 13
|
|
{ 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 14
|
|
{ 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }};// 15
|
|
|
|
BYTE const lrtoul[3] = { 3, 4, 5 };
|
|
BYTE const urtoll[3] = { 3, 2, 1 };
|
|
BYTE const lltour[3] = { 7, 6, 5 };
|
|
BYTE const ultolr[3] = { 7, 0, 1 };
|
|
|
|
int mx, my, md;
|
|
|
|
mx = abs(x2 - x1);
|
|
if (mx > 15) mx = 15;
|
|
my = abs(y2 - y1);
|
|
if (my > 15) my = 15;
|
|
md = Dirs[my][mx];
|
|
|
|
if (x1 > x2) {
|
|
if (y1 > y2) md = lrtoul[md];
|
|
else md = urtoll[md];
|
|
} else {
|
|
if (y1 > y2) md = lltour[md];
|
|
else md = ultolr[md];
|
|
}
|
|
|
|
return (md);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
static int GetDirection16(int x1, int y1, int x2, int y2)
|
|
{
|
|
const BYTE Dirs[16][16] = {
|
|
{ 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0
|
|
{ 4, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1
|
|
{ 4, 3, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, // 2
|
|
{ 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, // 3
|
|
{ 4, 4, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 4
|
|
{ 4, 4, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 5
|
|
{ 4, 4, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1 }, // 6
|
|
{ 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 }, // 7
|
|
{ 4, 4, 4, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1 }, // 8
|
|
{ 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1 }, // 9
|
|
{ 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1 }, // 10
|
|
{ 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1 }, // 11
|
|
{ 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }, // 12
|
|
{ 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }, // 13
|
|
{ 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2 }, // 14
|
|
{ 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2 }};// 15
|
|
|
|
const BYTE lrtoul[5] = { 6, 7, 8, 9, 10 };
|
|
const BYTE urtoll[5] = { 6, 5, 4, 3, 2 };
|
|
const BYTE lltour[5] = { 14, 13, 12, 11, 10 };
|
|
const BYTE ultolr[5] = { 14, 15, 0, 1, 2 };
|
|
|
|
int mx, my, md;
|
|
|
|
mx = abs(x2 - x1);
|
|
if (mx > 15) mx = 15;
|
|
my = abs(y2 - y1);
|
|
if (my > 15) my = 15;
|
|
md = Dirs[my][mx];
|
|
|
|
if (x1 > x2) {
|
|
if (y1 > y2) md = lrtoul[md];
|
|
else md = urtoll[md];
|
|
} else {
|
|
if (y1 > y2) md = lltour[md];
|
|
else md = ultolr[md];
|
|
}
|
|
|
|
return (md);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void DeleteMissile(int mi, int i)
|
|
{
|
|
app_assert(nummissiles <= MAXMISSILES);
|
|
missileavail[MAXMISSILES - nummissiles] = mi;
|
|
--nummissiles;
|
|
|
|
if ((nummissiles > 0) && (i != nummissiles)) {
|
|
app_assert(i < MAXMISSILES);
|
|
missileactive[i] = missileactive[nummissiles];
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
static void GetMissileVel(int i, int sx, int sy, int dx, int dy, int v)
|
|
{
|
|
double dxp, dyp, dr;
|
|
|
|
dxp = (((dx - sx) << 5) - ((dy - sy) << 5)) << 16;
|
|
dyp = (((dx - sx) << 5) + ((dy - sy) << 5)) << 16;
|
|
dr = sqrt((dxp * dxp) + (dyp * dyp));
|
|
app_assert(i < MAXMISSILES);
|
|
missile[i]._mixvel = static_cast<long>(((v << 16) * dxp) / dr);
|
|
missile[i]._miyvel = static_cast<long>(((v << 15) * dyp) / dr);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
static void PutMissile(int i)
|
|
{
|
|
int mx, my;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
mx = missile[i]._mix;
|
|
my = missile[i]._miy;
|
|
|
|
if (mx <= 0 || my <= 0 || mx >= DMAXX || my >= DMAXY)
|
|
missile[i]._miDelFlag = TRUE;
|
|
|
|
if (!missile[i]._miDelFlag) {
|
|
dFlags[mx][my] |= BFLAG_MISSILE;
|
|
if (dMissile[mx][my] == 0) dMissile[mx][my] = (char)i + 1;
|
|
else dMissile[mx][my] = -1;
|
|
if (missile[i]._miPreFlag) MissilePreFlag = TRUE;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
static BYTE GetDirNum(int mi)
|
|
{
|
|
app_assert(mi < MAXMISSILES);
|
|
return (misfiledata[(missile[mi]._miAnimType)].mAnimFAmt >= 8) ? missile[mi]._mimfnum : 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
static void GetMissilePos(int i)
|
|
{
|
|
long mx, my;
|
|
long dx, dy;
|
|
long lx, ly; // lighting offsets
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
mx = missile[i]._mitxoff >> 16;
|
|
my = missile[i]._mityoff >> 16;
|
|
dx = (mx + (my << 1));
|
|
dy = ((my << 1) - mx);
|
|
|
|
if (dx < 0) {
|
|
lx = -((-dx) >> 3);
|
|
dx = -((-dx) >> 6);
|
|
} else {
|
|
lx = dx >> 3;
|
|
dx = dx >> 6;
|
|
}
|
|
|
|
if (dy < 0) {
|
|
ly = -((-dy) >> 3);
|
|
dy = -((-dy) >> 6);
|
|
} else {
|
|
ly = dy >> 3;
|
|
dy = dy >> 6;
|
|
}
|
|
|
|
missile[i]._mix = dx + missile[i]._misx;
|
|
missile[i]._miy = dy + missile[i]._misy;
|
|
missile[i]._mixoff = mx - ((dx - dy) << 5);
|
|
missile[i]._miyoff = my - ((dx + dy) << 4);
|
|
ChangeLightOff(missile[i]._mlid, lx - (dx << 3), ly - (dy << 3));
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
* MoveMissilePos
|
|
*
|
|
* Adjusts missile's drawing location to prevent overlapping tiles
|
|
* Written specifically for monster missiles (e.g., Rhino), which are large.
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
static void MoveMissilePos(int i)
|
|
{
|
|
int dx,dy;
|
|
int mx,my;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
switch (missile[i]._mimfnum) {
|
|
case 0 : // Down
|
|
dx = 1;
|
|
dy = 1;
|
|
break;
|
|
case 1 : // Down Left
|
|
dx = 1;
|
|
dy = 1;
|
|
break;
|
|
case 2 : // Left
|
|
dx = 0;
|
|
dy = 1;
|
|
break;
|
|
case 3 : // Up Left
|
|
dx = 0;
|
|
dy = 0;
|
|
break;
|
|
case 4 : // Up
|
|
dx = 0;
|
|
dy = 0;
|
|
break;
|
|
case 5 : // Up Right
|
|
dx = 0;
|
|
dy = 0;
|
|
break;
|
|
case 6 : // Right
|
|
dx = 1;
|
|
dy = 0;
|
|
break;
|
|
case 7 : // Down Right
|
|
dx = 1;
|
|
dy = 1;
|
|
break;
|
|
}
|
|
|
|
mx = missile[i]._mix + dx;
|
|
my = missile[i]._miy + dy;
|
|
|
|
// note -- _misource is the monster which became this missile
|
|
if (PosOkMonst(missile[i]._misource,mx,my)) {
|
|
missile[i]._mix += dx;
|
|
missile[i]._miy += dy;
|
|
missile[i]._mixoff -= ((dx - dy) << 5);
|
|
missile[i]._miyoff -= ((dx + dy) << 4);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
BOOL MonsterTrapHit(int m, int mindam, int maxdam, int dist, int t, byte shift)
|
|
{
|
|
int hit, hper;
|
|
long dam;
|
|
int mor; // monster's resist type
|
|
int mir;
|
|
BOOL resist = FALSE;
|
|
BOOL ret;
|
|
|
|
app_assert(m < MAXMONSTERS);
|
|
if (monster[m].mtalkmsg != 0) return FALSE;
|
|
|
|
if ((monster[m]._mhitpoints >> HP_SHIFT) <= 0) return FALSE;
|
|
|
|
app_assert(monster[m].MType != NULL);
|
|
if(monster[m].MType->mtype == MT_ILLWEAV && monster[m]._mgoal == MG_RUN_AWAY)
|
|
return FALSE;
|
|
|
|
if (monster[m]._mmode == MM_MISSILE) return(FALSE);
|
|
|
|
mir = missiledata[t].mResist;
|
|
mor = monster[m].mMagicRes;
|
|
if( (mor & M_IM && mir == MIMT_MISC)
|
|
|| (mor & M_IF && mir == MIMT_FIRE)
|
|
|| (mor & M_IL && mir == MIMT_LGHT))
|
|
return FALSE;
|
|
|
|
if( (mor & M_RM && mir == MIMT_MISC)
|
|
|| (mor & M_RF && mir == MIMT_FIRE)
|
|
|| (mor & M_RL && mir == MIMT_LGHT))
|
|
resist = TRUE;
|
|
|
|
hit = random(68, 100);
|
|
hper = 90 - monster[m].mArmorClass - dist;
|
|
if (hper < 5) hper = 5;
|
|
if (hper > 95) hper = 95;
|
|
if (CheckMonsterHit(m, ret))
|
|
return(ret);
|
|
#if CHEATS
|
|
else if((hit < hper) || simplecheat || cheatflag || (monster[m]._mmode == MM_STONE)) {
|
|
#else
|
|
else if((hit < hper) || (monster[m]._mmode == MM_STONE)) {
|
|
#endif
|
|
dam = random(68, maxdam - mindam + 1) + mindam;
|
|
if (shift == 0) dam = dam << HP_SHIFT;
|
|
if (resist)
|
|
monster[m]._mhitpoints -= dam >> 2;
|
|
else
|
|
monster[m]._mhitpoints -= dam;
|
|
|
|
#if CHEATS
|
|
if (simplecheat || cheatflag) monster[m]._mhitpoints = 0;
|
|
#endif
|
|
// rjs - x2 dam if stone - if (monster[m]._mmode == MM_STONE) monster[m]._mhitpoints -= dam;
|
|
if ((monster[m]._mhitpoints >> HP_SHIFT) <= 0) {
|
|
if (monster[m]._mmode == MM_STONE) {
|
|
M_StartKill(m, -1);
|
|
monster[m]._mmode = MM_STONE;
|
|
} else M_StartKill(m, -1);
|
|
}
|
|
else if(resist)
|
|
{
|
|
PlayEffect(m, MS_GOTHIT);
|
|
}
|
|
else
|
|
{
|
|
if (monster[m]._mmode == MM_STONE) {
|
|
if (m > 3) M_StartHit(m, -1, dam); // dont let golems get hit
|
|
monster[m]._mmode = MM_STONE;
|
|
} else {
|
|
if (m > 3) M_StartHit(m, -1, dam); // dont let golems get hit
|
|
}
|
|
}
|
|
return(TRUE);
|
|
} else return(FALSE);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
BOOL MonsterMHit(int pnum, int m, int mindam, int maxdam, int dist, int t, byte shift)
|
|
{
|
|
int hit, hper;
|
|
long dam;
|
|
int mor; // monster's resist type
|
|
int mir; // missile resistance category
|
|
BOOL resist = FALSE;
|
|
BOOL ret;
|
|
|
|
app_assert(m < MAXMONSTERS);
|
|
if (monster[m].mtalkmsg != 0) return(FALSE);
|
|
|
|
if ((monster[m]._mhitpoints >> HP_SHIFT) <= 0) return(FALSE);
|
|
|
|
app_assert(monster[m].MData != NULL);
|
|
if ((t == MIT_HBOLT) &&
|
|
(monster[m].MType->mtype != MT_DIABLO) &&
|
|
(monster[m].MData->mMonstClass != MC_UNDEAD)) return(FALSE);
|
|
|
|
app_assert(monster[m].MType != NULL);
|
|
if(monster[m].MType->mtype == MT_ILLWEAV && monster[m]._mgoal == MG_RUN_AWAY)
|
|
return FALSE;
|
|
|
|
if (monster[m]._mmode == MM_MISSILE) return(FALSE);
|
|
|
|
mir = missiledata[t].mResist;
|
|
mor = monster[m].mMagicRes;
|
|
if( (mor & M_IM && mir == MIMT_MISC)
|
|
|| (mor & M_IF && mir == MIMT_FIRE)
|
|
|| (mor & M_IL && mir == MIMT_LGHT)
|
|
|| (mor & M_IA && mir == MIMT_ACID))
|
|
return FALSE;
|
|
|
|
if( (mor & M_RM && mir == MIMT_MISC)
|
|
|| (mor & M_RF && mir == MIMT_FIRE)
|
|
|| (mor & M_RL && mir == MIMT_LGHT))
|
|
resist = TRUE;
|
|
|
|
hit = random(69, 100);
|
|
if (missiledata[t].mType == MIS_WEAP) {
|
|
hper = BASE_TO_HIT + plr[pnum]._pLevel - monster[m].mArmorClass - plr[pnum]._pIEnAc;
|
|
hper += plr[pnum]._pDexterity + plr[pnum]._pIBonusToHit;
|
|
hper -= (dist * dist) >> 1;
|
|
if (plr[pnum]._pClass == CLASS_ROGUE) hper += 20;
|
|
if (plr[pnum]._pClass == CLASS_WARRIOR ||
|
|
plr[pnum]._pClass == CLASS_BARD) hper += 10;
|
|
} else {
|
|
hper = BASE_TO_HIT + plr[pnum]._pMagic - (monster[m].mLevel << 1) - dist;
|
|
if (plr[pnum]._pClass == CLASS_SORCEROR) hper += 20;
|
|
else if (plr[pnum]._pClass == CLASS_BARD) hper += 10;
|
|
}
|
|
if (hper < 5) hper = 5;
|
|
if (hper > 95) hper = 95;
|
|
if (monster[m]._mmode == MM_STONE) hit = 0;
|
|
if (CheckMonsterHit(m, ret))
|
|
return(ret);
|
|
#if CHEATS
|
|
else if((hit < hper) || cheatflag || simplecheat) {
|
|
#else
|
|
else if (hit < hper) {
|
|
#endif
|
|
if (t == MIT_BONESPIRIT)
|
|
dam = (monster[m]._mhitpoints / 3) >> HP_SHIFT;
|
|
else
|
|
dam = random(70, maxdam - mindam + 1) + mindam;
|
|
if (missiledata[t].mType == MIS_WEAP) {
|
|
dam += (dam * plr[pnum]._pIBonusDam) / 100;
|
|
dam += plr[pnum]._pIBonusDamMod;
|
|
if (plr[pnum]._pClass == CLASS_ROGUE) dam += plr[pnum]._pDamageMod;
|
|
else dam += (plr[pnum]._pDamageMod >> 1);
|
|
}
|
|
if (shift == 0) dam = dam << HP_SHIFT;
|
|
if (resist) dam = dam >> 2;
|
|
if (pnum == myplr) monster[m]._mhitpoints -= dam;
|
|
|
|
if (plr[pnum]._pIFlags & IAF_MNOHEAL) monster[m]._mFlags |= MFLAG_NOHEAL;
|
|
#if CHEATS
|
|
//if (pnum == myplr && cheatflag) monster[m]._mhitpoints = 0;
|
|
#endif
|
|
//rjs - x2 stone dam - if (pnum == myplr && monster[m]._mmode == MM_STONE) monster[m]._mhitpoints -= dam;
|
|
|
|
if ((monster[m]._mhitpoints >> HP_SHIFT) <= 0) {
|
|
if (monster[m]._mmode == MM_STONE) {
|
|
M_StartKill(m, pnum);
|
|
monster[m]._mmode = MM_STONE;
|
|
} else M_StartKill(m, pnum);
|
|
//(old) AddPlrExperience(pnum, monster[m].mLevel, monster[m].mExp);
|
|
//(new, but moved) AddPlrMonstExper(monster[m].mLevel, monster[m].mExp, monster[m].mWhoHit);
|
|
}
|
|
else if(resist)
|
|
{
|
|
PlayEffect(m, MS_GOTHIT);
|
|
}
|
|
else
|
|
{
|
|
if (monster[m]._mmode == MM_STONE) {
|
|
if (m > 3) M_StartHit(m, pnum, dam);
|
|
monster[m]._mmode = MM_STONE;
|
|
} else {
|
|
if ((missiledata[t].mType == MIS_WEAP) && (plr[pnum]._pIFlags & IAF_KNOCKBACK)) M_GetKnockback(m);
|
|
if (m > 3) M_StartHit(m, pnum, dam);
|
|
}
|
|
}
|
|
// wake up monster if it's inactive
|
|
if(!monster[m]._msquelch)
|
|
{
|
|
monster[m]._msquelch = 255;
|
|
monster[m]._lastx = plr[pnum]._px;
|
|
monster[m]._lasty = plr[pnum]._py;
|
|
}
|
|
return(TRUE);
|
|
} else return(FALSE);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
BOOL PlayerMHit(int pnum, int m, int dist, int mind, int maxd, int mtype, byte shift, BOOL earflag)
|
|
{
|
|
int hit, hper, tac;
|
|
long dam;
|
|
int blk, blkper, blkdir;
|
|
int resper = 0;
|
|
|
|
app_assert(pnum < MAX_PLRS);
|
|
if ((plr[pnum]._pHitPoints >> HP_SHIFT) <= 0) return(FALSE);
|
|
if (plr[pnum]._pInvincible) return(FALSE);
|
|
if (((plr[pnum]._pSpellFlags & SF_ETHER) != 0) && (missiledata[mtype].mType == MIS_WEAP)) return(FALSE);
|
|
|
|
hit = random(72, 100);
|
|
#if CHEATS
|
|
if (simplecheat || cheatflag) hit = 1000;
|
|
#endif
|
|
if (missiledata[mtype].mType == MIS_WEAP) {
|
|
// rjs tac = (byte)plr[pnum]._pArmorClass + plr[pnum]._pIAC + plr[pnum]._pIBonusAC;
|
|
tac = plr[pnum]._pIAC + plr[pnum]._pIBonusAC;
|
|
tac += (plr[pnum]._pDexterity / 5);
|
|
if (m != -1) hper = 30 + monster[m].mHit - tac + ((monster[m].mLevel - plr[pnum]._pLevel) << 1) - (dist << 1);
|
|
else hper = 100 - (tac >> 1) - (dist << 1);
|
|
} else {
|
|
if (m != -1) hper = 40 + (monster[m].mLevel << 1) - (plr[pnum]._pLevel << 1) - (dist << 1);
|
|
else hper = 40;
|
|
}
|
|
if (hper < 10) hper = 10;
|
|
if ((currlevel == 14) && (hper < 20)) hper = 20;
|
|
if ((currlevel == 15) && (hper < 25)) hper = 25;
|
|
if ((currlevel == 16) && (hper < 30)) hper = 30;
|
|
if (((plr[pnum]._pmode == PM_STAND) || (plr[pnum]._pmode == PM_ATTACK)) && (plr[pnum]._pBlockFlag)) blk = random(73, 100);
|
|
else blk = 100;
|
|
if (shift == 1) blk = 100; // can't block continous damage spells
|
|
if (mtype == MIT_ACIDPUD) blk = 100; // can't block acid puddles (drb)
|
|
if (m != -1) blkper = plr[pnum]._pBaseToBlk + plr[pnum]._pDexterity - ((monster[m].mLevel - plr[pnum]._pLevel) << 1);
|
|
else blkper = plr[pnum]._pBaseToBlk + plr[pnum]._pDexterity;
|
|
if (blkper < 0) blkper = 0;
|
|
if (blkper > 100) blkper = 100;
|
|
switch(missiledata[mtype].mResist) {
|
|
case MIMT_FIRE:
|
|
resper = plr[pnum]._pFireResist;
|
|
break;
|
|
case MIMT_LGHT:
|
|
resper = plr[pnum]._pLghtResist;
|
|
break;
|
|
case MIMT_MISC:
|
|
case MIMT_ACID:
|
|
resper = plr[pnum]._pMagResist;
|
|
break;
|
|
default:
|
|
resper = 0;
|
|
break;
|
|
}
|
|
if (hit < hper) {
|
|
// Hit, so calc damage
|
|
if (mtype == MIT_BONESPIRIT) {
|
|
dam = plr[pnum]._pHitPoints / 3;
|
|
} else {
|
|
if (shift == 0) {
|
|
dam = (maxd - mind + 1) << HP_SHIFT;
|
|
dam = random(75, dam) + (mind << HP_SHIFT);
|
|
if (plr[pnum]._pIFlags & IAF_TRAPDAM) dam = dam >> 1;
|
|
dam += (plr[pnum]._pIGetHit << HP_SHIFT);
|
|
if (dam < (1 << HP_SHIFT)) dam = (1 << HP_SHIFT);
|
|
} else {
|
|
dam = maxd - mind + 1;
|
|
dam = random(75, dam) + mind;
|
|
if (plr[pnum]._pIFlags & IAF_TRAPDAM) dam = dam >> 1;
|
|
dam += plr[pnum]._pIGetHit;
|
|
if (dam < (1 << HP_SHIFT)) dam = (1 << HP_SHIFT);
|
|
}
|
|
}
|
|
|
|
// Did I resist?
|
|
if (resper > 0) {
|
|
dam -= (dam * resper) / 100;
|
|
if (pnum == myplr) {
|
|
plr[pnum]._pHitPoints -= dam;
|
|
plr[pnum]._pHPBase -= dam;
|
|
}
|
|
if (plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) {
|
|
plr[pnum]._pHitPoints = plr[pnum]._pMaxHP;
|
|
plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase;
|
|
}
|
|
if ((plr[pnum]._pHitPoints >> HP_SHIFT) <= 0) {
|
|
// rjs - manashld fix? - plr[pnum]._pHitPoints = 0;
|
|
StartPlrKill(pnum, earflag);
|
|
}
|
|
else {
|
|
// No get hit
|
|
if (plr[pnum]._pClass == CLASS_WARRIOR) PlaySfxLoc(PS_WARR69, plr[pnum]._px, plr[pnum]._py);
|
|
#if !IS_VERSION(SHAREWARE)
|
|
else if (plr[pnum]._pClass == CLASS_ROGUE) PlaySfxLoc(PS_ROGUE69, plr[pnum]._px, plr[pnum]._py);
|
|
else if (plr[pnum]._pClass == CLASS_SORCEROR) PlaySfxLoc(PS_MAGE69, plr[pnum]._px, plr[pnum]._py);
|
|
else if (plr[pnum]._pClass == CLASS_MONK) PlaySfxLoc(PS_MONK69, plr[pnum]._px, plr[pnum]._py);
|
|
else if (plr[pnum]._pClass == CLASS_BARD) PlaySfxLoc(PS_BARD69, plr[pnum]._px, plr[pnum]._py);
|
|
#endif
|
|
|
|
//PlaySfxLoc(PS_LGHIT, plr[pnum]._px, plr[pnum]._py);
|
|
drawhpflag = TRUE;
|
|
}
|
|
return(TRUE);
|
|
} else {
|
|
// Did I block?
|
|
if (blk < blkper) {
|
|
if (m != -1) blkdir = GetDirection(plr[pnum]._px, plr[pnum]._py, monster[m]._mx, monster[m]._my);
|
|
else blkdir = plr[pnum]._pdir;
|
|
StartPlrBlock(pnum, blkdir);
|
|
return(TRUE);
|
|
} else {
|
|
if (pnum == myplr) {
|
|
plr[pnum]._pHitPoints -= dam;
|
|
plr[pnum]._pHPBase -= dam;
|
|
}
|
|
if (plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) {
|
|
plr[pnum]._pHitPoints = plr[pnum]._pMaxHP;
|
|
plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase;
|
|
}
|
|
if ((plr[pnum]._pHitPoints >> HP_SHIFT) <= 0) {
|
|
// rjs - manashld fix? - plr[pnum]._pHitPoints = 0;
|
|
StartPlrKill(pnum, earflag);
|
|
} else StartPlrHit(pnum, dam, FALSE);
|
|
return(TRUE);
|
|
}
|
|
}
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
BOOL Plr2PlrMHit(int pnum, int p, int mindam, int maxdam, int dist, int mtype, byte shift)
|
|
{
|
|
int hit, hper, tac;
|
|
long dam;
|
|
int blk, blkper, blkdir;
|
|
int resper;
|
|
|
|
// pnum is missiles source
|
|
// p is missiles dest
|
|
|
|
app_assert(p < MAX_PLRS);
|
|
if (plr[p]._pInvincible) return(FALSE);
|
|
if (mtype == MIT_HBOLT) return(FALSE);
|
|
if (((plr[p]._pSpellFlags & SF_ETHER) != 0) && (missiledata[mtype].mType == MIS_WEAP)) return(FALSE);
|
|
|
|
switch(missiledata[mtype].mResist) {
|
|
case MIMT_FIRE:
|
|
resper = plr[p]._pFireResist;
|
|
break;
|
|
case MIMT_LGHT:
|
|
resper = plr[p]._pLghtResist;
|
|
break;
|
|
case MIMT_MISC:
|
|
case MIMT_ACID:
|
|
resper = plr[p]._pMagResist;
|
|
break;
|
|
default:
|
|
resper = 0;
|
|
break;
|
|
}
|
|
hit = random(69, 100);
|
|
if (missiledata[mtype].mType == MIS_WEAP) {
|
|
//rjs tac = (byte)plr[p]._pArmorClass + plr[p]._pIAC + plr[p]._pIBonusAC;
|
|
tac = plr[p]._pIAC + plr[p]._pIBonusAC;
|
|
tac += (plr[p]._pDexterity / 5);
|
|
hper = BASE_TO_HIT + plr[pnum]._pLevel - tac;
|
|
hper += plr[pnum]._pDexterity + plr[pnum]._pIBonusToHit;
|
|
hper -= (dist * dist) >> 1;
|
|
if (plr[pnum]._pClass == CLASS_ROGUE) hper += 20;
|
|
if (plr[pnum]._pClass == CLASS_WARRIOR) hper += 10;
|
|
} else {
|
|
hper = BASE_TO_HIT + plr[pnum]._pMagic - (plr[p]._pLevel << 1) - dist;
|
|
if (plr[pnum]._pClass == CLASS_SORCEROR) hper += 20;
|
|
}
|
|
if (hper < 5) hper = 5;
|
|
if (hper > 95) hper = 95;
|
|
if (hit < hper) {
|
|
// Hit, calc blk %
|
|
if (((plr[p]._pmode == PM_STAND) || (plr[p]._pmode == PM_ATTACK)) && (plr[p]._pBlockFlag)) blk = random(73, 100);
|
|
else blk = 100;
|
|
if (shift == 1) blk = 100; // can't block continous damage spells
|
|
blkper = plr[p]._pBaseToBlk + plr[p]._pDexterity - ((plr[pnum]._pLevel - plr[p]._pLevel) << 1);
|
|
if (blkper < 0) blkper = 0;
|
|
if (blkper > 100) blkper = 100;
|
|
// Hit, so calc damage
|
|
if (mtype == MIT_BONESPIRIT) {
|
|
dam = plr[p]._pHitPoints / 3;
|
|
} else {
|
|
dam = random(70, maxdam - mindam + 1) + mindam;
|
|
if (missiledata[mtype].mType == MIS_WEAP) {
|
|
dam += (dam * plr[pnum]._pIBonusDam) / 100;
|
|
dam += plr[pnum]._pIBonusDamMod + plr[pnum]._pDamageMod;
|
|
}
|
|
if (shift == 0) dam = dam << HP_SHIFT;
|
|
}
|
|
// NEW! Take 1/2 damage from plr spells (drb 11/23)
|
|
if (missiledata[mtype].mType != MIS_WEAP) dam = dam >> 1;
|
|
// Did I resist?
|
|
if (resper > 0) {
|
|
dam -= (dam * resper) / 100;
|
|
// No get hit
|
|
if (pnum == myplr) NetSendCmdDamage(TRUE, p, dam);
|
|
if (plr[pnum]._pClass == CLASS_WARRIOR) PlaySfxLoc(PS_WARR69, plr[pnum]._px, plr[pnum]._py);
|
|
#if !IS_VERSION(SHAREWARE)
|
|
else if (plr[pnum]._pClass == CLASS_ROGUE) PlaySfxLoc(PS_ROGUE69, plr[pnum]._px, plr[pnum]._py);
|
|
else if (plr[pnum]._pClass == CLASS_SORCEROR) PlaySfxLoc(PS_MAGE69, plr[pnum]._px, plr[pnum]._py);
|
|
else if (plr[pnum]._pClass == CLASS_MONK) PlaySfxLoc(PS_MONK69, plr[pnum]._px, plr[pnum]._py);
|
|
else if (plr[pnum]._pClass == CLASS_BARD) PlaySfxLoc(PS_BARD69, plr[pnum]._px, plr[pnum]._py);
|
|
#endif
|
|
|
|
//PlaySfxLoc(PS_LGHIT, plr[p]._px, plr[p]._py);
|
|
return(TRUE);
|
|
} else {
|
|
// Did I block?
|
|
if (blk < blkper) {
|
|
blkdir = GetDirection(plr[p]._px, plr[p]._py, plr[pnum]._px, plr[pnum]._py);
|
|
StartPlrBlock(p, blkdir);
|
|
return(TRUE);
|
|
} else {
|
|
if (pnum == myplr) NetSendCmdDamage(TRUE, p, dam);
|
|
StartPlrHit(p, dam, FALSE);
|
|
return(TRUE);
|
|
}
|
|
}
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
static void CheckMissileCol(int i, int mindam, int maxdam, byte shift, int mx, int my, byte nodel)
|
|
{
|
|
int pn,oi;
|
|
BOOL earflag;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
app_assert(mx < MAXDUNX);
|
|
app_assert(my < MAXDUNY);
|
|
if ((missile[i]._miAnimType == MF_FIRE)
|
|
|| (missile[i]._miAnimType == MF_LIGHTNING && missile[i]._mixvel == 0 && missile[i]._miyvel == 0)
|
|
|| (missile[i]._misource == -1)) {
|
|
if (dMonster[mx][my] > 0) {
|
|
if (missile[i]._miAnimType == MF_FIRE
|
|
|| missile[i]._miAnimType == MF_LIGHTNING) {
|
|
if (MonsterMHit(missile[i]._misource, dMonster[mx][my] - 1, mindam, maxdam, missile[i]._midist, missile[i]._mitype, shift)) {
|
|
if (nodel == 0) missile[i]._mirange = 0;
|
|
missile[i]._miHitFlag = TRUE;
|
|
}
|
|
} else {
|
|
if (MonsterTrapHit(dMonster[mx][my] - 1, mindam, maxdam, missile[i]._midist, missile[i]._mitype, shift)) {
|
|
if (nodel == 0) missile[i]._mirange = 0;
|
|
missile[i]._miHitFlag = TRUE;
|
|
}
|
|
}
|
|
}
|
|
if (dPlayer[mx][my] > 0) {
|
|
if (missile[i]._miAnimType == MF_FIRE
|
|
|| missile[i]._miAnimType == MF_LIGHTNING) earflag = TRUE;
|
|
else earflag = FALSE;
|
|
if (PlayerMHit(dPlayer[mx][my] - 1, -1, missile[i]._midist, mindam, maxdam, missile[i]._mitype, shift, earflag)) {
|
|
if (nodel == 0) missile[i]._mirange = 0;
|
|
missile[i]._miHitFlag = TRUE;
|
|
}
|
|
}
|
|
} else {
|
|
if (missile[i]._micaster == MI_ENEMYMONST) {
|
|
if (dMonster[mx][my] > 0) {
|
|
if (MonsterMHit(missile[i]._misource, dMonster[mx][my] - 1, mindam, maxdam, missile[i]._midist, missile[i]._mitype, shift)) {
|
|
if (nodel == 0) missile[i]._mirange = 0;
|
|
missile[i]._miHitFlag = TRUE;
|
|
}
|
|
} else {
|
|
if ((dMonster[mx][my] < 0) && (monster[-(dMonster[mx][my] + 1)]._mmode == MM_STONE)) {
|
|
if (MonsterMHit(missile[i]._misource, -(dMonster[mx][my] + 1), mindam, maxdam, missile[i]._midist, missile[i]._mitype, shift)) {
|
|
if (nodel == 0) missile[i]._mirange = 0;
|
|
missile[i]._miHitFlag = TRUE;
|
|
}
|
|
}
|
|
}
|
|
if ((dPlayer[mx][my] > 0) && ((dPlayer[mx][my]-1) != missile[i]._misource)) {
|
|
if (Plr2PlrMHit(missile[i]._misource, dPlayer[mx][my]-1, mindam, maxdam, missile[i]._midist, missile[i]._mitype, shift)) {
|
|
if (nodel == 0) missile[i]._mirange = 0;
|
|
missile[i]._miHitFlag = TRUE;
|
|
}
|
|
}
|
|
} else {
|
|
if (((monster[missile[i]._misource]._mFlags & MFLAG_MID) != 0) && ((dMonster[mx][my] > 0) && (monster[(dMonster[mx][my] - 1)]._mFlags & MFLAG_MKILLER) != 0)) {
|
|
if (MonsterTrapHit(dMonster[mx][my] - 1, mindam, maxdam, missile[i]._midist, missile[i]._mitype, shift)) {
|
|
if (nodel == 0) missile[i]._mirange = 0;
|
|
missile[i]._miHitFlag = TRUE;
|
|
}
|
|
}
|
|
if (dPlayer[mx][my] > 0) {
|
|
if (PlayerMHit(dPlayer[mx][my] - 1, missile[i]._misource, missile[i]._midist, mindam, maxdam, missile[i]._mitype, shift, FALSE)) {
|
|
if (nodel == 0) missile[i]._mirange = 0;
|
|
missile[i]._miHitFlag = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dObject[mx][my] != 0) {
|
|
if (dObject[mx][my] > 0) oi = dObject[mx][my] - 1;
|
|
else oi = -(dObject[mx][my] + 1);
|
|
if (!object[oi]._oMissFlag) {
|
|
if (object[oi]._oBreak == OBJ_BREAKABLE) BreakObject(-1, oi);
|
|
if (nodel == 0) missile[i]._mirange = 0;
|
|
missile[i]._miHitFlag = FALSE;
|
|
}
|
|
}
|
|
|
|
pn = dPiece[mx][my];
|
|
app_assert(pn <= MAXTILES);
|
|
if (nMissileTable[pn]) {
|
|
if (nodel == 0) missile[i]._mirange = 0;
|
|
missile[i]._miHitFlag = FALSE;
|
|
}
|
|
|
|
if ((missile[i]._mirange == 0) && (missiledata[missile[i]._mitype].miSFX != -1)) {
|
|
PlaySfxLoc(missiledata[missile[i]._mitype].miSFX, missile[i]._mix, missile[i]._miy);
|
|
}
|
|
}
|
|
|
|
static void SetMissAnim(int mi, int animtype)
|
|
{
|
|
int dir;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
dir = missile[mi]._mimfnum;
|
|
missile[mi]._miAnimType = animtype;
|
|
|
|
missile[mi]._miAnimFlags = misfiledata[animtype].mFlags;
|
|
missile[mi]._miAnimData = misfiledata[animtype].mAnimData[dir];
|
|
missile[mi]._miAnimDelay = misfiledata[animtype].mAnimDelay[dir];
|
|
missile[mi]._miAnimLen = misfiledata[animtype].mAnimLen[dir];
|
|
missile[mi]._miAnimWidth = misfiledata[animtype].mAnimWidth[dir];
|
|
missile[mi]._miAnimWidth2 = misfiledata[animtype].mAnimWidth2[dir];
|
|
missile[mi]._miAnimCnt = 0;
|
|
missile[mi]._miAnimFrame = 1;
|
|
}
|
|
|
|
|
|
void SetMissDir(int mi, int dir)
|
|
{
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._mimfnum = dir;
|
|
SetMissAnim(mi, missile[mi]._miAnimType);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------**
|
|
**---------------------- Initialization Routines ------------------------**
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
#if RLE_DRAW
|
|
void ILoadMissileGFX(BYTE mf) {
|
|
int i;
|
|
char strbuff[256];
|
|
BYTE *p;
|
|
MisFileData * pMisDat;
|
|
|
|
pMisDat = &misfiledata[mf];
|
|
if (pMisDat->mFlags & MFF_MULTI) {
|
|
// All directions are packed into one file
|
|
sprintf(strbuff,"Missiles\\%s" CEL_EXT, pMisDat->mAnimPath);
|
|
p = LoadFileInMemSig(strbuff,NULL,'MISS');
|
|
for (i = 0; i < pMisDat->mAnimFAmt; ++i)
|
|
pMisDat->mAnimData[i] = p + (reinterpret_cast<DWORD *>(p))[i];
|
|
}
|
|
else if (pMisDat->mAnimFAmt == 1) {
|
|
sprintf(strbuff,"Missiles\\%s" CEL_EXT, pMisDat->mAnimPath);
|
|
if(! pMisDat->mAnimData[0])
|
|
pMisDat->mAnimData[0] = LoadFileInMemSig(strbuff,NULL,'MISS');
|
|
}
|
|
else {
|
|
for (i = 0; i < pMisDat->mAnimFAmt; ++i) {
|
|
sprintf(strbuff, "Missiles\\%s%i" CEL_EXT, pMisDat->mAnimPath, i + 1);
|
|
if(! pMisDat->mAnimData[i])
|
|
pMisDat->mAnimData[i] = LoadFileInMemSig(strbuff,NULL,'MISS');
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
#if !RLE_DRAW
|
|
void ILoadMissileGFX(BYTE mf) {
|
|
int i;
|
|
char strbuff[256];
|
|
BYTE *p;
|
|
|
|
if (misfiledata[mf].mFlags & MFF_MULTI) {
|
|
// All directions are packed into one file
|
|
sprintf(strbuff,"Missiles\\%s.CEL", misfiledata[mf].mAnimPath);
|
|
p = LoadFileInMemSig(strbuff,NULL,'MISS');
|
|
for (i = 0; i < misfiledata[mf].mAnimFAmt; ++i) {
|
|
misfiledata[mf].mAnimData[i] = p + *static_cast<DWORD *>(p + (i<<2));
|
|
}
|
|
}
|
|
else if (misfiledata[mf].mAnimFAmt == 1) {
|
|
sprintf(strbuff,"Missiles\\%s.CEL", misfiledata[mf].mAnimPath);
|
|
if(! misfiledata[mf].mAnimData[0])
|
|
misfiledata[mf].mAnimData[0] = LoadFileInMemSig(strbuff,NULL,'MISS');
|
|
} else {
|
|
for (i = 0; i < misfiledata[mf].mAnimFAmt; ++i) {
|
|
sprintf(strbuff, "Missiles\\%s%i.CEL", misfiledata[mf].mAnimPath, i + 1);
|
|
if(! misfiledata[mf].mAnimData[i])
|
|
misfiledata[mf].mAnimData[i] = LoadFileInMemSig(strbuff,NULL,'MISS');
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void InitMissileGFX()
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; misfiledata[i].mAnimFAmt; ++i) {
|
|
if (!(misfiledata[i].mFlags & MFF_MONSTONLY)) {
|
|
ILoadMissileGFX(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
static void FreeMissileFile(int i)
|
|
{
|
|
int j;
|
|
void * y;
|
|
|
|
if (misfiledata[i].mFlags & MFF_MULTI)
|
|
{
|
|
if(misfiledata[i].mAnimData[0])
|
|
{
|
|
y = static_cast<void *> (misfiledata[i].mAnimData[0] - (misfiledata[i].mAnimFAmt << 2));
|
|
DiabloFreePtr(y);
|
|
misfiledata[i].mAnimData[0] = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (j = 0; j < misfiledata[i].mAnimFAmt; ++j)
|
|
if(misfiledata[i].mAnimData[j])
|
|
{
|
|
DiabloFreePtr(misfiledata[i].mAnimData[j]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void FreeMissileGFX()
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; misfiledata[i].mAnimFAmt; ++i) {
|
|
if (!(misfiledata[i].mFlags & MFF_MONSTONLY)) {
|
|
FreeMissileFile(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void IFreeMissileGFX()
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; misfiledata[i].mAnimFAmt; ++i)
|
|
if(misfiledata[i].mFlags & MFF_MONSTONLY)
|
|
FreeMissileFile(i);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void InitMissiles()
|
|
{
|
|
int i, j, mx;
|
|
|
|
// Delete any active infravision/ etheralize
|
|
plr[myplr]._pSpellFlags &= ~SF_ETHER;
|
|
if (plr[myplr]._pInfraFlag == TRUE) {
|
|
app_assert(nummissiles <= MAXMISSILES);
|
|
for (i = 0; i < nummissiles; ++i) {
|
|
mx = missileactive[i];
|
|
app_assert(mx < MAXMISSILES);
|
|
if ((missile[mx]._mitype == MIT_INFRA) && (missile[mx]._misource == myplr))
|
|
CalcPlrItemVals(missile[mx]._misource,TRUE);
|
|
}
|
|
}
|
|
|
|
nummissiles = 0;
|
|
for (i = 0; i < MAXMISSILES; ++i) {
|
|
missileavail[i] = i;
|
|
missileactive[i] = 0;
|
|
}
|
|
|
|
nummissilevars = 0;
|
|
for (i = 0; i < MAXMISSILES; ++i) {
|
|
missilevars[i][0] = -1;
|
|
missilevars[i][1] = 0;
|
|
missilevars[i][2] = 0;
|
|
}
|
|
|
|
for (j = 0; j < DMAXY; ++j) {
|
|
for (i = 0; i < DMAXX; ++i) {
|
|
dFlags[i][j] = dFlags[i][j] & ~BFLAG_MISSILE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------**
|
|
**------------------ Missile Initialization Routines --------------------**
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddRuneOfFire(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
if (id >= 0) {
|
|
UseMana(id, SPL_RUNEOFFIRE);
|
|
}
|
|
if (SetMissileLocation(mi, &dx, &dy, 10)) {
|
|
missile[mi]._miVar1 = MIT_MISEXP;
|
|
missile[mi]._miDelFlag = FALSE;
|
|
missile[mi]._mlid = AddLight(dx, dy, 8);
|
|
}
|
|
else missile[mi]._miDelFlag = TRUE;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddRuneOfLight(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
if (id >= 0) {
|
|
UseMana(id, SPL_RUNEOFLIGHT);
|
|
}
|
|
if (SetMissileLocation(mi, &dx, &dy, 10)) {
|
|
missile[mi]._miVar1 = MIT_LIGHTBALL;
|
|
missile[mi]._miDelFlag = FALSE;
|
|
missile[mi]._mlid = AddLight(dx, dy, 8);
|
|
}
|
|
else missile[mi]._miDelFlag = TRUE;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddRuneOfNova(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
if (id >= 0) {
|
|
UseMana(id, SPL_RUNEOFNOVA);
|
|
}
|
|
if (SetMissileLocation(mi, &sx, &sy, 10)) {
|
|
missile[mi]._miVar1 = MIT_NOVA;
|
|
missile[mi]._miDelFlag = FALSE;
|
|
missile[mi]._mlid = AddLight(sx, sy, 8);
|
|
}
|
|
else missile[mi]._miDelFlag = TRUE;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddRuneOfImmolation(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
if (id >= 0) {
|
|
UseMana(id, SPL_RUNEOFIMMOLATION);
|
|
}
|
|
if (SetMissileLocation(mi, &dx, &dy, 10)) {
|
|
missile[mi]._miVar1 = MIT_IMMOLATION;
|
|
missile[mi]._miDelFlag = FALSE;
|
|
missile[mi]._mlid = AddLight(dx, dy, 8);
|
|
|
|
}
|
|
else missile[mi]._miDelFlag = TRUE;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddRuneOfStone(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
if (id >= 0) {
|
|
UseMana(id, SPL_RUNEOFSTONE);
|
|
}
|
|
if (SetMissileLocation(mi, &dx, &dy, 10)) {
|
|
missile[mi]._miVar1 = MIT_STONE;
|
|
missile[mi]._miDelFlag = FALSE;
|
|
missile[mi]._mlid = AddLight(dx, dy, 8);
|
|
}
|
|
else missile[mi]._miDelFlag = TRUE;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddReflect(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
if (id >= 0) {
|
|
if (plr[id]._pReflectCount < 0)
|
|
plr[id]._pReflectCount = 0;
|
|
|
|
plr[id]._pReflectCount += GetSpellLevel(id, SPL_REFLECT) * plr[id]._pLevel;
|
|
UseMana(id, SPL_REFLECT);
|
|
}
|
|
missile[mi]._mirange = 0;
|
|
missile[mi]._miDelFlag = TRUE;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddBerserk(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
if (id >= 0) {
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._misource = id;
|
|
|
|
// search in a 5 radius around tile clicked for monster
|
|
for (int k = 0; k < 6; ++k) {
|
|
int const l = CrawlNum[k];
|
|
int j = l + 1;
|
|
for (int i = CrawlTable[l]; i > 0; --i, j += 2) {
|
|
int const tx = dx + CrawlTable[j];
|
|
int const ty = dy + CrawlTable[(j + 1)];
|
|
if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
int mid = dMonster[tx][ty];
|
|
if (mid > 0) --mid;
|
|
else mid = -(mid + 1);
|
|
|
|
if ((mid > 3)
|
|
&& (monster[mid]._uniqtype == 0)
|
|
&& (monster[mid]._mAi != AI_DIABLO)
|
|
&& (monster[mid]._mmode != MM_FADEIN)
|
|
&& (monster[mid]._mmode != MM_FADEOUT)
|
|
//&& (monster[mid]._mmode != MM_DEATH)
|
|
&& (monster[mid]._mmode != MM_MISSILE)) {
|
|
i = -99;
|
|
k = 6;
|
|
int const SpellLevel = GetSpellLevel(id, SPL_BERSERK);
|
|
monster[mid]._mFlags |= MFLAG_BERSERK | MFLAG_MKILLER;
|
|
monster[mid].mMinDamage = static_cast<BYTE>(SpellLevel + monster[mid].mMinDamage * (1.0 + (0.01 * (random(145,10) + 20))));
|
|
monster[mid].mMaxDamage = static_cast<BYTE>(SpellLevel + monster[mid].mMaxDamage * (1.0 + (0.01 * (random(145,10) + 20))));
|
|
monster[mid].mMinDamage2 = static_cast<BYTE>(SpellLevel + monster[mid].mMinDamage2 * (1.0 + (0.01 * (random(145,10) + 20))));
|
|
monster[mid].mMaxDamage2 = static_cast<BYTE>(SpellLevel + monster[mid].mMaxDamage2 * (1.0 + (0.01 * (random(145,10) + 20))));
|
|
UseMana(id, SPL_BERSERK);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
missile[mi]._mirange = 0;
|
|
missile[mi]._miDelFlag = TRUE;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddDisEnchant(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._misource = id;
|
|
|
|
// search in a 3 radius around chest trap for players.
|
|
for (int k = 0; k < 3; ++k) {
|
|
int const l = CrawlNum[k];
|
|
int j = l + 1;
|
|
for (int i = CrawlTable[l]; i > 0; --i, j += 2) {
|
|
int const tx = sx + CrawlTable[j];
|
|
int const ty = sy + CrawlTable[(j + 1)];
|
|
if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
int pid = dPlayer[tx][ty];
|
|
|
|
if (pid == 0)
|
|
continue;
|
|
|
|
if (pid > 0) --pid;
|
|
else pid = -(pid + 1);
|
|
|
|
// Belt items only.
|
|
if (random(205, 2)) {
|
|
// distroy healing and mana potions && 1/2 rejuvination.
|
|
for (int splIndex = 0; splIndex < MAXSPD; ++splIndex) {
|
|
if (plr[pid].SpdList[splIndex]._itype == IT_MISC
|
|
&& (plr[pid].SpdList[splIndex]._iMiscId == IMID_PLHEAL
|
|
|| plr[pid].SpdList[splIndex]._iMiscId == IMID_PHEAL
|
|
|| plr[pid].SpdList[splIndex]._iMiscId == IMID_PMANA
|
|
|| plr[pid].SpdList[splIndex]._iMiscId == IMID_PFMANA
|
|
|| plr[pid].SpdList[splIndex]._iMiscId == IMID_REJUV)
|
|
) {
|
|
RemoveSpdBarItem(pid, splIndex);
|
|
}
|
|
else if (plr[pid].SpdList[splIndex]._iMiscId == IMID_FREJUV){
|
|
int const idata = ItemMiscIdIdx(IMID_REJUV);
|
|
SetPlrHandItem(&plr[pid].HoldItem, idata);
|
|
GetPlrHandSeed(&plr[pid].HoldItem);
|
|
plr[pid].HoldItem._iStatFlag = TRUE;
|
|
plr[pid].SpdList[splIndex] = plr[pid].HoldItem;
|
|
}
|
|
}
|
|
}
|
|
else if (random(206, 2)) {
|
|
// downgrade full potions to partial
|
|
// Partical go away.
|
|
for (int splIndex = 0; splIndex < MAXSPD; ++splIndex) {
|
|
if (plr[pid].SpdList[splIndex]._itype == IT_MISC ) {
|
|
switch (plr[pid].SpdList[splIndex]._iMiscId)
|
|
{
|
|
case IMID_PHEAL:
|
|
{
|
|
int const idata = ItemMiscIdIdx(IMID_PLHEAL);
|
|
SetPlrHandItem(&plr[pid].HoldItem, idata);
|
|
GetPlrHandSeed(&plr[pid].HoldItem);
|
|
plr[pid].HoldItem._iStatFlag = TRUE;
|
|
plr[pid].SpdList[splIndex] = plr[pid].HoldItem;
|
|
}
|
|
break;
|
|
case IMID_PFMANA:
|
|
{
|
|
int const idata = ItemMiscIdIdx(IMID_PMANA);
|
|
SetPlrHandItem(&plr[pid].HoldItem, idata);
|
|
GetPlrHandSeed(&plr[pid].HoldItem);
|
|
plr[pid].HoldItem._iStatFlag = TRUE;
|
|
plr[pid].SpdList[splIndex] = plr[pid].HoldItem;
|
|
}
|
|
break;
|
|
case IMID_FREJUV:
|
|
{
|
|
int const idata = ItemMiscIdIdx(IMID_REJUV);
|
|
SetPlrHandItem(&plr[pid].HoldItem, idata);
|
|
GetPlrHandSeed(&plr[pid].HoldItem);
|
|
plr[pid].HoldItem._iStatFlag = TRUE;
|
|
plr[pid].SpdList[splIndex] = plr[pid].HoldItem;
|
|
}
|
|
break;
|
|
case IMID_PMANA:
|
|
case IMID_PLHEAL:
|
|
case IMID_REJUV:
|
|
RemoveSpdBarItem(pid, splIndex);
|
|
break;
|
|
}
|
|
force_redraw = FULLDRAW;
|
|
}
|
|
}
|
|
}
|
|
else if (random(207, 2)) {
|
|
// convert rejuventation to healing or mana.
|
|
for (int splIndex = 0; splIndex < MAXSPD; ++splIndex) {
|
|
if (plr[pid].SpdList[splIndex]._itype == IT_MISC ) {
|
|
if(plr[pid].SpdList[splIndex]._iMiscId == IMID_REJUV) {
|
|
int const idata = ItemMiscIdIdx(random(210,2) ? IMID_PLHEAL : IMID_PMANA);
|
|
SetPlrHandItem(&plr[pid].HoldItem, idata);
|
|
GetPlrHandSeed(&plr[pid].HoldItem);
|
|
plr[pid].HoldItem._iStatFlag = TRUE;
|
|
plr[pid].SpdList[splIndex] = plr[pid].HoldItem;
|
|
}
|
|
else if(plr[pid].SpdList[splIndex]._iMiscId == IMID_FREJUV) {
|
|
int const idata = ItemMiscIdIdx(random(211,2) ? IMID_PHEAL : IMID_PFMANA);
|
|
SetPlrHandItem(&plr[pid].HoldItem, idata);
|
|
GetPlrHandSeed(&plr[pid].HoldItem);
|
|
plr[pid].HoldItem._iStatFlag = TRUE;
|
|
plr[pid].SpdList[splIndex] = plr[pid].HoldItem;
|
|
}
|
|
force_redraw = FULLDRAW;
|
|
}
|
|
}
|
|
}
|
|
else if (random(208, 5)) {
|
|
// distroy scrolls and oils.
|
|
for (int splIndex = 0; splIndex < MAXSPD; ++splIndex) {
|
|
if ( (plr[pid].SpdList[splIndex]._iMiscId > IMID_FIRSTOIL
|
|
&& plr[pid].SpdList[splIndex]._iMiscId < IMID_LASTOIL)
|
|
|| plr[pid].SpdList[splIndex]._iMiscId == IMID_SCROLL
|
|
|| plr[pid].SpdList[splIndex]._iMiscId == IMID_TSCROLL
|
|
) {
|
|
RemoveSpdBarItem(pid, splIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
missile[mi]._mirange = 0;
|
|
missile[mi]._miDelFlag = TRUE;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddManaRemove(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._misource = id;
|
|
|
|
// search in a 3 radius around chest trap for players.
|
|
for (int k = 0; k < 3; ++k) {
|
|
int const l = CrawlNum[k];
|
|
int j = l + 1;
|
|
for (int i = CrawlTable[l]; i > 0; --i, j += 2) {
|
|
int const tx = sx + CrawlTable[j];
|
|
int const ty = sy + CrawlTable[(j + 1)];
|
|
if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
int pid = dPlayer[tx][ty];
|
|
|
|
if (pid == 0)
|
|
continue;
|
|
|
|
if (pid > 0) --pid;
|
|
else pid = -(pid + 1);
|
|
|
|
plr[pid]._pMana = 0;
|
|
plr[pid]._pManaBase = plr[pid]._pMana - (plr[pid]._pMaxMana - plr[pid]._pMaxManaBase);
|
|
CalcPlrInv(pid, FALSE);
|
|
drawmanaflag = TRUE;
|
|
}
|
|
}
|
|
}
|
|
missile[mi]._mirange = 0;
|
|
missile[mi]._miDelFlag = TRUE;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddLArrow(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
if ((sx == dx) && (sy == dy)) {
|
|
dx += XDirAdd[midir];
|
|
dy += YDirAdd[midir];
|
|
}
|
|
|
|
if (mienemy == MI_ENEMYMONST) {
|
|
if (plr[id]._pClass == CLASS_ROGUE) GetMissileVel(mi,sx,sy,dx,dy,31+(plr[id]._pLevel>>2));
|
|
else if (plr[id]._pClass == CLASS_WARRIOR) GetMissileVel(mi,sx,sy,dx,dy,31+(plr[id]._pLevel>>3));
|
|
else GetMissileVel(mi,sx,sy,dx,dy,32);
|
|
} else GetMissileVel(mi,sx,sy,dx,dy,32);
|
|
|
|
SetMissDir(mi, GetDirection16(sx,sy,dx,dy));
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._mirange = 256;
|
|
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
missile[mi]._mlid = AddLight(sx, sy, 5);
|
|
|
|
//PutMissile(mi);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddArrow(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
int av;
|
|
|
|
if ((sx == dx) && (sy == dy)) {
|
|
dx += XDirAdd[midir];
|
|
dy += YDirAdd[midir];
|
|
}
|
|
|
|
if (mienemy == MI_ENEMYMONST) {
|
|
av = 32;
|
|
if (plr[id]._pIFlags & IAF_RNDARROW) av = random(64, 32) + 16; // rnd arrow speed
|
|
if (plr[id]._pClass == CLASS_ROGUE) av += (plr[id]._pLevel-1) >> 2; // rouge level speed increase
|
|
if (plr[id]._pClass == CLASS_WARRIOR) av += (plr[id]._pLevel-1) >> 3; // warrior level speed increase
|
|
GetMissileVel(mi,sx,sy,dx,dy,av);
|
|
} else GetMissileVel(mi,sx,sy,dx,dy,32);
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miAnimFrame = GetDirection16(sx,sy,dx,dy) + 1;
|
|
|
|
missile[mi]._mirange = 256;
|
|
|
|
//PutMissile(mi);
|
|
}
|
|
|
|
void AddSpecialArrow(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA
|
|
int extraspeed = 0;
|
|
|
|
// if ((sx == dx) && (sy == dy)) {
|
|
// dx += XDirAdd[midir];
|
|
// dy += YDirAdd[midir];
|
|
// }
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
if (mienemy == MI_ENEMYMONST)
|
|
{
|
|
if (plr[id]._pClass == CLASS_ROGUE)
|
|
extraspeed = (plr[id]._pLevel-1) >> 2; // rogue level speed increase
|
|
else if (plr[id]._pClass == CLASS_WARRIOR)
|
|
extraspeed = (plr[id]._pLevel-1) >> 3; // warrior level speed increase
|
|
}
|
|
|
|
missile[mi]._mirange = 1;
|
|
missile[mi]._miVar1 = dx;
|
|
missile[mi]._miVar2 = dy;
|
|
missile[mi]._miVar3 = extraspeed;
|
|
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void GetVileMissPos(int mi, int dx, int dy)
|
|
{
|
|
int xx, yy;
|
|
app_assert(mi < MAXMISSILES);
|
|
for (int l = 1; l < 50; ++l) {
|
|
for (int j = -l; j <= l; ++j) {
|
|
yy = dy + j;
|
|
for (int i = -l; i <= l; ++i) {
|
|
xx = dx + i;
|
|
if (PosOkPlayer(myplr,xx,yy)) {
|
|
missile[mi]._mix = xx;
|
|
missile[mi]._miy = yy;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// There is just no way it will ever reach here
|
|
missile[mi]._mix = dx;
|
|
missile[mi]._miy = dy;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
#define DIST(x,y,d) (abs(x) < d && abs(y) < d)
|
|
|
|
// Flag for fireman missile
|
|
#define MIF_DIDHIT 1
|
|
|
|
#define MINAWAY 3
|
|
#define MAXAWAY 6
|
|
|
|
void AddRndTeleport(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_PHASE) || !PRE_BETA
|
|
int pn, r1, r2;
|
|
|
|
int nTries = 0;
|
|
do {
|
|
// don't get stuck in an infinite loop...
|
|
if (++nTries > 500) {
|
|
r1 = 0;
|
|
r2 = 0;
|
|
break;
|
|
}
|
|
|
|
r1 = random(58, MAXAWAY - MINAWAY) + MINAWAY + 1;
|
|
r2 = random(58, MAXAWAY - MINAWAY) + MINAWAY + 1;
|
|
if (random(58, 2) == 1) r1 = -r1;
|
|
if (random(58, 2) == 1) r2 = -r2;
|
|
pn = dPiece[sx + r1][sy + r2];
|
|
} while (nSolidTable[pn] != 0 || dObject[sx + r1][sy + r2] != 0 || dMonster[sx + r1][sy + r2] != 0);
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._mirange = 2;
|
|
missile[mi]._miVar1 = 0;
|
|
|
|
// special code for Vile Betrayer quest
|
|
if ((setlevel) && (setlvlnum == 5)) {
|
|
int oi = dObject[dx][dy]-1;
|
|
if ((object[oi]._otype == OBJ_MCIRCLE1) || (object[oi]._otype == OBJ_MCIRCLE2)) {
|
|
missile[mi]._mix = dx;
|
|
missile[mi]._miy = dy;
|
|
if (!PosOkPlayer(myplr, dx, dy)) GetVileMissPos(mi, dx, dy);
|
|
}
|
|
}
|
|
else {
|
|
missile[mi]._mix = sx + r1;
|
|
missile[mi]._miy = sy + r2;
|
|
|
|
if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_PHASE);
|
|
}
|
|
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
#undef max
|
|
void AddTeleStairs(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
int minDist = std::numeric_limits<int>::is_specialized && std::numeric_limits<int>::is_bounded
|
|
? std::numeric_limits<int>::max() : 99999;
|
|
if (id >= 0) {
|
|
sx = plr[id]._px;
|
|
sy = plr[id]._py;
|
|
}
|
|
|
|
int rx = sx;
|
|
int ry = sy;
|
|
|
|
for (int i = 0;i < numtrigs && i < MAXTRIGGERS; ++i) {
|
|
if (trigs[i]._tmsg == WM_DIABTWARPUP
|
|
|| trigs[i]._tmsg == WM_DIABPREVLVL
|
|
|| trigs[i]._tmsg == WM_DIABNEXTLVL
|
|
|| trigs[i]._tmsg == WM_DIABRTNLVL) {
|
|
|
|
int triggerx;
|
|
int triggery;
|
|
|
|
if ((leveltype == 1 || leveltype == 2)
|
|
&& (trigs[i]._tmsg == WM_DIABNEXTLVL
|
|
|| trigs[i]._tmsg == WM_DIABPREVLVL
|
|
|| trigs[i]._tmsg == WM_DIABRTNLVL) ){
|
|
triggerx = trigs[i]._tx;
|
|
triggery = trigs[i]._ty + 1;
|
|
}
|
|
else {
|
|
triggerx = trigs[i]._tx + 1;
|
|
triggery = trigs[i]._ty;
|
|
}
|
|
|
|
int xdiff = sx - triggerx;
|
|
xdiff *= xdiff;
|
|
int ydiff = sy - triggery;
|
|
ydiff *= ydiff;
|
|
int const NewDist = xdiff + ydiff;
|
|
|
|
if (NewDist < minDist)
|
|
{
|
|
minDist = NewDist;
|
|
rx = triggerx;
|
|
ry = triggery;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._mirange = 2;
|
|
missile[mi]._miVar1 = 0;
|
|
missile[mi]._mix = rx;
|
|
missile[mi]._miy = ry;
|
|
|
|
if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_TELESTAIRS);
|
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddFirebolt(int mi, int sx, int sy, int dx, int dy, int midir, char micaster, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_FIREBOLT) || !PRE_BETA
|
|
int sp, i, mx;
|
|
|
|
if ((sx == dx) && (sy == dy)) {
|
|
dx += XDirAdd[midir];
|
|
dy += YDirAdd[midir];
|
|
}
|
|
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
if (micaster == MI_ENEMYMONST)
|
|
{
|
|
app_assert(nummissiles <= MAXMISSILES);
|
|
for (i = 0; i < nummissiles; ++i) {
|
|
mx = missileactive[i];
|
|
app_assert(mx < MAXMISSILES);
|
|
if ((missile[mx]._mitype == MIT_GUARDIAN) &&
|
|
(missile[mx]._misource == id) && (missile[mx]._miVar3 == mi)) {
|
|
break;
|
|
}
|
|
}
|
|
if (i == nummissiles) UseMana(id, SPL_FIREBOLT);
|
|
|
|
if (id != -1) {
|
|
sp = 16 + (missile[mi]._mispllvl << 1);
|
|
if (sp >= 63) sp = 63;
|
|
} else sp = 16;
|
|
}
|
|
else
|
|
sp = 26;
|
|
|
|
GetMissileVel(mi,sx,sy,dx,dy,sp);
|
|
SetMissDir(mi, GetDirection16(sx,sy,dx,dy));
|
|
|
|
missile[mi]._mirange = 256;
|
|
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
missile[mi]._mlid = AddLight(sx, sy, 8);
|
|
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddMagmaball(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
GetMissileVel(mi,sx,sy,dx,dy,16);
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
// Graphics don't line up, so we have to move them...
|
|
missile[mi]._mitxoff += 3*missile[mi]._mixvel;
|
|
missile[mi]._mityoff += 3*missile[mi]._miyvel;
|
|
|
|
GetMissilePos(mi);
|
|
|
|
missile[mi]._mirange = 256;
|
|
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
missile[mi]._mlid = AddLight(sx, sy, 8);
|
|
|
|
//PutMissile(mi);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddKrull(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
GetMissileVel(mi,sx,sy,dx,dy,16);
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._mirange = 256;
|
|
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
// missile[mi]._mlid = AddLight(sx, sy, 8);
|
|
|
|
PutMissile(mi);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddTeleport(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_TELE) || !PRE_BETA
|
|
int i, pn;
|
|
int k, l, j;
|
|
int tx, ty;
|
|
|
|
app_assert(dx < MAXDUNX);
|
|
app_assert(dy < MAXDUNY);
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miDelFlag = TRUE;
|
|
for (k = 0; k < 6; ++k) {
|
|
l = CrawlNum[k];
|
|
j = l + 1;
|
|
for (i = CrawlTable[l]; i > 0; --i) {
|
|
tx = dx + CrawlTable[j];
|
|
ty = dy + CrawlTable[(j + 1)];
|
|
if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
pn = dPiece[tx][ty];
|
|
if ((nSolidTable[pn] | dMonster[tx][ty] | dObject[tx][ty] | dPlayer[tx][ty]) == 0) {
|
|
missile[mi]._mix = tx;
|
|
missile[mi]._miy = ty;
|
|
missile[mi]._misx = tx;
|
|
missile[mi]._misy = ty;
|
|
missile[mi]._miDelFlag = FALSE;
|
|
k = 6;
|
|
break;
|
|
}
|
|
}
|
|
j += 2;
|
|
}
|
|
}
|
|
|
|
if (missile[mi]._miDelFlag == FALSE) {
|
|
UseMana(id, SPL_TELE);
|
|
missile[mi]._mirange = 2;
|
|
}
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddLightball(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
GetMissileVel(mi,sx,sy,dx,dy,16);
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._midam = dam;
|
|
|
|
missile[mi]._miAnimFrame = random(63, 8) + 1;
|
|
|
|
missile[mi]._mirange = 255;
|
|
|
|
if (id < 0) {
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
} else {
|
|
missile[mi]._miVar1 = plr[id]._px;
|
|
missile[mi]._miVar2 = plr[id]._py;
|
|
}
|
|
|
|
//PutMissile(mi);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddFirewall(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_WALL) || !PRE_BETA
|
|
int i;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._midam = (random(53, 10) + random(53, 10) + 2 + (id > 0) ? plr[id]._pLevel : currlevel) << 4;
|
|
missile[mi]._midam = missile[mi]._midam >> 1;
|
|
|
|
GetMissileVel(mi,sx,sy,dx,dy,16);
|
|
|
|
missile[mi]._mirange = 10;
|
|
for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._mirange += 10;
|
|
|
|
if (mienemy != MI_ENEMYMONST || id < 0) // trap or somesuch
|
|
{
|
|
missile[mi]._mirange = missile[mi]._mirange + currlevel;
|
|
}
|
|
else
|
|
{
|
|
missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7);
|
|
}
|
|
missile[mi]._mirange = missile[mi]._mirange << 4;
|
|
|
|
missile[mi]._miVar1 = missile[mi]._mirange - missile[mi]._miAnimLen;
|
|
missile[mi]._miVar2 = 0;
|
|
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddFireball(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA
|
|
int i;
|
|
|
|
if ((sx == dx) && (sy == dy)) {
|
|
dx += XDirAdd[midir];
|
|
dy += YDirAdd[midir];
|
|
}
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
if (mienemy == MI_ENEMYMONST)
|
|
{
|
|
missile[mi]._midam = (random(60, 10) + random(60, 10) + 2 + plr[id]._pLevel) << 1;
|
|
for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3);
|
|
|
|
i = 16 + (missile[mi]._mispllvl << 1);
|
|
if (i > 50) i = 50;
|
|
|
|
UseMana(id, SPL_FIREBALL);
|
|
}
|
|
else
|
|
{
|
|
i = 16;
|
|
}
|
|
|
|
GetMissileVel(mi,sx,sy,dx,dy,i);
|
|
SetMissDir(mi, GetDirection16(sx,sy,dx,dy));
|
|
|
|
missile[mi]._mirange = 256;
|
|
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
missile[mi]._miVar3 = 0;
|
|
missile[mi]._miVar4 = sx;
|
|
missile[mi]._miVar5 = sy;
|
|
|
|
missile[mi]._mlid = AddLight(sx, sy, 8);
|
|
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddSpiralFireBall(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA
|
|
int i;
|
|
|
|
if ((sx == dx) && (sy == dy)) {
|
|
dx += XDirAdd[midir];
|
|
dy += YDirAdd[midir];
|
|
}
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
if (mienemy == MI_ENEMYMONST)
|
|
{
|
|
missile[mi]._midam = (random(60, 10) + random(60, 10) + 2 + plr[id]._pLevel) << 1;
|
|
for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3);
|
|
|
|
i = 16 + (missile[mi]._mispllvl << 1);
|
|
if (i > 50) i = 50;
|
|
|
|
UseMana(id, SPL_FIREBALL);
|
|
}
|
|
else
|
|
{
|
|
i = 16;
|
|
}
|
|
|
|
GetMissileVel(mi,sx,sy,dx,dy,i);
|
|
SetMissDir(mi, GetDirection16(sx,sy,dx,dy));
|
|
|
|
missile[mi]._mirange = 256;
|
|
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
missile[mi]._miVar3 = 0;
|
|
missile[mi]._miVar4 = sx;
|
|
missile[mi]._miVar5 = sy;
|
|
missile[mi]._miVar6 = 2;
|
|
missile[mi]._miVar7 = 2;
|
|
|
|
missile[mi]._mlid = AddLight(sx, sy, 8);
|
|
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
void AddFBArrow(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA
|
|
int i;
|
|
|
|
if ((sx == dx) && (sy == dy)) {
|
|
dx += XDirAdd[midir];
|
|
dy += YDirAdd[midir];
|
|
}
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
if (mienemy == MI_ENEMYMONST)
|
|
{
|
|
i = 16 + missile[mi]._mispllvl;
|
|
if (i > 50) i = 50;
|
|
|
|
// UseMana(id, SPL_FIREBALL);
|
|
}
|
|
else
|
|
{
|
|
i = 16;
|
|
}
|
|
|
|
GetMissileVel(mi,sx,sy,dx,dy,i);
|
|
SetMissDir(mi, GetDirection16(sx,sy,dx,dy));
|
|
|
|
missile[mi]._mirange = 256;
|
|
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
missile[mi]._miVar3 = 0;
|
|
missile[mi]._miVar4 = sx;
|
|
missile[mi]._miVar5 = sy;
|
|
|
|
missile[mi]._mlid = AddLight(sx, sy, 8);
|
|
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddLightctrl(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
if (dam == 0 && mienemy == MI_ENEMYMONST) UseMana(id, SPL_LIGHTNING); // if not 0 - probably is chain lightning
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
|
|
GetMissileVel(mi,sx,sy,dx,dy,32);
|
|
|
|
missile[mi]._miAnimFrame = random(52, 8) + 1;
|
|
|
|
missile[mi]._mirange = 256;
|
|
}
|
|
|
|
void AddLTArrow(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
app_assert(mi < MAXMISSILES);
|
|
|
|
if ((sx == dx) && (sy == dy)) {
|
|
dx += XDirAdd[midir];
|
|
dy += YDirAdd[midir];
|
|
}
|
|
|
|
GetMissileVel(mi,sx,sy,dx,dy,32);
|
|
missile[mi]._miAnimFrame = random(52, 8) + 1;
|
|
|
|
missile[mi]._mirange = 255;
|
|
|
|
if (id < 0) {
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
} else {
|
|
missile[mi]._miVar1 = plr[id]._px;
|
|
missile[mi]._miVar2 = plr[id]._py;
|
|
}
|
|
|
|
//PutMissile(mi);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddLightning(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_LIGHTNING) || !PRE_BETA
|
|
// Note: midir is used to pass in the missile # of the root of the lightning chain.
|
|
// A negative midir means that this is not part of a chain.
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._misx = dx;
|
|
missile[mi]._misy = dy;
|
|
|
|
if(midir >= 0)
|
|
{
|
|
missile[mi]._mixoff = missile[midir]._mixoff;
|
|
missile[mi]._miyoff = missile[midir]._miyoff;
|
|
missile[mi]._mitxoff = missile[midir]._mitxoff;
|
|
missile[mi]._mityoff = missile[midir]._mityoff;
|
|
}
|
|
|
|
missile[mi]._miAnimFrame = random(52, 8) + 1;
|
|
|
|
if (midir >= 0 && mienemy != MI_ENEMYPLR && id != -1) {
|
|
missile[mi]._mirange = 6 + (missile[mi]._mispllvl >> 1);
|
|
} else {
|
|
if (midir >= 0 && id != -1) {
|
|
missile[mi]._mirange = 10;
|
|
} else missile[mi]._mirange = 8;
|
|
}
|
|
|
|
missile[mi]._mlid = AddLight(missile[mi]._mix, missile[mi]._miy, 4);
|
|
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddMisexp(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
|
|
if (mienemy != MI_ENEMYMONST && id > 0) {
|
|
app_assert(id < MAXMONSTERS);
|
|
app_assert(monster[id].MType != NULL);
|
|
switch (monster[id].MType->mtype)
|
|
{
|
|
case MT_SUCCUBUS:
|
|
SetMissAnim(mi,MF_FLAREXP);
|
|
break;
|
|
case MT_SNOWWICH:
|
|
SetMissAnim(mi,MF_BFLAREXP);
|
|
break;
|
|
case MT_HLSPWN:
|
|
SetMissAnim(mi,MF_DFLAREXP);
|
|
break;
|
|
case MT_SOLBRNR:
|
|
SetMissAnim(mi,MF_CFLAREXP);
|
|
break;
|
|
}
|
|
}
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._mix = missile[dx]._mix;
|
|
missile[mi]._miy = missile[dx]._miy;
|
|
missile[mi]._misx = missile[dx]._misx;
|
|
missile[mi]._misy = missile[dx]._misy;
|
|
missile[mi]._mixoff = missile[dx]._mixoff;
|
|
missile[mi]._miyoff = missile[dx]._miyoff;
|
|
missile[mi]._mitxoff = missile[dx]._mitxoff;
|
|
missile[mi]._mityoff = missile[dx]._mityoff;
|
|
missile[mi]._mixvel = 0;
|
|
missile[mi]._miyvel = 0;
|
|
|
|
missile[mi]._mirange = missile[mi]._miAnimLen;
|
|
missile[mi]._miVar1 = 0;
|
|
|
|
//PutMissile(mi);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddWeapexp(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._mix = sx;
|
|
missile[mi]._miy = sy;
|
|
missile[mi]._misx = sx;
|
|
missile[mi]._misy = sy;
|
|
missile[mi]._mixvel = 0;
|
|
missile[mi]._miyvel = 0;
|
|
missile[mi]._miVar1 = 0;
|
|
missile[mi]._miVar2 = dx;
|
|
|
|
missile[mi]._mimfnum = 0;
|
|
if (dx == 1) SetMissAnim(mi, MF_EXP1);
|
|
else SetMissAnim(mi, MF_CBOLT);
|
|
missile[mi]._mirange = missile[mi]._miAnimLen - 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
BOOL CheckIfTrig(int x, int y)
|
|
{
|
|
int i;
|
|
|
|
app_assert(numtrigs <= MAXTRIGGERS);
|
|
for (i = 0; i < numtrigs; ++i)
|
|
if (((x == trigs[i]._tx) && (y == trigs[i]._ty)) ||
|
|
((abs(trigs[i]._tx-x) < 2) && (abs(trigs[i]._ty-y) < 2))) return(TRUE);
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddTown(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_TOWN) || !PRE_BETA
|
|
int i, pn;
|
|
int k, l, j;
|
|
int tx, ty, mx;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
if (currlevel != 0) {
|
|
missile[mi]._miDelFlag = TRUE;
|
|
for (k = 0; k < 6; ++k) {
|
|
l = CrawlNum[k];
|
|
j = l + 1;
|
|
for (i = CrawlTable[l]; i > 0; --i) {
|
|
tx = dx + CrawlTable[j];
|
|
ty = dy + CrawlTable[(j + 1)];
|
|
if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
pn = dPiece[tx][ty];
|
|
app_assert(pn <= MAXTILES);
|
|
if (((nSolidTable[pn] | dObject[tx][ty] | nMissileTable[pn] |
|
|
dPlayer[tx][ty] | dMissile[tx][ty]) == 0) &&
|
|
(!CheckIfTrig(tx, ty))) {
|
|
missile[mi]._mix = tx;
|
|
missile[mi]._miy = ty;
|
|
missile[mi]._misx = tx;
|
|
missile[mi]._misy = ty;
|
|
missile[mi]._miDelFlag = FALSE;
|
|
k = 6;
|
|
break;
|
|
}
|
|
}
|
|
j += 2;
|
|
}
|
|
}
|
|
} else {
|
|
tx = dx;
|
|
ty = dy;
|
|
missile[mi]._mix = tx;
|
|
missile[mi]._miy = ty;
|
|
missile[mi]._misx = tx;
|
|
missile[mi]._misy = ty;
|
|
missile[mi]._miDelFlag = FALSE;
|
|
}
|
|
|
|
missile[mi]._mirange = 100;
|
|
missile[mi]._miVar1 = missile[mi]._mirange - (missile[mi]._miAnimLen);
|
|
missile[mi]._miVar2 = 0;
|
|
|
|
// Move current portal?
|
|
for (i = 0; i < nummissiles; ++i) {
|
|
mx = missileactive[i];
|
|
if ((missile[mx]._mitype == MIT_TOWN) &&
|
|
(mx != mi) &&
|
|
(missile[mx]._misource == id)) {
|
|
missile[mx]._mirange = 0;
|
|
}
|
|
}
|
|
|
|
PutMissile(mi);
|
|
|
|
if (id == myplr && missile[mi]._miDelFlag == FALSE && currlevel != 0) {
|
|
if (!setlevel) NetSendCmdLocParam3(TRUE, CMD_ACTIVATEPORTAL, tx, ty, currlevel, leveltype, FALSE);
|
|
else NetSendCmdLocParam3(TRUE, CMD_ACTIVATEPORTAL, tx, ty, setlvlnum, leveltype, TRUE);
|
|
}
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddFlash(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_FLASH) || !PRE_BETA
|
|
int i;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
if (mienemy == MI_ENEMYMONST) {
|
|
if (id != -1) {
|
|
missile[mi]._midam = 0;
|
|
for (i = 0; i <= plr[id]._pLevel; ++i) missile[mi]._midam += random(55, 20) + 1;
|
|
for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3);
|
|
missile[mi]._midam += missile[mi]._midam >> 1;
|
|
UseMana(id, SPL_FLASH);
|
|
} else {
|
|
missile[mi]._midam = (currlevel >> 1);
|
|
}
|
|
}
|
|
else
|
|
missile[mi]._midam = monster[id].mLevel << 1;
|
|
|
|
missile[mi]._mirange = 19;
|
|
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddAura(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_FLASH) || !PRE_BETA
|
|
|
|
#if defined(HELLFIRE2)
|
|
app_assert(mi < MAXMISSILES);
|
|
if (mienemy == MI_ENEMYMONST) {
|
|
if (id != -1) {
|
|
missile[mi]._midam = 0;
|
|
missile[mi]._mirange = 245 + (10 * missile[mi]._mispllvl) + (2 * (id > 0) ? plr[id].plrlevel : 1);
|
|
plr[id]._pBaseToBlk += 50;
|
|
UseMana(id, SPL_AURA);
|
|
}
|
|
}
|
|
#endif
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddAura2(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_FLASH) || !PRE_BETA
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
if (mienemy == MI_ENEMYMONST) {
|
|
if (id != -1) {
|
|
missile[mi]._midam = 0;
|
|
missile[mi]._mirange = 245 + (10 * missile[mi]._mispllvl) + (2 * (id > 0) ? plr[id].plrlevel : 1);
|
|
}
|
|
}
|
|
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddFlash2(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_FLASH) || !PRE_BETA
|
|
int i;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
if (mienemy == MI_ENEMYMONST)
|
|
{
|
|
if (id != -1) {
|
|
missile[mi]._midam = 0;
|
|
for (i = 0; i <= plr[id]._pLevel; ++i) missile[mi]._midam += random(56, 2) + 1;
|
|
for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3);
|
|
missile[mi]._midam += missile[mi]._midam >> 1;
|
|
} else {
|
|
missile[mi]._midam = (currlevel >> 1);
|
|
}
|
|
}
|
|
|
|
missile[mi]._miPreFlag = TRUE;
|
|
|
|
missile[mi]._mirange = 19;
|
|
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddManashield(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_MANASHLD) || !PRE_BETA
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._mirange = ((plr[id]._pLevel << 4) << 1) + (plr[id]._pLevel << 4);
|
|
|
|
missile[mi]._miVar1 = plr[id]._pHitPoints;
|
|
missile[mi]._miVar2 = plr[id]._pHPBase;
|
|
|
|
missile[mi]._miVar8 = KILL_UNKNOWN; // killed by unknown source (inited)
|
|
|
|
if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_MANASHLD);
|
|
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddFiremove(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._midam = random(59, 10) + 1 + plr[id]._pLevel;
|
|
|
|
GetMissileVel(mi,sx,sy,dx,dy,16);
|
|
|
|
missile[mi]._mirange = 255;
|
|
missile[mi]._miVar1 = 0;
|
|
missile[mi]._miVar2 = 0;
|
|
|
|
++missile[mi]._mix;
|
|
++missile[mi]._miy;
|
|
missile[mi]._miyoff-=32;
|
|
//PutMissile(mi);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddGuardian(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_GUARDIAN) || !PRE_BETA
|
|
int i, pn;
|
|
int k, l, j;
|
|
int tx, ty;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._midam = random(62, 10) + 1 + (plr[id]._pLevel >> 1);
|
|
for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3);
|
|
|
|
missile[mi]._miDelFlag = TRUE;
|
|
for (k = 0; k < 6; ++k) {
|
|
l = CrawlNum[k];
|
|
j = l + 1;
|
|
for (i = CrawlTable[l]; i > 0; --i) {
|
|
tx = dx + CrawlTable[j];
|
|
ty = dy + CrawlTable[(j + 1)];
|
|
app_assert(tx < MAXDUNX);
|
|
app_assert(ty < MAXDUNY);
|
|
pn = dPiece[tx][ty];
|
|
app_assert(pn <= MAXTILES);
|
|
if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
//if ((dFlags[tx][ty] & BFLAG_VISIBLE) &&
|
|
if ((LineClear(sx, sy, tx, ty)) &&
|
|
((nSolidTable[pn] | dMonster[tx][ty] | dObject[tx][ty] | nMissileTable[pn] | dMissile[tx][ty]) == 0)) {
|
|
missile[mi]._mix = tx;
|
|
missile[mi]._miy = ty;
|
|
missile[mi]._misx = tx;
|
|
missile[mi]._misy = ty;
|
|
missile[mi]._miDelFlag = FALSE;
|
|
UseMana(id, SPL_GUARDIAN);
|
|
k = 6;
|
|
break;
|
|
}
|
|
}
|
|
j += 2;
|
|
}
|
|
}
|
|
|
|
if (missile[mi]._miDelFlag == TRUE) return;
|
|
missile[mi]._misource = id;
|
|
missile[mi]._mlid = AddLight(missile[mi]._mix, missile[mi]._miy, 1);
|
|
|
|
missile[mi]._mirange = (plr[id]._pLevel >> 1) + missile[mi]._mispllvl;
|
|
missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7);
|
|
if (missile[mi]._mirange > 30) missile[mi]._mirange = 30;
|
|
missile[mi]._mirange = missile[mi]._mirange << 4;
|
|
if (missile[mi]._mirange < 30) missile[mi]._mirange = 30;
|
|
|
|
missile[mi]._miVar1 = missile[mi]._mirange - (missile[mi]._miAnimLen);
|
|
missile[mi]._miVar2 = 0;
|
|
missile[mi]._miVar3 = 1;
|
|
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddChain(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_CHAIN) || !PRE_BETA
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miVar1 = dx;
|
|
missile[mi]._miVar2 = dy;
|
|
|
|
missile[mi]._mirange = 1;
|
|
UseMana(id, SPL_CHAIN);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
/*void AddChainOLD(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
int i, k, j, mx;
|
|
|
|
if (dam == 0) {
|
|
k = 0;
|
|
j = -1;
|
|
for (i = 0; i < nummissilevars; ++i) {
|
|
mx = missilevars[i][0];
|
|
if (mx >= 0 && missile[mx]._mitype == MIT_CHAIN && missile[mx]._miVar8 > k) k = missile[mx]._miVar8;
|
|
if (mx < 0) j = i;
|
|
}
|
|
++k;
|
|
missile[mi]._miVar8 = k;
|
|
if (j == -1) {
|
|
++nummissilevars;
|
|
j = nummissilevars;
|
|
}
|
|
missilevars[j][0] = mi;
|
|
missilevars[j][1] = MIT_CHAIN;
|
|
missilevars[j][2] = 0;
|
|
} else {
|
|
for (i = 0; i < nummissilevars; ++i) {
|
|
mx = missilevars[i][0];
|
|
if (mx >= 0 && missile[mx]._mitype == MIT_CHAIN && missile[mx]._miVar8 == dam) missilevars[i][2]++;
|
|
}
|
|
}
|
|
|
|
k = 0;
|
|
missile[mi]._midam = 0;
|
|
for (i = 0; i < nummissiles; ++i) {
|
|
mx = missileactive[i];
|
|
if (missile[mx]._mitype == MIT_CHAIN && missile[mx]._midam > k) k = missile[mx]._midam;
|
|
if (missile[mx]._mitype == MIT_CHAINBALL && missile[mx]._miVar1 > k) k = missile[mx]._miVar1;
|
|
}
|
|
++k;
|
|
missile[mi]._midam = k;
|
|
|
|
missile[mi]._mirange = 12 + GetSpellLevel(id, SPL_LIGHTNING);
|
|
missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7);
|
|
|
|
missile[mi]._miVar1 = 0;
|
|
missile[mi]._miVar2 = 0;
|
|
missile[mi]._miVar3 = 0;
|
|
missile[mi]._miVar4 = 0;
|
|
missile[mi]._miVar5 = dx;
|
|
missile[mi]._miVar6 = dy;
|
|
missile[mi]._miVar7 = 0;
|
|
|
|
UseMana(id, SPL_CHAIN);
|
|
}*/
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
/*void AddChainballOLD(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
int i, mx;
|
|
|
|
missile[mi]._miVar1 = dam;
|
|
missile[mi]._miVar2 = 0;
|
|
missile[mi]._miVar3 = 0;
|
|
missile[mi]._miVar4 = 0;
|
|
|
|
for (i = 0; i < nummissiles; ++i) {
|
|
mx = missileactive[i];
|
|
if ((missile[mx]._mitype == MIT_CHAIN) && (missile[mx]._miVar2 == 1) && (missile[mx]._midam == dam)) {
|
|
missile[mi]._miVar2 = missile[mx]._miVar2;
|
|
missile[mi]._miVar3 = missile[mx]._miVar3;
|
|
missile[mi]._miVar4 = missile[mx]._miVar4;
|
|
}
|
|
if ((missile[mx]._mitype == MIT_CHAIN) && (missile[mx]._midam == dam))
|
|
missile[mi]._miVar8 = missile[mx]._miVar8;
|
|
}
|
|
|
|
if (dMonster[sx][sy] != 0) {
|
|
missile[mi]._miVar5 = sx;
|
|
missile[mi]._miVar6 = sy;
|
|
} else {
|
|
missile[mi]._miVar5 = 0;
|
|
missile[mi]._miVar6 = 0;
|
|
}
|
|
|
|
missile[mi]._midam = (random(61, plr[id]._pLevel) + random(61, 6) + 4) << HP_SHIFT;
|
|
|
|
GetMissileVel(mi, sx, sy, dx, dy, 16);
|
|
|
|
missile[mi]._mirange = ((plr[id]._pLevel << 4) << 1) + (GetSpellLevel(id, SPL_CHAIN) << 4);
|
|
|
|
PutMissile(mi);
|
|
}*/
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddBlood(int mi, int sx, int sy, int str, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
SetMissDir(mi, str);
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._midam = 0;
|
|
|
|
missile[mi]._miLightFlag = TRUE;
|
|
|
|
missile[mi]._mirange = 250;
|
|
//PutMissile(mi);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddBone(int mi, int sx, int sy, int str, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
if (str > 3) str = 2;
|
|
SetMissDir(mi, str);
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._midam = 0;
|
|
|
|
missile[mi]._miLightFlag = TRUE;
|
|
|
|
missile[mi]._mirange = 250;
|
|
//PutMissile(mi);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddMetal(int mi, int sx, int sy, int str, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
if (str > 3) str = 2;
|
|
SetMissDir(mi, str);
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._midam = 0;
|
|
|
|
missile[mi]._miLightFlag = TRUE;
|
|
|
|
missile[mi]._mirange = (missile[mi]._miAnimLen);
|
|
//PutMissile(mi);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddRhino(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
AnimStruct *anim;
|
|
|
|
app_assert(id < MAXMONSTERS);
|
|
app_assert(monster[id].MType != NULL);
|
|
if (EquivMonst(monster[id].MType->mtype, MT_HORNED))
|
|
anim = &monster[id].MType->Anims[MA_SPECIAL];
|
|
else if (EquivMonst(monster[id].MType->mtype, MT_NSNAKE))
|
|
anim = &monster[id].MType->Anims[MA_ATTACK];
|
|
else
|
|
anim = &monster[id].MType->Anims[MA_WALK];
|
|
|
|
GetMissileVel(mi,sx,sy,dx,dy,18);
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._mimfnum = midir;
|
|
missile[mi]._miAnimFlags = NULL;
|
|
missile[mi]._miAnimData = anim->Cels[midir];
|
|
missile[mi]._miAnimDelay = anim->Rate;
|
|
missile[mi]._miAnimLen = anim->Frames;
|
|
missile[mi]._miAnimWidth = monster[id].MType->mAnimWidth;
|
|
missile[mi]._miAnimWidth2 = monster[id].MType->mAnimWidth2;
|
|
missile[mi]._miAnimAdd = 1;
|
|
if (EquivMonst(monster[id].MType->mtype, MT_NSNAKE))
|
|
missile[mi]._miAnimFrame = 7;
|
|
|
|
missile[mi]._miVar1 = 0;
|
|
missile[mi]._miVar2 = 0;
|
|
|
|
missile[mi]._miLightFlag = TRUE;
|
|
if(monster[id]._uniqtype) {
|
|
missile[mi]._miUniqTrans = monster[id]._uniqtrans+1;
|
|
missile[mi]._mlid = monster[id].mlid;
|
|
}
|
|
|
|
missile[mi]._mirange = 256;
|
|
|
|
PutMissile(mi);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddFireman(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
AnimStruct *anim;
|
|
|
|
app_assert(id < MAXMONSTERS);
|
|
app_assert(monster[id].MType != NULL);
|
|
anim = &monster[id].MType->Anims[MA_WALK];
|
|
|
|
GetMissileVel(mi,sx,sy,dx,dy,16);
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._mimfnum = midir;
|
|
missile[mi]._miAnimFlags = NULL;
|
|
missile[mi]._miAnimData = anim->Cels[midir];
|
|
missile[mi]._miAnimDelay = anim->Rate;
|
|
missile[mi]._miAnimLen = anim->Frames;
|
|
missile[mi]._miAnimWidth = monster[id].MType->mAnimWidth;
|
|
missile[mi]._miAnimWidth2 = monster[id].MType->mAnimWidth2;
|
|
missile[mi]._miAnimAdd = 1;
|
|
|
|
missile[mi]._miVar1 = 0;
|
|
missile[mi]._miVar2 = 0;
|
|
|
|
missile[mi]._miLightFlag = TRUE;
|
|
if(monster[id]._uniqtype)
|
|
missile[mi]._miUniqTrans = monster[id]._uniqtrans+1;
|
|
|
|
dMonster[monster[id]._mx][monster[id]._my] = 0;
|
|
|
|
missile[mi]._mirange = 256;
|
|
|
|
PutMissile(mi);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddFlare(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
int d;
|
|
|
|
if ((sx == dx) && (sy == dy)) {
|
|
dx += XDirAdd[midir];
|
|
dy += YDirAdd[midir];
|
|
}
|
|
|
|
GetMissileVel(mi,sx,sy,dx,dy,16);
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._mirange = 256;
|
|
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
missile[mi]._mlid = AddLight(sx, sy, 8);
|
|
|
|
if (mienemy == MI_ENEMYMONST) {
|
|
UseMana(id, SPL_BSTAR);
|
|
d = 5;
|
|
//for (k = missile[mi]._mispllvl; k > 0; --k) d -= 1;
|
|
//if (d <= 0) d = 1;
|
|
#if CHEATS
|
|
if (simplecheat || cheatflag) d = 0;
|
|
#endif
|
|
|
|
plr[id]._pHitPoints -= (d << HP_SHIFT);
|
|
plr[id]._pHPBase -= (d << HP_SHIFT);
|
|
drawhpflag = TRUE;
|
|
|
|
if (plr[id]._pHitPoints <= 0) {
|
|
// rjs - manashld fix? - plr[id]._pHitPoints = 0;
|
|
StartPlrKill(id, FALSE);
|
|
}
|
|
} else {
|
|
if (id > 0) {
|
|
if (monster[id].MType->mtype == MT_SUCCUBUS) SetMissAnim(mi,MF_FLARE);
|
|
if (monster[id].MType->mtype == MT_SNOWWICH) SetMissAnim(mi,MF_BFLARE);
|
|
if (monster[id].MType->mtype == MT_HLSPWN) SetMissAnim(mi,MF_DFLARE);
|
|
if (monster[id].MType->mtype == MT_SOLBRNR) SetMissAnim(mi,MF_CFLARE);
|
|
}
|
|
}
|
|
|
|
//PutMissile(mi);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddAcid(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
GetMissileVel(mi,sx,sy,dx,dy,16);
|
|
|
|
SetMissDir(mi, GetDirection16(sx,sy,dx,dy));
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._mirange = 15 + 5*(monster[id]._mint+1);
|
|
missile[mi]._mlid = -1;
|
|
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
|
|
PutMissile(mi);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
/*void AddDoom(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
int i, j, k, l;
|
|
int mid;
|
|
|
|
// search in a 5 radius around tile clicked for monster
|
|
for (k = 0; k < 6; ++k) {
|
|
l = CrawlNum[k];
|
|
j = l + 1;
|
|
for (i = CrawlTable[l]; i > 0; --i) {
|
|
mid = dMonster[(dx + CrawlTable[j])][(dy + CrawlTable[(j + 1)])];
|
|
if (mid != 0) {
|
|
if (mid > 0) --mid;
|
|
else mid = -(mid + 1);
|
|
if ((monster[mid]._mhitpoints >> HP_SHIFT) > 0) {
|
|
missile[mi]._miVar1 = dx + CrawlTable[j];
|
|
missile[mi]._miVar2 = dy + CrawlTable[j + 1];
|
|
missile[mi]._miVar3 = mid;
|
|
i = -99;
|
|
k = 6;
|
|
break;
|
|
}
|
|
}
|
|
j += 2;
|
|
}
|
|
}
|
|
|
|
// if no monsters found in search
|
|
if (i != -99) {
|
|
missile[mi]._miDelFlag = TRUE;
|
|
return;
|
|
}
|
|
|
|
GetMissileVel(mi, sx, sy, missile[mi]._miVar1, missile[mi]._miVar2, 16);
|
|
SetMissDir(mi, GetDirection(sx, sy, missile[mi]._miVar1, missile[mi]._miVar2));
|
|
|
|
missile[mi]._mix = sx;
|
|
missile[mi]._miy = sy;
|
|
missile[mi]._misx = sx;
|
|
missile[mi]._misy = sy;
|
|
missile[mi]._misource = id;
|
|
missile[mi]._midam = 26;
|
|
|
|
missile[mi]._mirange = ((plr[id]._pLevel << 4) >> 2) + (plr[id]._pLevel << 4) ;
|
|
for (i = GetSpellLevel(id, SPL_DOOM); i > 0; --i) missile[mi]._mirange += ((missile[mi]._mirange << 4) >> 3);
|
|
missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7);
|
|
|
|
UseMana(id, SPL_DOOM);
|
|
PutMissile(mi);
|
|
}*/
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddFireonly(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._midam = dam;
|
|
missile[mi]._mixvel = 0;
|
|
missile[mi]._miyvel = 0;
|
|
|
|
missile[mi]._mirange = 50;
|
|
missile[mi]._miVar1 = missile[mi]._mirange - missile[mi]._miAnimLen;
|
|
missile[mi]._miVar2 = 0;
|
|
|
|
//PutMissile(mi);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddAcidpud(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
int monst;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._mixvel = 0;
|
|
missile[mi]._miyvel = 0;
|
|
|
|
missile[mi]._mixoff = 0;
|
|
missile[mi]._miyoff = 0;
|
|
/*
|
|
missile[mi]._misx = missile[dx]._misx;
|
|
missile[mi]._misy = missile[dx]._misy;
|
|
missile[mi]._mixoff = missile[dx]._mixoff;
|
|
missile[mi]._miyoff = missile[dx]._miyoff;
|
|
missile[mi]._mitxoff = missile[dx]._mitxoff;
|
|
missile[mi]._mityoff = missile[dx]._mityoff;
|
|
*/
|
|
|
|
missile[mi]._miLightFlag = TRUE;
|
|
|
|
// MoveMissilePos(mi);
|
|
|
|
monst = missile[mi]._misource;
|
|
missile[mi]._mirange = random(50,15) + 40*(monster[monst]._mint + 1);
|
|
|
|
missile[mi]._miPreFlag = TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddStone(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_STONE) || !PRE_BETA
|
|
int i, j, k, l, tx, ty;
|
|
int mid;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._misource = id;
|
|
|
|
// search in a 5 radius around tile clicked for monster
|
|
for (k = 0; k < 6; ++k) {
|
|
l = CrawlNum[k];
|
|
j = l + 1;
|
|
for (i = CrawlTable[l]; i > 0; --i) {
|
|
tx = dx + CrawlTable[j];
|
|
ty = dy + CrawlTable[(j + 1)];
|
|
if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
mid = dMonster[tx][ty];
|
|
if (mid > 0) --mid;
|
|
else mid = -(mid + 1);
|
|
if ((mid > 3)
|
|
&& (monster[mid]._mAi != AI_DIABLO)
|
|
&& (monster[mid]._mmode != MM_FADEIN)
|
|
&& (monster[mid]._mmode != MM_FADEOUT)
|
|
//&& (monster[mid]._mmode != MM_DEATH)
|
|
&& (monster[mid]._mmode != MM_MISSILE)) {
|
|
i = -99;
|
|
k = 6;
|
|
missile[mi]._miVar1 = monster[mid]._mmode;
|
|
missile[mi]._miVar2 = mid;
|
|
monster[mid]._mmode = MM_STONE;
|
|
break;
|
|
}
|
|
}
|
|
j += 2;
|
|
}
|
|
}
|
|
|
|
// if no monsters found in search
|
|
if (i != -99) {
|
|
missile[mi]._miDelFlag = TRUE;
|
|
return;
|
|
}
|
|
|
|
missile[mi]._mix = tx;
|
|
missile[mi]._miy = ty;
|
|
missile[mi]._misx = missile[mi]._mix;
|
|
missile[mi]._misy = missile[mi]._miy;
|
|
|
|
missile[mi]._mirange = 6 + missile[mi]._mispllvl;
|
|
//if (missile[mi]._mirange == 0) missile[mi]._mirange = 1;
|
|
//for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._mirange += (missile[mi]._mirange >> 3);
|
|
missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7);
|
|
if (missile[mi]._mirange > 15) missile[mi]._mirange = 15;
|
|
missile[mi]._mirange = missile[mi]._mirange << 4;
|
|
UseMana(id, SPL_STONE);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
/*void AddInvis(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
int i;
|
|
|
|
missile[mi]._mirange = plr[id]._pLevel << 4;
|
|
for (i = GetSpellLevel(id, SPL_INVIS); i > 0; --i) missile[mi]._mirange += ((missile[mi]._mirange << 4) >> 3);
|
|
missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7);
|
|
UseMana(id, SPL_INVIS);
|
|
missile[mi]._miDelFlag = TRUE;
|
|
}*/
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddGolem(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_GOLEM) || !PRE_BETA
|
|
int i, mx;
|
|
//int tx, ty, k, j, l;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
|
|
missile[mi]._miDelFlag = FALSE;
|
|
for (i = 0; i < nummissiles; ++i) {
|
|
mx = missileactive[i];
|
|
if ((missile[mx]._mitype == MIT_GOLEM) && (mx != mi) &&
|
|
(missile[mx]._misource == id)) {
|
|
missile[mi]._miDelFlag = TRUE;
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*for (k = 0; k < 6; ++k) {
|
|
l = CrawlNum[k];
|
|
j = l + 1;
|
|
for (i = CrawlTable[l]; i > 0; --i) {
|
|
tx = dx + CrawlTable[j];
|
|
ty = dy + CrawlTable[(j + 1)];
|
|
if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
pn = dPiece[tx][ty];
|
|
if ((LineClear(sx, sy, tx, ty)) &&
|
|
((nSolidTable[pn] | dMonster[tx][ty] | dObject[tx][ty]) == 0)) {*/
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
missile[mi]._miVar4 = dx;
|
|
missile[mi]._miVar5 = dy;
|
|
if ((monster[id]._mx != 1 || monster[id]._my != 0) && (id == myplr)) M_StartKill(id, id);
|
|
//missile[mi]._miDelFlag = FALSE;
|
|
UseMana(id, SPL_GOLEM);
|
|
/*k = 6;
|
|
break;
|
|
}
|
|
}
|
|
j += 2;
|
|
}
|
|
}*/
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddEther(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_ETHER) || !PRE_BETA
|
|
int i;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._mirange = (plr[id]._pLevel << 4) >> 1;
|
|
for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._mirange += (missile[mi]._mirange >> 3);
|
|
missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7);
|
|
|
|
missile[mi]._miVar1 = plr[id]._pHitPoints;
|
|
missile[mi]._miVar2 = plr[id]._pHPBase;
|
|
|
|
if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_ETHER);
|
|
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddBloodR(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_BLOODR) || !PRE_BETA
|
|
int manaval;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miDelFlag = TRUE;
|
|
return; // spell deleted - left code here just in case
|
|
|
|
if (!(plr[id]._pIFlags & IAF_LMANA)) {
|
|
plr[id]._pHitPoints -= (10 << HP_SHIFT);
|
|
plr[id]._pHPBase -= (10 << HP_SHIFT);
|
|
|
|
manaval = ((missile[mi]._mispllvl + 8) << MANA_SHIFT);
|
|
plr[id]._pMana += manaval;
|
|
plr[id]._pManaBase += manaval;
|
|
|
|
if (plr[id]._pMana > plr[id]._pMaxMana) plr[id]._pMana = plr[id]._pMaxMana;
|
|
if (plr[id]._pManaBase > plr[id]._pMaxManaBase) plr[id]._pManaBase = plr[id]._pMaxManaBase;
|
|
|
|
if (plr[id]._pHitPoints <= 0) {
|
|
// rjs - manashld fix? - plr[id]._pHitPoints = 0;
|
|
StartPlrKill(id, FALSE);
|
|
}
|
|
}
|
|
|
|
UseMana(id, SPL_BLOODR);
|
|
drawhpflag = TRUE;
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddSpurt(int mi, int sx, int sy, int str, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._midam = dam;
|
|
missile[mi]._mix = sx;
|
|
missile[mi]._miy = sy;
|
|
missile[mi]._misx = sx;
|
|
missile[mi]._misy = sy;
|
|
missile[mi]._misource = id;
|
|
|
|
if (dam == 1)
|
|
SetMissDir(mi, 0);
|
|
else
|
|
SetMissDir(mi, 1);
|
|
|
|
missile[mi]._miLightFlag = TRUE;
|
|
|
|
missile[mi]._mirange = missile[mi]._miAnimLen;
|
|
//PutMissile(mi);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddBoom(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._mix = dx;
|
|
missile[mi]._miy = dy;
|
|
missile[mi]._misx = dx;
|
|
missile[mi]._misy = dy;
|
|
missile[mi]._mixvel = 0;
|
|
missile[mi]._miyvel = 0;
|
|
missile[mi]._midam = dam;
|
|
|
|
missile[mi]._mirange = missile[mi]._miAnimLen;
|
|
missile[mi]._miVar1 = 0;
|
|
|
|
//PutMissile(mi);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddHeal(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_HEAL) || !PRE_BETA
|
|
int i;
|
|
long l;
|
|
|
|
l = (random(57, 10) + 1) << HP_SHIFT;
|
|
for (i = 0; i < plr[id]._pLevel; ++i) l += ((random(57, 4) + 1) << HP_SHIFT);
|
|
app_assert(mi < MAXMISSILES);
|
|
for (i = 0; i < missile[mi]._mispllvl; ++i) l += ((random(57, 6) + 1) << HP_SHIFT);
|
|
if (plr[id]._pClass == CLASS_WARRIOR) l = l << 1;
|
|
if (plr[id]._pClass == CLASS_ROGUE) l += (l >> 1);
|
|
plr[id]._pHitPoints += l;
|
|
if (plr[id]._pHitPoints > plr[id]._pMaxHP) plr[id]._pHitPoints = plr[id]._pMaxHP;
|
|
plr[id]._pHPBase += l;
|
|
if (plr[id]._pHPBase > plr[id]._pMaxHPBase) plr[id]._pHPBase = plr[id]._pMaxHPBase;
|
|
|
|
UseMana(id, SPL_HEAL);
|
|
drawhpflag = TRUE;
|
|
|
|
missile[mi]._miDelFlag = TRUE;
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddMana(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_HEAL) || !PRE_BETA
|
|
int i;
|
|
long l;
|
|
|
|
l = (random(57, 10) + 1) << MANA_SHIFT;
|
|
for (i = 0; i < plr[id]._pLevel; ++i) l += ((random(57, 4) + 1) << MANA_SHIFT);
|
|
app_assert(mi < MAXMISSILES);
|
|
for (i = 0; i < missile[mi]._mispllvl; ++i) l += ((random(57, 6) + 1) << MANA_SHIFT);
|
|
if (plr[id]._pClass == CLASS_SORCEROR) l = l << 1;
|
|
if (plr[id]._pClass == CLASS_ROGUE) l += (l >> 1);
|
|
|
|
plr[id]._pMana += l;
|
|
if (plr[id]._pMana > plr[id]._pMaxMana) plr[id]._pMana = plr[id]._pMaxMana;
|
|
plr[id]._pManaBase += l;
|
|
if (plr[id]._pManaBase > plr[id]._pMaxManaBase) plr[id]._pManaBase = plr[id]._pMaxManaBase;
|
|
|
|
UseMana(id, SPL_MANA);
|
|
drawmanaflag = TRUE;
|
|
|
|
missile[mi]._miDelFlag = TRUE;
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
void AddFMana(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_HEAL) || !PRE_BETA
|
|
app_assert(mi < MAXMISSILES);
|
|
plr[id]._pMana = plr[id]._pMaxMana;
|
|
plr[id]._pManaBase = plr[id]._pMaxManaBase;
|
|
UseMana(id, SPL_FMANA);
|
|
drawmanaflag = TRUE;
|
|
#endif
|
|
missile[mi]._miDelFlag = TRUE;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddHealOther(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_HEALOTHER) || !PRE_BETA
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miDelFlag = TRUE;
|
|
UseMana(id, SPL_HEALOTHER);
|
|
if (id == myplr) {
|
|
NewCursor(HEALOTHER_CURS);
|
|
}
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddElement(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_ELEMENT) || !PRE_BETA
|
|
int i;
|
|
|
|
if ((sx == dx) && (sy == dy)) {
|
|
dx += XDirAdd[midir];
|
|
dy += YDirAdd[midir];
|
|
}
|
|
|
|
//missile[mi]._midam = 0;
|
|
//for (i = 0; i < plr[id]._pLevel; ++i) missile[mi]._midam += random(67, 6) + 1;
|
|
//for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3);
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._midam = (random(60, 10) + random(60, 10) + 2 + plr[id]._pLevel) << 1;
|
|
for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3);
|
|
missile[mi]._midam = missile[mi]._midam >> 1;
|
|
|
|
GetMissileVel(mi, sx, sy, dx, dy, 16);
|
|
SetMissDir(mi, GetDirection8(sx, sy, dx, dy));
|
|
|
|
missile[mi]._mirange = 256;
|
|
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
missile[mi]._miVar3 = 0;
|
|
missile[mi]._miVar4 = dx;
|
|
missile[mi]._miVar5 = dy;
|
|
|
|
missile[mi]._mlid = AddLight(sx, sy, 8);
|
|
|
|
UseMana(id, SPL_ELEMENT);
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddIdentify(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_IDENTIFY) || !PRE_BETA
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miDelFlag = TRUE;
|
|
UseMana(id, SPL_IDENTIFY);
|
|
if (id == myplr) {
|
|
if (sbookflag) sbookflag = FALSE;
|
|
if (!invflag) invflag = TRUE;
|
|
NewCursor(IDENTIFY_CURS);
|
|
}
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddFirewallC(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_WALL) || !PRE_BETA
|
|
int i, pn;
|
|
int k, l, j;
|
|
int tx, ty;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miDelFlag = TRUE;
|
|
for (k = 0; k < 6; ++k) {
|
|
l = CrawlNum[k];
|
|
j = l + 1;
|
|
for (i = CrawlTable[l]; i > 0; --i) {
|
|
tx = dx + CrawlTable[j];
|
|
ty = dy + CrawlTable[(j + 1)];
|
|
if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
pn = dPiece[tx][ty];
|
|
//if ((dFlags[tx][ty] & BFLAG_VISIBLE) && ((sx != tx) || (sy != ty)) &&
|
|
if ((LineClear(sx, sy, tx, ty)) && ((sx != tx) || (sy != ty)) &&
|
|
((nSolidTable[pn] | dObject[tx][ty]) == 0)) {
|
|
missile[mi]._miVar1 = tx;
|
|
missile[mi]._miVar2 = ty;
|
|
missile[mi]._miVar5 = tx;
|
|
missile[mi]._miVar6 = ty;
|
|
missile[mi]._miDelFlag = FALSE;
|
|
k = 6;
|
|
break;
|
|
}
|
|
}
|
|
j += 2;
|
|
}
|
|
}
|
|
|
|
if (missile[mi]._miDelFlag == TRUE) return;
|
|
|
|
missile[mi]._miVar7 = 0;
|
|
missile[mi]._miVar8 = 0;
|
|
|
|
//midir = GetDirection(sx, sy, tx, ty);
|
|
missile[mi]._miVar3 = (midir - 2) & 0x0007;
|
|
missile[mi]._miVar4 = (midir + 2) & 0x0007;
|
|
|
|
missile[mi]._mirange = 7;
|
|
UseMana(id, SPL_WALL);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddFlameBox(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_WALL) || !PRE_BETA
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miDelFlag = TRUE;
|
|
|
|
if (mienemy == MI_ENEMYMONST){
|
|
UseMana(id, SPL_RINGOFFIRE);
|
|
}
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
missile[mi]._miDelFlag = FALSE;
|
|
|
|
missile[mi]._miVar3 = 0;
|
|
missile[mi]._miVar4 = 0;
|
|
missile[mi]._miVar5 = 0;
|
|
missile[mi]._miVar6 = 0;
|
|
missile[mi]._miVar7 = 0;
|
|
missile[mi]._miVar8 = 0;
|
|
|
|
missile[mi]._mirange = 7;
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddShowMagicItems(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_WALL) || !PRE_BETA
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miDelFlag = FALSE;
|
|
|
|
missile[mi]._miVar1 = 0;
|
|
missile[mi]._miVar2 = 0;
|
|
missile[mi]._miVar3 = 0;
|
|
missile[mi]._miVar4 = 0;
|
|
missile[mi]._miVar5 = 0;
|
|
missile[mi]._miVar6 = 0;
|
|
missile[mi]._miVar7 = 0;
|
|
missile[mi]._miVar8 = 0;
|
|
|
|
HighLightAllItems = true;
|
|
missile[mi]._mirange = 245 + (10 * missile[mi]._mispllvl) + (2 * (id > 0) ? plr[id].plrlevel : 1);
|
|
if (mienemy == MI_ENEMYMONST){
|
|
UseMana(id, SPL_SHOWMAGITEMS);
|
|
}
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddInfra(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_INFRA) || !PRE_BETA
|
|
int i;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._mirange = 99 << 4;
|
|
for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._mirange += (missile[mi]._mirange >> 3);
|
|
missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7);
|
|
|
|
if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_INFRA);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddWave(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_WAVE) || !PRE_BETA
|
|
missile[mi]._miVar1 = dx;
|
|
missile[mi]._miVar2 = dy;
|
|
missile[mi]._miVar3 = 0;
|
|
missile[mi]._miVar4 = 0;
|
|
missile[mi]._mirange = 1;
|
|
missile[mi]._miAnimFrame = 4;
|
|
UseMana(id, SPL_WAVE);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddNova(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_NOVA) || !PRE_BETA
|
|
int k;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miVar1 = dx;
|
|
missile[mi]._miVar2 = dy;
|
|
if (id != -1) {
|
|
missile[mi]._midam = random(66, 6) + random(66, 6) + random(66, 6) + random(66, 6) + random(66, 6);
|
|
missile[mi]._midam += 5 + plr[id]._pLevel;
|
|
missile[mi]._midam = missile[mi]._midam >> 1;
|
|
for (k = missile[mi]._mispllvl; k > 0; --k) missile[mi]._midam += (missile[mi]._midam >> 3);
|
|
if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_NOVA);
|
|
} else {
|
|
missile[mi]._midam = random(66, 3) + random(66, 3) + random(66, 3);
|
|
missile[mi]._midam += (currlevel >> 1);
|
|
}
|
|
missile[mi]._mirange = 1;
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddBoil(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
// not in game
|
|
missile[mi]._miDelFlag = TRUE;
|
|
return;
|
|
/*
|
|
#if (PRE_BETA && PRE_BLOODB) || !PRE_BETA
|
|
missile[mi]._miVar1 = dx;
|
|
missile[mi]._miVar2 = dy;
|
|
missile[mi]._mirange = 1;
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif*/
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddRepair(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_REPAIR) || !PRE_BETA
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miDelFlag = TRUE;
|
|
UseMana(id, SPL_REPAIR);
|
|
if (id == myplr) {
|
|
if (sbookflag) sbookflag = FALSE;
|
|
if (!invflag) invflag = TRUE;
|
|
NewCursor(REPAIR_CURS);
|
|
}
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddRecharge(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_RECHARGE) || !PRE_BETA
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miDelFlag = TRUE;
|
|
UseMana(id, SPL_RECHARGE);
|
|
if (id == myplr) {
|
|
if (sbookflag) sbookflag = FALSE;
|
|
if (!invflag) invflag = TRUE;
|
|
NewCursor(RECHARGE_CURS);
|
|
}
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddDisarm(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_DISARM) || !PRE_BETA
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miDelFlag = TRUE;
|
|
UseMana(id, SPL_DISARM);
|
|
if (id == myplr) {
|
|
NewCursor(DISARM_CURS);
|
|
}
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddApoca(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_APOCA) || !PRE_BETA
|
|
int i;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miVar1 = 8;
|
|
missile[mi]._miVar2 = sy - missile[mi]._miVar1;
|
|
missile[mi]._miVar3 = sy + missile[mi]._miVar1;
|
|
missile[mi]._miVar4 = sx - missile[mi]._miVar1;
|
|
missile[mi]._miVar5 = sx + missile[mi]._miVar1;
|
|
missile[mi]._miVar6 = missile[mi]._miVar4;
|
|
|
|
if (missile[mi]._miVar2 <= 0) missile[mi]._miVar2 = 1;
|
|
if (missile[mi]._miVar3 >= MAXDUNY) missile[mi]._miVar3 = MAXDUNY - 1;
|
|
if (missile[mi]._miVar4 <= 0) missile[mi]._miVar4 = 1;
|
|
if (missile[mi]._miVar5 >= MAXDUNX) missile[mi]._miVar5 = MAXDUNX - 1;
|
|
|
|
for (i = 0; i < plr[id]._pLevel; ++i) missile[mi]._midam += random(67, 6) + 1;
|
|
|
|
missile[mi]._mirange = 255;
|
|
missile[mi]._miDelFlag = FALSE;
|
|
UseMana(id, SPL_APOCA);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddFlame(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int seqno)
|
|
{
|
|
#if (PRE_BETA && PRE_FLAME) || !PRE_BETA
|
|
// seqno: the number of flame chunk for this spell instance
|
|
int i;
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miVar2 = 0;
|
|
//for (i = 0; i < 2 - seqno; ++i) {
|
|
for (i = seqno; i > 0; --i) {
|
|
missile[mi]._miVar2 += 5;
|
|
}
|
|
|
|
missile[mi]._misx = dx;
|
|
missile[mi]._misy = dy;
|
|
|
|
missile[mi]._mixoff = missile[midir]._mixoff;
|
|
missile[mi]._miyoff = missile[midir]._miyoff;
|
|
missile[mi]._mitxoff = missile[midir]._mitxoff;
|
|
missile[mi]._mityoff = missile[midir]._mityoff;
|
|
missile[mi]._mirange = 20 + missile[mi]._miVar2;
|
|
missile[mi]._mlid = AddLight(sx, sy, 1);
|
|
|
|
if (mienemy == MI_ENEMYMONST) {
|
|
missile[mi]._midam = (random(79, plr[id]._pLevel) + random(79, 2) + 2) << 3;
|
|
missile[mi]._midam += missile[mi]._midam >> 1;
|
|
//missile[mi]._midam = plr[id]._pLevel << 2;
|
|
//for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3);
|
|
//missile[mi]._midam = missile[mi]._midam << 1 + missile[mi]._midam;
|
|
} else {
|
|
missile[mi]._midam = random(77, monster[id].mMaxDamage - monster[id].mMinDamage + 1) + monster[id].mMinDamage;
|
|
}
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddFlamec(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_FLAME) || !PRE_BETA
|
|
//int k;
|
|
//int tsx, tsy;
|
|
|
|
if ((sx == dx) && (sy == dy)) {
|
|
dx += XDirAdd[midir];
|
|
dy += YDirAdd[midir];
|
|
}
|
|
|
|
GetMissileVel(mi, sx, sy, dx, dy, 32);
|
|
if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_FLAME);
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
missile[mi]._miVar3 = 0;
|
|
missile[mi]._mirange = 256;
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddCbolt(int mi, int sx, int sy, int dx, int dy, int midir, char micaster, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_CBOLT) || !PRE_BETA
|
|
app_assert(mi < MAXMISSILES);
|
|
if (micaster == MI_ENEMYMONST)
|
|
{
|
|
if (id == myplr) {
|
|
missile[mi]._mirnd = random(63, 15) + 1;
|
|
// INSERT send seed code
|
|
} else {
|
|
// INSERT get seed from network message for syncing
|
|
// used as a number idx not a seed so no SetRndSeed necessary
|
|
missile[mi]._mirnd = random(63, 15) + 1;
|
|
}
|
|
missile[mi]._midam = random(68, plr[id]._pMagic >> 2) + 1;
|
|
//for (i = missile[mi]._mispllvl; i > 0; --i) ++missile[mi]._midam;
|
|
}
|
|
else
|
|
{
|
|
missile[mi]._mirnd = random(63, 15) + 1;
|
|
missile[mi]._midam = 15;
|
|
}
|
|
|
|
if ((sx == dx) && (sy == dy)) {
|
|
dx += XDirAdd[midir];
|
|
dy += YDirAdd[midir];
|
|
}
|
|
|
|
missile[mi]._miAnimFrame = random(63, 8) + 1;
|
|
missile[mi]._mlid = AddLight(sx, sy, 5);
|
|
GetMissileVel(mi, sx, sy, dx, dy, 8);
|
|
|
|
missile[mi]._miVar1 = 5;
|
|
missile[mi]._miVar2 = midir;
|
|
missile[mi]._miVar3 = 0;
|
|
|
|
missile[mi]._mirange = 256;
|
|
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
void AddCBArrow(int mi, int sx, int sy, int dx, int dy, int midir, char micaster, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_CBOLT) || !PRE_BETA
|
|
app_assert(mi < MAXMISSILES);
|
|
if (micaster == MI_ENEMYMONST)
|
|
{
|
|
if (id == myplr) {
|
|
missile[mi]._mirnd = random(63, 15) + 1;
|
|
// INSERT send seed code
|
|
} else {
|
|
// INSERT get seed from network message for syncing
|
|
// used as a number idx not a seed so no SetRndSeed necessary
|
|
missile[mi]._mirnd = random(63, 15) + 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
missile[mi]._mirnd = random(63, 15) + 1;
|
|
missile[mi]._midam = 15;
|
|
}
|
|
|
|
if ((sx == dx) && (sy == dy)) {
|
|
dx += XDirAdd[midir];
|
|
dy += YDirAdd[midir];
|
|
}
|
|
|
|
missile[mi]._miAnimFrame = random(63, 8) + 1;
|
|
missile[mi]._mlid = AddLight(sx, sy, 5);
|
|
GetMissileVel(mi, sx, sy, dx, dy, 8);
|
|
|
|
missile[mi]._miVar1 = 5;
|
|
missile[mi]._miVar2 = midir;
|
|
missile[mi]._miVar3 = 0;
|
|
|
|
missile[mi]._mirange = 256;
|
|
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddHbolt(int mi, int sx, int sy, int dx, int dy, int midir, char micaster, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_HBOLT) || !PRE_BETA
|
|
int sp;
|
|
|
|
if ((sx == dx) && (sy == dy)) {
|
|
dx += XDirAdd[midir];
|
|
dy += YDirAdd[midir];
|
|
}
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
if (id != -1) {
|
|
sp = 16 + (missile[mi]._mispllvl << 1);
|
|
if (sp >= 63) sp = 63;
|
|
} else sp = 16;
|
|
|
|
GetMissileVel(mi, sx, sy, dx, dy, sp);
|
|
SetMissDir(mi, GetDirection16(sx, sy, dx, dy));
|
|
|
|
missile[mi]._mirange = 256;
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
missile[mi]._mlid = AddLight(sx, sy, 8);
|
|
missile[mi]._midam = random(69, 10) + 9 + plr[id]._pLevel;
|
|
|
|
UseMana(id, SPL_HBOLT);
|
|
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
void AddHBArrow(int mi, int sx, int sy, int dx, int dy, int midir, char micaster, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_HBOLT) || !PRE_BETA
|
|
int sp;
|
|
|
|
if ((sx == dx) && (sy == dy)) {
|
|
dx += XDirAdd[midir];
|
|
dy += YDirAdd[midir];
|
|
}
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
if (id != -1) {
|
|
sp = 16 + (missile[mi]._mispllvl << 1);
|
|
if (sp >= 63) sp = 63;
|
|
} else sp = 16;
|
|
|
|
GetMissileVel(mi, sx, sy, dx, dy, sp);
|
|
SetMissDir(mi, GetDirection16(sx, sy, dx, dy));
|
|
|
|
missile[mi]._mirange = 256;
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
missile[mi]._mlid = AddLight(sx, sy, 8);
|
|
|
|
//PutMissile(mi);
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddResurrect(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_RESURRECT) || !PRE_BETA
|
|
UseMana(id, SPL_RESURRECT);
|
|
if (id == myplr) {
|
|
NewCursor(RESURRECT_CURS);
|
|
}
|
|
#endif
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miDelFlag = TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddResurrectBeam(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_RESURRECT) || !PRE_BETA
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._mix = dx;
|
|
missile[mi]._miy = dy;
|
|
missile[mi]._misx = missile[mi]._mix;
|
|
missile[mi]._misy = missile[mi]._miy;
|
|
missile[mi]._mixvel = 0;
|
|
missile[mi]._miyvel = 0;
|
|
missile[mi]._mirange = misfiledata[MF_RESURRECT].mAnimLen[0];
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddTelekinesis(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_TELEKINESIS) || !PRE_BETA
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miDelFlag = TRUE;
|
|
UseMana(id, SPL_TELEKINESIS);
|
|
if (id == myplr) {
|
|
NewCursor(TELE_CURS);
|
|
}
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
/*void AddBoneSpirit(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
int d, mid, mx, my;
|
|
|
|
if ((sx == dx) && (sy == dy)) {
|
|
dx += XDirAdd[midir];
|
|
dy += YDirAdd[midir];
|
|
}
|
|
|
|
GetMissileVel(mi, sx, sy, dx, dy, 16);
|
|
|
|
missile[mi]._mirange = 256;
|
|
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
missile[mi]._mlid = AddLight(sx, sy, 8);
|
|
|
|
if (mienemy == MI_ENEMYMONST) {
|
|
UseMana(id, SPL_BONESPIRIT);
|
|
d = 6;
|
|
|
|
#if CHEATS
|
|
if (simplecheat || cheatflag) d = 0;
|
|
#endif
|
|
|
|
plr[id]._pHitPoints -= (d << HP_SHIFT);
|
|
plr[id]._pHPBase -= (d << HP_SHIFT);
|
|
drawhpflag = TRUE;
|
|
|
|
if (plr[id]._pHitPoints <= 0) {
|
|
// rjs - manashld fix? - plr[id]._pHitPoints = 0;
|
|
StartPlrKill(id, FALSE);
|
|
}
|
|
|
|
if (dPlayer[dx][dy] != 0) {
|
|
missile[mi]._miVar6 = 1;
|
|
if (dPlayer[dx][dy] > 0) mid = dPlayer[dx][dy] - 1;
|
|
else mid = -(dPlayer[dx][dy] + 1);
|
|
mx = plr[mid]._px;
|
|
my = plr[mid]._py;
|
|
} else {
|
|
missile[mi]._miVar6 = 0;
|
|
if (dMonster[dx][dy] <= 0) mid = FindClosest(sx, sy, 19);
|
|
else mid = dMonster[dx][dy] - 1;
|
|
mx = monster[mid]._mx;
|
|
my = monster[mid]._my;
|
|
}
|
|
|
|
if (mid > 0) {
|
|
missile[mi]._miVar3 = mid;
|
|
GetMissileVel(mi, sx, sy, mx, my, 16);
|
|
SetMissDir(mi, GetDirection8(sx, sy, mx, my));
|
|
}
|
|
}
|
|
|
|
PutMissile(mi);
|
|
}
|
|
|
|
*/
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddBoneSpirit(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
#if (PRE_BETA && PRE_BONESPIRIT) || !PRE_BETA
|
|
int d;
|
|
|
|
if ((sx == dx) && (sy == dy)) {
|
|
dx += XDirAdd[midir];
|
|
dy += YDirAdd[midir];
|
|
}
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._midam = 0;
|
|
|
|
GetMissileVel(mi, sx, sy, dx, dy, 16);
|
|
SetMissDir(mi, GetDirection8(sx, sy, dx, dy));
|
|
|
|
missile[mi]._mirange = 256;
|
|
|
|
missile[mi]._miVar1 = sx;
|
|
missile[mi]._miVar2 = sy;
|
|
missile[mi]._miVar3 = 0;
|
|
missile[mi]._miVar4 = dx;
|
|
missile[mi]._miVar5 = dy;
|
|
|
|
missile[mi]._mlid = AddLight(sx, sy, 8);
|
|
|
|
if (mienemy == MI_ENEMYMONST) {
|
|
UseMana(id, SPL_BONESPIRIT);
|
|
d = 6;
|
|
#if CHEATS
|
|
if (simplecheat || cheatflag) d = 0;
|
|
#endif
|
|
plr[id]._pHitPoints -= (d << HP_SHIFT);
|
|
plr[id]._pHPBase -= (d << HP_SHIFT);
|
|
drawhpflag = TRUE;
|
|
|
|
if (plr[id]._pHitPoints <= 0) {
|
|
// rjs - manashld fix? - plr[id]._pHitPoints = 0;
|
|
StartPlrKill(id, FALSE);
|
|
}
|
|
|
|
}
|
|
#else
|
|
missile[mi]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddRportal(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._mix = sx;
|
|
missile[mi]._miy = sy;
|
|
missile[mi]._misx = sx;
|
|
missile[mi]._misy = sy;
|
|
|
|
missile[mi]._mirange = 100;
|
|
missile[mi]._miVar1 = missile[mi]._mirange - (missile[mi]._miAnimLen);
|
|
missile[mi]._miVar2 = 0;
|
|
|
|
PutMissile(mi);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddDiabApoca(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
|
|
{
|
|
BOOL LineClear(int x1, int y1, int x2, int y2);
|
|
int pnum;
|
|
|
|
for (pnum = 0; pnum < gbMaxPlayers; ++pnum)
|
|
{
|
|
if (plr[pnum].plractive
|
|
&& LineClear(sx,sy,plr[pnum]._pfutx, plr[pnum]._pfuty))
|
|
AddMissile(0, 0, plr[pnum]._pfutx, plr[pnum]._pfuty, 0, MIT_FIREPLAR, mienemy, id, dam, 0);
|
|
}
|
|
app_assert(mi < MAXMISSILES);
|
|
missile[mi]._miDelFlag = TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int AddMissile(int sx, int sy, int v1, int v2, int midir, int mitype, char micaster, int id, int v3, int spllvl)
|
|
{
|
|
// v1 and v2 are usually dx and dy (this can be different per missile)
|
|
// v3 is usually damage amount
|
|
|
|
int mi;
|
|
|
|
// check if exceeded number of missiles
|
|
if (nummissiles >= MAXMISSILES)
|
|
return -1;
|
|
|
|
// get next missile id that is available
|
|
mi = missileavail[0];
|
|
missileavail[0] = missileavail[MAXMISSILES - nummissiles - 1];
|
|
missileactive[nummissiles] = mi;
|
|
++nummissiles;
|
|
|
|
// Zero out the data first.
|
|
memset(&missile[mi], 0, sizeof(MissileStruct));
|
|
|
|
// do some standard missile setups
|
|
missile[mi]._mitype = mitype;
|
|
missile[mi]._micaster = micaster;
|
|
missile[mi]._misource = id;
|
|
missile[mi]._miAnimType = missiledata[mitype].mFileNum;
|
|
missile[mi]._miDrawFlag = missiledata[mitype].mDraw;
|
|
|
|
missile[mi]._mispllvl = spllvl;
|
|
|
|
missile[mi]._mimfnum = midir;
|
|
if (missile[mi]._miAnimType != MF_NONE
|
|
&& misfiledata[(missile[mi]._miAnimType)].mAnimFAmt >= 8)
|
|
SetMissDir(mi, midir);
|
|
else
|
|
SetMissDir(mi, 0);
|
|
|
|
missile[mi]._mix = sx;
|
|
missile[mi]._miy = sy;
|
|
missile[mi]._mixoff = 0;
|
|
missile[mi]._miyoff = 0;
|
|
missile[mi]._misx = sx;
|
|
missile[mi]._misy = sy;
|
|
missile[mi]._mitxoff = 0;
|
|
missile[mi]._mityoff = 0;
|
|
|
|
missile[mi]._miDelFlag = FALSE;
|
|
missile[mi]._miAnimAdd = 1;
|
|
|
|
missile[mi]._miLightFlag = FALSE;
|
|
missile[mi]._miPreFlag = FALSE;
|
|
missile[mi]._miUniqTrans = FALSE;
|
|
missile[mi]._midam = v3;
|
|
missile[mi]._miHitFlag = FALSE;
|
|
missile[mi]._midist = 0;
|
|
missile[mi]._mlid = -1;
|
|
missile[mi]._mirnd = 0;
|
|
|
|
if (missiledata[mitype].mlSFX != -1)
|
|
PlaySfxLoc(missiledata[mitype].mlSFX, missile[mi]._mix, missile[mi]._miy);
|
|
|
|
missiledata[mitype].mAddProc(mi, sx, sy, v1, v2, midir, micaster, id, v3);
|
|
|
|
return mi;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
/*int ChainBounceOLD (int i, int sx, int sy)
|
|
{
|
|
int j, mi, mx, dir;
|
|
|
|
if (dMonster[sx][sy] != 0) {
|
|
|
|
if (dMonster[sx][sy] > 0) mi = dMonster[sx][sy] - 1;
|
|
else mi = -(dMonster[sx][sy] + 1);
|
|
|
|
if ((monster[mi]._mhitpoints >> HP_SHIFT) > 0) {
|
|
for (j = 0; j < nummissilevars; ++j) {
|
|
mx = missilevars[j][0];
|
|
if ((mx >= 0) && (missile[mx]._mitype == MIT_CHAIN) && (missile[mx]._miVar8 == missile[i]._miVar8) &&
|
|
(missilevars[j][2] >= (plr[(missile[i]._misource)]._pLevel >> 1))) {
|
|
missilevars[j][0] = -1;
|
|
return 3;
|
|
}
|
|
}
|
|
dir = GetDirection(missile[i]._mix, missile[i]._miy, sx, sy);
|
|
AddMissile(missile[i]._mix, missile[i]._miy, sx, sy, dir, MIT_CHAIN, MI_ENEMYMONST, missile[i]._misource, missile[i]._miVar8);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}*/
|
|
|
|
extern BOOL LineClear(int x1, int y1, int x2, int y2);
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
int Sentfire(int i, int sx, int sy)
|
|
{
|
|
int ex, dir;
|
|
|
|
ex = 0;
|
|
app_assert(i < MAXMISSILES);
|
|
if (LineClear(missile[i]._mix, missile[i]._miy, sx, sy)
|
|
&& (dMonster[sx][sy] > 0)
|
|
&& ((monster[(dMonster[sx][sy] - 1)]._mhitpoints >> HP_SHIFT) > 0)
|
|
&& ((dMonster[sx][sy]-1) > 3)) {
|
|
dir = GetDirection(missile[i]._mix, missile[i]._miy, sx, sy);
|
|
missile[i]._miVar3 = missileavail[0]; // get next mid
|
|
AddMissile(missile[i]._mix, missile[i]._miy, sx, sy, dir, MIT_FIREBOLT, MI_ENEMYMONST, missile[i]._misource, missile[i]._midam, GetSpellLevel(missile[i]._misource, SPL_FIREBOLT));
|
|
ex = -1;
|
|
}
|
|
|
|
if (ex == -1) {
|
|
SetMissDir(i, 2);
|
|
missile[i]._miVar2 = 3;
|
|
}
|
|
|
|
return (ex);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Dummy(int i)
|
|
{}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Rune(int i)
|
|
{
|
|
int const tx = missile[i]._mix;
|
|
int const ty = missile[i]._miy;
|
|
int mid = dMonster[tx][ty];
|
|
int pid = dPlayer[tx][ty];
|
|
|
|
if (mid != 0
|
|
|| pid != 0) {
|
|
|
|
int dir;
|
|
|
|
if (mid != 0) {
|
|
if (mid > 0) --mid;
|
|
else mid = -(mid + 1);
|
|
|
|
dir = GetDirection(missile[i]._mixoff, missile[i]._miyoff,
|
|
monster[mid]._mxoff, monster[mid]._myoff);
|
|
}
|
|
else {
|
|
if (pid > 0) --pid;
|
|
else pid = -(pid + 1);
|
|
|
|
dir = GetDirection(missile[i]._mixoff, missile[i]._miyoff,
|
|
plr[pid]._pxoff, plr[pid]._pyoff);
|
|
}
|
|
if (missile[i]._miVar1 == MIT_MISEXP){
|
|
AddMissile(tx, ty, i, 0, dir, missile[i]._miVar1, MI_ENEMYMONST, missile[i]._misource, missile[i]._midam, missile[i]._mispllvl);
|
|
}
|
|
else {
|
|
AddMissile(tx, ty, tx, ty, dir, missile[i]._miVar1, MI_ENEMYMONST, missile[i]._misource, missile[i]._midam, missile[i]._mispllvl);
|
|
}
|
|
missile[i]._miDelFlag = TRUE;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Golem(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_GOLEM) || !PRE_BETA
|
|
int id, pn;
|
|
int j, k, l, m;
|
|
int tx, ty;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
id = missile[i]._misource;
|
|
|
|
if (monster[id]._mx == 1 && monster[id]._my == 0) {
|
|
for (k = 0; k < 6; ++k) {
|
|
l = CrawlNum[k];
|
|
j = l + 1;
|
|
for (m = CrawlTable[l]; m > 0; --m) {
|
|
tx = missile[i]._miVar4 + CrawlTable[j];
|
|
ty = missile[i]._miVar5 + CrawlTable[(j + 1)];
|
|
if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
pn = dPiece[tx][ty];
|
|
if ((LineClear(missile[i]._miVar1, missile[i]._miVar2, tx, ty)) &&
|
|
((nSolidTable[pn] | dMonster[tx][ty] | dObject[tx][ty]) == 0)) {
|
|
k = 6;
|
|
SpawnGolum(id, tx, ty, i);
|
|
break;
|
|
}
|
|
}
|
|
j += 2;
|
|
}
|
|
}
|
|
}
|
|
missile[i]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_SetManashield(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_MANASHLD) || !PRE_BETA
|
|
ManashieldFlag = 1;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_LArrow(int i)
|
|
{
|
|
int p, mind, maxd, rst;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
p = missile[i]._misource;
|
|
if (missile[i]._miAnimType != MF_CBOLT && missile[i]._miAnimType != MF_EXP1) {
|
|
++missile[i]._midist;
|
|
missile[i]._mitxoff += missile[i]._mixvel;
|
|
missile[i]._mityoff += missile[i]._miyvel;
|
|
GetMissilePos(i);
|
|
if (p != -1) {
|
|
if (missile[i]._micaster == MI_ENEMYMONST) {
|
|
mind = plr[p]._pIMinDam;
|
|
maxd = plr[p]._pIMaxDam;
|
|
} else {
|
|
mind = monster[p].mMinDamage;
|
|
maxd = monster[p].mMaxDamage;
|
|
}
|
|
} else {
|
|
mind = currlevel + random(68, 10) + 1;
|
|
maxd = (currlevel * 2) + random(68, 10) + 1;
|
|
}
|
|
if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy)) {
|
|
rst = missiledata[(missile[i]._mitype)].mResist;
|
|
missiledata[(missile[i]._mitype)].mResist = MIMT_NONE;
|
|
CheckMissileCol(i, mind, maxd, 0, missile[i]._mix, missile[i]._miy, 0);
|
|
missiledata[(missile[i]._mitype)].mResist = rst;
|
|
}
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._mimfnum = 0;
|
|
missile[i]._mitxoff -= missile[i]._mixvel;
|
|
missile[i]._mityoff -= missile[i]._miyvel;
|
|
GetMissilePos(i);
|
|
if (missile[i]._mitype == MIT_LARROW) {
|
|
SetMissAnim(i, MF_CBOLT);
|
|
missile[i]._mirange = missile[i]._miAnimLen - 1;
|
|
} else {
|
|
SetMissAnim(i, MF_EXP1);
|
|
missile[i]._mirange = missile[i]._miAnimLen - 1;
|
|
}
|
|
} else {
|
|
if ((missile[i]._mix != missile[i]._miVar1) || (missile[i]._miy != missile[i]._miVar2)) {
|
|
missile[i]._miVar1 = missile[i]._mix;
|
|
missile[i]._miVar2 = missile[i]._miy;
|
|
ChangeLight(missile[i]._mlid, missile[i]._miVar1, missile[i]._miVar2, 5);
|
|
}
|
|
}
|
|
} else {
|
|
ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, 5 + missile[i]._miAnimFrame);
|
|
rst = missiledata[(missile[i]._mitype)].mResist;
|
|
// drb.patch1.start.02/25/97
|
|
if (missile[i]._mitype == MIT_LARROW) {
|
|
if (p != -1) {
|
|
mind = plr[p]._pILMinDam;
|
|
maxd = plr[p]._pILMaxDam;
|
|
} else {
|
|
mind = currlevel + random(68, 10) + 1;
|
|
maxd = (currlevel * 2) + random(68, 10) + 1;
|
|
}
|
|
missiledata[MIT_LARROW].mResist = MIMT_LGHT;
|
|
CheckMissileCol(i, mind, maxd, 0, missile[i]._mix, missile[i]._miy, 1);
|
|
}
|
|
if (missile[i]._mitype == MIT_FARROW) {
|
|
if (p != -1) {
|
|
mind = plr[p]._pIFMinDam;
|
|
maxd = plr[p]._pIFMaxDam;
|
|
} else {
|
|
mind = currlevel + random(68, 10) + 1;
|
|
maxd = (currlevel * 2) + random(68, 10) + 1;
|
|
}
|
|
missiledata[MIT_FARROW].mResist = MIMT_FIRE;
|
|
CheckMissileCol(i, mind, maxd, 0, missile[i]._mix, missile[i]._miy, 1);
|
|
}
|
|
// endpatch1.2/25/97
|
|
missiledata[(missile[i]._mitype)].mResist = rst;
|
|
}
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
AddUnLight(missile[i]._mlid);
|
|
}
|
|
|
|
PutMissile(i);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Arrow(int i)
|
|
{
|
|
int p, mind, maxd;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
++missile[i]._midist;
|
|
missile[i]._mitxoff += missile[i]._mixvel;
|
|
missile[i]._mityoff += missile[i]._miyvel;
|
|
GetMissilePos(i);
|
|
p = missile[i]._misource;
|
|
if (p != -1) {
|
|
if (missile[i]._micaster == MI_ENEMYMONST) {
|
|
mind = plr[p]._pIMinDam;
|
|
maxd = plr[p]._pIMaxDam;
|
|
} else {
|
|
mind = monster[p].mMinDamage;
|
|
maxd = monster[p].mMaxDamage;
|
|
}
|
|
} else {
|
|
mind = currlevel;
|
|
maxd = currlevel * 2;
|
|
}
|
|
if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy))
|
|
CheckMissileCol(i, mind, maxd, 0, missile[i]._mix, missile[i]._miy, 0);
|
|
if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
|
|
PutMissile(i);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Firebolt(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_FIREBOLT) || !PRE_BETA
|
|
int omx, omy, d, p;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
|
|
if (missile[i]._mitype == MIT_BONESPIRIT && missile[i]._mimfnum == 8) {
|
|
if (missile[i]._mirange == 0) {
|
|
if(missile[i]._mlid >= 0) AddUnLight(missile[i]._mlid);
|
|
missile[i]._miDelFlag = TRUE;
|
|
PlaySfxLoc(LS_BSIMPCT, missile[i]._mix, missile[i]._miy);
|
|
}
|
|
PutMissile(i);
|
|
return;
|
|
}
|
|
|
|
omx = missile[i]._mitxoff;
|
|
omy = missile[i]._mityoff;
|
|
|
|
missile[i]._mitxoff += missile[i]._mixvel;
|
|
missile[i]._mityoff += missile[i]._miyvel;
|
|
GetMissilePos(i);
|
|
|
|
p = missile[i]._misource;
|
|
if (p != -1) {
|
|
if (missile[i]._micaster == MI_ENEMYMONST) {
|
|
switch(missile[i]._mitype) {
|
|
case MIT_FLARE:
|
|
d = ((plr[p]._pMagic>>1)-(plr[p]._pMagic>>3)) + (missile[i]._mispllvl << 1) + missile[i]._mispllvl;
|
|
break;
|
|
case MIT_FIREBOLT:
|
|
d = random(75, 10) + 1 + (plr[p]._pMagic >> 3) + missile[i]._mispllvl;
|
|
break;
|
|
case MIT_BONESPIRIT:
|
|
//d = (monster[missile[i]._miVar3]._mhitpoints >> HP_SHIFT) >> 1;
|
|
d = 0;
|
|
break;
|
|
}
|
|
} else d = (random(77, monster[p].mMaxDamage - monster[p].mMinDamage + 1) + monster[p].mMinDamage);
|
|
} else d = random(78, currlevel << 1) + currlevel;
|
|
|
|
if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy))
|
|
CheckMissileCol(i, d, d, 0, missile[i]._mix, missile[i]._miy, 0);
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
missile[i]._mitxoff = omx;
|
|
missile[i]._mityoff = omy;
|
|
GetMissilePos(i);
|
|
switch(missile[i]._mitype) {
|
|
case MIT_FLARE:
|
|
AddMissile(missile[i]._mix, missile[i]._miy, i, 0, missile[i]._mimfnum, MIT_FLAREXP, missile[i]._micaster, missile[i]._misource, 0, 0);
|
|
break;
|
|
case MIT_FIREBOLT:
|
|
case MIT_MAGMABALL:
|
|
AddMissile(missile[i]._mix, missile[i]._miy, i, 0, missile[i]._mimfnum, MIT_MISEXP, missile[i]._micaster, missile[i]._misource, 0, 0);
|
|
break;
|
|
case MIT_ACID:
|
|
AddMissile(missile[i]._mix, missile[i]._miy, i, 0, missile[i]._mimfnum, MIT_ACIDSPLAT, missile[i]._micaster, missile[i]._misource, 0, 0);
|
|
break;
|
|
case MIT_BONESPIRIT:
|
|
SetMissDir(i, 8);
|
|
missile[i]._mirange = 7;
|
|
missile[i]._miDelFlag = FALSE;
|
|
PutMissile(i);
|
|
return;
|
|
}
|
|
if(missile[i]._mlid >= 0) AddUnLight(missile[i]._mlid);
|
|
} else {
|
|
if ((missile[i]._mix != missile[i]._miVar1) || (missile[i]._miy != missile[i]._miVar2)) {
|
|
missile[i]._miVar1 = missile[i]._mix;
|
|
missile[i]._miVar2 = missile[i]._miy;
|
|
if(missile[i]._mlid >= 0) ChangeLight(missile[i]._mlid, missile[i]._miVar1, missile[i]._miVar2, 8);
|
|
}
|
|
}
|
|
|
|
PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Lightball(int i)
|
|
{
|
|
int j, tx, ty, oi;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
tx = missile[i]._miVar1;
|
|
ty = missile[i]._miVar2;
|
|
|
|
--missile[i]._mirange;
|
|
missile[i]._mitxoff += missile[i]._mixvel;
|
|
missile[i]._mityoff += missile[i]._miyvel;
|
|
|
|
GetMissilePos(i);
|
|
j = missile[i]._mirange;
|
|
CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 0, missile[i]._mix, missile[i]._miy, 0);
|
|
if (missile[i]._miHitFlag == TRUE) missile[i]._mirange = j;
|
|
|
|
// fix for shires and fireing nova - rjs
|
|
if (dObject[tx][ty] != 0 && tx == missile[i]._mix && ty == missile[i]._miy) {
|
|
if (dObject[tx][ty] > 0) oi = dObject[tx][ty] - 1;
|
|
else oi = -(dObject[tx][ty] + 1);
|
|
if (object[oi]._otype == OBJ_SHRINEL || object[oi]._otype == OBJ_SHRINER) missile[i]._mirange = j;
|
|
}
|
|
|
|
if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
|
|
PutMissile(i);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Krull(int i)
|
|
{
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
missile[i]._mitxoff += missile[i]._mixvel;
|
|
missile[i]._mityoff += missile[i]._miyvel;
|
|
|
|
GetMissilePos(i);
|
|
CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 0, missile[i]._mix, missile[i]._miy, 0);
|
|
|
|
if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
|
|
PutMissile(i);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Acidpud(int i)
|
|
{
|
|
int range;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
|
|
// GetMissilePos(i);
|
|
range = missile[i]._mirange;
|
|
CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 0);
|
|
missile[i]._mirange = range; // CheckMissileCol clears range if there's a collision,
|
|
// but this missile sticks around even after a collision
|
|
|
|
// MoveMissilePos(i);
|
|
|
|
if (missile[i]._mirange == 0)
|
|
{
|
|
if(missile[i]._mimfnum)
|
|
missile[i]._miDelFlag = TRUE;
|
|
else
|
|
{
|
|
SetMissDir(i, 1);
|
|
missile[i]._mirange = missile[i]._miAnimLen;
|
|
}
|
|
}
|
|
|
|
PutMissile(i);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Firewall(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_WALL) || !PRE_BETA
|
|
int ExpLight[14] = {2,3,4,5,5,6,7,8,9,10,11,12,12};
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
|
|
if (missile[i]._mirange == missile[i]._miVar1) {
|
|
SetMissDir(i, 1);
|
|
missile[i]._miAnimFrame = random(83, 11) + 1;
|
|
}
|
|
|
|
if (missile[i]._mirange == missile[i]._miAnimLen - 1) {
|
|
SetMissDir(i, 0);
|
|
missile[i]._miAnimFrame = 13;
|
|
missile[i]._miAnimAdd = -1;
|
|
}
|
|
|
|
CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 1);
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
AddUnLight(missile[i]._mlid);
|
|
}
|
|
|
|
if ((missile[i]._mimfnum != 0) && (missile[i]._mirange != 0) &&
|
|
(missile[i]._miAnimAdd != -1) && (missile[i]._miVar2 < 12)) {
|
|
|
|
if (missile[i]._miVar2 == 0)
|
|
missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]);
|
|
ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]);
|
|
++missile[i]._miVar2;
|
|
}
|
|
|
|
PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Fireball(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA
|
|
int dam, px, py, id, mx, my;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
id = missile[i]._misource;
|
|
dam = missile[i]._midam;
|
|
|
|
//dam = missile[i]._mispllvl; // rjs test
|
|
//missiledata[(missile[i]._mitype)].mResist = MIMT_NONE;
|
|
|
|
--missile[i]._mirange;
|
|
|
|
if (missile[i]._micaster == MI_ENEMYMONST) {
|
|
px = plr[id]._px;
|
|
py = plr[id]._py;
|
|
} else {
|
|
px = monster[id]._mx;
|
|
py = monster[id]._my;
|
|
}
|
|
|
|
if (missile[i]._miAnimType == MF_BIGEXP) {
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
AddUnLight(missile[i]._mlid);
|
|
}
|
|
|
|
PutMissile(i);
|
|
return;
|
|
}
|
|
|
|
missile[i]._mitxoff += missile[i]._mixvel;
|
|
missile[i]._mityoff += missile[i]._miyvel;
|
|
GetMissilePos(i);
|
|
|
|
if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy))
|
|
CheckMissileCol(i, dam, dam, 0, missile[i]._mix, missile[i]._miy, 0);
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
mx = missile[i]._mix;
|
|
my = missile[i]._miy;
|
|
|
|
ChangeLight(missile[i]._mlid, mx, my, missile[i]._miAnimFrame);
|
|
|
|
if (CheckBlock(px, py, mx , my ) == 0) CheckMissileCol(i, dam, dam, 0, mx, my, 1);
|
|
if (CheckBlock(px, py, mx , my + 1) == 0) CheckMissileCol(i, dam, dam, 0, mx, my + 1, 1);
|
|
if (CheckBlock(px, py, mx , my - 1) == 0) CheckMissileCol(i, dam, dam, 0, mx, my - 1, 1);
|
|
if (CheckBlock(px, py, mx + 1, my ) == 0) CheckMissileCol(i, dam, dam, 0, mx + 1, my, 1);
|
|
if (CheckBlock(px, py, mx + 1, my - 1) == 0) CheckMissileCol(i, dam, dam, 0, mx + 1, my - 1, 1);
|
|
if (CheckBlock(px, py, mx + 1, my + 1) == 0) CheckMissileCol(i, dam, dam, 0, mx + 1, my + 1, 1);
|
|
if (CheckBlock(px, py, mx - 1, my ) == 0) CheckMissileCol(i, dam, dam, 0, mx - 1, my, 1);
|
|
if (CheckBlock(px, py, mx - 1, my + 1) == 0) CheckMissileCol(i, dam, dam, 0, mx - 1, my + 1, 1);
|
|
if (CheckBlock(px, py, mx - 1, my - 1) == 0) CheckMissileCol(i, dam, dam, 0, mx - 1, my - 1, 1);
|
|
|
|
//++missile[i]._mix;
|
|
//++missile[i]._miy;
|
|
//missile[i]._miyoff -= 32;
|
|
|
|
if ((!TransList[dTransVal[mx][my]]) ||
|
|
((missile[i]._mixvel < 0) &&
|
|
((TransList[dTransVal[mx][my+1]] && nSolidTable[dPiece[mx][my+1]]) ||
|
|
(TransList[dTransVal[mx][my-1]] && nSolidTable[dPiece[mx][my-1]])))) {
|
|
++missile[i]._mix;
|
|
++missile[i]._miy;
|
|
missile[i]._miyoff -= 32;
|
|
}
|
|
|
|
if (((missile[i]._miyvel > 0) &&
|
|
((TransList[dTransVal[mx+1][my]] && nSolidTable[dPiece[mx+1][my]]) ||
|
|
(TransList[dTransVal[mx-1][my]] && nSolidTable[dPiece[mx-1][my]])))) {
|
|
missile[i]._miyoff -= 32;
|
|
}
|
|
|
|
if (((missile[i]._mixvel > 0) &&
|
|
((TransList[dTransVal[mx][my+1]] && nSolidTable[dPiece[mx][my+1]]) ||
|
|
(TransList[dTransVal[mx][my-1]] && nSolidTable[dPiece[mx][my-1]])))) {
|
|
missile[i]._mixoff -= 32;
|
|
}
|
|
|
|
missile[i]._mimfnum = 0;
|
|
SetMissAnim(i, MF_BIGEXP);
|
|
missile[i]._mirange = missile[i]._miAnimLen - 1;
|
|
|
|
} else {
|
|
if ((missile[i]._mix != missile[i]._miVar1) || (missile[i]._miy != missile[i]._miVar2)) {
|
|
missile[i]._miVar1 = missile[i]._mix;
|
|
missile[i]._miVar2 = missile[i]._miy;
|
|
ChangeLight(missile[i]._mlid, missile[i]._miVar1, missile[i]._miVar2, 8);
|
|
}
|
|
}
|
|
|
|
PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
// Doesn't work yet. GWP
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_SpiralFireBall(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA
|
|
int px, py, mx, my;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
int const id = missile[i]._misource;
|
|
int const dam = missile[i]._midam;
|
|
|
|
|
|
int xcurve;
|
|
int ycurve;
|
|
|
|
// Set the direction into a spiral.
|
|
if (missile[i]._miVar7 < 0) {
|
|
missile[i]._miVar6 *= 2;
|
|
missile[i]._miVar7 = missile[i]._miVar6;
|
|
|
|
--missile[i]._mimfnum;
|
|
if (missile[i]._mimfnum < 0)
|
|
missile[i]._mimfnum = 7;
|
|
}
|
|
else --missile[i]._miVar7;
|
|
|
|
switch (missile[i]._mimfnum) {
|
|
case 0: // Down
|
|
xcurve = missile[i]._mixvel;
|
|
ycurve = 0;
|
|
break;
|
|
case 1: // Down left
|
|
xcurve = missile[i]._mixvel;
|
|
ycurve = missile[i]._miyvel;
|
|
break;
|
|
case 2: // Left
|
|
xcurve = 0;
|
|
ycurve = missile[i]._miyvel;
|
|
break;
|
|
case 3: // Up Left
|
|
xcurve = missile[i]._mixvel;
|
|
ycurve = missile[i]._miyvel;
|
|
break;
|
|
case 4: // Up
|
|
xcurve = missile[i]._mixvel;
|
|
ycurve = 0;
|
|
break;
|
|
case 5: // Up right
|
|
xcurve = missile[i]._mixvel;
|
|
ycurve = missile[i]._miyvel;
|
|
break;
|
|
case 6: // Right
|
|
xcurve = 0;
|
|
ycurve = missile[i]._miyvel;
|
|
break;
|
|
case 7: // Down Right
|
|
xcurve = missile[i]._mixvel;
|
|
ycurve = missile[i]._miyvel;
|
|
break;
|
|
}
|
|
|
|
|
|
--missile[i]._mirange;
|
|
|
|
if (missile[i]._micaster == MI_ENEMYMONST) {
|
|
px = plr[id]._px;
|
|
py = plr[id]._py;
|
|
} else {
|
|
px = monster[id]._mx;
|
|
py = monster[id]._my;
|
|
}
|
|
|
|
if (missile[i]._miAnimType == MF_BIGEXP) {
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
AddUnLight(missile[i]._mlid);
|
|
}
|
|
|
|
PutMissile(i);
|
|
return;
|
|
}
|
|
|
|
missile[i]._mitxoff += xcurve;
|
|
missile[i]._mityoff += ycurve;
|
|
GetMissilePos(i);
|
|
|
|
if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy))
|
|
CheckMissileCol(i, dam, dam, 0, missile[i]._mix, missile[i]._miy, 0);
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
mx = missile[i]._mix;
|
|
my = missile[i]._miy;
|
|
|
|
ChangeLight(missile[i]._mlid, mx, my, missile[i]._miAnimFrame);
|
|
|
|
if (CheckBlock(px, py, mx , my ) == 0) CheckMissileCol(i, dam, dam, 0, mx, my, 1);
|
|
if (CheckBlock(px, py, mx , my + 1) == 0) CheckMissileCol(i, dam, dam, 0, mx, my + 1, 1);
|
|
if (CheckBlock(px, py, mx , my - 1) == 0) CheckMissileCol(i, dam, dam, 0, mx, my - 1, 1);
|
|
if (CheckBlock(px, py, mx + 1, my ) == 0) CheckMissileCol(i, dam, dam, 0, mx + 1, my, 1);
|
|
if (CheckBlock(px, py, mx + 1, my - 1) == 0) CheckMissileCol(i, dam, dam, 0, mx + 1, my - 1, 1);
|
|
if (CheckBlock(px, py, mx + 1, my + 1) == 0) CheckMissileCol(i, dam, dam, 0, mx + 1, my + 1, 1);
|
|
if (CheckBlock(px, py, mx - 1, my ) == 0) CheckMissileCol(i, dam, dam, 0, mx - 1, my, 1);
|
|
if (CheckBlock(px, py, mx - 1, my + 1) == 0) CheckMissileCol(i, dam, dam, 0, mx - 1, my + 1, 1);
|
|
if (CheckBlock(px, py, mx - 1, my - 1) == 0) CheckMissileCol(i, dam, dam, 0, mx - 1, my - 1, 1);
|
|
|
|
//++missile[i]._mix;
|
|
//++missile[i]._miy;
|
|
//missile[i]._miyoff -= 32;
|
|
|
|
if ((!TransList[dTransVal[mx][my]]) ||
|
|
((missile[i]._mixvel < 0) &&
|
|
((TransList[dTransVal[mx][my+1]] && nSolidTable[dPiece[mx][my+1]]) ||
|
|
(TransList[dTransVal[mx][my-1]] && nSolidTable[dPiece[mx][my-1]])))) {
|
|
++missile[i]._mix;
|
|
++missile[i]._miy;
|
|
missile[i]._miyoff -= 32;
|
|
}
|
|
|
|
if (((missile[i]._miyvel > 0) &&
|
|
((TransList[dTransVal[mx+1][my]] && nSolidTable[dPiece[mx+1][my]]) ||
|
|
(TransList[dTransVal[mx-1][my]] && nSolidTable[dPiece[mx-1][my]])))) {
|
|
missile[i]._miyoff -= 32;
|
|
}
|
|
|
|
if (((missile[i]._mixvel > 0) &&
|
|
((TransList[dTransVal[mx][my+1]] && nSolidTable[dPiece[mx][my+1]]) ||
|
|
(TransList[dTransVal[mx][my-1]] && nSolidTable[dPiece[mx][my-1]])))) {
|
|
missile[i]._mixoff -= 32;
|
|
}
|
|
|
|
missile[i]._mimfnum = 0;
|
|
SetMissAnim(i, MF_BIGEXP);
|
|
missile[i]._mirange = missile[i]._miAnimLen - 1;
|
|
|
|
} else {
|
|
if ((missile[i]._mix != missile[i]._miVar1) || (missile[i]._miy != missile[i]._miVar2)) {
|
|
missile[i]._miVar1 = missile[i]._mix;
|
|
missile[i]._miVar2 = missile[i]._miy;
|
|
ChangeLight(missile[i]._mlid, missile[i]._miVar1, missile[i]._miVar2, 8);
|
|
}
|
|
}
|
|
|
|
PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Lightctrl(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_LIGHTNING) || !PRE_BETA
|
|
int pn, dam, p, mx, my;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
dam = 0;
|
|
|
|
p = missile[i]._misource;
|
|
if (p != -1) {
|
|
if (missile[i]._micaster == MI_ENEMYMONST) {
|
|
dam = random(79, plr[p]._pLevel) + random(79, 2) + 2;
|
|
dam = dam << HP_SHIFT;
|
|
} else {
|
|
dam = (random(80, monster[p].mMaxDamage - monster[p].mMinDamage + 1) + monster[p].mMinDamage) << 1;
|
|
}
|
|
} else {
|
|
dam = random(81, currlevel) + (currlevel << 1);
|
|
}
|
|
|
|
missile[i]._mitxoff += missile[i]._mixvel;
|
|
missile[i]._mityoff += missile[i]._miyvel;
|
|
GetMissilePos(i);
|
|
mx = missile[i]._mix;
|
|
my = missile[i]._miy;
|
|
|
|
app_assert(mx < MAXDUNX);
|
|
app_assert(my < MAXDUNY);
|
|
pn = dPiece[mx][my];
|
|
app_assert(pn <= MAXTILES);
|
|
if (missile[i]._misource == -1) {
|
|
if ((mx != missile[i]._misx) || (my != missile[i]._misy))
|
|
if (nMissileTable[pn]) missile[i]._mirange = 0;
|
|
} else {
|
|
if (nMissileTable[pn]) missile[i]._mirange = 0;
|
|
}
|
|
|
|
if ((!nMissileTable[pn]) && ((mx != missile[i]._miVar1) || (my != missile[i]._miVar2)) &&
|
|
(mx > 0) && (my > 0) && (mx < DMAXX) && (my < DMAXY)) {
|
|
// Add LIGHTNING if the player or trap threw this, otherwise add THINLIGHT for thin demon
|
|
if (missile[i]._misource != -1) {
|
|
if (missile[i]._micaster == MI_ENEMYPLR && EquivMonst(monster[missile[i]._misource].MType->mtype, MT_STORM))
|
|
AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_THINLIGHT, missile[i]._micaster, missile[i]._misource, dam, missile[i]._mispllvl);
|
|
else
|
|
AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_LIGHTNING, missile[i]._micaster, missile[i]._misource, dam, missile[i]._mispllvl);
|
|
} else {
|
|
AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_LIGHTNING, missile[i]._micaster, missile[i]._misource, dam, missile[i]._mispllvl);
|
|
}
|
|
missile[i]._miVar1 = missile[i]._mix;
|
|
missile[i]._miVar2 = missile[i]._miy;
|
|
}
|
|
|
|
if ((missile[i]._mirange == 0) || (mx <= 0) || (my <= 0) || (mx >= DMAXX) || (my > DMAXY))
|
|
missile[i]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
void MI_LTArrow(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_LIGHTNING) || !PRE_BETA
|
|
int pn, mx, my;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
|
|
missile[i]._mitxoff += missile[i]._mixvel;
|
|
missile[i]._mityoff += missile[i]._miyvel;
|
|
GetMissilePos(i);
|
|
mx = missile[i]._mix;
|
|
my = missile[i]._miy;
|
|
|
|
app_assert(mx < MAXDUNX);
|
|
app_assert(my < MAXDUNY);
|
|
pn = dPiece[mx][my];
|
|
app_assert(pn <= MAXTILES);
|
|
if (missile[i]._misource == -1) {
|
|
if ((mx != missile[i]._misx) || (my != missile[i]._misy))
|
|
if (nMissileTable[pn]) missile[i]._mirange = 0;
|
|
} else {
|
|
if (nMissileTable[pn]) missile[i]._mirange = 0;
|
|
}
|
|
|
|
if ((!nMissileTable[pn]) && ((mx != missile[i]._miVar1) || (my != missile[i]._miVar2)) &&
|
|
(mx > 0) && (my > 0) && (mx < DMAXX) && (my < DMAXY)) {
|
|
// Add LIGHTNING if the player or trap threw this, otherwise add THINLIGHT for thin demon
|
|
if (missile[i]._misource != -1) {
|
|
if (missile[i]._micaster == MI_ENEMYPLR && EquivMonst(monster[missile[i]._misource].MType->mtype, MT_STORM))
|
|
AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_THINLIGHT, missile[i]._micaster, missile[i]._misource, missile[i]._midam, missile[i]._mispllvl);
|
|
else
|
|
AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_LIGHTNING, missile[i]._micaster, missile[i]._misource, missile[i]._midam, missile[i]._mispllvl);
|
|
} else {
|
|
AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_LIGHTNING, missile[i]._micaster, missile[i]._misource, missile[i]._midam, missile[i]._mispllvl);
|
|
}
|
|
missile[i]._miVar1 = missile[i]._mix;
|
|
missile[i]._miVar2 = missile[i]._miy;
|
|
}
|
|
|
|
if ((missile[i]._mirange == 0) || (mx <= 0) || (my <= 0) || (mx >= DMAXX) || (my > DMAXY))
|
|
missile[i]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Lightning(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_LIGHTNING) || !PRE_BETA
|
|
int j;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
|
|
j = missile[i]._mirange;
|
|
if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy))
|
|
CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 0);
|
|
if (missile[i]._miHitFlag == TRUE) missile[i]._mirange = j;
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
AddUnLight(missile[i]._mlid);
|
|
}
|
|
PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Town(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_TOWN) || !PRE_BETA
|
|
int p;
|
|
|
|
int ExpLight[17] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15,15};
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
if (missile[i]._mirange > 1) --missile[i]._mirange;
|
|
|
|
if (missile[i]._mirange == missile[i]._miVar1) {
|
|
SetMissDir(i, 1);
|
|
}
|
|
|
|
if ((currlevel != 0) && (missile[i]._mimfnum != 1) && (missile[i]._mirange != 0)) {
|
|
if (missile[i]._miVar2 == 0)
|
|
missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]);
|
|
ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]);
|
|
++missile[i]._miVar2;
|
|
}
|
|
|
|
for (p = 0; p < MAX_PLRS; ++p) {
|
|
if (! plr[p].plractive) continue;
|
|
if (currlevel != plr[p].plrlevel) continue;
|
|
if (plr[p]._pLvlChanging) continue;
|
|
if (plr[p]._pmode != PM_STAND) continue;
|
|
if (plr[p]._px != missile[i]._mix) continue;
|
|
if (plr[p]._py != missile[i]._miy) continue;
|
|
|
|
ClrPlrPath(p);
|
|
if (p == myplr) {
|
|
NetSendCmdParam1(TRUE,CMD_WARP,missile[i]._misource);
|
|
plr[p]._pmode = PM_NEWLVL;
|
|
}
|
|
}
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
AddUnLight(missile[i]._mlid);
|
|
}
|
|
PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Flash(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_FLASH) || !PRE_BETA
|
|
app_assert(i < MAXMISSILES);
|
|
if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1))
|
|
plr[missile[i]._misource]._pInvincible = TRUE;
|
|
--missile[i]._mirange;
|
|
|
|
CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix-1, missile[i]._miy, 1);
|
|
CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 1);
|
|
CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix+1, missile[i]._miy, 1);
|
|
CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix-1, missile[i]._miy+1, 1);
|
|
CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy+1, 1);
|
|
CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix+1, missile[i]._miy+1, 1);
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1))
|
|
plr[(missile[i]._misource)]._pInvincible = FALSE;
|
|
}
|
|
PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Aura(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_FLASH) || !PRE_BETA
|
|
app_assert(i < MAXMISSILES);
|
|
if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1)) {
|
|
missile[i]._mix = plr[missile[i]._misource]._pfutx;
|
|
missile[i]._miy = plr[missile[i]._misource]._pfuty;
|
|
}
|
|
--missile[i]._mirange;
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1))
|
|
plr[(missile[i]._misource)]._pBaseToBlk -= 50;
|
|
}
|
|
PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Aura2(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_FLASH) || !PRE_BETA
|
|
app_assert(i < MAXMISSILES);
|
|
if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1)) {
|
|
missile[i]._mix = plr[missile[i]._misource]._pfutx;
|
|
missile[i]._miy = plr[missile[i]._misource]._pfuty;
|
|
}
|
|
--missile[i]._mirange;
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
}
|
|
PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Flash2(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_FLASH) || !PRE_BETA
|
|
app_assert(i < MAXMISSILES);
|
|
if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1))
|
|
plr[(missile[i]._misource)]._pInvincible = TRUE;
|
|
--missile[i]._mirange;
|
|
|
|
CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix-1, missile[i]._miy-1, 1);
|
|
CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy-1, 1);
|
|
CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix+1, missile[i]._miy-1, 1);
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1))
|
|
plr[(missile[i]._misource)]._pInvincible = FALSE;
|
|
}
|
|
PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Manashield(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_MANASHLD) || !PRE_BETA
|
|
int j, id;
|
|
long diff, pct;
|
|
|
|
//--missile[i]._mirange;
|
|
app_assert(i < MAXMISSILES);
|
|
id = missile[i]._misource;
|
|
|
|
missile[i]._mix = plr[id]._px;
|
|
missile[i]._miy = plr[id]._py;
|
|
missile[i]._mitxoff = plr[id]._pxoff << 16;
|
|
missile[i]._mityoff = plr[id]._pyoff << 16;
|
|
|
|
if (plr[id]._pmode == PM_WALK3) {
|
|
missile[i]._misx = plr[id]._pfutx;
|
|
missile[i]._misy = plr[id]._pfuty;
|
|
} else {
|
|
missile[i]._misx = plr[id]._px;
|
|
missile[i]._misy = plr[id]._py;
|
|
}
|
|
|
|
GetMissilePos(i);
|
|
|
|
if (plr[id]._pmode == PM_WALK3) {
|
|
if (plr[id]._pdir == DIR_L) ++missile[i]._mix;
|
|
else ++missile[i]._miy;
|
|
}
|
|
|
|
if (id != myplr) {
|
|
if (currlevel != plr[id].plrlevel) missile[i]._miDelFlag = TRUE;
|
|
PutMissile(i);
|
|
return;
|
|
}
|
|
|
|
if (plr[id]._pMana <= 0 || (!plr[id].plractive)) missile[i]._mirange = 0;
|
|
|
|
if (plr[id]._pHitPoints < missile[i]._miVar1) {
|
|
diff = missile[i]._miVar1 - plr[id]._pHitPoints;
|
|
pct = 0;
|
|
for (j = 0; j < missile[i]._mispllvl && j < 7; ++j) pct += 3;
|
|
if (pct > 0) diff = diff - (diff / pct);
|
|
if (diff < 0) diff = 0;
|
|
drawmanaflag = TRUE;
|
|
drawhpflag = TRUE;
|
|
if (plr[id]._pMana >= diff) {
|
|
plr[id]._pHitPoints = missile[i]._miVar1;
|
|
plr[id]._pHPBase = missile[i]._miVar2;
|
|
plr[id]._pMana -= diff;
|
|
plr[id]._pManaBase -= diff;
|
|
} else {
|
|
plr[id]._pHitPoints -= (diff - plr[id]._pMana);
|
|
plr[id]._pHPBase -= (diff - plr[id]._pMana);
|
|
plr[id]._pMana = 0;
|
|
plr[id]._pManaBase = -(plr[id]._pMaxMana - plr[id]._pMaxManaBase);
|
|
missile[i]._mirange = 0;
|
|
missile[i]._miDelFlag = TRUE;
|
|
if (plr[id]._pHitPoints < 0) SetPlayerHitPoints(id, 0);
|
|
if (((plr[id]._pHitPoints >> HP_SHIFT) == 0) && (id == myplr))
|
|
StartPlrKill(id, missile[i]._miVar8);
|
|
}
|
|
}
|
|
|
|
missile[i]._miVar1 = plr[id]._pHitPoints;
|
|
missile[i]._miVar2 = plr[id]._pHPBase;
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
NetSendCmd(TRUE, CMD_ENDSHIELD);
|
|
}
|
|
PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Ether(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_ETHER) || !PRE_BETA
|
|
int id;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
id = missile[i]._misource;
|
|
|
|
missile[i]._mix = plr[id]._px;
|
|
missile[i]._miy = plr[id]._py;
|
|
missile[i]._mitxoff = plr[id]._pxoff << 16;
|
|
missile[i]._mityoff = plr[id]._pyoff << 16;
|
|
|
|
if (plr[id]._pmode == PM_WALK3) {
|
|
missile[i]._misx = plr[id]._pfutx;
|
|
missile[i]._misy = plr[id]._pfuty;
|
|
} else {
|
|
missile[i]._misx = plr[id]._px;
|
|
missile[i]._misy = plr[id]._py;
|
|
}
|
|
|
|
GetMissilePos(i);
|
|
|
|
if (plr[id]._pmode == PM_WALK3) {
|
|
if (plr[id]._pdir == DIR_L) ++missile[i]._mix;
|
|
else ++missile[i]._miy;
|
|
}
|
|
|
|
plr[id]._pSpellFlags |= SF_ETHER;
|
|
|
|
if (missile[i]._mirange == 0 || plr[id]._pHitPoints <= 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
plr[id]._pSpellFlags &= ~SF_ETHER;
|
|
}
|
|
|
|
PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Firemove(int i)
|
|
{
|
|
int j;
|
|
int ExpLight[14] = {2,3,4,5,5,6,7,8,9,10,11,12,12};
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mix;
|
|
--missile[i]._miy;
|
|
missile[i]._miyoff+=32;
|
|
|
|
++missile[i]._miVar1;
|
|
|
|
if (missile[i]._miVar1 == missile[i]._miAnimLen) {
|
|
SetMissDir(i, 1);
|
|
missile[i]._miAnimFrame = random(82, 11) + 1;
|
|
}
|
|
|
|
missile[i]._mitxoff += missile[i]._mixvel;
|
|
missile[i]._mityoff += missile[i]._miyvel;
|
|
GetMissilePos(i);
|
|
|
|
j = missile[i]._mirange;
|
|
CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 0, missile[i]._mix, missile[i]._miy, 0);
|
|
if (missile[i]._miHitFlag == TRUE) missile[i]._mirange = j;
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
AddUnLight(missile[i]._mlid);
|
|
}
|
|
if ((missile[i]._mimfnum == 0) && (missile[i]._mirange != 0)) {
|
|
if (missile[i]._miVar2 == 0)
|
|
missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]);
|
|
ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]);
|
|
++missile[i]._miVar2;
|
|
}
|
|
else if ((missile[i]._mix != missile[i]._miVar3) || (missile[i]._miy != missile[i]._miVar4)) {
|
|
missile[i]._miVar3 = missile[i]._mix;
|
|
missile[i]._miVar4 = missile[i]._miy;
|
|
ChangeLight(missile[i]._mlid, missile[i]._miVar3, missile[i]._miVar4, 8);
|
|
}
|
|
++missile[i]._mix;
|
|
++missile[i]._miy;
|
|
missile[i]._miyoff-=32;
|
|
PutMissile(i);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Guardian(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_GUARDIAN) || !PRE_BETA
|
|
int j, k, sx, sy, sx1, sy1, ex;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
if (missile[i]._miVar2 > 0) --missile[i]._miVar2;
|
|
|
|
if ((missile[i]._mirange == missile[i]._miVar1) || ((missile[i]._mimfnum == 2) &&
|
|
(missile[i]._miVar2 == 0))) {
|
|
SetMissDir(i, 1);
|
|
}
|
|
|
|
if ((missile[i]._mirange % 16) == 0) {
|
|
ex = 0;
|
|
for (k = 0; (k < 23) && (ex != -1); ++k) {
|
|
for (j = 10; (j >= 0) && (ex != -1); j-=2) {
|
|
if (vCrawlTable[k][j] == 0 && vCrawlTable[k][j + 1] == 0) break;
|
|
if ((sx1 != vCrawlTable[k][j]) || (sy1 != vCrawlTable[k][j + 1])) {
|
|
sx = missile[i]._mix + vCrawlTable[k][j];
|
|
sy = missile[i]._miy + vCrawlTable[k][j+1];
|
|
ex = Sentfire(i, sx, sy);
|
|
if (ex == -1) break;
|
|
|
|
sx = missile[i]._mix - vCrawlTable[k][j];
|
|
sy = missile[i]._miy - vCrawlTable[k][j+1];
|
|
ex = Sentfire(i, sx, sy);
|
|
if (ex == -1) break;
|
|
|
|
sx = missile[i]._mix + vCrawlTable[k][j];
|
|
sy = missile[i]._miy - vCrawlTable[k][j+1];
|
|
ex = Sentfire(i, sx, sy);
|
|
if (ex == -1) break;
|
|
|
|
sx = missile[i]._mix - vCrawlTable[k][j];
|
|
sy = missile[i]._miy + vCrawlTable[k][j+1];
|
|
ex = Sentfire(i, sx, sy);
|
|
if (ex == -1) break;
|
|
|
|
sx1 = vCrawlTable[k][j];
|
|
sy1 = vCrawlTable[k][j + 1];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (missile[i]._mirange == 14) {
|
|
SetMissDir(i, 0);
|
|
missile[i]._miAnimFrame = 15;
|
|
missile[i]._miAnimAdd = -1;
|
|
}
|
|
|
|
missile[i]._miVar3 += missile[i]._miAnimAdd;
|
|
if (missile[i]._miVar3 > 15) {
|
|
missile[i]._miVar3 = 15;
|
|
} else {
|
|
if (missile[i]._miVar3 > 0)
|
|
ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, missile[i]._miVar3);
|
|
}
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
AddUnLight(missile[i]._mlid);
|
|
}
|
|
|
|
PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Chain(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_CHAIN) || !PRE_BETA
|
|
int sx, sy, id, dir;
|
|
int l, n, m, k, rad;
|
|
int tx, ty;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
id = missile[i]._misource;
|
|
sx = missile[i]._mix;
|
|
sy = missile[i]._miy;
|
|
|
|
dir = GetDirection(sx, sy, missile[i]._miVar1, missile[i]._miVar2);
|
|
AddMissile(sx, sy, missile[i]._miVar1, missile[i]._miVar2, dir, MIT_LIGHTCTRL, MI_ENEMYMONST, id, 1, missile[i]._mispllvl);
|
|
|
|
rad = 3 + missile[i]._mispllvl;
|
|
if (rad > 19) rad = 19;
|
|
for (m = 1; m < rad; ++m) {
|
|
n = CrawlNum[m];
|
|
l = n + 1;
|
|
for (k = CrawlTable[n]; k > 0; --k) {
|
|
tx = sx + CrawlTable[l];
|
|
ty = sy + CrawlTable[(l + 1)];
|
|
if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
if ((dMonster[tx][ty]) > 0) {
|
|
dir = GetDirection(sx, sy, tx, ty);
|
|
AddMissile(sx, sy, tx, ty, dir, MIT_LIGHTCTRL, MI_ENEMYMONST, id, 1, missile[i]._mispllvl);
|
|
}
|
|
}
|
|
l += 2;
|
|
}
|
|
}
|
|
|
|
--missile[i]._mirange;
|
|
if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
/*void MI_ChainOLD(int i)
|
|
{
|
|
int dir;
|
|
|
|
if ((missile[i]._mirange % 3) == 0) {
|
|
dir = GetDirection(missile[i]._mix, missile[i]._miy, missile[i]._miVar5, missile[i]._miVar6);
|
|
AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._miVar5, missile[i]._miVar6, dir, MIT_CHAINBALL, MI_ENEMYMONST, missile[i]._misource, missile[i]._midam);
|
|
++missile[i]._miVar7;
|
|
}
|
|
|
|
--missile[i]._mirange;
|
|
if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
|
|
}*/
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
/*void MI_ChainballOLD(int i)
|
|
{
|
|
int mx, id;
|
|
int k, l, m, n, rad;
|
|
|
|
--missile[i]._mirange;
|
|
id = missile[i]._misource;
|
|
|
|
missile[i]._mitxoff += missile[i]._mixvel;
|
|
missile[i]._mityoff += missile[i]._miyvel;
|
|
GetMissilePos(i);
|
|
|
|
if ((missile[i]._miVar2 == 1) && (missile[i]._mix == missile[i]._miVar3) && (missile[i]._miy == missile[i]._miVar4)) {
|
|
missile[i]._miVar2 = 0;
|
|
missile[i]._mirange = 0;
|
|
|
|
k = 0;
|
|
for (l = 0; l < nummissiles; ++l) {
|
|
mx = missileactive[l];
|
|
if (missile[mx]._mitype == MIT_CHAINBALL && missile[i]._miVar1 == missile[mx]._miVar1) ++k;
|
|
if ((missile[mx]._mitype == MIT_CHAIN) && (missile[i]._miVar1 == missile[mx]._midam))
|
|
k+=((4 + (GetSpellLevel(id, SPL_LIGHTNING) / 3)) - missile[mx]._miVar7);
|
|
}
|
|
|
|
if (k == 1) {
|
|
rad = 6 + GetSpellLevel(id, SPL_CHAIN);
|
|
if (rad > 19) rad = 19;
|
|
for (m = 1; m < rad; ++m) {
|
|
n = CrawlNum[m];
|
|
l = n + 1;
|
|
for (k = CrawlTable[n]; k > 0; --k) {
|
|
if (ChainBounce (i, missile[i]._mix + CrawlTable[l], missile[i]._miy + CrawlTable[(l + 1)]) > 0) {
|
|
m = rad;
|
|
break;
|
|
}
|
|
l += 2;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if ((missile[i]._mix != missile[i]._miVar5) || (missile[i]._miy != missile[i]._miVar6))
|
|
CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 0);
|
|
|
|
if (missile[i]._miHitFlag == TRUE && missile[i]._mirange == 0 && missile[i]._miVar2 == 0) {
|
|
for (l = 0; l < nummissiles; ++l) {
|
|
mx = missileactive[l];
|
|
if ((missile[mx]._mitype == MIT_CHAIN && missile[i]._miVar1 == missile[mx]._midam) ||
|
|
(missile[mx]._mitype == MIT_CHAINBALL && missile[i]._miVar1 == missile[mx]._miVar1)) {
|
|
missile[mx]._miVar2 = 1; // flag hit and cont until v3, v4
|
|
missile[mx]._miVar3 = missile[i]._mix; // x of hit
|
|
missile[mx]._miVar4 = missile[i]._miy; // y of hit
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
|
|
PutMissile(i);
|
|
}*/
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Blood(int i)
|
|
{
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
|
|
if (missile[i]._miAnimFrame == missile[i]._miAnimLen) {
|
|
// missile[i]._miAnimFrame = missile[i]._miAnimLen;
|
|
missile[i]._miPreFlag = TRUE;
|
|
}
|
|
PutMissile(i);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Weapexp(int i)
|
|
{
|
|
int id, mind, maxd;
|
|
int ExpLight[10] = {9,10,11,12,11,10,8,6,4,2};
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
|
|
id = missile[i]._misource;
|
|
if (missile[i]._miVar2 == 1) {
|
|
mind = plr[id]._pIFMinDam;
|
|
maxd = plr[id]._pIFMaxDam;
|
|
missiledata[missile[i]._mitype].mResist = MIMT_FIRE;
|
|
} else {
|
|
mind = plr[id]._pILMinDam;
|
|
maxd = plr[id]._pILMaxDam;
|
|
missiledata[missile[i]._mitype].mResist = MIMT_LGHT;
|
|
}
|
|
|
|
CheckMissileCol(i, mind, maxd, 0, missile[i]._mix, missile[i]._miy, 0);
|
|
|
|
if (missile[i]._miVar1 == 0) {
|
|
missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar1)]);
|
|
} else {
|
|
if (missile[i]._mirange != 0)
|
|
ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar1)]);
|
|
}
|
|
|
|
++missile[i]._miVar1;
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
AddUnLight(missile[i]._mlid);
|
|
return;
|
|
}
|
|
|
|
PutMissile(i);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Misexp(int i)
|
|
{
|
|
int ExpLight[10] = {9,10,11,12,11,10,8,6,4,2};
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
AddUnLight(missile[i]._mlid);
|
|
return;
|
|
}
|
|
|
|
if (missile[i]._miVar1 == 0) {
|
|
missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar1)]);
|
|
} else {
|
|
if (missile[i]._mirange != 0)
|
|
ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar1)]);
|
|
}
|
|
|
|
++missile[i]._miVar1;
|
|
PutMissile(i);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Acidsplat(int i)
|
|
{
|
|
int monst;
|
|
int dam;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
if (missile[i]._mirange == missile[i]._miAnimLen) {
|
|
++missile[i]._mix;
|
|
++missile[i]._miy;
|
|
missile[i]._miyoff-=32;
|
|
}
|
|
|
|
--missile[i]._mirange;
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
monst = missile[i]._misource;
|
|
dam = (monster[monst].MData->mLevel < 2) ? 1:2;
|
|
AddMissile(missile[i]._mix, missile[i]._miy, i, 0, missile[i]._mimfnum, MIT_ACIDPUD, MI_ENEMYPLR, missile[i]._misource, dam, missile[i]._mispllvl);
|
|
return;
|
|
}
|
|
|
|
PutMissile(i);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Teleport(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_TELE) || !PRE_BETA
|
|
int id;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
id = missile[i]._misource;
|
|
|
|
//sprintf(tempstr, "X: %i Y: %i FX: %i FY: %i", plr[myplr]._px, plr[myplr]._py, plr[myplr]._pfutx, plr[myplr]._pfuty);
|
|
//AddPanelString(tempstr, TEXT_LEFT);
|
|
|
|
--missile[i]._mirange;
|
|
if (missile[i]._mirange <= 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
return;
|
|
}
|
|
|
|
dPlayer[(plr[id]._px)][(plr[id]._py)] = 0;
|
|
PlrClrTrans(plr[id]._px, plr[id]._py);
|
|
plr[id]._px = missile[i]._mix;
|
|
plr[id]._py = missile[i]._miy;
|
|
plr[id]._pfutx = plr[id]._px;
|
|
plr[id]._pfuty = plr[id]._py;
|
|
plr[id]._poldx = plr[id]._px;
|
|
plr[id]._poldy = plr[id]._py;
|
|
PlrDoTrans(plr[id]._px, plr[id]._py);
|
|
missile[i]._miVar1 = 1;
|
|
dPlayer[(plr[id]._px)][(plr[id]._py)] = 1 + (char)id;
|
|
|
|
if (leveltype != 0) {
|
|
ChangeLightXY(plr[id]._plid, plr[id]._px, plr[id]._py);
|
|
ChangeVisionXY(plr[id]._pvid, plr[id]._px, plr[id]._py);
|
|
}
|
|
|
|
if (id == myplr) {
|
|
ViewX = plr[id]._px - ScrollInfo._sdx;
|
|
ViewY = plr[id]._py - ScrollInfo._sdy;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
/*void MI_Doom(int i)
|
|
{
|
|
int k, l, m, n;
|
|
int mid;
|
|
|
|
--missile[i]._mirange;
|
|
|
|
// check if monster moved
|
|
mid = dMonster[(missile[i]._miVar1)][(missile[i]._miVar2)];
|
|
if (mid != 0) {
|
|
if (mid > 0) --mid;
|
|
else mid = -(mid + 1);
|
|
}
|
|
|
|
// if he did search again
|
|
if (mid != missile[i]._miVar3) {
|
|
for (m = 0; m < 6; ++m) {
|
|
n = CrawlNum[m];
|
|
l = n + 1;
|
|
for (k = CrawlTable[n]; k > 0; --k) {
|
|
mid = dMonster[((missile[i]._miVar1) + CrawlTable[l])][((missile[i]._miVar2) + CrawlTable[(l + 1)])];
|
|
if (mid != 0) {
|
|
if (mid > 0) --mid;
|
|
else mid = -(mid + 1);
|
|
if (mid == missile[i]._miVar3) {
|
|
missile[i]._miVar1 += CrawlTable[l];
|
|
missile[i]._miVar2 += CrawlTable[l + 1];
|
|
k = -99;
|
|
m = 6;
|
|
break;
|
|
}
|
|
}
|
|
l += 2;
|
|
}
|
|
}
|
|
|
|
// if monster killed before doom kills it
|
|
if (k != -99) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
PutMissile(i);
|
|
return;
|
|
}
|
|
|
|
// get new velocity and directions
|
|
GetMissileVel(i, missile[i]._mix, missile[i]._miy, missile[i]._miVar1, missile[i]._miVar2, 16);
|
|
SetMissDir(i, GetDirection(missile[i]._mix, missile[i]._miy, missile[i]._miVar1, missile[i]._miVar2));
|
|
}
|
|
|
|
|
|
// move missile
|
|
if (missile[i]._mimfnum != 9) {
|
|
missile[i]._mitxoff += missile[i]._mixvel;
|
|
missile[i]._mityoff += missile[i]._miyvel;
|
|
GetMissilePos(i);
|
|
}
|
|
|
|
// get mid for current missile pos - for checking if target monster killed
|
|
mid = dMonster[(missile[i]._mix)][(missile[i]._miy)];
|
|
if (mid != 0) {
|
|
if (mid > 0) --mid;
|
|
else mid = -(mid + 1);
|
|
}
|
|
|
|
// check for collision if not followed monster dont end missile
|
|
k = missile[i]._mirange;
|
|
if ((missile[i]._mix != plr[myplr]._px) || (missile[i]._miy != plr[myplr]._py)) CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 0);
|
|
if ((missile[i]._mirange == 0) && (mid != missile[i]._miVar3) && (missile[i]._miHitFlag == TRUE)) missile[i]._mirange = k;
|
|
|
|
// if target monster not dead halt missile in place
|
|
if ((missile[i]._mirange == 0) && (mid == missile[i]._miVar3)) {
|
|
missile[i]._mirange = k;
|
|
if ((monster[mid]._mhitpoints >> HP_SHIFT) > 0) {
|
|
if (missile[i]._mimfnum != 9) {
|
|
SetMissDir(i, 9);
|
|
}
|
|
} else {
|
|
// target is killed so re-search
|
|
for (m = 1; m < 6; ++m) {
|
|
n = CrawlNum[m];
|
|
l = n + 1;
|
|
for (k = CrawlTable[n]; k > 0; --k) {
|
|
mid = dMonster[((missile[i]._miVar1) + CrawlTable[l])][((missile[i]._miVar2) + CrawlTable[(l + 1)])];
|
|
if (mid != 0) {
|
|
if (mid > 0) --mid;
|
|
else mid = -(mid + 1);
|
|
if ((monster[mid]._mhitpoints >> HP_SHIFT) > 0) {
|
|
missile[i]._miVar1 += CrawlTable[l];
|
|
missile[i]._miVar2 += CrawlTable[l + 1];
|
|
missile[i]._miVar3 = mid;
|
|
k = -99;
|
|
m = 6;
|
|
break;
|
|
}
|
|
}
|
|
l += 2;
|
|
}
|
|
}
|
|
|
|
// get new velocity and directions
|
|
if (k == 0) missile[i]._mirange = 0;
|
|
else {
|
|
GetMissileVel(i, missile[i]._mix, missile[i]._miy, missile[i]._miVar1, missile[i]._miVar2, 16);
|
|
SetMissDir(i, GetDirection(missile[i]._mix, missile[i]._miy, missile[i]._miVar1, missile[i]._miVar2));
|
|
}
|
|
}
|
|
}
|
|
|
|
// delete or place missile
|
|
if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
|
|
PutMissile(i);
|
|
}*/
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Stone (int i)
|
|
{
|
|
#if (PRE_BETA && PRE_STONE) || !PRE_BETA
|
|
int m;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
m = missile[i]._miVar2;
|
|
|
|
if (monster[m]._mhitpoints == 0 && missile[i]._miAnimType != MF_STONE) {
|
|
SetMissAnim(i, MF_STONE);
|
|
missile[i]._mirange = 11;
|
|
}
|
|
|
|
|
|
if (monster[m]._mmode != MM_STONE) missile[i]._miDelFlag = TRUE;
|
|
|
|
else {
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
if (monster[m]._mhitpoints > 0) {
|
|
// app_assert(dMonster[monster[m]._mx][monster[m]._my] == m+1
|
|
// || dMonster[monster[m]._mx][monster[m]._my] == -(m+1));
|
|
monster[m]._mmode = missile[i]._miVar1;
|
|
}
|
|
else AddDead(monster[m]._mx, monster[m]._my, stonendx, monster[m]._mdir);
|
|
}
|
|
|
|
if (missile[i]._miAnimType == MF_STONE) PutMissile(i);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Boom(int i)
|
|
{
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
if (missile[i]._miVar1 == 0) CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 0, missile[i]._mix, missile[i]._miy, 1);
|
|
if (missile[i]._miHitFlag == TRUE) missile[i]._miVar1 = 1;
|
|
|
|
if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
|
|
PutMissile(i);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Rhino(int i)
|
|
{
|
|
int mix,miy;
|
|
int mix2, miy2;
|
|
int omx, omy;
|
|
int monst;
|
|
BOOL placemiss = FALSE;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
monst = missile[i]._misource;
|
|
|
|
app_assert(monst < MAXMONSTERS);
|
|
if (monster[monst]._mmode != MM_MISSILE) { // monster got blood-boiled or something
|
|
missile[i]._miDelFlag = TRUE;
|
|
return;
|
|
}
|
|
|
|
GetMissilePos(i);
|
|
|
|
omx = missile[i]._mix;
|
|
omy = missile[i]._miy;
|
|
|
|
dMonster[omx][omy] = NULL;
|
|
|
|
if (monster[monst]._mAi == AI_SNAKE)
|
|
{
|
|
// Snake should stop a few frames before it enters player's square
|
|
// So we run its animation a few frames ahead here and test below
|
|
// to see if the square is available
|
|
missile[i]._mitxoff += 2*missile[i]._mixvel;
|
|
missile[i]._mityoff += 2*missile[i]._miyvel;
|
|
|
|
GetMissilePos(i);
|
|
|
|
mix2 = missile[i]._mix;
|
|
miy2 = missile[i]._miy;
|
|
|
|
missile[i]._mitxoff -= 1*missile[i]._mixvel;
|
|
missile[i]._mityoff -= 1*missile[i]._miyvel;
|
|
}
|
|
else
|
|
{
|
|
missile[i]._mitxoff += missile[i]._mixvel;
|
|
missile[i]._mityoff += missile[i]._miyvel;
|
|
}
|
|
|
|
GetMissilePos(i);
|
|
|
|
mix = missile[i]._mix;
|
|
miy = missile[i]._miy;
|
|
|
|
|
|
if (PosOkMonst(monst, mix, miy)
|
|
&& (monster[monst]._mAi != AI_SNAKE || PosOkMonst(monst, mix2, miy2)))
|
|
{
|
|
dMonster[mix][miy] = -(monst + 1);
|
|
monster[monst]._mx = monster[monst]._moldx = monster[monst]._mfutx = mix;
|
|
monster[monst]._my = monster[monst]._moldy = monster[monst]._mfuty = miy;
|
|
|
|
if(monster[monst]._uniqtype)
|
|
ChangeLightXY(missile[i]._mlid, mix, miy);
|
|
|
|
MoveMissilePos(i);
|
|
PutMissile(i);
|
|
}
|
|
else
|
|
{
|
|
MissToMonst(i,omx,omy);
|
|
missile[i]._miDelFlag = TRUE;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Fireman(int i)
|
|
{
|
|
int mix,miy;
|
|
int omx, omy;
|
|
int id, m;
|
|
BOOL placemiss = FALSE;
|
|
int px,py, p;
|
|
|
|
GetMissilePos(i);
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
omx = missile[i]._mix;
|
|
omy = missile[i]._miy;
|
|
|
|
missile[i]._mitxoff += missile[i]._mixvel;
|
|
missile[i]._mityoff += missile[i]._miyvel;
|
|
|
|
GetMissilePos(i);
|
|
|
|
m = missile[i]._misource;
|
|
mix = missile[i]._mix;
|
|
miy = missile[i]._miy;
|
|
|
|
p = monster[m]._menemy;
|
|
if ((monster[m]._mFlags & MFLAG_MID) == 0) {
|
|
px = plr[p]._px;
|
|
py = plr[p]._py;
|
|
} else {
|
|
px = monster[p]._mx;
|
|
py = monster[p]._my;
|
|
}
|
|
|
|
if((mix != omx || miy != omy)
|
|
&&
|
|
((missile[i]._miVar1 & MIF_DIDHIT
|
|
&& !DIST(omx-px, omy-py, 4))
|
|
|| missile[i]._miVar2 > 1)
|
|
&& PosOkMonst(missile[i]._misource, omx, omy)
|
|
)
|
|
{
|
|
// return to monster domain
|
|
MissToMonst(i,omx, omy);
|
|
missile[i]._miDelFlag = TRUE;
|
|
}
|
|
|
|
else
|
|
if ((monster[m]._mFlags & MFLAG_MID) == 0) id = dPlayer[mix][miy];
|
|
else id = dMonster[mix][miy];
|
|
if(!PosOkMissile(mix, miy)
|
|
|| (id > 0 && !(missile[i]._miVar1 & MIF_DIDHIT)))
|
|
{
|
|
// bounce away
|
|
missile[i]._mixvel = -missile[i]._mixvel;
|
|
missile[i]._miyvel = -missile[i]._miyvel;
|
|
missile[i]._mimfnum = opposite[missile[i]._mimfnum];
|
|
missile[i]._miAnimData = monster[m].MType->Anims[MA_WALK].Cels[missile[i]._mimfnum];
|
|
|
|
++missile[i]._miVar2;
|
|
|
|
if(id > 0)
|
|
{
|
|
missile[i]._miVar1 |= MIF_DIDHIT;
|
|
}
|
|
placemiss = TRUE;
|
|
}
|
|
else
|
|
placemiss = TRUE;
|
|
|
|
if(placemiss)
|
|
{
|
|
// ChangeLightXY(monster[m].mlid, monster[m]._mx, monster[m]._my);
|
|
|
|
MoveMissilePos(i);
|
|
PutMissile(i);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_FirewallC(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_WALL) || !PRE_BETA
|
|
int tx, ty, pn, id;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
id = missile[i]._misource;
|
|
if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
|
|
else {
|
|
// if you take this out of here the wall will go though everything (hence using the nsolidtable)
|
|
//if (missile[i]._miVar1 >= MAXDUNX || missile[i]._miVar2 >= MAXDUNY)
|
|
// app_fatal("Tried placing firewall piece off edge of map at (%d,%d)",missile[i]._miVar1,missile[i]._miVar2);
|
|
pn = dPiece[missile[i]._miVar1][missile[i]._miVar2];
|
|
app_assert(pn <= MAXTILES);
|
|
tx = missile[i]._miVar1 + XDirAdd[missile[i]._miVar3];
|
|
ty = missile[i]._miVar2 + YDirAdd[missile[i]._miVar3];
|
|
if (nMissileTable[pn] == 0 && missile[i]._miVar8 == 0 && tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
AddMissile(missile[i]._miVar1, missile[i]._miVar2, missile[i]._miVar1, missile[i]._miVar2, plr[id]._pdir, MIT_FIREWALL, MI_ENEMYMONST, id, 0, missile[i]._mispllvl);
|
|
missile[i]._miVar1 = tx;
|
|
missile[i]._miVar2 = ty;
|
|
} else missile[i]._miVar8 = 1;
|
|
|
|
// if you take this out of here the wall will go though everything (hence using the nsolidtable)
|
|
//if (missile[i]._miVar5 >= MAXDUNX || missile[i]._miVar6 >= MAXDUNY)
|
|
// app_fatal("Tried placing firewall piece off edge of map at (%d,%d)",missile[i]._miVar5,missile[i]._miVar6);
|
|
pn = dPiece[missile[i]._miVar5][missile[i]._miVar6];
|
|
app_assert(pn <= MAXTILES);
|
|
tx = missile[i]._miVar5 + XDirAdd[missile[i]._miVar4];
|
|
ty = missile[i]._miVar6 + YDirAdd[missile[i]._miVar4];
|
|
if (nMissileTable[pn] == 0 && missile[i]._miVar7 == 0 && tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
AddMissile(missile[i]._miVar5, missile[i]._miVar6, missile[i]._miVar5, missile[i]._miVar6, plr[id]._pdir, MIT_FIREWALL, MI_ENEMYMONST, id, 0, missile[i]._mispllvl);
|
|
missile[i]._miVar5 = tx;
|
|
missile[i]._miVar6 = ty;
|
|
} else missile[i]._miVar7 = 1;
|
|
}
|
|
#endif
|
|
}
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_FlameBox(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_WALL) || !PRE_BETA
|
|
app_assert(i < MAXMISSILES);
|
|
missile[i]._miDelFlag = TRUE;
|
|
int const id = missile[i]._micaster;
|
|
int const l = CrawlNum[3];
|
|
int j = l + 1;
|
|
int const dam = ((random(53, 10) + random(53, 10) + 2 + ((id > 0) ? plr[id]._pLevel : currlevel)) << 4) >> 1;
|
|
|
|
for (int m = CrawlTable[l]; m > 0; --m, j+=2) {
|
|
int const tx = missile[i]._miVar1 + CrawlTable[j];
|
|
int const ty = missile[i]._miVar2 + CrawlTable[j + 1];
|
|
|
|
if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
int const pn = dPiece[tx][ty];
|
|
|
|
if (!nSolidTable[pn] && dObject[tx][ty] == 0)
|
|
{
|
|
if (nMissileTable[pn] == 0 && missile[i]._miVar8 == 0 && tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
AddMissile(tx, ty, tx, ty, 0, MIT_FIREWALL, MI_ENEMYMONST, id, dam, missile[i]._mispllvl);
|
|
} else missile[i]._miVar8 = 1;
|
|
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_LightBox(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_WALL) || !PRE_BETA
|
|
app_assert(i < MAXMISSILES);
|
|
missile[i]._miDelFlag = TRUE;
|
|
int const id = missile[i]._micaster;
|
|
int const l = CrawlNum[3];
|
|
int j = l + 1;
|
|
int const dam = ((random(53, 10) + random(53, 10) + 2 + ((id > 0) ? plr[id]._pLevel : currlevel)) << 4) >> 1;
|
|
|
|
for (int m = CrawlTable[l]; m > 0; --m, j+=2) {
|
|
int const tx = missile[i]._miVar1 + CrawlTable[j];
|
|
int const ty = missile[i]._miVar2 + CrawlTable[j + 1];
|
|
|
|
if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
int const pn = dPiece[tx][ty];
|
|
|
|
if (!nSolidTable[pn] && dObject[tx][ty] == 0)
|
|
{
|
|
if (nMissileTable[pn] == 0 && missile[i]._miVar8 == 0 && tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
AddMissile(tx, ty, tx, ty, 0, MIT_LIGHTWALL, MI_ENEMYMONST, id, dam, missile[i]._mispllvl);
|
|
} else missile[i]._miVar8 = 1;
|
|
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_ShowMagicItems(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_WALL) || !PRE_BETA
|
|
app_assert(i < MAXMISSILES);
|
|
|
|
--missile[i]._mirange;
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
HighLightAllItems = false;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_LightwallC(int i)
|
|
{
|
|
// GWP 9/4/97
|
|
// Copy of MI_FirewallC with switched to call the MIT_LIGHTWALL instead of MIT_FIREWALL
|
|
#if (PRE_BETA && PRE_WALL) || !PRE_BETA
|
|
int tx, ty, pn;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
|
|
int const id = missile[i]._misource;
|
|
int const dam = ((random(53, 10) + random(53, 10) + 2 + ((id > 0) ? plr[id]._pLevel : 0)) << 4) >> 1;
|
|
|
|
if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
|
|
else {
|
|
// if you take this out of here the wall will go though everything (hence using the nsolidtable)
|
|
//if (missile[i]._miVar1 >= MAXDUNX || missile[i]._miVar2 >= MAXDUNY)
|
|
// app_fatal("Tried placing firewall piece off edge of map at (%d,%d)",missile[i]._miVar1,missile[i]._miVar2);
|
|
pn = dPiece[missile[i]._miVar1][missile[i]._miVar2];
|
|
app_assert(pn <= MAXTILES);
|
|
tx = missile[i]._miVar1 + XDirAdd[missile[i]._miVar3];
|
|
ty = missile[i]._miVar2 + YDirAdd[missile[i]._miVar3];
|
|
if (nMissileTable[pn] == 0 && missile[i]._miVar8 == 0 && tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
AddMissile(missile[i]._miVar1, missile[i]._miVar2, missile[i]._miVar1, missile[i]._miVar2, plr[id]._pdir, MIT_LIGHTWALL, MI_ENEMYMONST, id, dam, missile[i]._mispllvl);
|
|
missile[i]._miVar1 = tx;
|
|
missile[i]._miVar2 = ty;
|
|
} else missile[i]._miVar8 = 1;
|
|
|
|
// if you take this out of here the wall will go though everything (hence using the nsolidtable)
|
|
//if (missile[i]._miVar5 >= MAXDUNX || missile[i]._miVar6 >= MAXDUNY)
|
|
// app_fatal("Tried placing firewall piece off edge of map at (%d,%d)",missile[i]._miVar5,missile[i]._miVar6);
|
|
pn = dPiece[missile[i]._miVar5][missile[i]._miVar6];
|
|
app_assert(pn <= MAXTILES);
|
|
tx = missile[i]._miVar5 + XDirAdd[missile[i]._miVar4];
|
|
ty = missile[i]._miVar6 + YDirAdd[missile[i]._miVar4];
|
|
if (nMissileTable[pn] == 0 && missile[i]._miVar7 == 0 && tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) {
|
|
AddMissile(missile[i]._miVar5, missile[i]._miVar6, missile[i]._miVar5, missile[i]._miVar6, plr[id]._pdir, MIT_LIGHTWALL, MI_ENEMYMONST, id, dam, missile[i]._mispllvl);
|
|
missile[i]._miVar5 = tx;
|
|
missile[i]._miVar6 = ty;
|
|
} else missile[i]._miVar7 = 1;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Infra(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_INFRA) || !PRE_BETA
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
plr[(missile[i]._misource)]._pInfraFlag = TRUE;
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
CalcPlrItemVals(missile[i]._misource,TRUE);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Apoca(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_APOCA) || !PRE_BETA
|
|
int j, k, id;
|
|
BOOL exit;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
id = missile[i]._misource;
|
|
|
|
exit = FALSE;
|
|
for (j = missile[i]._miVar2; (j < missile[i]._miVar3) && (exit == FALSE); ++j) {
|
|
for (k = missile[i]._miVar4; (k < missile[i]._miVar5) && (exit == FALSE); ++k) {
|
|
if (dMonster[k][j] > 3 && nSolidTable[(dPiece[k][j])] == 0) {
|
|
AddMissile(k, j, k, j, plr[id]._pdir, MIT_BOOM, MI_ENEMYMONST, id, missile[i]._midam, 0);
|
|
exit = TRUE;
|
|
}
|
|
}
|
|
if (exit == FALSE) missile[i]._miVar4 = missile[i]._miVar6;
|
|
}
|
|
|
|
if (exit == TRUE) {
|
|
missile[i]._miVar2 = j - 1;
|
|
missile[i]._miVar4 = k;
|
|
} else missile[i]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Wave(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_WAVE) || !PRE_BETA
|
|
int dira, dirb, nxa, nya, nxb, nyb;
|
|
int pn, sd, j, f1, f2, id, sx, sy, dx, dy;
|
|
|
|
f1 = 0;
|
|
f2 = 0;
|
|
app_assert(i < MAXMISSILES);
|
|
id = missile[i]._misource;
|
|
sx = missile[i]._mix;
|
|
sy = missile[i]._miy;
|
|
dx = missile[i]._miVar1;
|
|
dy = missile[i]._miVar2;
|
|
|
|
sd = GetDirection(sx, sy, dx, dy);
|
|
dira = (sd - 2) & 0x0007;
|
|
dirb = (sd + 2) & 0x0007;
|
|
nxa = sx + XDirAdd[sd];
|
|
nya = sy + YDirAdd[sd];
|
|
|
|
//if (nxa >= MAXDUNX || nya >= MAXDUNY)
|
|
// app_fatal("Tried placing flamewave piece off edge of map at (%d,%d)",nxa,nya);
|
|
pn = dPiece[nxa][nya];
|
|
app_assert(pn <= MAXTILES);
|
|
if (nMissileTable[pn] == 0) {
|
|
AddMissile(nxa, nya, nxa + XDirAdd[sd], nya + YDirAdd[sd], plr[id]._pdir, MIT_FIREMOVE, MI_ENEMYMONST, id, 0, missile[i]._mispllvl);
|
|
|
|
nxa += XDirAdd[dira];
|
|
nya += YDirAdd[dira];
|
|
nxb = sx + XDirAdd[sd] + XDirAdd[dirb];
|
|
nyb = sy + YDirAdd[sd] + YDirAdd[dirb];
|
|
for (j = 0; j < (2 + (missile[i]._mispllvl>>1)); ++j) {
|
|
//if (nxa >= MAXDUNX || nya >= MAXDUNY)
|
|
// app_fatal("Tried placing flamewave piece off edge of map at (%d,%d)",nxa,nya);
|
|
pn = dPiece[nxa][nya];
|
|
app_assert(pn <= MAXTILES);
|
|
if (nMissileTable[pn] == 0 && f1 == 0 && nxa > 0 && nxa < MAXDUNX && nya > 0 && nya < MAXDUNY) {
|
|
AddMissile(nxa, nya, nxa + XDirAdd[sd], nya + YDirAdd[sd], plr[id]._pdir, MIT_FIREMOVE, MI_ENEMYMONST, id, 0, missile[i]._mispllvl);
|
|
nxa += XDirAdd[dira];
|
|
nya += YDirAdd[dira];
|
|
} else f1 = 1;
|
|
|
|
//if (nxb >= MAXDUNX || nyb >= MAXDUNY)
|
|
// app_fatal("Tried placing flamewave piece off edge of map at (%d,%d)",nxb,nyb);
|
|
pn = dPiece[nxb][nyb];
|
|
app_assert(pn <= MAXTILES);
|
|
if (nMissileTable[pn] == 0 && f2 == 0 && nxb > 0 && nxb < MAXDUNX && nyb > 0 && nyb < MAXDUNY) {
|
|
AddMissile(nxb, nyb, nxb + XDirAdd[sd], nyb + YDirAdd[sd], plr[id]._pdir, MIT_FIREMOVE, MI_ENEMYMONST, id, 0, missile[i]._mispllvl);
|
|
nxb += XDirAdd[dirb];
|
|
nyb += YDirAdd[dirb];
|
|
} else f2 = 1;
|
|
}
|
|
}
|
|
|
|
--missile[i]._mirange;
|
|
if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
#define RAD 6
|
|
|
|
void MI_Nova(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_NOVA) || !PRE_BETA
|
|
int k, id, sx, sy, dir, en;
|
|
int sx1, sy1, dam, dx, dy;
|
|
|
|
sx1 = sy1 = 0;
|
|
app_assert(i < MAXMISSILES);
|
|
id = missile[i]._misource;
|
|
dam = missile[i]._midam;
|
|
sx = missile[i]._mix;
|
|
sy = missile[i]._miy;
|
|
dx = missile[i]._miVar1;
|
|
dy = missile[i]._miVar2;
|
|
if (id != -1) {
|
|
dir = plr[id]._pdir;
|
|
en = MI_ENEMYMONST;
|
|
} else {
|
|
dir = 0;
|
|
en = MI_ENEMYPLR;
|
|
}
|
|
|
|
for (k = 0; k < 23; ++k) {
|
|
if ((sx1 != vCrawlTable[k][RAD]) || (sy1 != vCrawlTable[k][RAD + 1])) {
|
|
dx = sx + vCrawlTable[k][RAD];
|
|
dy = sy + vCrawlTable[k][RAD + 1];
|
|
AddMissile(sx, sy, dx, dy, dir, MIT_LIGHTBALL, en, id, dam, missile[i]._mispllvl);
|
|
|
|
dx = sx - vCrawlTable[k][RAD];
|
|
dy = sy - vCrawlTable[k][RAD + 1];
|
|
AddMissile(sx, sy, dx, dy, dir, MIT_LIGHTBALL, en, id, dam, missile[i]._mispllvl);
|
|
|
|
dx = sx - vCrawlTable[k][RAD];
|
|
dy = sy + vCrawlTable[k][RAD + 1];
|
|
AddMissile(sx, sy, dx, dy, dir, MIT_LIGHTBALL, en, id, dam, missile[i]._mispllvl);
|
|
|
|
dx = sx + vCrawlTable[k][RAD];
|
|
dy = sy - vCrawlTable[k][RAD + 1];
|
|
AddMissile(sx, sy, dx, dy, dir, MIT_LIGHTBALL, en, id, dam, missile[i]._mispllvl);
|
|
|
|
sx1 = vCrawlTable[k][RAD];
|
|
sy1 = vCrawlTable[k][RAD + 1];
|
|
}
|
|
}
|
|
|
|
--missile[i]._mirange;
|
|
if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void MI_FireNova(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_NOVA) || !PRE_BETA
|
|
int k, id, sx, sy, dir, en;
|
|
int sx1, sy1, dam, dx, dy;
|
|
|
|
sx1 = sy1 = 0;
|
|
app_assert(i < MAXMISSILES);
|
|
id = missile[i]._misource;
|
|
dam = missile[i]._midam;
|
|
sx = missile[i]._mix;
|
|
sy = missile[i]._miy;
|
|
dx = missile[i]._miVar1;
|
|
dy = missile[i]._miVar2;
|
|
if (id != -1) {
|
|
dir = plr[id]._pdir;
|
|
en = MI_ENEMYMONST;
|
|
} else {
|
|
dir = 0;
|
|
en = MI_ENEMYPLR;
|
|
}
|
|
|
|
for (k = 0; k < 23; ++k) {
|
|
if ((sx1 != vCrawlTable[k][RAD]) || (sy1 != vCrawlTable[k][RAD + 1])) {
|
|
dx = sx + vCrawlTable[k][RAD];
|
|
dy = sy + vCrawlTable[k][RAD + 1];
|
|
AddMissile(sx, sy, dx, dy, dir, MIT_FBARROW, en, id, dam, missile[i]._mispllvl);
|
|
|
|
dx = sx - vCrawlTable[k][RAD];
|
|
dy = sy - vCrawlTable[k][RAD + 1];
|
|
AddMissile(sx, sy, dx, dy, dir, MIT_FBARROW, en, id, dam, missile[i]._mispllvl);
|
|
|
|
dx = sx - vCrawlTable[k][RAD];
|
|
dy = sy + vCrawlTable[k][RAD + 1];
|
|
AddMissile(sx, sy, dx, dy, dir, MIT_FBARROW, en, id, dam, missile[i]._mispllvl);
|
|
|
|
dx = sx + vCrawlTable[k][RAD];
|
|
dy = sy - vCrawlTable[k][RAD + 1];
|
|
AddMissile(sx, sy, dx, dy, dir, MIT_FBARROW, en, id, dam, missile[i]._mispllvl);
|
|
|
|
sx1 = vCrawlTable[k][RAD];
|
|
sy1 = vCrawlTable[k][RAD + 1];
|
|
}
|
|
}
|
|
|
|
--missile[i]._mirange;
|
|
if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
void MI_SpecialArrow(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA
|
|
int id, sx, sy, dir, en;
|
|
int sx1, sy1, dam, dx, dy;
|
|
|
|
sx1 = sy1 = 0;
|
|
app_assert(i < MAXMISSILES);
|
|
id = missile[i]._misource;
|
|
dam = missile[i]._midam;
|
|
sx = missile[i]._mix;
|
|
sy = missile[i]._miy;
|
|
dx = missile[i]._miVar1;
|
|
dy = missile[i]._miVar2;
|
|
int extraspeed = missile[i]._miVar3;
|
|
|
|
int mitype = MIT_ARROW;
|
|
if (id != -1) {
|
|
dir = plr[id]._pdir;
|
|
en = MI_ENEMYMONST;
|
|
switch(plr[id]._pILMinDam)
|
|
{
|
|
case 0: mitype = MIT_FBARROW; break;
|
|
case 1: mitype = MIT_LTARROW; break;
|
|
case 2: mitype = MIT_CBARROW; break;
|
|
case 3: mitype = MIT_HBARROW; break;
|
|
default: break;
|
|
}
|
|
} else {
|
|
dir = 0;
|
|
en = MI_ENEMYPLR;
|
|
}
|
|
|
|
AddMissile(sx, sy, dx, dy, dir, mitype, en, id, dam, extraspeed);
|
|
if (mitype == MIT_CBARROW)
|
|
{
|
|
AddMissile(sx, sy, dx, dy, dir, mitype, en, id, dam, extraspeed);
|
|
AddMissile(sx, sy, dx, dy, dir, mitype, en, id, dam, extraspeed);
|
|
}
|
|
|
|
--missile[i]._mirange;
|
|
if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
|
|
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Boil(int i)
|
|
{
|
|
app_assert(i < MAXMISSILES);
|
|
missile[i]._miDelFlag = TRUE;
|
|
return;
|
|
|
|
/*#if (PRE_BETA && PRE_BLOODB) || !PRE_BETA
|
|
int j, mid, id, dx, dy, pct;
|
|
long dm;
|
|
|
|
BOOL M_Talker (int);
|
|
|
|
id = missile[i]._misource;
|
|
dx = missile[i]._miVar1;
|
|
dy = missile[i]._miVar2;
|
|
mid = dMonster[dx][dy];
|
|
|
|
if (mid > 0) --mid;
|
|
else mid = -(mid + 1);
|
|
if (mid > 0) {
|
|
if ((M_Talker(mid) && monster[mid].mtalkmsg != 0) || ((plr[id]._pLevel - 6 + missile[i]._mispllvl) <= monster[mid].mLevel)) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
return;
|
|
}
|
|
|
|
if (monster[mid].mMagicRes & M_IM) return;
|
|
|
|
dm = monster[mid]._mhitpoints;
|
|
monster[mid]._mhitpoints = 0;
|
|
M_StartKill(mid, id);
|
|
AddPlrExperience(id, monster[mid].mLevel, monster[mid].mExp);
|
|
dMonster[monster[mid]._mx][monster[mid]._my] = 0;
|
|
monster[mid]._mDelFlag = TRUE;
|
|
AddMissile(monster[mid]._mx, monster[mid]._my, monster[mid]._mx, monster[mid]._my, plr[id]._pdir, MIT_SPURT, MI_ENEMYMONST, id, (random(87, 2) + 1), 0);
|
|
AddDead(monster[mid]._mx, monster[mid]._my, spurtndx, monster[mid]._mdir);
|
|
|
|
pct = 0;
|
|
for (j = 0; j < missile[i]._mispllvl && j < 5; ++j) pct += 10;
|
|
//dm = (monster[mid]._mmaxhp >> 1);
|
|
if (pct > 0) dm -= (dm / pct);
|
|
plr[id]._pHitPoints -= dm;
|
|
plr[id]._pHPBase -= dm;
|
|
|
|
if (plr[id]._pHitPoints > plr[id]._pMaxHP) {
|
|
plr[id]._pHitPoints = plr[id]._pMaxHP;
|
|
plr[id]._pHPBase = plr[id]._pMaxHPBase;
|
|
}
|
|
if (plr[id]._pHitPoints <= 0) {
|
|
// rjs - manashld fix? - plr[id]._pHitPoints = 0;
|
|
StartPlrKill(id, FALSE);
|
|
} else StartPlrHit(id, dm);
|
|
|
|
PlaySfxLoc(LS_BLODBOIL, monster[mid]._mx, monster[mid]._my);
|
|
UseMana(id, SPL_BLOODB);
|
|
}
|
|
--missile[i]._mirange;
|
|
if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
|
|
#endif*/
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Flame(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_FLAME) || !PRE_BETA
|
|
int k, id;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
id = missile[i]._misource;
|
|
--missile[i]._mirange;
|
|
--missile[i]._miVar2;
|
|
|
|
k = missile[i]._mirange;
|
|
CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 0);
|
|
if ((missile[i]._mirange == 0) && (missile[i]._miHitFlag == TRUE)) missile[i]._mirange = k;
|
|
if (missile[i]._miVar2 == 0) missile[i]._miAnimFrame = 20;
|
|
if (missile[i]._miVar2 <= 0) {
|
|
k = missile[i]._miAnimFrame;
|
|
if (k > 11) k = 24 - k;
|
|
ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, k);
|
|
}
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
AddUnLight(missile[i]._mlid);
|
|
}
|
|
if (missile[i]._miVar2 <= 0) PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Flamec(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_FLAME) || !PRE_BETA
|
|
int id, pn;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
id = missile[i]._misource;
|
|
|
|
missile[i]._mitxoff += missile[i]._mixvel;
|
|
missile[i]._mityoff += missile[i]._miyvel;
|
|
GetMissilePos(i);
|
|
|
|
if ((missile[i]._mix != missile[i]._miVar1) || (missile[i]._miy != missile[i]._miVar2)) {
|
|
app_assert(missile[i]._mix < MAXDUNX);
|
|
app_assert(missile[i]._miy < MAXDUNY);
|
|
pn = dPiece[missile[i]._mix][missile[i]._miy];
|
|
app_assert(pn <= MAXTILES);
|
|
if (nMissileTable[pn] == 0)
|
|
AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_FLAME, missile[i]._micaster, id, missile[i]._miVar3, missile[i]._mispllvl);
|
|
else
|
|
missile[i]._mirange = 0;
|
|
missile[i]._miVar1 = missile[i]._mix;
|
|
missile[i]._miVar2 = missile[i]._miy;
|
|
++missile[i]._miVar3;
|
|
}
|
|
|
|
if (missile[i]._mirange == 0 || missile[i]._miVar3 == 3) missile[i]._miDelFlag = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Cbolt(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_CBOLT) || !PRE_BETA
|
|
int bpath[16] = { -1, 0, 1, -1, 0, 1, -1, -1, 0, 0, 1, 1, 0, 1, -1, 0 };
|
|
int sx, sy, dx, dy, md;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
if (missile[i]._miAnimType != MF_LIGHTNING) {
|
|
if (missile[i]._miVar3 == 0) {
|
|
md = (missile[i]._miVar2 + bpath[missile[i]._mirnd]) & 0x07;
|
|
missile[i]._mirnd = (missile[i]._mirnd + 1) & 0x0f;
|
|
sx = missile[i]._mix;
|
|
sy = missile[i]._miy;
|
|
dx = sx + XDirAdd[md];
|
|
dy = sy + YDirAdd[md];
|
|
GetMissileVel(i, sx, sy, dx, dy, 8);
|
|
missile[i]._miVar3 = 16;
|
|
} else --missile[i]._miVar3;
|
|
|
|
missile[i]._mitxoff += missile[i]._mixvel;
|
|
missile[i]._mityoff += missile[i]._miyvel;
|
|
GetMissilePos(i);
|
|
|
|
CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 0, missile[i]._mix, missile[i]._miy, 0);
|
|
if (missile[i]._miHitFlag == TRUE) {
|
|
missile[i]._miVar1 = 8;
|
|
missile[i]._mimfnum = 0;
|
|
missile[i]._mixoff = 0;
|
|
missile[i]._miyoff = 0;
|
|
SetMissAnim(i, MF_LIGHTNING);
|
|
missile[i]._mirange = missile[i]._miAnimLen;
|
|
GetMissilePos(i);
|
|
}
|
|
|
|
ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, missile[i]._miVar1);
|
|
}
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
AddUnLight(missile[i]._mlid);
|
|
}
|
|
|
|
PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Hbolt(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_HBOLT) || !PRE_BETA
|
|
int dam;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
if (missile[i]._miAnimType != MF_HEXPL) {
|
|
missile[i]._mitxoff += missile[i]._mixvel;
|
|
missile[i]._mityoff += missile[i]._miyvel;
|
|
|
|
GetMissilePos(i);
|
|
|
|
dam = missile[i]._midam;
|
|
if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy))
|
|
CheckMissileCol(i, dam, dam, 0, missile[i]._mix, missile[i]._miy, 0);
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._mitxoff -= missile[i]._mixvel;
|
|
missile[i]._mityoff -= missile[i]._miyvel;
|
|
GetMissilePos(i);
|
|
missile[i]._mimfnum = 0;
|
|
SetMissAnim(i, MF_HEXPL);
|
|
missile[i]._mirange = missile[i]._miAnimLen - 1;
|
|
} else {
|
|
if ((missile[i]._mix != missile[i]._miVar1) || (missile[i]._miy != missile[i]._miVar2)) {
|
|
missile[i]._miVar1 = missile[i]._mix;
|
|
missile[i]._miVar2 = missile[i]._miy;
|
|
ChangeLight(missile[i]._mlid, missile[i]._miVar1, missile[i]._miVar2, 8);
|
|
}
|
|
}
|
|
} else {
|
|
ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, 7 + missile[i]._miAnimFrame);
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
AddUnLight(missile[i]._mlid);
|
|
}
|
|
}
|
|
PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Element(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_ELEMENT) || !PRE_BETA
|
|
int j, mid, sd, dam;
|
|
int cx, cy, px, py, id;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
dam = missile[i]._midam;
|
|
id = missile[i]._misource;
|
|
|
|
if (missile[i]._miAnimType == MF_BIGEXP) {
|
|
cx = missile[i]._mix;
|
|
cy = missile[i]._miy;
|
|
px = plr[id]._px;
|
|
py = plr[id]._py;
|
|
ChangeLight(missile[i]._mlid, cx, cy, missile[i]._miAnimFrame);
|
|
|
|
if (CheckBlock(px, py, cx , cy ) == 0) CheckMissileCol(i, dam, dam, 1, cx, cy, 1);
|
|
if (CheckBlock(px, py, cx , cy + 1) == 0) CheckMissileCol(i, dam, dam, 1, cx, cy + 1, 1);
|
|
if (CheckBlock(px, py, cx , cy - 1) == 0) CheckMissileCol(i, dam, dam, 1, cx, cy - 1, 1);
|
|
if (CheckBlock(px, py, cx + 1, cy ) == 0) CheckMissileCol(i, dam, dam, 1, cx + 1, cy, 1);
|
|
if (CheckBlock(px, py, cx + 1, cy - 1) == 0) CheckMissileCol(i, dam, dam, 1, cx + 1, cy - 1, 1);
|
|
if (CheckBlock(px, py, cx + 1, cy + 1) == 0) CheckMissileCol(i, dam, dam, 1, cx + 1, cy + 1, 1);
|
|
if (CheckBlock(px, py, cx - 1, cy ) == 0) CheckMissileCol(i, dam, dam, 1, cx - 1, cy, 1);
|
|
if (CheckBlock(px, py, cx - 1, cy + 1) == 0) CheckMissileCol(i, dam, dam, 1, cx - 1, cy + 1, 1);
|
|
if (CheckBlock(px, py, cx - 1, cy - 1) == 0) CheckMissileCol(i, dam, dam, 1, cx - 1, cy - 1, 1);
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
AddUnLight(missile[i]._mlid);
|
|
}
|
|
|
|
PutMissile(i);
|
|
return;
|
|
}
|
|
|
|
missile[i]._mitxoff += missile[i]._mixvel;
|
|
missile[i]._mityoff += missile[i]._miyvel;
|
|
GetMissilePos(i);
|
|
cx = missile[i]._mix;
|
|
cy = missile[i]._miy;
|
|
|
|
j = missile[i]._mirange;
|
|
CheckMissileCol(i, dam, dam, 0, cx, cy, 0);
|
|
|
|
if (missile[i]._miVar3 == 0) {
|
|
//if (missile[i]._mirange == 0 && missile[i]._miHitFlag == TRUE) missile[i]._mirange = j;
|
|
//if ((missile[i]._mirange == 0) && (missile[i]._miHitFlag != TRUE)) missile[i]._miVar3 = 1;
|
|
if ((cx == missile[i]._miVar4) && (cy == missile[i]._miVar5)) missile[i]._miVar3 = 1;
|
|
}
|
|
|
|
if (missile[i]._miVar3 == 1) {
|
|
missile[i]._miVar3 = 2;
|
|
missile[i]._mirange = 255;
|
|
mid = FindClosest(cx, cy, 19);
|
|
if (mid > 0) {
|
|
sd = GetDirection8(cx, cy, monster[mid]._mx, monster[mid]._my);
|
|
SetMissDir(i, sd);
|
|
GetMissileVel(i, cx, cy, monster[mid]._mx, monster[mid]._my, 16);
|
|
} else {
|
|
sd = plr[id]._pdir;
|
|
SetMissDir(i, sd);
|
|
GetMissileVel(i, cx, cy, cx + XDirAdd[sd], cy + YDirAdd[sd], 16);
|
|
}
|
|
}
|
|
|
|
if ((cx != missile[i]._miVar1) || (cy != missile[i]._miVar2)) {
|
|
missile[i]._miVar1 = cx;
|
|
missile[i]._miVar2 = cy;
|
|
ChangeLight(missile[i]._mlid, cx, cy, 8);
|
|
}
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._mimfnum = 0;
|
|
SetMissAnim(i, MF_BIGEXP);
|
|
missile[i]._mirange = missile[i]._miAnimLen - 1;
|
|
}
|
|
|
|
PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Bonespirit(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_BONESPIRIT) || !PRE_BETA
|
|
int j, mid, sd, dam;
|
|
int cx, cy, id;
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
dam = missile[i]._midam;
|
|
id = missile[i]._misource;
|
|
|
|
if (missile[i]._mimfnum == 8) {
|
|
cx = missile[i]._mix;
|
|
cy = missile[i]._miy;
|
|
//px = plr[id]._px;
|
|
//py = plr[id]._py;
|
|
ChangeLight(missile[i]._mlid, cx, cy, missile[i]._miAnimFrame);
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
AddUnLight(missile[i]._mlid);
|
|
}
|
|
|
|
PutMissile(i);
|
|
return;
|
|
}
|
|
|
|
missile[i]._mitxoff += missile[i]._mixvel;
|
|
missile[i]._mityoff += missile[i]._miyvel;
|
|
GetMissilePos(i);
|
|
cx = missile[i]._mix;
|
|
cy = missile[i]._miy;
|
|
|
|
j = missile[i]._mirange;
|
|
CheckMissileCol(i, dam, dam, 0, cx, cy, 0);
|
|
|
|
if (missile[i]._miVar3 == 0) {
|
|
//if (missile[i]._mirange == 0 && missile[i]._miHitFlag == TRUE) missile[i]._mirange = j;
|
|
//if ((missile[i]._mirange == 0) && (missile[i]._miHitFlag != TRUE)) missile[i]._miVar3 = 1;
|
|
if ((cx == missile[i]._miVar4) && (cy == missile[i]._miVar5)) missile[i]._miVar3 = 1;
|
|
}
|
|
|
|
if (missile[i]._miVar3 == 1) {
|
|
missile[i]._miVar3 = 2;
|
|
missile[i]._mirange = 255;
|
|
mid = FindClosest(cx, cy, 19);
|
|
if (mid > 0) {
|
|
missile[i]._midam = (monster[mid]._mhitpoints >> HP_SHIFT) >> 1;
|
|
sd = GetDirection8(cx, cy, monster[mid]._mx, monster[mid]._my);
|
|
SetMissDir(i, sd);
|
|
GetMissileVel(i, cx, cy, monster[mid]._mx, monster[mid]._my, 16);
|
|
} else {
|
|
sd = plr[id]._pdir;
|
|
SetMissDir(i, sd);
|
|
GetMissileVel(i, cx, cy, cx + XDirAdd[sd], cy + YDirAdd[sd], 16);
|
|
}
|
|
}
|
|
|
|
if ((cx != missile[i]._miVar1) || (cy != missile[i]._miVar2)) {
|
|
missile[i]._miVar1 = cx;
|
|
missile[i]._miVar2 = cy;
|
|
ChangeLight(missile[i]._mlid, cx, cy, 8);
|
|
}
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
SetMissDir(i, 8);
|
|
missile[i]._mirange = 7;
|
|
}
|
|
|
|
PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_ResurrectBeam(int i)
|
|
{
|
|
#if (PRE_BETA && PRE_RESURRECT) || !PRE_BETA
|
|
app_assert(i < MAXMISSILES);
|
|
--missile[i]._mirange;
|
|
if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
|
|
PutMissile(i);
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MI_Rportal(int i)
|
|
{
|
|
int ExpLight[17] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15,15};
|
|
|
|
app_assert(i < MAXMISSILES);
|
|
if (missile[i]._mirange > 1) --missile[i]._mirange;
|
|
|
|
if (missile[i]._mirange == missile[i]._miVar1) {
|
|
SetMissDir(i, 1);
|
|
}
|
|
|
|
if ((currlevel != 0) && (missile[i]._mimfnum != 1) && (missile[i]._mirange != 0)) {
|
|
if (missile[i]._miVar2 == 0)
|
|
missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]);
|
|
ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]);
|
|
++missile[i]._miVar2;
|
|
}
|
|
|
|
if (missile[i]._mirange == 0) {
|
|
missile[i]._miDelFlag = TRUE;
|
|
AddUnLight(missile[i]._mlid);
|
|
}
|
|
|
|
PutMissile(i);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void ProcessMissiles ()
|
|
{
|
|
int i, mi;
|
|
|
|
|
|
for (i = 0; i < nummissiles; ++i) {
|
|
mi = missileactive[i];
|
|
dFlags[missile[mi]._mix][missile[mi]._miy] &= BFMASK_MISSILE;
|
|
dMissile[missile[mi]._mix][missile[mi]._miy] = 0;
|
|
}
|
|
|
|
i = 0;
|
|
while (i < nummissiles) {
|
|
mi = missileactive[i];
|
|
if (missile[mi]._miDelFlag) {
|
|
DeleteMissile(mi, i);
|
|
i = 0;
|
|
} else ++i;
|
|
}
|
|
|
|
MissilePreFlag = FALSE;
|
|
ManashieldFlag = 0;
|
|
for (i = 0; i < nummissiles; ++i) {
|
|
mi = missileactive[i];
|
|
|
|
missiledata[missile[mi]._mitype].mProc(mi);
|
|
|
|
if(!(missile[mi]._miAnimFlags & MFF_STATIC))
|
|
{
|
|
++missile[mi]._miAnimCnt;
|
|
if (missile[mi]._miAnimCnt >= missile[mi]._miAnimDelay) {
|
|
missile[mi]._miAnimCnt = 0;
|
|
missile[mi]._miAnimFrame += missile[mi]._miAnimAdd;
|
|
if (missile[mi]._miAnimFrame > missile[mi]._miAnimLen) missile[mi]._miAnimFrame = 1;
|
|
if (missile[mi]._miAnimFrame < 1) missile[mi]._miAnimFrame = missile[mi]._miAnimLen;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ManashieldFlag) {
|
|
for (i = 0; i < nummissiles; ++i) {
|
|
mi = missileactive[i];
|
|
if (missile[mi]._mitype == MIT_MANASHIELD) MI_Manashield(mi);
|
|
}
|
|
}
|
|
|
|
i = 0;
|
|
while (i < nummissiles) {
|
|
mi = missileactive[i];
|
|
if (missile[mi]._miDelFlag) {
|
|
DeleteMissile(mi, i);
|
|
i = 0;
|
|
} else ++i;
|
|
}
|
|
}
|
|
|
|
void SyncMissAnim()
|
|
{
|
|
int i,mi;
|
|
|
|
for (i = 0; i < nummissiles; ++i)
|
|
{
|
|
app_assert(i < MAXMISSILES);
|
|
mi = missileactive[i];
|
|
|
|
app_assert(mi < MAXMISSILES);
|
|
MissileStruct *Miss = &missile[mi];
|
|
|
|
Miss->_miAnimData = misfiledata[Miss->_miAnimType].mAnimData[Miss->_mimfnum];
|
|
|
|
if (Miss->_mitype == MIT_RHINO)
|
|
{
|
|
AnimStruct *anim;
|
|
|
|
if (EquivMonst(monster[Miss->_misource].MType->mtype, MT_HORNED))
|
|
anim = &monster[Miss->_misource].MType->Anims[MA_SPECIAL];
|
|
else if (EquivMonst(monster[Miss->_misource].MType->mtype, MT_NSNAKE))
|
|
anim = &monster[Miss->_misource].MType->Anims[MA_ATTACK];
|
|
else
|
|
anim = &monster[Miss->_misource].MType->Anims[MA_WALK];
|
|
|
|
missile[mi]._miAnimData = anim->Cels[Miss->_mimfnum];
|
|
}
|
|
// need similar section for Fireman
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** Used when we need to "emergency" delete missiles
|
|
**-----------------------------------------------------------------------*/
|
|
void ClearMissileSpot(int mi)
|
|
{
|
|
app_assert(mi < MAXMISSILES);
|
|
dFlags[missile[mi]._mix][missile[mi]._miy] &= BFMASK_MISSILE;
|
|
dMissile[missile[mi]._mix][missile[mi]._miy] = 0;
|
|
}
|