mirror of
https://github.com/jmarshall23/Hellfire.git
synced 2026-08-12 07:50:53 +02:00
4760 lines
142 KiB
C++
4760 lines
142 KiB
C++
/*-----------------------------------------------------------------------**
|
|
** Diablo
|
|
**
|
|
** Player file
|
|
**
|
|
** (C)1995 Condor, Inc. All rights reserved.
|
|
**
|
|
**-----------------------------------------------------------------------**
|
|
** $Header: /Diablo/PLAYER.CPP 11 10-03-97 13:40 Jmcreynolds $
|
|
**-----------------------------------------------------------------------**
|
|
**
|
|
** File Routines
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
#include "diablo.h"
|
|
#pragma hdrstop
|
|
#include "storm/h/storm.h"
|
|
#include "sound.h"
|
|
#include "msg.h"
|
|
#include "multi.h"
|
|
#include "debug.h"
|
|
#include "engine.h"
|
|
#include "gendung.h"
|
|
#include "palette.h"
|
|
#include "items.h"
|
|
#include "player.h"
|
|
#include "monster.h"
|
|
#include "missiles.h"
|
|
#include "spells.h"
|
|
#include "inv.h"
|
|
#include "lighting.h"
|
|
#include "cursor.h"
|
|
#include "control.h"
|
|
#include "effects.h"
|
|
#include "objects.h"
|
|
#include "town.h"
|
|
#include "towners.h"
|
|
#include "monstint.h"
|
|
#include "monstdat.h"
|
|
#include "gamemenu.h"
|
|
#include "stores.h"
|
|
#include "spelldat.h"
|
|
#include "path.h"
|
|
#include "quests.h"
|
|
#include "minitext.h"
|
|
#include "textdat.h"
|
|
#include "portal.h"
|
|
#include "themes.h"
|
|
#include "objdat.h"
|
|
|
|
void SetPlrHandItem(ItemStruct *h, int idata);
|
|
void GetPlrHandSeed(ItemStruct *h);
|
|
void GetGoldSeed(int pnum, ItemStruct *h);
|
|
void SetPrlHandSeed(ItemStruct *h, int iseed);
|
|
void FixPlrWalkTags(int pnum);
|
|
void RemovePlrFromMap(int pnum);
|
|
void SetPlrHandGoldCurs(ItemStruct *h);
|
|
|
|
extern BOOL GoldAutoPlace(int pnum);
|
|
extern HSARCHIVE ghsHFBardArchive;
|
|
extern HSARCHIVE ghsHFBarbarianArchive;
|
|
/*-----------------------------------------------------------------------*
|
|
** Global Variables
|
|
**-----------------------------------------------------------------------*/
|
|
// pjw.patch1.start
|
|
// PlayerStruct plr[MAX_PLRS];
|
|
PlayerStruct * plr = NULL;
|
|
// pjw.patch1.end
|
|
int myplr;
|
|
int deathdelay;
|
|
BOOL deathflag;
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** File Variables
|
|
**-----------------------------------------------------------------------*/
|
|
// Init View offsets
|
|
int plrxoff[9] = { 0, 2, 0, 2, 1, 0, 1, 2, 1 };
|
|
int plryoff[9] = { 0, 2, 2, 0, 1, 1, 0, 1, 2 };
|
|
|
|
int plrxoff2[9] = { 0, 1, 0, 1, 2, 0, 1, 2, 2 };
|
|
int plryoff2[9] = { 0, 0, 1, 1, 0, 2, 2, 1, 2 };
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
char PlrGFXAnimLens[NUM_CLASSES][11] = {
|
|
// Warrior
|
|
// AS, AT, AW, BL, DT, Magic, HT, ST, WL, AFrame, SFrame
|
|
{ 10, 16, 8, 2, 20, 20, 6, 20, 8, 9, 14 },
|
|
// Rogue
|
|
// AS, AT, AW, BL, DT, Magic, HT, ST, WL, AFrame, SFrame
|
|
{ 8, 18, 8, 4, 20, 16, 7, 20, 8, 10, 12 },
|
|
// Sorceror
|
|
// AS, AT, AW, BL, DT, Magic, HT, ST, WL, AFrame, SFrame
|
|
{ 8, 16, 8, 6, 20, 12, 8, 20, 8, 12, 8 },
|
|
// Monk
|
|
// AS, AT, AW, BL, DT, Magic, HT, ST, WL, AFrame, SFrame
|
|
{ 8, 16, 8, 3, 20, 18, 6, 20, 8, 12, 13 },
|
|
// Fix this when we get art.
|
|
// Bard
|
|
// AS, AT, AW, BL, DT, Magic, HT, ST, WL, AFrame, SFrame
|
|
{ 8, 18, 8, 4, 20, 16, 7, 20, 8, 10, 12 },
|
|
// Barbarian
|
|
// AS, AT, AW, BL, DT, Magic, HT, ST, WL, AFrame, SFrame
|
|
{ 10, 16, 8, 2, 20, 20, 6, 20, 8, 9, 14 },
|
|
};
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
// Different walk velocities for different classes
|
|
int PlrWalkTbl[NUM_CLASSES][3] = {
|
|
{ 2048, 1024, 512 }, // Warrior (8 frames)
|
|
//{ 2730, 1365, 682 }, // Warrior (6 frames)
|
|
{ 2048, 1024, 512 }, // Rogue (8 frames)
|
|
//{ 2340, 1170, 585 }, // Rogue (7 frames)
|
|
{ 2048, 1024, 512 }, // Sorceror (8 frames)
|
|
{ 2048, 1024, 512 }, // Monk (8 frames)
|
|
{ 2048, 1024, 512 }, // Bard (8 frames)
|
|
{ 2048, 1024, 512 } }; // Barbarian (8 frames)
|
|
|
|
// Different walk lengths for different classes
|
|
//int PlrWalkLenTbl[3] = { 6, 7, 8 };
|
|
int PlrWalkLenTbl[NUM_CLASSES] = { 8, 8, 8, 8, 8, 8 };
|
|
|
|
extern DWORD gbWalkOn; // double speed walk
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
int StrengthTbl[NUM_CLASSES] = { 30, 20, 15, 25, 20, 40};
|
|
int MagicTbl[NUM_CLASSES] = { 10, 15, 35, 15, 20, 0};
|
|
int DexterityTbl[NUM_CLASSES] = { 20, 30, 15, 25, 25, 20};
|
|
int VitalityTbl[NUM_CLASSES] = { 25, 20, 20, 20, 20, 25};
|
|
|
|
//int ToHitTbl[NUM_CLASSES] = { 50, 50, 50 };
|
|
int ToBlkTbl[NUM_CLASSES] = { 30, 20, 10, 25, 25, 30};
|
|
|
|
char *ClassStrTbl[NUM_CLASSES] = { "Warrior",
|
|
"Rogue",
|
|
"Sorceror",
|
|
"Monk",
|
|
"Bard",
|
|
"Barbarian" };
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
int MaxStats[NUM_CLASSES][4] = {
|
|
// Str, Mag, Dex, Vit.
|
|
{ 250, 50, 60, 100 }, // warrior
|
|
{ 55, 70, 250, 80 }, // rogue
|
|
{ 45, 250, 85, 80 }, // sorceror
|
|
{ 150, 80, 150, 80 }, // monk
|
|
{ 120, 120, 120, 100 }, // bard
|
|
{ 255, 0, 55, 150 }, // barbarian
|
|
};
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
#define MAX_EXPLVLS 50
|
|
|
|
long ExpLvlsTbl[MAX_EXPLVLS+1] = {
|
|
/* 0, // 0 Changed 11/5 Dave
|
|
1000, // 1
|
|
2400, // 2
|
|
4353, // 3
|
|
7070, // 4
|
|
10837, // 5
|
|
16044, // 6
|
|
23217, // 7
|
|
33065, // 8
|
|
46542, // 9
|
|
64925, // 10
|
|
89917, // 11
|
|
123782, // 12
|
|
169516, // 13*/
|
|
|
|
0, // 0
|
|
2000, // 1
|
|
4620, // 2
|
|
8040, // 3
|
|
12489, // 4
|
|
18258, // 5
|
|
25712, // 6
|
|
35309, // 7
|
|
47622, // 8
|
|
63364, // 9
|
|
83419, // 10
|
|
108879, // 11
|
|
141086, // 12
|
|
181683, // 13
|
|
231075, // 14
|
|
313656, // 15
|
|
424067, // 16
|
|
571190, // 17
|
|
766569, // 18
|
|
1025154, // 19
|
|
1366227, // 10
|
|
1814568, // 21
|
|
2401895, // 22
|
|
3168651, // 23
|
|
4166200, // 24
|
|
5459523, // 25
|
|
7130496, // 26
|
|
9281874, // 27
|
|
12042092, // 28
|
|
15571031, // 29
|
|
20066900, // 30
|
|
25774405, // 31
|
|
32994399, // 32
|
|
42095202, // 33
|
|
53525811, // 34
|
|
67831218, // 35
|
|
85670061, // 36
|
|
107834823, // 37
|
|
135274799, // 38
|
|
169122009, // 39
|
|
210720231, // 40
|
|
261657253, // 41
|
|
323800420, // 42
|
|
399335440, // 43
|
|
490808349, // 44
|
|
601170414, // 45
|
|
733825617, // 46
|
|
892680222, // 47
|
|
1082908612, // 48
|
|
1310707109, // 49
|
|
1583495809 }; // 50
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** player animation files
|
|
**-----------------------------------------------------------------------*/
|
|
static const char plrgfxlmh[] = "LMH";
|
|
static const char plrgfxweap[] = "NUSDBAMHT";
|
|
static const char sgcCharClass[NUM_CLASSES] = { 'W', 'R', 'S', 'M', 'B', 'C' };
|
|
static const char sgcAlterCharClass[NUM_CLASSES] = { 'W', 'R', 'S', 'M', 'R', 'W'};
|
|
static const char * const sgpszCharDir[NUM_CLASSES] = {
|
|
"Warrior","Rogue","Sorceror","Monk","Bard","Barbarian"
|
|
};
|
|
static const char * const sgpszAlterCharDir[NUM_CLASSES] = {
|
|
"Warrior","Rogue","Sorceror","Monk","Rogue","Warrior"
|
|
};
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void SetAnimPtrs(BYTE *pData, BYTE *pAnim[]) {
|
|
for (int i = 0; i < 8; i++)
|
|
pAnim[i] = pData + ((DWORD*)pData)[i];
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** loads player anims based on bit flags
|
|
**-----------------------------------------------------------------------*/
|
|
void LoadPlrGFX(int pnum,DWORD dwLoad) {
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("LoadPlrGFX: illegal player %d",pnum);
|
|
// get a pointer to the player
|
|
PlayerStruct * pPlayer = &plr[pnum];
|
|
|
|
// calculate which player type, weapon and armor values to use
|
|
#if IS_VERSION(SHAREWARE)
|
|
app_assert(pPlayer->_pClass == CLASS_WARRIOR);
|
|
#else
|
|
app_assert((DWORD) pPlayer->_pClass <= NUM_CLASSES);
|
|
#endif
|
|
|
|
char szPlrType[16];
|
|
char const * pszPlrPath = "";
|
|
if ((pPlayer->_pClass == CLASS_BARD && ghsHFBardArchive == NULL)
|
|
|| (pPlayer->_pClass == CLASS_BARBARIAN && ghsHFBarbarianArchive == NULL))
|
|
{
|
|
sprintf(
|
|
szPlrType,
|
|
"%c%c%c",
|
|
sgcAlterCharClass[pPlayer->_pClass], // player class
|
|
plrgfxlmh[pPlayer->_pgfxnum >> PGFX_CSHIFT], // armor class
|
|
plrgfxweap[pPlayer->_pgfxnum & PGFX_MASK] // weapon
|
|
);
|
|
pszPlrPath = sgpszAlterCharDir[pPlayer->_pClass];
|
|
} else {
|
|
sprintf(
|
|
szPlrType,
|
|
"%c%c%c",
|
|
sgcCharClass[pPlayer->_pClass], // player class
|
|
plrgfxlmh[pPlayer->_pgfxnum >> PGFX_CSHIFT], // armor class
|
|
plrgfxweap[pPlayer->_pgfxnum & PGFX_MASK] // weapon
|
|
);
|
|
pszPlrPath = sgpszCharDir[pPlayer->_pClass];
|
|
}
|
|
// get player directory
|
|
|
|
// load file
|
|
BYTE * pData;
|
|
BYTE ** ppAnim;
|
|
const char * pszAnim;
|
|
for (DWORD dwBit = 1; dwBit <= PGL_ALL; dwBit <<= 1) {
|
|
// load this graphic set?
|
|
if (! (dwBit & dwLoad)) continue;
|
|
|
|
switch (dwBit) {
|
|
|
|
case PGL_STAND:
|
|
// load dungeon/town stand
|
|
pszAnim = leveltype ? "AS" : "ST";
|
|
pData = pPlayer->_pNData;
|
|
ppAnim = pPlayer->_pNAnim;
|
|
break;
|
|
|
|
case PGL_WALK:
|
|
// load dungeon/town walk
|
|
pszAnim = leveltype ? "AW" : "WL";
|
|
pData = pPlayer->_pWData;
|
|
ppAnim = pPlayer->_pWAnim;
|
|
break;
|
|
|
|
case PGL_DEAD:
|
|
// dead anim only valid for guy holding no weapons
|
|
if ((pPlayer->_pgfxnum & PGFX_MASK) != PGFX_NGUY) continue;
|
|
pszAnim = "DT";
|
|
pData = pPlayer->_pDData;
|
|
ppAnim = pPlayer->_pDAnim;
|
|
break;
|
|
|
|
case PGL_ATTACK:
|
|
if (! leveltype) continue;
|
|
pszAnim = "AT";
|
|
pData = pPlayer->_pAData;
|
|
ppAnim = pPlayer->_pAAnim;
|
|
break;
|
|
|
|
case PGL_HIT:
|
|
if (! leveltype) continue;
|
|
pszAnim = "HT";
|
|
pData = pPlayer->_pHData;
|
|
ppAnim = pPlayer->_pHAnim;
|
|
break;
|
|
|
|
case PGL_LMAG:
|
|
if (! leveltype) continue;
|
|
pszAnim = "LM";
|
|
pData = pPlayer->_pLData;
|
|
ppAnim = pPlayer->_pLAnim;
|
|
break;
|
|
|
|
case PGL_FMAG:
|
|
if (! leveltype) continue;
|
|
pszAnim = "FM";
|
|
pData = pPlayer->_pFData;
|
|
ppAnim = pPlayer->_pFAnim;
|
|
break;
|
|
|
|
case PGL_TMAG:
|
|
if (! leveltype) continue;
|
|
pszAnim = "QM";
|
|
pData = pPlayer->_pTData;
|
|
ppAnim = pPlayer->_pTAnim;
|
|
break;
|
|
|
|
case PGL_BLOCK:
|
|
if (! leveltype) continue;
|
|
if (! pPlayer->_pBlockFlag) continue;
|
|
pszAnim = "BL";
|
|
pData = pPlayer->_pBData;
|
|
ppAnim = pPlayer->_pBAnim;
|
|
break;
|
|
|
|
default:
|
|
app_fatal("PLR:2");
|
|
break;
|
|
}
|
|
|
|
char szBuf[256];
|
|
sprintf(
|
|
szBuf,
|
|
#if RLE_DRAW
|
|
"PlrGFX\\%s\\%s\\%s%s.CL2",
|
|
#else
|
|
"PlrGFX\\%s\\%s\\%s%s.CEL",
|
|
#endif
|
|
pszPlrPath,
|
|
szPlrType,
|
|
szPlrType,
|
|
pszAnim
|
|
);
|
|
|
|
app_assert(pData);
|
|
LoadFileWithMem(szBuf,pData);
|
|
SetAnimPtrs(pData,ppAnim);
|
|
pPlayer->_pGFXLoad |= dwBit;
|
|
}
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** loads all player anims
|
|
**-----------------------------------------------------------------------*/
|
|
void InitPlayerGFX(int pnum) {
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("InitPlayerGFX: illegal player %d",pnum);
|
|
if ((plr[pnum]._pHitPoints >> HP_SHIFT) == 0) {
|
|
plr[pnum]._pgfxnum = PGFX_NGUY;
|
|
LoadPlrGFX(pnum, PGL_DEAD);
|
|
} else {
|
|
LoadPlrGFX(pnum,PGL_ALL);
|
|
}
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
static DWORD calc_plr_mem(const char * pszAnim) {
|
|
DWORD dwMax = 0;
|
|
|
|
for (DWORD dwClass = 0; dwClass < NUM_CLASSES; dwClass++) {
|
|
#if IS_VERSION(SHAREWARE)
|
|
if (dwClass != CLASS_WARRIOR) continue;
|
|
#endif
|
|
|
|
for (const char * pszArmor = plrgfxlmh; *pszArmor; pszArmor++) {
|
|
#if IS_VERSION(SHAREWARE)
|
|
if (pszArmor != plrgfxlmh) break;
|
|
#endif
|
|
|
|
for (const char * pszWeap = plrgfxweap; *pszWeap; pszWeap++) {
|
|
char szPlrType[16];
|
|
char szBuf[256];
|
|
|
|
if ((dwClass == CLASS_BARD && ghsHFBardArchive == NULL)
|
|
|| (dwClass == CLASS_BARBARIAN && ghsHFBarbarianArchive == NULL))
|
|
{
|
|
sprintf( szPlrType, "%c%c%c",
|
|
sgcAlterCharClass[dwClass],
|
|
*pszArmor,
|
|
*pszWeap );
|
|
sprintf( szBuf,
|
|
#if RLE_DRAW
|
|
"PlrGFX\\%s\\%s\\%s%s.CL2",
|
|
#else
|
|
"PlrGFX\\%s\\%s\\%s%s.CEL",
|
|
#endif
|
|
sgpszAlterCharDir[dwClass],
|
|
szPlrType,
|
|
szPlrType,
|
|
pszAnim
|
|
); //whew
|
|
} else {
|
|
sprintf( szPlrType, "%c%c%c",
|
|
sgcCharClass[dwClass],
|
|
*pszArmor,
|
|
*pszWeap );
|
|
sprintf( szBuf,
|
|
#if RLE_DRAW
|
|
"PlrGFX\\%s\\%s\\%s%s.CL2",
|
|
#else
|
|
"PlrGFX\\%s\\%s\\%s%s.CEL",
|
|
#endif
|
|
sgpszCharDir[dwClass],
|
|
szPlrType,
|
|
szPlrType,
|
|
pszAnim
|
|
); //whew
|
|
}
|
|
|
|
HSFILE hsFile;
|
|
if (! patSFileOpenFile(szBuf,&hsFile,TRUE))
|
|
continue;
|
|
|
|
app_assert(hsFile);
|
|
DWORD dwSize = patSFileGetFileSize(hsFile);
|
|
patSFileCloseFile(hsFile);
|
|
dwMax = max(dwMax,dwSize);
|
|
}
|
|
}
|
|
}
|
|
|
|
return dwMax;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
// remember to update these numbers if we ever add another set of
|
|
// player graphics
|
|
|
|
void InitPlrGFXMem(int pnum) {
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("InitPlrGFXMem: illegal player %d",pnum);
|
|
app_assert(! plr[pnum]._pNData);
|
|
|
|
{
|
|
static DWORD dwMem = (ghsHFBardArchive == NULL && ghsHFBarbarianArchive == NULL )
|
|
? 0x35E28 : max(calc_plr_mem("AS"),calc_plr_mem("ST"));
|
|
plr[pnum]._pNData = DiabloAllocPtrSig(dwMem,'PGFN');
|
|
}
|
|
{
|
|
static DWORD dwMem = (ghsHFBardArchive == NULL && ghsHFBarbarianArchive == NULL)
|
|
? 0x16EB9 : max(calc_plr_mem("AW"),calc_plr_mem("WL"));
|
|
plr[pnum]._pWData = DiabloAllocPtrSig(dwMem,'PGFW');
|
|
}
|
|
{
|
|
static DWORD dwMem = (ghsHFBardArchive == NULL && ghsHFBarbarianArchive == NULL)
|
|
? 0x40047 : calc_plr_mem("AT");
|
|
plr[pnum]._pAData = DiabloAllocPtrSig(dwMem,'PGFA');
|
|
}
|
|
{
|
|
static DWORD dwMem = (ghsHFBardArchive == NULL && ghsHFBarbarianArchive == NULL)
|
|
? 0x16484 : calc_plr_mem("HT");
|
|
plr[pnum]._pHData = DiabloAllocPtrSig(dwMem,'PGFH');
|
|
}
|
|
{
|
|
static DWORD dwMem = (ghsHFBardArchive == NULL && ghsHFBarbarianArchive == NULL)
|
|
? 0x4AD88 : calc_plr_mem("LM");
|
|
plr[pnum]._pLData = DiabloAllocPtrSig(dwMem,'PGFL');
|
|
}
|
|
{
|
|
static DWORD dwMem = (ghsHFBardArchive == NULL && ghsHFBarbarianArchive == NULL)
|
|
? 0x67AED : calc_plr_mem("FM");
|
|
plr[pnum]._pFData = DiabloAllocPtrSig(dwMem,'PGFF');
|
|
}
|
|
{
|
|
static DWORD dwMem = (ghsHFBardArchive == NULL && ghsHFBarbarianArchive == NULL)
|
|
? 0x92F55 : calc_plr_mem("QM");
|
|
plr[pnum]._pTData = DiabloAllocPtrSig(dwMem,'PGFT');
|
|
}
|
|
{
|
|
static DWORD dwMem = (ghsHFBardArchive == NULL && ghsHFBarbarianArchive == NULL)
|
|
? 0x3A8A6 : calc_plr_mem("DT");
|
|
plr[pnum]._pDData = DiabloAllocPtrSig(dwMem,'PGFD');
|
|
}
|
|
{
|
|
static DWORD dwMem = (ghsHFBardArchive == NULL && ghsHFBarbarianArchive == NULL)
|
|
? 0x10FE3 : calc_plr_mem("BL");
|
|
plr[pnum]._pBData = DiabloAllocPtrSig(dwMem,'PGFB');
|
|
}
|
|
|
|
// no gfx loaded
|
|
plr[pnum]._pGFXLoad = 0;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void FreePlayerGFX(int pnum) {
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("FreePlayerGFX: illegal player %d",pnum);
|
|
DiabloFreePtr(plr[pnum]._pNData);
|
|
DiabloFreePtr(plr[pnum]._pWData);
|
|
DiabloFreePtr(plr[pnum]._pAData);
|
|
DiabloFreePtr(plr[pnum]._pHData);
|
|
DiabloFreePtr(plr[pnum]._pLData);
|
|
DiabloFreePtr(plr[pnum]._pFData);
|
|
DiabloFreePtr(plr[pnum]._pTData);
|
|
DiabloFreePtr(plr[pnum]._pDData);
|
|
DiabloFreePtr(plr[pnum]._pBData);
|
|
plr[pnum]._pGFXLoad = 0;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void NewPlrAnim(int pnum, BYTE *pAnim, int numFrames, int Delay, long width)
|
|
{
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("NewPlrAnim: illegal player %d",pnum);
|
|
plr[pnum]._pAnimData = pAnim;
|
|
plr[pnum]._pAnimLen = numFrames;
|
|
plr[pnum]._pAnimFrame = 1;
|
|
plr[pnum]._pAnimCnt = 0;
|
|
plr[pnum]._pAnimDelay = Delay;
|
|
plr[pnum]._pAnimWidth = width;
|
|
plr[pnum]._pAnimWidth2 = (width - 64) >> 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void ClearPlrPVars(int pnum)
|
|
{
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("ClearPlrPVars: illegal player %d",pnum);
|
|
plr[pnum]._pVar1 = 0;
|
|
plr[pnum]._pVar2 = 0;
|
|
plr[pnum]._pVar3 = 0;
|
|
plr[pnum]._pVar4 = 0;
|
|
plr[pnum]._pVar5 = 0;
|
|
plr[pnum]._pVar6 = 0;
|
|
plr[pnum]._pVar7 = 0;
|
|
plr[pnum]._pVar8 = 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void SetPlrAnims(int pnum)
|
|
{
|
|
int gn,pc;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("SetPlrAnims: illegal player %d",pnum);
|
|
plr[pnum]._pNWidth = 96;
|
|
plr[pnum]._pWWidth = 96;
|
|
plr[pnum]._pAWidth = 128;
|
|
plr[pnum]._pHWidth = 96;
|
|
plr[pnum]._pSWidth = 96;
|
|
plr[pnum]._pDWidth = 128;
|
|
plr[pnum]._pBWidth = 96;
|
|
|
|
pc = plr[pnum]._pClass;
|
|
if (leveltype == 0) {
|
|
plr[pnum]._pNFrames = PlrGFXAnimLens[pc][7];
|
|
plr[pnum]._pWFrames = PlrGFXAnimLens[pc][8];
|
|
plr[pnum]._pDFrames = PlrGFXAnimLens[pc][4];
|
|
plr[pnum]._pSFrames = PlrGFXAnimLens[pc][5];
|
|
plr[pnum]._pSFNum = PlrGFXAnimLens[pc][10];
|
|
}
|
|
else {
|
|
plr[pnum]._pNFrames = PlrGFXAnimLens[pc][0];
|
|
plr[pnum]._pWFrames = PlrGFXAnimLens[pc][2];
|
|
plr[pnum]._pAFrames = PlrGFXAnimLens[pc][1];
|
|
plr[pnum]._pHFrames = PlrGFXAnimLens[pc][6];
|
|
plr[pnum]._pSFrames = PlrGFXAnimLens[pc][5];
|
|
plr[pnum]._pDFrames = PlrGFXAnimLens[pc][4];
|
|
plr[pnum]._pBFrames = PlrGFXAnimLens[pc][3];
|
|
plr[pnum]._pAFNum = PlrGFXAnimLens[pc][9];
|
|
plr[pnum]._pSFNum = PlrGFXAnimLens[pc][10];
|
|
}
|
|
|
|
gn = plr[pnum]._pgfxnum & PGFX_MASK;
|
|
if (pc == CLASS_WARRIOR) {
|
|
if (gn == PGFX_BGUY) { // Bow
|
|
if (leveltype != 0) plr[pnum]._pNFrames = 8;
|
|
plr[pnum]._pAWidth = 96;
|
|
plr[pnum]._pAFNum = 11;
|
|
}
|
|
else if (gn == PGFX_FGUY) { // Axe
|
|
plr[pnum]._pAFrames = 20;
|
|
plr[pnum]._pAFNum = 10;
|
|
}
|
|
else if (gn == PGFX_TGUY) { // Staff
|
|
plr[pnum]._pAFrames = 16;
|
|
plr[pnum]._pAFNum = 11;
|
|
}
|
|
}
|
|
#if !IS_VERSION(SHAREWARE)
|
|
else if (pc == CLASS_ROGUE) {
|
|
if (gn == PGFX_FGUY) { // Axe
|
|
plr[pnum]._pAFrames = 22;
|
|
plr[pnum]._pAFNum = 13;
|
|
}
|
|
else if (gn == PGFX_BGUY) { // Bow
|
|
plr[pnum]._pAFrames = 12;
|
|
plr[pnum]._pAFNum = 7;
|
|
}
|
|
else if (gn == PGFX_TGUY) { // Staff
|
|
plr[pnum]._pAFrames = 16;
|
|
plr[pnum]._pAFNum = 11;
|
|
}
|
|
}
|
|
else if (pc == CLASS_SORCEROR) {
|
|
plr[pnum]._pSWidth = 128;
|
|
|
|
if (gn == PGFX_NGUY) { // No weapon
|
|
plr[pnum]._pAFrames = 20;
|
|
}
|
|
else if (gn == PGFX_SGUY) { // Shield only
|
|
plr[pnum]._pAFNum = 9;
|
|
}
|
|
else if (gn == PGFX_BGUY) { // Bow
|
|
plr[pnum]._pAFrames = 20;
|
|
plr[pnum]._pAFNum = 16;
|
|
}
|
|
else if (gn == PGFX_FGUY) { // Axe
|
|
plr[pnum]._pAFrames = 24;
|
|
plr[pnum]._pAFNum = 16;
|
|
}
|
|
}
|
|
|
|
else if (pc == CLASS_MONK)
|
|
{
|
|
plr[pnum]._pNWidth = 112;
|
|
plr[pnum]._pWWidth = 112;
|
|
plr[pnum]._pAWidth = 130;
|
|
plr[pnum]._pHWidth = 98;
|
|
plr[pnum]._pSWidth = 114;
|
|
plr[pnum]._pDWidth = 160;
|
|
plr[pnum]._pBWidth = 98;
|
|
|
|
switch(gn)
|
|
{
|
|
case PGFX_NGUY:
|
|
case PGFX_SGUY: // may want to slow this down
|
|
plr[pnum]._pAFrames = 12;
|
|
plr[pnum]._pAFNum = 7;
|
|
break;
|
|
case PGFX_BGUY:
|
|
plr[pnum]._pAFrames = 20;
|
|
plr[pnum]._pAFNum = 14;
|
|
break;
|
|
case PGFX_FGUY:
|
|
plr[pnum]._pAFrames = 23;
|
|
plr[pnum]._pAFNum = 14;
|
|
break;
|
|
case PGFX_TGUY:
|
|
plr[pnum]._pAFrames = 13;
|
|
plr[pnum]._pAFNum = 8;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
//
|
|
// Fix this when the art arrives.
|
|
//
|
|
//
|
|
else if (pc == CLASS_BARD)
|
|
{
|
|
if (gn == PGFX_FGUY) { // Axe
|
|
plr[pnum]._pAFrames = 22;
|
|
plr[pnum]._pAFNum = 13;
|
|
}
|
|
else if (gn == PGFX_BGUY) { // Bow
|
|
plr[pnum]._pAFrames = 12;
|
|
plr[pnum]._pAFNum = 11;
|
|
}
|
|
else if (gn == PGFX_TGUY) { // Staff
|
|
plr[pnum]._pAFrames = 16;
|
|
plr[pnum]._pAFNum = 11;
|
|
}
|
|
else if (gn == PGFX_GUY) { // Sword and shield
|
|
plr[pnum]._pAFNum = 10;
|
|
}
|
|
else if (gn == PGFX_XGUY) { // Sword
|
|
plr[pnum]._pAFNum = 10;
|
|
}
|
|
}
|
|
else if (pc == CLASS_BARBARIAN)
|
|
{
|
|
if (gn == PGFX_FGUY) { // Axe
|
|
plr[pnum]._pAFrames = 20;
|
|
plr[pnum]._pAFNum = 8;
|
|
}
|
|
else if (gn == PGFX_BGUY) { // Bow
|
|
if (leveltype != 0) plr[pnum]._pNFrames = 8;
|
|
plr[pnum]._pAWidth = 96;
|
|
plr[pnum]._pAFNum = 11;
|
|
}
|
|
else if (gn == PGFX_TGUY) { // Staff
|
|
plr[pnum]._pAFrames = 16;
|
|
plr[pnum]._pAFNum = 11;
|
|
}
|
|
else if (gn == PGFX_ZGUY) { // Mace
|
|
plr[pnum]._pAFNum = 8;
|
|
}
|
|
else if (gn == PGFX_CGUY) { // Mace with Shield
|
|
plr[pnum]._pAFNum = 8;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void PlrInitReserved(PlayerStruct * p) {
|
|
app_assert(p != NULL);
|
|
// REMEMBER -- every time you remove a variable from this
|
|
// list to rename it, it MUST be initialized in CreatePlayer()
|
|
// or you will screw up the character with unitialized data!!!!
|
|
// ALSO -- you MUST initialize the variable in UnPackPlayer()
|
|
// in packplr.cpp!!!
|
|
p->bReserved5 = 0;
|
|
p->bReserved6 = 0;
|
|
p->bReserved7 = 0;
|
|
p->bReserved8 = 0;
|
|
|
|
p->wReserved2 = 0;
|
|
p->wReserved3 = 0;
|
|
p->wReserved4 = 0;
|
|
p->wReserved5 = 0;
|
|
p->wReserved6 = 0;
|
|
p->wReserved7 = 0;
|
|
p->wReserved8 = 0;
|
|
|
|
p->dwReserved4 = 0;
|
|
p->dwReserved5 = 0;
|
|
p->dwReserved6 = 0;
|
|
p->dwReserved7 = 0;
|
|
p->dwReserved8 = 0;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void CreatePlayer(int pnum, char c) {
|
|
|
|
// This isn't good C++ but it beats the lack of initialization currently done.
|
|
memset(&plr[pnum], 0, sizeof(PlayerStruct));
|
|
PlrInitReserved(&plr[pnum]);
|
|
|
|
int i;
|
|
char vc;
|
|
|
|
// dig.patch1.start.2/4/97
|
|
// time() returns -1 if clock is set far ahead, e.g., the year 2097.
|
|
// Many customers have broken clock, resulting in all games being the same.
|
|
|
|
// SetRndSeed((int) time(NULL));
|
|
SetRndSeed((int) GetTickCount());
|
|
// dig.patch1.end.2/4/97
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("CreatePlayer: illegal player %d",pnum);
|
|
plr[pnum]._pClass = c;
|
|
|
|
vc = StrengthTbl[c];
|
|
if (vc < 0) vc = 0;
|
|
plr[pnum]._pStrength = vc;
|
|
plr[pnum]._pBaseStr = vc;
|
|
vc = MagicTbl[c];
|
|
if (vc < 0) vc = 0;
|
|
plr[pnum]._pMagic = vc;
|
|
plr[pnum]._pBaseMag = vc;
|
|
vc = DexterityTbl[c];
|
|
if (vc < 0) vc = 0;
|
|
plr[pnum]._pDexterity = vc;
|
|
plr[pnum]._pBaseDex = vc;
|
|
vc = VitalityTbl[c];
|
|
if (vc < 0) vc = 0;
|
|
plr[pnum]._pVitality = vc;
|
|
plr[pnum]._pBaseVit = vc;
|
|
|
|
plr[pnum]._pStatPts = 0;
|
|
|
|
plr[pnum].pTownWarps = 0;
|
|
plr[pnum].pDungMsgs = 0;
|
|
plr[pnum].pHellfireMsgs = 0;
|
|
plr[pnum].pLvlLoad = 0;
|
|
plr[pnum].pDiabloKillLevel = 0;
|
|
plr[pnum]._gnDifficulty = D_NORMAL;
|
|
|
|
|
|
if (plr[pnum]._pClass == CLASS_MONK)
|
|
plr[pnum]._pDamageMod = ((plr[pnum]._pStrength + plr[pnum]._pDexterity) * plr[pnum]._pLevel) / 150;
|
|
else if (plr[pnum]._pClass == CLASS_ROGUE ||
|
|
plr[pnum]._pClass == CLASS_BARD)
|
|
plr[pnum]._pDamageMod = ((plr[pnum]._pStrength + plr[pnum]._pDexterity) * plr[pnum]._pLevel) / 200;
|
|
else // Warrior and Barbarian
|
|
plr[pnum]._pDamageMod = (plr[pnum]._pStrength * plr[pnum]._pLevel) / 100;
|
|
plr[pnum]._pBaseToBlk = ToBlkTbl[c];
|
|
|
|
plr[pnum]._pHitPoints = (plr[pnum]._pVitality + 10) << HP_SHIFT;
|
|
if (plr[pnum]._pClass == CLASS_WARRIOR
|
|
|| plr[pnum]._pClass == CLASS_BARBARIAN ) plr[pnum]._pHitPoints = plr[pnum]._pHitPoints << 1;
|
|
else if (plr[pnum]._pClass == CLASS_ROGUE ||
|
|
plr[pnum]._pClass == CLASS_MONK ||
|
|
plr[pnum]._pClass == CLASS_BARD) plr[pnum]._pHitPoints += (plr[pnum]._pHitPoints >> 1);
|
|
plr[pnum]._pMaxHP = plr[pnum]._pHitPoints;
|
|
plr[pnum]._pHPBase = plr[pnum]._pHitPoints;
|
|
plr[pnum]._pMaxHPBase = plr[pnum]._pHitPoints;
|
|
|
|
plr[pnum]._pMana = plr[pnum]._pMagic << MANA_SHIFT;
|
|
if (plr[pnum]._pClass == CLASS_SORCEROR) plr[pnum]._pMana = plr[pnum]._pMana << 1; // 2x
|
|
else if( plr[pnum]._pClass == CLASS_BARD) plr[pnum]._pMana += (plr[pnum]._pMana * 3)/4; // 1.75
|
|
else if (plr[pnum]._pClass == CLASS_ROGUE ||
|
|
plr[pnum]._pClass == CLASS_MONK ) plr[pnum]._pMana += (plr[pnum]._pMana >> 1); // 1.5x
|
|
plr[pnum]._pMaxMana = plr[pnum]._pMana;
|
|
plr[pnum]._pManaBase = plr[pnum]._pMana;
|
|
plr[pnum]._pMaxManaBase = plr[pnum]._pMana;
|
|
|
|
plr[pnum]._pLevel = 1;
|
|
plr[pnum]._pMaxLvl = plr[pnum]._pLevel;
|
|
|
|
plr[pnum]._pExperience = 0;
|
|
plr[pnum]._pMaxExp = plr[pnum]._pExperience;
|
|
plr[pnum]._pNextExper = ExpLvlsTbl[1];
|
|
|
|
plr[pnum]._pArmorClass = 0;
|
|
|
|
if (plr[pnum]._pClass == CLASS_BARBARIAN) {
|
|
plr[pnum]._pMagResist = 1;
|
|
plr[pnum]._pFireResist = 1;
|
|
plr[pnum]._pLghtResist = 1;
|
|
}
|
|
else {
|
|
plr[pnum]._pMagResist = 0;
|
|
plr[pnum]._pFireResist = 0;
|
|
plr[pnum]._pLghtResist = 0;
|
|
}
|
|
|
|
plr[pnum]._pLightRad = PLRLRAD;
|
|
|
|
plr[pnum]._pInfraFlag = FALSE;
|
|
|
|
if (c == CLASS_WARRIOR) plr[pnum]._pAblSpells = (_int64)(1) << (SPL_REPAIR-1);
|
|
#if !IS_VERSION(SHAREWARE)
|
|
else if (c == CLASS_ROGUE) plr[pnum]._pAblSpells = (_int64)(1) << (SPL_DISARM-1);
|
|
else if (c == CLASS_SORCEROR) plr[pnum]._pAblSpells = (_int64)(1) << (SPL_RECHARGE-1);
|
|
else if (c == CLASS_MONK) plr[pnum]._pAblSpells = (__int64)(1) << (SPL_SHOWMAGITEMS-1);
|
|
else if (c == CLASS_BARD) plr[pnum]._pAblSpells = (_int64)(1) << (SPL_IDENTIFY-1);
|
|
else if (c == CLASS_BARBARIAN) plr[pnum]._pAblSpells = (_int64)(1) << (SPL_RAGE-1);
|
|
#endif
|
|
|
|
if (c == CLASS_SORCEROR) plr[pnum]._pMemSpells = (_int64)(1) << (SPL_FIREBOLT-1);
|
|
else plr[pnum]._pMemSpells = 0;
|
|
|
|
for (i = 0; i < 64; i++)
|
|
plr[pnum]._pSplLvl[i] = 0;
|
|
plr[pnum]._pSpellFlags = 0;
|
|
if (plr[pnum]._pClass == CLASS_SORCEROR)
|
|
plr[pnum]._pSplLvl[SPL_FIREBOLT] = 2;
|
|
|
|
for (i = 0; i < 3; i++) plr[pnum]._pSplHotKey[i] = -1;
|
|
|
|
if (c == CLASS_WARRIOR) plr[pnum]._pgfxnum = PGFX_GUY;
|
|
#if !IS_VERSION(SHAREWARE)
|
|
else if (c == CLASS_ROGUE) plr[pnum]._pgfxnum = PGFX_BGUY;
|
|
else if (c == CLASS_SORCEROR) plr[pnum]._pgfxnum = PGFX_TGUY;
|
|
else if (c == CLASS_MONK) plr[pnum]._pgfxnum = PGFX_TGUY;
|
|
else if (c == CLASS_BARD) plr[pnum]._pgfxnum = PGFX_GUY;
|
|
else if (c == CLASS_BARBARIAN) plr[pnum]._pgfxnum = PGFX_GUY;
|
|
#endif
|
|
|
|
for (i = 0; i < NUMLEVELS; i++)
|
|
plr[pnum]._pLvlVisited[i] = FALSE;
|
|
for (i = 0; i < NUMSLEVELS; i++)
|
|
plr[pnum]._pSLvlVisited[i] = FALSE;
|
|
|
|
plr[pnum]._pLvlChanging = FALSE;
|
|
plr[pnum].pTownWarps = 0;
|
|
plr[pnum].pLvlLoad = 0;
|
|
plr[pnum]._pIFlags2 = 0;
|
|
|
|
plr[pnum]._pReflectCount = 0;
|
|
|
|
InitDungMsgs(pnum);
|
|
|
|
CreatePlrItems(pnum);
|
|
|
|
SetRndSeed(0);
|
|
}
|
|
|
|
// drb.patch1.start.2/05/97
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
int CalcStatDiff(int pnum)
|
|
{
|
|
int c = plr[pnum]._pClass;
|
|
int d = MaxStats[c][0] - plr[pnum]._pBaseStr;
|
|
d += MaxStats[c][1] - plr[pnum]._pBaseMag;
|
|
d += MaxStats[c][2] - plr[pnum]._pBaseDex;
|
|
d += MaxStats[c][3] - plr[pnum]._pBaseVit;
|
|
return(d);
|
|
}
|
|
// drb.patch1.end.2/05/97
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void NextPlrLevel(int pnum) {
|
|
long l;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("NextPlrLevel: illegal player %d",pnum);
|
|
plr[pnum]._pLevel++;
|
|
plr[pnum]._pMaxLvl++;
|
|
CalcPlrInv(pnum,TRUE); // added by donald 8/26
|
|
|
|
// drb.patch1.start.2/05/97
|
|
// plr[pnum]._pStatPts += 5;
|
|
if (CalcStatDiff(pnum) < 5) plr[pnum]._pStatPts = CalcStatDiff(pnum);
|
|
else plr[pnum]._pStatPts += 5;
|
|
// drb.patch1.end.2/05/97
|
|
|
|
plr[pnum]._pNextExper = ExpLvlsTbl[plr[pnum]._pLevel];
|
|
|
|
if (plr[pnum]._pClass == CLASS_SORCEROR)
|
|
{
|
|
l = 1 << HP_SHIFT;
|
|
}
|
|
else
|
|
{
|
|
l = 2 << HP_SHIFT;
|
|
}
|
|
|
|
if (gbMaxPlayers == 1) l++;
|
|
plr[pnum]._pMaxHP += l;
|
|
plr[pnum]._pHitPoints = plr[pnum]._pMaxHP;
|
|
plr[pnum]._pMaxHPBase += l;
|
|
plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase;
|
|
if (pnum == myplr) drawhpflag = TRUE;
|
|
|
|
if (plr[pnum]._pClass == CLASS_WARRIOR)
|
|
{
|
|
l = 1 << MANA_SHIFT;
|
|
}
|
|
else if ( plr[pnum]._pClass == CLASS_BARBARIAN)
|
|
{
|
|
l = 0;
|
|
}
|
|
else
|
|
{
|
|
l = 2 << MANA_SHIFT;
|
|
}
|
|
if (gbMaxPlayers == 1) l++;
|
|
plr[pnum]._pMaxMana += l;
|
|
plr[pnum]._pMaxManaBase += l;
|
|
|
|
if (!(plr[pnum]._pIFlags & IAF_LMANA )) {
|
|
plr[pnum]._pMana = plr[pnum]._pMaxMana;
|
|
plr[pnum]._pManaBase = plr[pnum]._pMaxManaBase;
|
|
}
|
|
if (pnum == myplr
|
|
&& plr[pnum]._pMana > 0) drawmanaflag = TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void AddPlrExperience(int pnum, int lvl, long exp)
|
|
{
|
|
if (pnum != myplr) return;
|
|
if ((DWORD)myplr >= MAX_PLRS)
|
|
app_fatal("AddPlrExperience: illegal player %d",myplr);
|
|
if (plr[myplr]._pHitPoints <= 0) return;
|
|
|
|
double v = (1 + (((double)lvl - (double)plr[pnum]._pLevel) * 0.1)) * (double)exp;
|
|
long e = long(v);
|
|
if (e < 0) e = 0;
|
|
|
|
// put limits on how fast you go up levels
|
|
if (gbMaxPlayers > 1) {
|
|
long lLevel = max(0,plr[pnum]._pLevel);
|
|
lLevel = min(lLevel,MAX_EXPLVLS);
|
|
long lMax = ExpLvlsTbl[lLevel] / 20;
|
|
e = min(e,lMax);
|
|
lMax = lLevel * 200;
|
|
e = min(e,lMax);
|
|
}
|
|
|
|
// upgrade player
|
|
plr[pnum]._pExperience += e;
|
|
if ((DWORD) plr[pnum]._pExperience > 2000000000)
|
|
plr[pnum]._pExperience = 2000000000;
|
|
if (plr[pnum]._pExperience >= ExpLvlsTbl[MAX_EXPLVLS-1]) {
|
|
plr[pnum]._pLevel = MAX_EXPLVLS;
|
|
}
|
|
else {
|
|
for (int l = 0; plr[pnum]._pExperience >= ExpLvlsTbl[l]; l++);
|
|
if (l != plr[pnum]._pLevel) {
|
|
l -= plr[pnum]._pLevel;
|
|
for (int i = 0; i < l; i++)
|
|
NextPlrLevel(pnum);
|
|
}
|
|
NetSendCmdParam1(FALSE, CMD_PLRLEVEL, plr[myplr]._pLevel);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void AddPlrMonstExper(int lvl, long exp, char pmask)
|
|
{
|
|
int totplrs = 0;
|
|
for (int i = 0; i < MAX_PLRS; i++)
|
|
if (pmask & (1 << i)) totplrs++;
|
|
|
|
if (totplrs) {
|
|
long myexp = exp / totplrs;
|
|
if (pmask & (1 << myplr)) AddPlrExperience(myplr, lvl, myexp);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void InitPlayer(int pnum, BOOL FirstTime)
|
|
{
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("InitPlayer: illegal player %d",pnum);
|
|
PlrInitReserved(&plr[pnum]);
|
|
|
|
if (FirstTime) {
|
|
/*if (plr[pnum]._pClass == CLASS_WARRIOR) {
|
|
plr[pnum]._pRSpell = SPL_REPAIR;
|
|
plr[pnum]._pRSplType = SPT_ABILITY;
|
|
}
|
|
#if !IS_VERSION(SHAREWARE)
|
|
else if (plr[pnum]._pClass == CLASS_ROGUE) {
|
|
plr[pnum]._pRSpell = SPL_DISARM;
|
|
plr[pnum]._pRSplType = SPT_ABILITY;
|
|
}
|
|
else if (plr[pnum]._pClass == CLASS_SORCEROR) {
|
|
plr[pnum]._pRSpell = SPL_FIREBOLT;
|
|
plr[pnum]._pRSplType = SPT_MEMORIZED;
|
|
}
|
|
else if (plr[pnum]._pClass == CLASS_MONK) {
|
|
plr[pnum]._pRSpell = SPL_SHOWMAGITEMS;
|
|
plr[pnum]._pRSplType = SPT_ABILITY;
|
|
}
|
|
else if (plr[pnum]._pClass == CLASS_BARD) {
|
|
plr[pnum]._pRSpell = SPL_IDENTIFY;
|
|
plr[pnum]._pRSplType = SPT_ABILITY;
|
|
}
|
|
else if (plr[pnum]._pClass == CLASS_BARBARIAN) {
|
|
plr[pnum]._pRSpell = SPL_RAGE;
|
|
plr[pnum]._pRSplType = SPT_ABILITY;
|
|
}
|
|
#endif
|
|
*/
|
|
|
|
plr[pnum]._pRSplType = SPT_NONE;
|
|
plr[pnum]._pRSpell = -1;
|
|
|
|
plr[pnum]._pSBkSpell = -1;
|
|
plr[pnum]._pSpell = plr[pnum]._pRSpell;
|
|
plr[pnum]._pSplType = plr[pnum]._pRSplType;
|
|
|
|
if ((plr[pnum]._pgfxnum & PGFX_MASK) == PGFX_BGUY)
|
|
plr[pnum]._pwtype = WEAP_RANGE;
|
|
else
|
|
plr[pnum]._pwtype = WEAP_H2H;
|
|
}
|
|
|
|
if ((plr[pnum].plrlevel == currlevel) || (leveldebug)) {
|
|
SetPlrAnims(pnum);
|
|
plr[pnum]._pxoff = 0;
|
|
plr[pnum]._pyoff = 0;
|
|
plr[pnum]._pxvel = 0;
|
|
plr[pnum]._pyvel = 0;
|
|
ClearPlrPVars(pnum);
|
|
|
|
if ((plr[pnum]._pHitPoints >> HP_SHIFT) > 0) {
|
|
plr[pnum]._pmode = PM_STAND;
|
|
NewPlrAnim(pnum, plr[pnum]._pNAnim[DIR_D], plr[pnum]._pNFrames, 3, plr[pnum]._pNWidth);
|
|
plr[pnum]._pAnimFrame = random(2, plr[pnum]._pNFrames - 1) + 1;
|
|
plr[pnum]._pAnimCnt = random(2, 3);
|
|
} else {
|
|
plr[pnum]._pmode = PM_DEATH;
|
|
NewPlrAnim(pnum, plr[pnum]._pDAnim[DIR_D], plr[pnum]._pDFrames, 1, plr[pnum]._pDWidth);
|
|
plr[pnum]._pAnimFrame = plr[pnum]._pAnimLen - 1;
|
|
plr[pnum]._pVar8 = plr[pnum]._pAnimLen << 1;
|
|
}
|
|
|
|
plr[pnum]._pdir = DIR_D;
|
|
plr[pnum]._peflag = 0;
|
|
|
|
if (pnum == myplr) {
|
|
// put me in my optimal space
|
|
if ((!FirstTime) || (currlevel != 0)) {
|
|
plr[pnum]._px = ViewX;
|
|
plr[pnum]._py = ViewY;
|
|
}
|
|
plr[pnum]._ptargx = plr[pnum]._px;
|
|
plr[pnum]._ptargy = plr[pnum]._py;
|
|
}
|
|
else {
|
|
// Make other players target position where he is now
|
|
plr[pnum]._ptargx = plr[pnum]._px;
|
|
plr[pnum]._ptargy = plr[pnum]._py;
|
|
|
|
// Find space for player
|
|
for (int i = 0; i < sizeof(plrxoff2)/sizeof(plrxoff2[0]) - 1; i++) {
|
|
if (PosOkPlayer(
|
|
pnum,
|
|
plr[pnum]._px + plrxoff2[i],
|
|
plr[pnum]._py + plryoff2[i]
|
|
)) break;
|
|
}
|
|
plr[pnum]._px += plrxoff2[i];
|
|
plr[pnum]._py += plryoff2[i];
|
|
}
|
|
|
|
plr[pnum]._pfutx = plr[pnum]._px;
|
|
plr[pnum]._pfuty = plr[pnum]._py;
|
|
plr[pnum].walkpath[0] = PCMD_NOTHING; // No buffered walking etc
|
|
plr[pnum].destAction = PCMD_NOTHING;
|
|
|
|
if (pnum == myplr)
|
|
plr[pnum]._plid = AddLight(plr[pnum]._px, plr[pnum]._py, plr[pnum]._pLightRad);
|
|
else
|
|
plr[pnum]._plid = -1;
|
|
plr[pnum]._pvid = AddVision(plr[pnum]._px, plr[pnum]._py,
|
|
plr[pnum]._pLightRad, pnum==myplr);
|
|
}
|
|
|
|
if (plr[pnum]._pClass == CLASS_WARRIOR)
|
|
plr[pnum]._pAblSpells = (_int64)(1) << (SPL_REPAIR-1);
|
|
#if !IS_VERSION(SHAREWARE)
|
|
else if (plr[pnum]._pClass == CLASS_ROGUE)
|
|
plr[pnum]._pAblSpells = (_int64)(1) << (SPL_DISARM-1);
|
|
else if (plr[pnum]._pClass == CLASS_SORCEROR)
|
|
plr[pnum]._pAblSpells = (_int64)(1) << (SPL_RECHARGE-1);
|
|
else if (plr[pnum]._pClass == CLASS_MONK)
|
|
plr[pnum]._pAblSpells = (__int64)(1) << (SPL_SHOWMAGITEMS-1);
|
|
else if (plr[pnum]._pClass == CLASS_BARD)
|
|
plr[pnum]._pAblSpells = (_int64)(1) << (SPL_IDENTIFY-1);
|
|
else if (plr[pnum]._pClass == CLASS_BARBARIAN)
|
|
plr[pnum]._pAblSpells = (_int64)(1) << (SPL_RAGE-1);
|
|
#endif
|
|
|
|
#if CHEATS
|
|
if (simplecheat && FirstTime) {
|
|
plr[pnum]._pMemSpells |= (_int64)(1) << SPL_TELE;
|
|
if (! plr[myplr]._pSplLvl[SPL_TELE])
|
|
plr[myplr]._pSplLvl[SPL_TELE] = 1;
|
|
}
|
|
if (cheatflag && FirstTime) {
|
|
//splhold = plr[pnum]._pMemSpells;
|
|
plr[pnum]._pMemSpells = 0x0fffffffffffffff;
|
|
//plr[pnum]._pMemSpells = 0x0000000000000000 | (((__int64)1) << (SPL_NOVA-1));
|
|
//plr[pnum]._pMemSpells = plr[pnum]._pMemSpells | (((__int64)1) << (SPL_TELE-1));
|
|
}
|
|
#endif
|
|
|
|
plr[pnum]._pNextExper = ExpLvlsTbl[plr[pnum]._pLevel];
|
|
plr[pnum]._pInvincible = FALSE;
|
|
|
|
if (pnum == myplr) {
|
|
deathdelay = 0;
|
|
deathflag = FALSE;
|
|
ScrollInfo._sxoff = 0;
|
|
ScrollInfo._syoff = 0;
|
|
ScrollInfo._sdir = SCRL_NONE;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void InitMultiView()
|
|
{
|
|
if ((DWORD)myplr >= MAX_PLRS)
|
|
app_fatal("InitPlayer: illegal player %d",myplr);
|
|
ViewX = plr[myplr]._px;
|
|
ViewY = plr[myplr]._py;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void CheckEFlag(int pnum, int flag2)
|
|
{
|
|
int tx,ty,tv;
|
|
int t;
|
|
WORD *mt;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("InitPlayer: illegal player %d",pnum);
|
|
tx = plr[pnum]._px - 1;
|
|
ty = plr[pnum]._py + 1;
|
|
tv = 0;
|
|
mt = &dMT2[CalcRot(tx,ty)].mt[0];
|
|
for(t = 2; t < 10; t++)
|
|
tv |= mt[t];
|
|
tv |= dSpecial[tx][ty];
|
|
tv |= nSolidTable[dPiece[tx][ty]];
|
|
if (tv != 0) plr[pnum]._peflag = 1;
|
|
else plr[pnum]._peflag = 0;
|
|
|
|
if ((flag2 == E_DOUBLE) && (plr[pnum]._peflag == 1)) {
|
|
tx = plr[pnum]._px;
|
|
ty = plr[pnum]._py + 2;
|
|
tv = 0;
|
|
mt = &dMT2[CalcRot(tx,ty)].mt[0];
|
|
for(t = 2; t < 10; t++)
|
|
tv |= mt[t];
|
|
tv |= dSpecial[tx][ty];
|
|
if (tv == 0) {
|
|
tx = plr[pnum]._px - 2;
|
|
ty = plr[pnum]._py + 1;
|
|
tv = 0;
|
|
mt = &dMT2[CalcRot(tx,ty)].mt[0];
|
|
for(t = 2; t < 10; t++)
|
|
tv |= mt[t];
|
|
tv |= dSpecial[tx][ty];
|
|
if (tv != 0) plr[pnum]._peflag = 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
int PlrGetDir(int pnum, int i)
|
|
{
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("PlrGetDir: illegal player %d",pnum);
|
|
return GetDirection(plr[pnum]._px, plr[pnum]._py, monster[i]._mx, monster[i]._my);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int PlrGetDirXY(int pnum, int xx, int yy)
|
|
{
|
|
int d;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("PlrGetDirXY: illegal player %d",pnum);
|
|
d = GetDirection(plr[pnum]._px, plr[pnum]._py, xx, yy);
|
|
if ((plr[pnum]._px == xx) && (plr[pnum]._py == yy)) d = plr[pnum]._pdir;
|
|
return (d);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
BOOL SolidLoc(int x, int y) {
|
|
return nSolidTable[dPiece[x][y]];
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
BOOL PlrDirOK(int i, int pdir) {
|
|
if ((DWORD)i >= MAX_PLRS)
|
|
app_fatal("PlrDirOK: illegal player %d",i);
|
|
long fx = plr[i]._px + offset_x[pdir];
|
|
long fy = plr[i]._py + offset_y[pdir];
|
|
if (fx < 0) return FALSE; // SKing fix Dave 4/3
|
|
if (dPiece[fx][fy] == 0) return FALSE;
|
|
if (! PosOkPlayer(i, fx, fy)) return FALSE;
|
|
|
|
BOOL ret = TRUE;
|
|
if(ret && pdir == DIR_R) ret = !SolidLoc(fx, fy+1) && !(dFlags[fx][fy+1] & BFLAG_PLRLR);
|
|
if(ret && pdir == DIR_L) ret = !SolidLoc(fx+1, fy) && !(dFlags[fx+1][fy] & BFLAG_PLRLR);
|
|
// if(ret && pdir == DIR_U) ret = !SolidLoc(fx+1, fy) && !SolidLoc(fx, fy+1);
|
|
// if(ret && pdir == DIR_D) ret = !SolidLoc(fx-1, fy) && !SolidLoc(fx, fy-1);
|
|
return ret;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void PlrClrTrans(int x, int y)
|
|
{
|
|
int i,j;
|
|
char v;
|
|
|
|
for (j = y-1; j <= y+1; j++) {
|
|
for (i = x-1; i <= x+1; i++) {
|
|
v = dTransVal[i][j];
|
|
TransList[v] = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void PlrDoTrans(int x, int y)
|
|
{
|
|
int i,j;
|
|
char v;
|
|
|
|
if ((leveltype == 1) || (leveltype == 2)) {
|
|
for (j = y-1; j <= y+1; j++) {
|
|
for (i = x-1; i <= x+1; i++) {
|
|
if (!nSolidTable[dPiece[i][j]]) {
|
|
v = dTransVal[i][j];
|
|
if (v != 0) TransList[v] = TRUE;
|
|
}
|
|
}
|
|
}
|
|
} else TransList[1] = TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void SetPlayerOld(int pnum)
|
|
{
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("SetPlayerOld: illegal player %d",pnum);
|
|
plr[pnum]._poldx = plr[pnum]._px;
|
|
plr[pnum]._poldy = plr[pnum]._py;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void FixPlayerLocation(int pnum,int bDir)
|
|
{
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("FixPlayerLocation: illegal player %d",pnum);
|
|
plr[pnum]._pfutx = plr[pnum]._px;
|
|
plr[pnum]._pfuty = plr[pnum]._py;
|
|
|
|
plr[pnum]._ptargx = plr[pnum]._px;
|
|
plr[pnum]._ptargy = plr[pnum]._py;
|
|
|
|
plr[pnum]._pxoff = 0;
|
|
plr[pnum]._pyoff = 0;
|
|
CheckEFlag(pnum, E_SINGLE);
|
|
plr[pnum]._pdir = bDir;
|
|
|
|
if (pnum == myplr) {
|
|
ScrollInfo._sxoff = 0;
|
|
ScrollInfo._syoff = 0;
|
|
ScrollInfo._sdir = SCRL_NONE;
|
|
ViewX = plr[pnum]._px;
|
|
ViewY = plr[pnum]._py;
|
|
}
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void StartStand(int pnum, int dir)
|
|
{
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("StartStand: illegal player %d",pnum);
|
|
if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) {
|
|
StartPlrKill(pnum, KILL_UNKNOWN);
|
|
return;
|
|
}
|
|
|
|
if ((plr[pnum]._pGFXLoad & PGL_STAND) == 0) LoadPlrGFX(pnum, PGL_STAND);
|
|
NewPlrAnim(pnum, plr[pnum]._pNAnim[dir], plr[pnum]._pNFrames, 3, plr[pnum]._pNWidth);
|
|
plr[pnum]._pmode = PM_STAND;
|
|
FixPlayerLocation(pnum,dir);
|
|
FixPlrWalkTags(pnum);
|
|
dPlayer[plr[pnum]._px][plr[pnum]._py] = 1 + (char)pnum;
|
|
SetPlayerOld(pnum);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void StartWalkStand(int pnum)
|
|
{
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("StartWalkStand: illegal player %d",pnum);
|
|
plr[pnum]._pmode = PM_STAND;
|
|
plr[pnum]._pfutx = plr[pnum]._px;
|
|
plr[pnum]._pfuty = plr[pnum]._py;
|
|
plr[pnum]._pxoff = 0;
|
|
plr[pnum]._pyoff = 0;
|
|
CheckEFlag(pnum, E_SINGLE);
|
|
if (pnum == myplr) {
|
|
ScrollInfo._sxoff = 0;
|
|
ScrollInfo._syoff = 0;
|
|
ScrollInfo._sdir = SCRL_NONE;
|
|
ViewX = plr[pnum]._px;
|
|
ViewY = plr[pnum]._py;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void PM_ChangeLightOff(int pnum)
|
|
{
|
|
int lx,ly;
|
|
int signx,signy;
|
|
static BYTE fix[] = {0,0,3,3,3,6,6,6,8};
|
|
int totx, toty;
|
|
int oldtotx, oldtoty;
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("PM_ChangeLightOff: illegal player %d",pnum);
|
|
LightListStruct * light = &LightList[plr[pnum]._plid];
|
|
|
|
// Convert from screen pixel offsets to dungeon coordinates
|
|
// i.e., 45 degree rotation
|
|
lx = (plr[pnum]._pxoff + (plr[pnum]._pyoff << 1));
|
|
ly = ((plr[pnum]._pyoff << 1) - plr[pnum]._pxoff);
|
|
|
|
// Divide these values by 8, because lighting offsets have
|
|
// 8 subdivisions per tile.
|
|
if (lx < 0)
|
|
{
|
|
signx = -1;
|
|
lx = -lx;
|
|
}
|
|
else
|
|
signx = 1;
|
|
|
|
if (ly < 0)
|
|
{
|
|
signy = -1;
|
|
ly = -ly;
|
|
}
|
|
else
|
|
signy = 1;
|
|
|
|
lx = lx >> 3;
|
|
ly = ly >> 3;
|
|
|
|
// Then, fix the offset, because
|
|
// the player lighting looks bad with full lighting resolution.
|
|
// lx = fix[lx];
|
|
// ly = fix[ly];
|
|
|
|
lx *= signx;
|
|
ly *= signy;
|
|
|
|
totx = (light->_lx << 3) + lx;
|
|
toty = (light->_ly << 3) + ly;
|
|
|
|
oldtotx = (light->_lx << 3) + light->_xoff;
|
|
oldtoty = (light->_ly << 3) + light->_yoff;
|
|
|
|
if(abs(totx-oldtotx) >= 3 || abs(toty-oldtoty) >= 3)
|
|
ChangeLightOff(plr[pnum]._plid, lx, ly);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void PM_ChangeOffset(int pnum)
|
|
{
|
|
long xo, yo;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("PM_ChangeOffset: illegal player %d",pnum);
|
|
plr[pnum]._pVar8++;
|
|
|
|
xo = plr[pnum]._pVar6 >> 8;
|
|
yo = plr[pnum]._pVar7 >> 8;
|
|
#if 0
|
|
plr[pnum]._pVar6 += plr[pnum]._pxvel;
|
|
plr[pnum]._pVar7 += plr[pnum]._pyvel;
|
|
#endif
|
|
|
|
plr[pnum]._pVar6 += plr[pnum]._pxvel;
|
|
plr[pnum]._pVar7 += plr[pnum]._pyvel;
|
|
|
|
if (currlevel == 0 && gbWalkOn) // double-speed walk
|
|
{
|
|
plr[pnum]._pVar6 += plr[pnum]._pxvel;
|
|
plr[pnum]._pVar7 += plr[pnum]._pyvel;
|
|
}
|
|
|
|
plr[pnum]._pxoff = plr[pnum]._pVar6 >> 8;
|
|
plr[pnum]._pyoff = plr[pnum]._pVar7 >> 8;
|
|
xo -= (plr[pnum]._pVar6 >> 8);
|
|
yo -= (plr[pnum]._pVar7 >> 8);
|
|
if ((pnum == myplr) && (ScrollInfo._sdir != SCRL_NONE)) {
|
|
ScrollInfo._sxoff += xo;
|
|
ScrollInfo._syoff += yo;
|
|
}
|
|
PM_ChangeLightOff(pnum);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void StartWalk(int pnum, int xvel, int yvel, int xadd, int yadd, int EndDir, int scrldir)
|
|
{
|
|
long fx,fy;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("StartWalk: illegal player %d",pnum);
|
|
if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) {
|
|
StartPlrKill(pnum, KILL_UNKNOWN);
|
|
return;
|
|
}
|
|
|
|
SetPlayerOld(pnum);
|
|
fx = plr[pnum]._px + xadd;
|
|
fy = plr[pnum]._py + yadd;
|
|
if (PlrDirOK(pnum, EndDir)) {
|
|
//PlrClrTrans(plr[pnum]._px, plr[pnum]._py);
|
|
//PlrDoTrans(fx, fy);
|
|
plr[pnum]._pfutx = fx;
|
|
plr[pnum]._pfuty = fy;
|
|
if (pnum == myplr) {
|
|
ScrollInfo._sdx = plr[pnum]._px - ViewX;
|
|
ScrollInfo._sdy = plr[pnum]._py - ViewY;
|
|
}
|
|
dPlayer[fx][fy] = -1 - (char)pnum;
|
|
plr[pnum]._pmode = PM_WALK;
|
|
plr[pnum]._pxvel = xvel;
|
|
plr[pnum]._pyvel = yvel;
|
|
plr[pnum]._pxoff = 0;
|
|
plr[pnum]._pyoff = 0;
|
|
plr[pnum]._pVar1 = xadd;
|
|
plr[pnum]._pVar2 = yadd;
|
|
plr[pnum]._pVar3 = EndDir;
|
|
if ((plr[pnum]._pGFXLoad & PGL_WALK) == 0) LoadPlrGFX(pnum, PGL_WALK);
|
|
NewPlrAnim(pnum, plr[pnum]._pWAnim[EndDir], plr[pnum]._pWFrames, 0, plr[pnum]._pWWidth);
|
|
plr[pnum]._pdir = EndDir;
|
|
plr[pnum]._pVar6 = 0;
|
|
plr[pnum]._pVar7 = 0;
|
|
plr[pnum]._pVar8 = 0;
|
|
CheckEFlag(pnum, E_SINGLE);
|
|
if (pnum == myplr) {
|
|
if (svgamode) {
|
|
if ((abs(ScrollInfo._sdx) < 3) && (abs(ScrollInfo._sdy) < 3)) ScrollInfo._sdir = scrldir;
|
|
else ScrollInfo._sdir = SCRL_NONE;
|
|
} else {
|
|
if ((abs(ScrollInfo._sdx) < 2) && (abs(ScrollInfo._sdy) < 2)) ScrollInfo._sdir = scrldir;
|
|
else ScrollInfo._sdir = SCRL_NONE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void StartWalk2(int pnum, int xvel, int yvel, int xoff, int yoff,
|
|
int xadd, int yadd, int EndDir, int scrldir)
|
|
{
|
|
long fx,fy;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("StartWalk2: illegal player %d",pnum);
|
|
if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) {
|
|
StartPlrKill(pnum, KILL_UNKNOWN);
|
|
return;
|
|
}
|
|
|
|
SetPlayerOld(pnum);
|
|
fx = plr[pnum]._px + xadd;
|
|
fy = plr[pnum]._py + yadd;
|
|
if (PlrDirOK(pnum, EndDir)) {
|
|
//PlrClrTrans(plr[pnum]._px, plr[pnum]._py);
|
|
//PlrDoTrans(fx, fy);
|
|
plr[pnum]._pfutx = fx;
|
|
plr[pnum]._pfuty = fy;
|
|
if (pnum == myplr) {
|
|
ScrollInfo._sdx = plr[pnum]._px - ViewX;
|
|
ScrollInfo._sdy = plr[pnum]._py - ViewY;
|
|
}
|
|
dPlayer[plr[pnum]._px][plr[pnum]._py] = -1 - (char)pnum;
|
|
plr[pnum]._pVar1 = plr[pnum]._px;
|
|
plr[pnum]._pVar2 = plr[pnum]._py;
|
|
plr[pnum]._px = fx;
|
|
plr[pnum]._py = fy;
|
|
dPlayer[plr[pnum]._px][plr[pnum]._py] = 1 + (char)pnum;
|
|
plr[pnum]._pxoff = xoff;
|
|
plr[pnum]._pyoff = yoff;
|
|
ChangeLightXY(plr[pnum]._plid, plr[pnum]._px, plr[pnum]._py);
|
|
PM_ChangeLightOff(pnum);
|
|
plr[pnum]._pmode = PM_WALK2;
|
|
plr[pnum]._pxvel = xvel;
|
|
plr[pnum]._pyvel = yvel;
|
|
plr[pnum]._pVar6 = xoff << 8;
|
|
plr[pnum]._pVar7 = yoff << 8;
|
|
plr[pnum]._pVar3 = EndDir;
|
|
if ((plr[pnum]._pGFXLoad & PGL_WALK) == 0) LoadPlrGFX(pnum, PGL_WALK);
|
|
NewPlrAnim(pnum, plr[pnum]._pWAnim[EndDir], plr[pnum]._pWFrames, 0, plr[pnum]._pWWidth);
|
|
plr[pnum]._pdir = EndDir;
|
|
plr[pnum]._pVar8 = 0;
|
|
if (EndDir == DIR_DR) CheckEFlag(pnum, E_DOUBLE);
|
|
else CheckEFlag(pnum, E_SINGLE);
|
|
if (pnum == myplr) {
|
|
if (svgamode) {
|
|
if ((abs(ScrollInfo._sdx) < 3) && (abs(ScrollInfo._sdy) < 3)) ScrollInfo._sdir = scrldir;
|
|
else ScrollInfo._sdir = SCRL_NONE;
|
|
} else {
|
|
if ((abs(ScrollInfo._sdx) < 2) && (abs(ScrollInfo._sdy) < 2)) ScrollInfo._sdir = scrldir;
|
|
else ScrollInfo._sdir = SCRL_NONE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void StartWalk3(int pnum, int xvel, int yvel, int xoff, int yoff,
|
|
int xadd, int yadd, int txa, int tya, int EndDir, int scrldir)
|
|
{
|
|
long fx,fy;
|
|
long tx,ty;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("StartWalk3: illegal player %d",pnum);
|
|
if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) {
|
|
StartPlrKill(pnum, KILL_UNKNOWN);
|
|
return;
|
|
}
|
|
|
|
SetPlayerOld(pnum);
|
|
fx = plr[pnum]._px + xadd;
|
|
fy = plr[pnum]._py + yadd;
|
|
tx = plr[pnum]._px + txa; // Temp location for drawing
|
|
ty = plr[pnum]._py + tya;
|
|
if (PlrDirOK(pnum, EndDir)) {
|
|
//PlrClrTrans(plr[pnum]._px, plr[pnum]._py);
|
|
//PlrDoTrans(fx, fy);
|
|
plr[pnum]._pfutx = fx;
|
|
plr[pnum]._pfuty = fy;
|
|
if (pnum == myplr) {
|
|
ScrollInfo._sdx = plr[pnum]._px - ViewX;
|
|
ScrollInfo._sdy = plr[pnum]._py - ViewY;
|
|
}
|
|
dPlayer[plr[pnum]._px][plr[pnum]._py] = -1 - (char)pnum;
|
|
dPlayer[fx][fy] = -1 - (char)pnum;
|
|
plr[pnum]._pVar4 = tx;
|
|
plr[pnum]._pVar5 = ty;
|
|
dFlags[tx][ty] |= BFLAG_PLRLR;
|
|
plr[pnum]._pxoff = xoff;
|
|
plr[pnum]._pyoff = yoff;
|
|
if(leveltype)
|
|
{
|
|
ChangeLightXY(plr[pnum]._plid, tx, ty);
|
|
PM_ChangeLightOff(pnum);
|
|
}
|
|
plr[pnum]._pmode = PM_WALK3;
|
|
plr[pnum]._pxvel = xvel;
|
|
plr[pnum]._pyvel = yvel;
|
|
plr[pnum]._pVar1 = fx;
|
|
plr[pnum]._pVar2 = fy;
|
|
plr[pnum]._pVar6 = xoff << 8;
|
|
plr[pnum]._pVar7 = yoff << 8;
|
|
plr[pnum]._pVar3 = EndDir;
|
|
if ((plr[pnum]._pGFXLoad & PGL_WALK) == 0) LoadPlrGFX(pnum, PGL_WALK);
|
|
NewPlrAnim(pnum, plr[pnum]._pWAnim[EndDir], plr[pnum]._pWFrames, 0, plr[pnum]._pWWidth);
|
|
plr[pnum]._pdir = EndDir;
|
|
plr[pnum]._pVar8 = 0;
|
|
CheckEFlag(pnum, E_SINGLE);
|
|
if (pnum == myplr) {
|
|
if (svgamode) {
|
|
if ((abs(ScrollInfo._sdx) < 3) && (abs(ScrollInfo._sdy) < 3)) ScrollInfo._sdir = scrldir;
|
|
else ScrollInfo._sdir = SCRL_NONE;
|
|
} else {
|
|
if ((abs(ScrollInfo._sdx) < 2) && (abs(ScrollInfo._sdy) < 2)) ScrollInfo._sdir = scrldir;
|
|
else ScrollInfo._sdir = SCRL_NONE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void StartAttack(int pnum, int d)
|
|
{
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("StartAttack: illegal player %d",pnum);
|
|
if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) {
|
|
StartPlrKill(pnum, KILL_UNKNOWN);
|
|
return;
|
|
}
|
|
|
|
if ((plr[pnum]._pGFXLoad & PGL_ATTACK) == 0) LoadPlrGFX(pnum, PGL_ATTACK);
|
|
NewPlrAnim(pnum, plr[pnum]._pAAnim[d], plr[pnum]._pAFrames, 0, plr[pnum]._pAWidth);
|
|
|
|
plr[pnum]._pmode = PM_ATTACK;
|
|
FixPlayerLocation(pnum,d);
|
|
SetPlayerOld(pnum);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void StartRangeAttack(int pnum, int d, int dx, int dy)
|
|
{
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("StartRangeAttack: illegal player %d",pnum);
|
|
if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) {
|
|
StartPlrKill(pnum, KILL_UNKNOWN);
|
|
return;
|
|
}
|
|
|
|
if ((plr[pnum]._pGFXLoad & PGL_ATTACK) == 0) LoadPlrGFX(pnum, PGL_ATTACK);
|
|
NewPlrAnim(pnum, plr[pnum]._pAAnim[d], plr[pnum]._pAFrames, 0, plr[pnum]._pAWidth);
|
|
|
|
plr[pnum]._pmode = PM_RATTACK;
|
|
FixPlayerLocation(pnum,d);
|
|
SetPlayerOld(pnum);
|
|
plr[pnum]._pVar1 = dx;
|
|
plr[pnum]._pVar2 = dy;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void StartPlrBlock(int pnum, int dir)
|
|
{
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("StartPlrBlock: illegal player %d",pnum);
|
|
if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) {
|
|
StartPlrKill(pnum, KILL_UNKNOWN);
|
|
return;
|
|
}
|
|
|
|
PlaySfxLoc(IS_ISWORD, plr[pnum]._px, plr[pnum]._py);
|
|
|
|
if ((plr[pnum]._pGFXLoad & PGL_BLOCK) == 0) LoadPlrGFX(pnum, PGL_BLOCK);
|
|
NewPlrAnim(pnum, plr[pnum]._pBAnim[dir], plr[pnum]._pBFrames, 2, plr[pnum]._pBWidth);
|
|
plr[pnum]._pmode = PM_BLOCK;
|
|
FixPlayerLocation(pnum,dir);
|
|
SetPlayerOld(pnum);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void StartSpell(int pnum, int d, int cx, int cy)
|
|
{
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("StartSpell: illegal player %d",pnum);
|
|
if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) {
|
|
StartPlrKill(pnum, KILL_UNKNOWN);
|
|
return;
|
|
}
|
|
|
|
if (leveltype != 0) {
|
|
switch (spelldata[plr[pnum]._pSpell].sType) {
|
|
case ST_FIRE :
|
|
if ((plr[pnum]._pGFXLoad & PGL_FMAG) == 0) LoadPlrGFX(pnum, PGL_FMAG);
|
|
NewPlrAnim(pnum, plr[pnum]._pFAnim[d], plr[pnum]._pSFrames, 0, plr[pnum]._pSWidth);
|
|
break;
|
|
case ST_LIGHT :
|
|
if ((plr[pnum]._pGFXLoad & PGL_LMAG) == 0) LoadPlrGFX(pnum, PGL_LMAG);
|
|
NewPlrAnim(pnum, plr[pnum]._pLAnim[d], plr[pnum]._pSFrames, 0, plr[pnum]._pSWidth);
|
|
break;
|
|
case ST_MISC :
|
|
if ((plr[pnum]._pGFXLoad & PGL_TMAG) == 0) LoadPlrGFX(pnum, PGL_TMAG);
|
|
NewPlrAnim(pnum, plr[pnum]._pTAnim[d], plr[pnum]._pSFrames, 0, plr[pnum]._pSWidth);
|
|
break;
|
|
}
|
|
}
|
|
PlaySfxLoc(spelldata[plr[pnum]._pSpell].sSFX, plr[pnum]._px, plr[pnum]._py);
|
|
|
|
plr[pnum]._pmode = PM_SPELL;
|
|
FixPlayerLocation(pnum,d);
|
|
SetPlayerOld(pnum);
|
|
|
|
plr[pnum]._pVar1 = cx;
|
|
plr[pnum]._pVar2 = cy;
|
|
//if (((plr[pnum]._pSplFrom == SPL_FROMBK) || (plr[pnum]._pSplFrom == SPL_FROMR)) && (pnum == myplr))
|
|
plr[pnum]._pVar4 = GetSpellLevel(pnum, plr[pnum]._pSpell);
|
|
//else
|
|
// plr[pnum]._pVar4 = 1;
|
|
plr[pnum]._pVar8 = 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void FixPlrWalkTags(int pnum) {
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("FixPlrWalkTags: illegal player %d",pnum);
|
|
|
|
int pp = pnum + 1;
|
|
int pn = -1 - pnum;
|
|
int px = plr[pnum]._poldx;
|
|
int py = plr[pnum]._poldy;
|
|
for (int y = py - 1; y <= py + 1; y++) {
|
|
for (int x = px - 1; x <= px + 1; x++) {
|
|
if (x < 0 || x >= DMAXX) continue;
|
|
if (y < 0 || y >= DMAXY) continue;
|
|
if (dPlayer[x][y] == pp || dPlayer[x][y] == pn)
|
|
dPlayer[x][y] = 0;
|
|
}
|
|
}
|
|
|
|
if (px < 0 || px >= DMAXX-1) return;
|
|
if (py < 0 || py >= DMAXY-1) return;
|
|
dFlags[px+1][py+0] &= BFMASK_PLRLR;
|
|
dFlags[px+0][py+1] &= BFMASK_PLRLR;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void RemovePlrFromMap(int pnum)
|
|
{
|
|
int pp = pnum + 1;
|
|
int pn = -1 - pnum;
|
|
int x,y;
|
|
for (y = 1; y < DMAXY; y++) {
|
|
for (x = 1; x < DMAXX; x++) {
|
|
if (((dPlayer[x][y-1] == pn) || (dPlayer[x-1][y] == pn)) && (dFlags[x][y] & BFLAG_PLRLR))
|
|
dFlags[x][y] &= BFMASK_PLRLR;
|
|
}
|
|
}
|
|
for (y = 0; y < DMAXY; y++) {
|
|
for (x = 0; x < DMAXX; x++) {
|
|
if (dPlayer[x][y] == pp || dPlayer[x][y] == pn)
|
|
dPlayer[x][y] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void StartPlrHit(int pnum, int dam, BOOL forcehit)
|
|
{
|
|
int pd;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("StartPlrHit: illegal player %d",pnum);
|
|
if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) {
|
|
StartPlrKill(pnum, KILL_UNKNOWN);
|
|
return;
|
|
}
|
|
|
|
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);
|
|
else if (plr[pnum]._pClass == CLASS_BARBARIAN) PlaySfxLoc(PS_BARBARIAN69, plr[pnum]._px, plr[pnum]._py);
|
|
#endif
|
|
//PlaySfxLoc(PS_LGHIT, plr[pnum]._px, plr[pnum]._py);
|
|
|
|
// Update hit bar
|
|
drawhpflag = TRUE;
|
|
|
|
if (plr[pnum]._pClass == CLASS_BARBARIAN)
|
|
{
|
|
if ((dam >> HP_SHIFT) < (plr[pnum]._pLevel + (plr[pnum]._pLevel/4))
|
|
&& !forcehit)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else if ((dam >> HP_SHIFT) < plr[pnum]._pLevel
|
|
&& !forcehit)
|
|
return;
|
|
|
|
pd = plr[pnum]._pdir;
|
|
if ((plr[pnum]._pGFXLoad & PGL_HIT) == 0) LoadPlrGFX(pnum, PGL_HIT);
|
|
NewPlrAnim(pnum, plr[pnum]._pHAnim[pd], plr[pnum]._pHFrames, 0, plr[pnum]._pHWidth);
|
|
plr[pnum]._pmode = PM_GOTHIT;
|
|
FixPlayerLocation(pnum,pd);
|
|
plr[pnum]._pVar8 = 1;
|
|
FixPlrWalkTags(pnum);
|
|
dPlayer[plr[pnum]._px][plr[pnum]._py] = 1 + (char)pnum;
|
|
SetPlayerOld(pnum);
|
|
}
|
|
// JMM.PATCH1.2/24/97
|
|
void ShowDupString( LPCSTR lpszMessage );
|
|
// END.PATCH1
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void RespawnDeadItem(ItemStruct *itm, int x, int y)
|
|
{
|
|
int ii;
|
|
|
|
if (numitems < MAXITEMS) {
|
|
// JMM.PATCH1.2/24/97
|
|
if(FindGetItem(itm->IDidx, itm->_iCreateInfo, itm->_iSeed) >= 0) {
|
|
DROPLOG(" Duplicate item detected!\n");
|
|
// JMM.PATCH1.2.22.97
|
|
// NetSendString(1 << myplr, "A duplicate item has been detected. Unable to drop.");
|
|
ShowDupString("A duplicate item has been detected. Destroying duplicate...");
|
|
SyncGetItem(x,y,itm->IDidx,itm->_iCreateInfo,itm->_iSeed);
|
|
// END.JMM.PATCH1.2.22.97
|
|
}
|
|
// ENDPATCH1.2/24/97
|
|
|
|
ii = itemavail[0];
|
|
dItem[x][y] = ii+1;
|
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1];
|
|
itemactive[numitems] = ii;
|
|
|
|
item[ii] = *itm;
|
|
item[ii]._ix = x;
|
|
item[ii]._iy = y;
|
|
|
|
RespawnItem(ii, TRUE);
|
|
numitems++;
|
|
|
|
itm->_itype = -1;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
static void PlrDeadItem(int pnum, ItemStruct *itm, int xx, int yy) {
|
|
|
|
// no item to drop?
|
|
if (itm->_itype == -1) return;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("PlrDeadItem: illegal player %d",pnum);
|
|
|
|
// try optimal position first
|
|
int x = plr[pnum]._px + xx;
|
|
int y = plr[pnum]._py + yy;
|
|
|
|
if ((xx != 0) || (yy != 0)) {
|
|
// Start placing
|
|
if (ItemSpaceOk(x, y)) {
|
|
RespawnDeadItem(itm, x, y);
|
|
plr[pnum].HoldItem = *itm;
|
|
NetSendCmdPItem(FALSE,CMD_RESPAWNITEM,x,y);
|
|
return;
|
|
}
|
|
}
|
|
|
|
for (int l = 1; l < 50; l++) {
|
|
for (int j = -l; j <= l; j++) {
|
|
y = plr[pnum]._py + j;
|
|
for (int i = -l; i <= l; i++) {
|
|
x = plr[pnum]._px + i;
|
|
if (! ItemSpaceOk(x,y)) continue;
|
|
|
|
// drop it
|
|
RespawnDeadItem(itm, x, y);
|
|
plr[pnum].HoldItem = *itm;
|
|
NetSendCmdPItem(FALSE,CMD_RESPAWNITEM,x,y);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void StartPlayerKill(int pnum, BOOL earflag)
|
|
{
|
|
ItemStruct * pi;
|
|
PlayerStruct * p = &plr[pnum];
|
|
ItemStruct ear;
|
|
int i;
|
|
|
|
// already dead?
|
|
if ((plr[pnum]._pHitPoints <= 0) && (plr[pnum]._pmode == PM_DEATH)) return;
|
|
|
|
// if it's me, let everyone know
|
|
if (myplr == pnum) NetSendCmdParam1(TRUE,CMD_PLRDEAD,earflag);
|
|
|
|
// dead players don't lose body items on diablo level
|
|
BOOL diablolevel = (gbMaxPlayers > 1) && (plr[pnum].plrlevel == 16);
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("StartPlayerKill: illegal player %d",pnum);
|
|
|
|
if (plr[pnum]._pClass == CLASS_WARRIOR) PlaySfxLoc(PS_DEAD, p->_px, p->_py);
|
|
#if !IS_VERSION(SHAREWARE)
|
|
else if (plr[pnum]._pClass == CLASS_ROGUE) PlaySfxLoc(PS_ROGUE71, p->_px, p->_py);
|
|
else if (plr[pnum]._pClass == CLASS_SORCEROR) PlaySfxLoc(PS_MAGE71, p->_px, p->_py);
|
|
else if (plr[pnum]._pClass == CLASS_MONK) PlaySfxLoc(PS_MONK71, p->_px, p->_py);
|
|
else if (plr[pnum]._pClass == CLASS_BARD) PlaySfxLoc(PS_BARD71, p->_px, p->_py);
|
|
else if (plr[pnum]._pClass == CLASS_BARBARIAN) PlaySfxLoc(PS_BARBARIAN71, p->_px, p->_py);
|
|
#endif
|
|
|
|
// Give the plr no items in hands gfx
|
|
if (p->_pgfxnum != PGFX_NGUY) {
|
|
p->_pgfxnum = PGFX_NGUY;
|
|
p->_pGFXLoad = 0;
|
|
SetPlrAnims(pnum);
|
|
}
|
|
|
|
if ((p->_pGFXLoad & PGL_DEAD) == 0) LoadPlrGFX(pnum, PGL_DEAD);
|
|
NewPlrAnim(pnum, p->_pDAnim[p->_pdir], p->_pDFrames, 1, p->_pDWidth);
|
|
p->_pmode = PM_DEATH;
|
|
p->_pBlockFlag = FALSE;
|
|
p->_pInvincible = TRUE;
|
|
SetPlayerHitPoints(pnum, 0);
|
|
p->_pVar8 = 1;
|
|
if ((pnum != myplr) && (earflag == FALSE) && !diablolevel) {
|
|
pi = &p->InvBody[0];
|
|
for (i = NUM_INVLOC; i--; pi++) pi->_itype = -1;
|
|
CalcPlrInv(pnum, FALSE);
|
|
}
|
|
|
|
if (plr[pnum].plrlevel != currlevel) return;
|
|
|
|
// Clean up map and set up vars for death
|
|
FixPlayerLocation(pnum,p->_pdir);
|
|
RemovePlrFromMap(pnum);
|
|
dFlags[p->_px][p->_py] |= BFLAG_DEADPLR;
|
|
SetPlayerOld(pnum);
|
|
|
|
// Bail out if this is not me
|
|
if (pnum != myplr) return;
|
|
|
|
drawhpflag = TRUE;
|
|
deathdelay = 30;
|
|
|
|
// Drop all item in hand
|
|
if (curs >= ICSTART) {
|
|
PlrDeadItem(pnum, &p->HoldItem, 0, 0);
|
|
NewCursor(GLOVE_CURS);
|
|
}
|
|
|
|
if (diablolevel)
|
|
return;
|
|
|
|
// Drop half of players gold
|
|
DropHalfPlayersGold(pnum);
|
|
|
|
// Drop player ear if killed by player
|
|
if (earflag == KILL_UNKNOWN) return;
|
|
|
|
if (earflag) {
|
|
SetPlrHandItem(&ear, IDI_EAR);
|
|
sprintf(ear._iName, "Ear of %s", plr[pnum]._pName);
|
|
if (plr[pnum]._pClass == CLASS_SORCEROR) ear._iCurs = ITEM_EAR1;
|
|
else if (plr[pnum]._pClass == CLASS_WARRIOR) ear._iCurs = ITEM_EAR2;
|
|
else if (plr[pnum]._pClass == CLASS_ROGUE) ear._iCurs = ITEM_EAR3;
|
|
// Fix this if necessary.
|
|
else if (plr[pnum]._pClass == CLASS_MONK) ear._iCurs = ITEM_EAR3;
|
|
else if (plr[pnum]._pClass == CLASS_BARD) ear._iCurs = ITEM_EAR3;
|
|
else if (plr[pnum]._pClass == CLASS_BARBARIAN) ear._iCurs = ITEM_EAR3;
|
|
|
|
ear._iCreateInfo = (plr[pnum]._pName[0] << 8) | plr[pnum]._pName[1];
|
|
ear._iSeed = (plr[pnum]._pName[2] << 24) |
|
|
(plr[pnum]._pName[3] << 16) |
|
|
(plr[pnum]._pName[4] << 8) |
|
|
plr[pnum]._pName[5];
|
|
ear._ivalue = plr[pnum]._pLevel;
|
|
// my ear already on ground?
|
|
int ii = FindGetItem(IDI_EAR, ear._iCreateInfo, ear._iSeed);
|
|
if (ii == -1) PlrDeadItem(pnum, &ear, 0, 0);
|
|
} else {
|
|
// Drop body items if killed by monster
|
|
pi = &p->InvBody[0];
|
|
for (i = NUM_INVLOC; i--; pi++) {
|
|
int pdd = (p->_pdir + i) & 0x07;
|
|
PlrDeadItem(pnum, pi, offset_x[pdd], offset_y[pdd]);
|
|
}
|
|
CalcPlrInv(pnum, FALSE);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void DropHalfPlayersGold(int pnum)
|
|
{
|
|
int i;
|
|
long hGold;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("DropHalfPlayersGold: illegal player %d",pnum);
|
|
|
|
// Get half of players gold
|
|
hGold = plr[pnum]._pGold >> 1;
|
|
|
|
// Remove gold from speed list first; if there is any
|
|
// Try non GOLD_VMAX first, then break into the GOLD_VMAX piles
|
|
for (i = 0; ((i < MAXSPD) && (hGold > 0)); i++) {
|
|
if ((plr[pnum].SpdList[i]._itype == IT_GOLD) &&
|
|
(plr[pnum].SpdList[i]._ivalue != GOLD_VMAX)) {
|
|
if (hGold < plr[pnum].SpdList[i]._ivalue) {
|
|
// update gold items value
|
|
plr[pnum].SpdList[i]._ivalue -= hGold;
|
|
// update gold items cursor
|
|
SetSpdbarGoldCurs(pnum, i);
|
|
// initialize hold item to gold type
|
|
SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD);
|
|
GetGoldSeed(pnum, &plr[pnum].HoldItem);
|
|
SetPlrHandGoldCurs(&plr[pnum].HoldItem);
|
|
// set hold items value equal to hGold
|
|
plr[pnum].HoldItem._ivalue = hGold;
|
|
// drop the hold item
|
|
PlrDeadItem(pnum, &plr[pnum].HoldItem, 0, 0);
|
|
// initialize so we can exit the loop
|
|
hGold = 0;
|
|
} else {
|
|
// decrement hGold by SpdList items value
|
|
hGold -= plr[pnum].SpdList[i]._ivalue;
|
|
// remove gold item from SpdList
|
|
RemoveSpdBarItem(pnum, i);
|
|
// initialize hold item to gold type
|
|
SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD);
|
|
GetGoldSeed(pnum, &plr[pnum].HoldItem);
|
|
SetPlrHandGoldCurs(&plr[pnum].HoldItem);
|
|
// set hold items value equal to SpdList items value
|
|
plr[pnum].HoldItem._ivalue = plr[pnum].SpdList[i]._ivalue;
|
|
// drop the hold item
|
|
PlrDeadItem(pnum, &plr[pnum].HoldItem, 0, 0);
|
|
// restart looping
|
|
i = -1;
|
|
}
|
|
}
|
|
}
|
|
if (hGold > 0) {
|
|
// SpdList GOLD_VMAX piles
|
|
for (i = 0; ((i < MAXSPD) && (hGold > 0)); i++) {
|
|
if (plr[pnum].SpdList[i]._itype == IT_GOLD) {
|
|
if (hGold < plr[pnum].SpdList[i]._ivalue) {
|
|
// update gold items value
|
|
plr[pnum].SpdList[i]._ivalue -= hGold;
|
|
// update gold items cursor
|
|
SetSpdbarGoldCurs(pnum, i);
|
|
// initialize hold item to gold type
|
|
SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD);
|
|
GetGoldSeed(pnum, &plr[pnum].HoldItem);
|
|
SetPlrHandGoldCurs(&plr[pnum].HoldItem);
|
|
// set hold items value equal to hGold
|
|
plr[pnum].HoldItem._ivalue = hGold;
|
|
// drop the hold item
|
|
PlrDeadItem(pnum, &plr[pnum].HoldItem, 0, 0);
|
|
// initialize so we can exit the loop
|
|
hGold = 0;
|
|
} else {
|
|
// decrement hGold by SpdList items value
|
|
hGold -= plr[pnum].SpdList[i]._ivalue;
|
|
// remove gold item from SpdList
|
|
RemoveSpdBarItem(pnum, i);
|
|
// initialize hold item to gold type
|
|
SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD);
|
|
GetGoldSeed(pnum, &plr[pnum].HoldItem);
|
|
SetPlrHandGoldCurs(&plr[pnum].HoldItem);
|
|
// set hold items value equal to SpdList items value
|
|
plr[pnum].HoldItem._ivalue = plr[pnum].SpdList[i]._ivalue;
|
|
// drop the hold item
|
|
PlrDeadItem(pnum, &plr[pnum].HoldItem, 0, 0);
|
|
// restart looping
|
|
i = -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
force_redraw = FULLDRAW;
|
|
|
|
// Remove gold from inventory list if there was no gold in the speed list
|
|
// or all gold from the speed list was deplenished.
|
|
// Try non GOLD_VMAX first, then break into the GOLD_VMAX piles
|
|
if (hGold > 0) {
|
|
for (i = 0; ((i < plr[pnum]._pNumInv) && (hGold > 0)); i++) {
|
|
if ((plr[pnum].InvList[i]._itype == IT_GOLD) &&
|
|
(plr[pnum].InvList[i]._ivalue != GOLD_VMAX)) {
|
|
if (hGold < plr[pnum].InvList[i]._ivalue) {
|
|
// update gold items value
|
|
plr[pnum].InvList[i]._ivalue -= hGold;
|
|
// update gold items cursor
|
|
SetGoldCurs(pnum, i);
|
|
// initialize hold item to gold type
|
|
SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD);
|
|
GetGoldSeed(pnum, &plr[pnum].HoldItem);
|
|
SetPlrHandGoldCurs(&plr[pnum].HoldItem);
|
|
// set hold items value equal to hGold
|
|
plr[pnum].HoldItem._ivalue = hGold;
|
|
// drop the hold item
|
|
PlrDeadItem(pnum, &plr[pnum].HoldItem, 0, 0);
|
|
hGold = 0;
|
|
} else {
|
|
// decrement hGold by InvList items value
|
|
hGold -= plr[pnum].InvList[i]._ivalue;
|
|
// remove gold item from InvList
|
|
RemoveInvItem(pnum, i);
|
|
// initialize hold item to gold type
|
|
SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD);
|
|
GetGoldSeed(pnum, &plr[pnum].HoldItem);
|
|
SetPlrHandGoldCurs(&plr[pnum].HoldItem);
|
|
// set hold items value equal to InvList items value
|
|
plr[pnum].HoldItem._ivalue = plr[pnum].InvList[i]._ivalue;
|
|
// drop the hold item
|
|
PlrDeadItem(pnum, &plr[pnum].HoldItem, 0, 0);
|
|
// restart looping
|
|
i = -1;
|
|
}
|
|
}
|
|
}
|
|
if (hGold > 0) {
|
|
// InvList GOLD_VMAX piles
|
|
for (i = 0; ((i < plr[pnum]._pNumInv) && (hGold > 0)); i++) {
|
|
if (plr[pnum].InvList[i]._itype == IT_GOLD) {
|
|
if (hGold < plr[pnum].InvList[i]._ivalue) {
|
|
// update gold items value
|
|
plr[pnum].InvList[i]._ivalue -= hGold;
|
|
// update gold items cursor
|
|
SetGoldCurs(pnum, i);
|
|
// initialize hold item to gold type
|
|
SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD);
|
|
GetGoldSeed(pnum, &plr[pnum].HoldItem);
|
|
SetPlrHandGoldCurs(&plr[pnum].HoldItem);
|
|
// set hold items value equal to hGold
|
|
plr[pnum].HoldItem._ivalue = hGold;
|
|
// drop the hold item
|
|
PlrDeadItem(pnum, &plr[pnum].HoldItem, 0, 0);
|
|
hGold = 0;
|
|
} else {
|
|
// decrement hGold by InvList items value
|
|
hGold -= plr[pnum].InvList[i]._ivalue;
|
|
// remove gold item from InvList
|
|
RemoveInvItem(pnum, i);
|
|
// initialize hold item to gold type
|
|
SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD);
|
|
GetGoldSeed(pnum, &plr[pnum].HoldItem);
|
|
SetPlrHandGoldCurs(&plr[pnum].HoldItem);
|
|
// set hold items value equal to InvList items value
|
|
plr[pnum].HoldItem._ivalue = plr[pnum].InvList[i]._ivalue;
|
|
// drop the hold item
|
|
PlrDeadItem(pnum, &plr[pnum].HoldItem, 0, 0);
|
|
// restart looping
|
|
i = -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// update players gold to account for losing half
|
|
plr[pnum]._pGold = CalculateGold(pnum);
|
|
}
|
|
|
|
|
|
void StripTopGold(int pnum)
|
|
{
|
|
int i;
|
|
long hGold;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("StripTopGold: illegal player %d",pnum);
|
|
|
|
ItemStruct tmpHold = plr[pnum].HoldItem;
|
|
|
|
// Remove gold from inventory list if there was no gold in the speed list
|
|
// or all gold from the speed list was deplenished.
|
|
// Try non GOLD_VMAX first, then break into the GOLD_VMAX piles
|
|
for (i = 0; i < plr[pnum]._pNumInv; i++)
|
|
{
|
|
if ((plr[pnum].InvList[i]._itype == IT_GOLD) &&
|
|
(plr[pnum].InvList[i]._ivalue > GOLD_VMAX))
|
|
{
|
|
|
|
// first, remove the gold from the slot
|
|
hGold = plr[pnum].InvList[i]._ivalue - GOLD_VMAX;
|
|
plr[pnum].InvList[i]._ivalue = GOLD_VMAX;
|
|
|
|
// update gold items cursor
|
|
SetGoldCurs(pnum, i);
|
|
// initialize hold item to gold type
|
|
SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD);
|
|
GetGoldSeed(pnum, &plr[pnum].HoldItem);
|
|
SetPlrHandGoldCurs(&plr[pnum].HoldItem);
|
|
// set hold items value equal to hGold
|
|
plr[pnum].HoldItem._ivalue = hGold;
|
|
|
|
hGold = 0;
|
|
// if it'll fit elsewhere, continue
|
|
if (!GoldAutoPlace(pnum)) // else drop the hold item
|
|
PlrDeadItem(pnum, &plr[pnum].HoldItem, 0, 0);
|
|
}
|
|
}
|
|
// update players gold
|
|
plr[pnum]._pGold = CalculateGold(pnum);
|
|
plr[pnum].HoldItem = tmpHold;
|
|
}
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void StartPlrKill(int pnum, BOOL earflag)
|
|
{
|
|
int i, mx;
|
|
|
|
// PATCH1.JMM
|
|
// no death on first level
|
|
if ((0 >= plr[pnum]._pHitPoints) && (0 == currlevel)) {
|
|
SetPlayerHitPoints(pnum,1<<HP_SHIFT);
|
|
return;
|
|
}
|
|
// ENDPATCH1.JMM
|
|
|
|
for (i = 0; i < nummissiles; i++) {
|
|
mx = missileactive[i];
|
|
if ((missile[mx]._mitype == MIT_MANASHIELD) && (missile[mx]._misource == pnum) && !missile[mx]._miDelFlag) {
|
|
if (earflag != KILL_UNKNOWN) missile[mx]._miVar8 = earflag; // killed by player?
|
|
return;
|
|
}
|
|
}
|
|
|
|
// took out setting hp to zero before this routine is called so manashld calc works - rjs
|
|
SetPlayerHitPoints(pnum, 0);
|
|
StartPlayerKill(pnum, earflag);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SyncPlrKill(int pnum, BOOL earflag)
|
|
{
|
|
app_assert((DWORD)pnum < MAX_PLRS);
|
|
StartPlayerKill(pnum, earflag);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void RemovePlrMissiles(int pnum)
|
|
{
|
|
int i, mx;
|
|
|
|
if ((currlevel != 0) && (pnum == myplr) && (monster[myplr]._mx != 1 || monster[myplr]._my != 0)) {
|
|
M_StartKill(myplr, myplr);
|
|
extern void AddDead(int, int, char, int);
|
|
AddDead(monster[myplr]._mx, monster[myplr]._my, monster[myplr].MType->mdeadval, monster[myplr]._mdir);
|
|
dMonster[monster[myplr]._mx][monster[myplr]._my] = 0;
|
|
monster[myplr]._mDelFlag = TRUE;
|
|
DeleteMonsterList();
|
|
}
|
|
|
|
void DeleteMissile(int, int);
|
|
for (i = 0; i < nummissiles; i++) {
|
|
mx = missileactive[i];
|
|
if ((missile[mx]._mitype == MIT_STONE) && (missile[mx]._misource == pnum))
|
|
monster[(missile[mx]._miVar2)]._mmode = missile[mx]._miVar1;
|
|
if ((missile[mx]._mitype == MIT_MANASHIELD) && (missile[mx]._misource == pnum)) {
|
|
ClearMissileSpot(mx);
|
|
DeleteMissile(mx, i);
|
|
}
|
|
if ((missile[mx]._mitype == MIT_ETHER) && (missile[mx]._misource == pnum)) {
|
|
ClearMissileSpot(mx);
|
|
DeleteMissile(mx, i);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void InitLevelChange(int pnum)
|
|
{
|
|
RemovePlrMissiles(pnum);
|
|
|
|
if ((pnum == myplr) && (qtextflag)) {
|
|
qtextflag = FALSE;
|
|
stream_stop();
|
|
}
|
|
// remove player from current level immediately
|
|
RemovePlrFromMap(pnum);
|
|
SetPlayerOld(pnum);
|
|
if (pnum == myplr) dPlayer[plr[myplr]._px][plr[myplr]._py] = 1 + myplr;
|
|
else plr[pnum]._pLvlVisited[plr[pnum].plrlevel] = TRUE;
|
|
|
|
ClrPlrPath(pnum);
|
|
plr[pnum].destAction = PCMD_NOTHING;
|
|
plr[pnum]._pLvlChanging = TRUE;
|
|
if (pnum == myplr) plr[pnum].pLvlLoad = LVLCHANGE_TIME;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void StartNewLvl(int pnum, int fom, int lvl)
|
|
{
|
|
InitLevelChange(pnum);
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("StartNewLvl: illegal player %d",pnum);
|
|
switch (fom) {
|
|
case WM_DIABNEXTLVL:
|
|
case WM_DIABPREVLVL:
|
|
case WM_DIABTOWNWARP:
|
|
//app_assert(plr[pnum].plrlevel != lvl);
|
|
plr[pnum].plrlevel = lvl;
|
|
break;
|
|
|
|
case WM_DIABTWARPUP:
|
|
plr[myplr].pTownWarps |= 1 << (leveltype - 2);
|
|
plr[pnum].plrlevel = lvl;
|
|
break;
|
|
|
|
case WM_DIABRETOWN:
|
|
// everything already set
|
|
break;
|
|
|
|
case WM_DIABRTNLVL:
|
|
// can't do any validation on this
|
|
// one since it stuffs into global vars
|
|
app_assert(gbMaxPlayers == 1);
|
|
plr[pnum].plrlevel = lvl;
|
|
break;
|
|
|
|
case WM_DIABSETLVL:
|
|
setlvlnum = lvl;
|
|
app_assert(gbMaxPlayers == 1);
|
|
break;
|
|
|
|
default:
|
|
app_fatal("StartNewLvl");
|
|
break;
|
|
}
|
|
|
|
if (pnum == myplr) {
|
|
plr[pnum]._pmode = PM_NEWLVL;
|
|
plr[pnum]._pInvincible = TRUE;
|
|
PostMessage(ghMainWnd,fom,0,0);
|
|
if (gbMaxPlayers > 1) NetSendCmdParam2(TRUE,CMD_NEWLVL,fom,lvl);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void RestartTownLvl(int pnum)
|
|
{
|
|
InitLevelChange(pnum);
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("RestartTownLvl: illegal player %d",pnum);
|
|
|
|
//app_assert(plr[pnum].plrlevel != 0);
|
|
plr[pnum].plrlevel = 0;
|
|
|
|
plr[pnum]._pInvincible = FALSE;
|
|
SetPlayerHitPoints(pnum, 1 << HP_SHIFT);
|
|
plr[pnum]._pMana = 0;
|
|
plr[pnum]._pManaBase = plr[pnum]._pMana - (plr[pnum]._pMaxMana - plr[pnum]._pMaxManaBase);
|
|
CalcPlrInv(pnum, FALSE);
|
|
|
|
if (pnum == myplr) {
|
|
plr[pnum]._pmode = PM_NEWLVL;
|
|
plr[pnum]._pInvincible = TRUE;
|
|
PostMessage(ghMainWnd,WM_DIABRETOWN,0,0);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void StartWarpLvl(int pnum, int pidx)
|
|
{
|
|
InitLevelChange(pnum);
|
|
|
|
if (gbMaxPlayers != 1) {
|
|
if (plr[pnum].plrlevel != 0) plr[pnum].plrlevel = 0;
|
|
else plr[pnum].plrlevel = portal[pidx].level;
|
|
}
|
|
|
|
if (pnum == myplr) {
|
|
SetCurrentPortal(pidx);
|
|
plr[pnum]._pmode = PM_NEWLVL;
|
|
plr[pnum]._pInvincible = TRUE;
|
|
PostMessage(ghMainWnd,WM_DIABWARPLVL,0,0);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int PM_DoStand(int pnum)
|
|
{
|
|
return(RUN_DONE);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
********************************** TEMP *********************************
|
|
**-----------------------------------------------------------------------*
|
|
|
|
BOOL rfix1 = FALSE;
|
|
BOOL rfix2 = FALSE;
|
|
|
|
void TempWalkFix(int pnum)
|
|
{
|
|
if (currlevel == 0) return;
|
|
if ((plr[pnum]._pClass == CLASS_ROGUE) && (plr[pnum]._pAnimLen == 6)) {
|
|
if ((plr[pnum]._pAnimFrame == 2) && !rfix1) {
|
|
plr[pnum]._pAnimFrame = 1;
|
|
rfix1 = TRUE;
|
|
} else rfix1 = FALSE;
|
|
if ((plr[pnum]._pAnimFrame == 4) && !rfix2) {
|
|
plr[pnum]._pAnimFrame = 3;
|
|
rfix2 = TRUE;
|
|
} else rfix2 = FALSE;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int PM_DoWalk(int pnum)
|
|
{
|
|
int rv;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("PM_DoWalk: illegal player %d",pnum);
|
|
|
|
#if 0
|
|
// changed _pAnimFrame == 2 to == 3 to prevent "extra" footstep == pat
|
|
// if ((plr[pnum]._pAnimFrame == 3)
|
|
// || (plr[pnum]._pWFrames == 8 && plr[pnum]._pAnimFrame == 7)
|
|
// || (plr[pnum]._pWFrames != 8 && plr[pnum]._pAnimFrame == 4))
|
|
// PlaySfxLoc(PS_WALK1, plr[pnum]._px, plr[pnum]._py);
|
|
//TempWalkFix(pnum);
|
|
#endif
|
|
|
|
if (currlevel == 0 && gbWalkOn) // double-speed walk in town
|
|
{
|
|
if (plr[pnum]._pAnimFrame%2 == 0) // should be even frames only
|
|
{
|
|
++plr[pnum]._pAnimFrame;
|
|
++plr[pnum]._pVar8;
|
|
}
|
|
if (plr[pnum]._pAnimFrame >= plr[pnum]._pWFrames)
|
|
plr[pnum]._pAnimFrame = 0;
|
|
}
|
|
|
|
int l = 8;
|
|
|
|
if (currlevel != 0) l = PlrWalkLenTbl[plr[pnum]._pClass];
|
|
if (plr[pnum]._pVar8 >= l) {
|
|
dPlayer[plr[pnum]._px][plr[pnum]._py] = 0;
|
|
plr[pnum]._px += plr[pnum]._pVar1;
|
|
plr[pnum]._py += plr[pnum]._pVar2;
|
|
dPlayer[plr[pnum]._px][plr[pnum]._py] = 1 + (char)pnum;
|
|
if (leveltype != 0) {
|
|
ChangeLightXY(plr[pnum]._plid, plr[pnum]._px, plr[pnum]._py);
|
|
ChangeVisionXY(plr[pnum]._pvid, plr[pnum]._px, plr[pnum]._py);
|
|
}
|
|
if (pnum == myplr) {
|
|
if (ScrollInfo._sdir != SCRL_NONE) {
|
|
ViewX = plr[pnum]._px - ScrollInfo._sdx;
|
|
ViewY = plr[pnum]._py - ScrollInfo._sdy;
|
|
}
|
|
}
|
|
if (plr[pnum].walkpath[0] != PCMD_NOTHING) StartWalkStand(pnum);
|
|
else StartStand(pnum, plr[pnum]._pVar3);
|
|
ClearPlrPVars(pnum);
|
|
if (leveltype != 0) ChangeLightOff(plr[pnum]._plid, 0, 0);
|
|
rv = RUN_AGAIN;
|
|
} else {
|
|
PM_ChangeOffset(pnum);
|
|
rv = RUN_DONE;
|
|
}
|
|
|
|
return (rv);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int PM_DoWalk2(int pnum)
|
|
{
|
|
int rv;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("PM_DoWalk2: illegal player %d",pnum);
|
|
|
|
#if 0
|
|
// changed _pAnimFrame == 2 to == 3 to prevent "extra" footstep == pat
|
|
if ((plr[pnum]._pAnimFrame == 3)
|
|
|| (plr[pnum]._pWFrames == 8 && plr[pnum]._pAnimFrame == 7)
|
|
|| (plr[pnum]._pWFrames != 8 && plr[pnum]._pAnimFrame == 4))
|
|
PlaySfxLoc(PS_WALK1, plr[pnum]._px, plr[pnum]._py);
|
|
//TempWalkFix(pnum);
|
|
#endif
|
|
if (currlevel == 0 && gbWalkOn) // double-speed walk in town
|
|
{
|
|
if (plr[pnum]._pAnimFrame%2 == 0) // should be even frames only
|
|
{
|
|
++plr[pnum]._pAnimFrame;
|
|
++plr[pnum]._pVar8;
|
|
}
|
|
if (plr[pnum]._pAnimFrame >= plr[pnum]._pWFrames)
|
|
plr[pnum]._pAnimFrame = 0;
|
|
}
|
|
|
|
int l = 8;
|
|
|
|
if (currlevel != 0) l = PlrWalkLenTbl[plr[pnum]._pClass];
|
|
if (plr[pnum]._pVar8 >= l) {
|
|
dPlayer[plr[pnum]._pVar1][plr[pnum]._pVar2] = 0;
|
|
if (leveltype != 0) {
|
|
ChangeLightXY(plr[pnum]._plid, plr[pnum]._px, plr[pnum]._py);
|
|
ChangeVisionXY(plr[pnum]._pvid, plr[pnum]._px, plr[pnum]._py);
|
|
}
|
|
if (pnum == myplr) {
|
|
if (ScrollInfo._sdir != SCRL_NONE) {
|
|
ViewX = plr[pnum]._px - ScrollInfo._sdx;
|
|
ViewY = plr[pnum]._py - ScrollInfo._sdy;
|
|
}
|
|
}
|
|
if (plr[pnum].walkpath[0] != PCMD_NOTHING) StartWalkStand(pnum);
|
|
else StartStand(pnum, plr[pnum]._pVar3);
|
|
ClearPlrPVars(pnum);
|
|
if (leveltype != 0) ChangeLightOff(plr[pnum]._plid, 0, 0);
|
|
rv = RUN_AGAIN;
|
|
} else {
|
|
PM_ChangeOffset(pnum);
|
|
rv = RUN_DONE;
|
|
}
|
|
|
|
return(rv);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int PM_DoWalk3(int pnum)
|
|
{
|
|
int rv;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("PM_DoWalk3: illegal player %d",pnum);
|
|
|
|
#if 0
|
|
// changed _pAnimFrame == 2 to == 3 to prevent "extra" footstep == pat
|
|
if ((plr[pnum]._pAnimFrame == 3)
|
|
|| (plr[pnum]._pWFrames == 8 && plr[pnum]._pAnimFrame == 7)
|
|
|| (plr[pnum]._pWFrames != 8 && plr[pnum]._pAnimFrame == 4))
|
|
PlaySfxLoc(PS_WALK1, plr[pnum]._px, plr[pnum]._py);
|
|
//TempWalkFix(pnum);
|
|
#endif
|
|
|
|
if (currlevel == 0 && gbWalkOn) // double-speed walk in town
|
|
{
|
|
if (plr[pnum]._pAnimFrame%2 == 0) // should be even frames only
|
|
{
|
|
++plr[pnum]._pAnimFrame;
|
|
++plr[pnum]._pVar8;
|
|
}
|
|
if (plr[pnum]._pAnimFrame >= plr[pnum]._pWFrames)
|
|
plr[pnum]._pAnimFrame = 0;
|
|
}
|
|
|
|
|
|
int l = 8;
|
|
|
|
if (currlevel != 0) l = PlrWalkLenTbl[plr[pnum]._pClass];
|
|
if (plr[pnum]._pVar8 >= l) {
|
|
dPlayer[plr[pnum]._px][plr[pnum]._py] = 0;
|
|
dFlags[plr[pnum]._pVar4][plr[pnum]._pVar5] &= BFMASK_PLRLR;
|
|
plr[pnum]._px = plr[pnum]._pVar1;
|
|
plr[pnum]._py = plr[pnum]._pVar2;
|
|
dPlayer[plr[pnum]._px][plr[pnum]._py] = 1 + (char)pnum;
|
|
if (leveltype != 0) {
|
|
ChangeLightXY(plr[pnum]._plid, plr[pnum]._px, plr[pnum]._py);
|
|
ChangeVisionXY(plr[pnum]._pvid, plr[pnum]._px, plr[pnum]._py);
|
|
}
|
|
if (pnum == myplr) {
|
|
if (ScrollInfo._sdir != SCRL_NONE) {
|
|
ViewX = plr[pnum]._px - ScrollInfo._sdx;
|
|
ViewY = plr[pnum]._py - ScrollInfo._sdy;
|
|
}
|
|
}
|
|
if (plr[pnum].walkpath[0] != PCMD_NOTHING) StartWalkStand(pnum);
|
|
else StartStand(pnum, plr[pnum]._pVar3);
|
|
ClearPlrPVars(pnum);
|
|
if (leveltype != 0) ChangeLightOff(plr[pnum]._plid, 0, 0);
|
|
rv = RUN_AGAIN;
|
|
} else {
|
|
PM_ChangeOffset(pnum);
|
|
rv = RUN_DONE;
|
|
}
|
|
|
|
return(rv);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
BOOL WeaponDur(int pnum, int durrnd)
|
|
{
|
|
if (pnum != myplr)
|
|
return FALSE;
|
|
|
|
if ((plr[pnum].Hand1Item._itype != -1) && (plr[pnum].Hand1Item._iClass == IC_WEAP)) {
|
|
if (plr[pnum].Hand1Item._iFlags2 & IAF2_DECAY) {
|
|
plr[pnum].Hand1Item._iPLDam -= 5;
|
|
if (plr[pnum].Hand1Item._iPLDam <= -100) {
|
|
NetSendCmdDelItem(TRUE, INVLOC_HAND1);
|
|
plr[pnum].Hand1Item._itype = -1;
|
|
CalcPlrInv(pnum,TRUE);
|
|
return(TRUE);
|
|
}
|
|
CalcPlrInv(pnum,TRUE);
|
|
}
|
|
}
|
|
if ((plr[pnum].Hand2Item._itype != -1) && (plr[pnum].Hand2Item._iClass == IC_WEAP)) {
|
|
if (plr[pnum].Hand2Item._iFlags2 & IAF2_DECAY) {
|
|
plr[pnum].Hand2Item._iPLDam -= 5;
|
|
if (plr[pnum].Hand2Item._iPLDam <= -100) {
|
|
NetSendCmdDelItem(TRUE, INVLOC_HAND1);
|
|
plr[pnum].Hand2Item._itype = -1;
|
|
CalcPlrInv(pnum,TRUE);
|
|
return(TRUE);
|
|
}
|
|
CalcPlrInv(pnum,TRUE);
|
|
}
|
|
}
|
|
|
|
// Item used, so change durability
|
|
if (random(3, durrnd))
|
|
return FALSE;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("WeaponDur: illegal player %d",pnum);
|
|
|
|
if ((plr[pnum].Hand1Item._itype != -1) && (plr[pnum].Hand1Item._iClass == IC_WEAP)) {
|
|
if (plr[pnum].Hand1Item._iDurability == INFINITE_DUR) return(FALSE);
|
|
plr[pnum].Hand1Item._iDurability--;
|
|
if (plr[pnum].Hand1Item._iDurability <= 0) {
|
|
NetSendCmdDelItem(TRUE, INVLOC_HAND1);
|
|
plr[pnum].Hand1Item._itype = -1;
|
|
CalcPlrInv(pnum,TRUE);
|
|
return(TRUE);
|
|
}
|
|
}
|
|
if ((plr[pnum].Hand2Item._itype != -1) && (plr[pnum].Hand2Item._iClass == IC_WEAP)) {
|
|
if (plr[pnum].Hand2Item._iDurability == INFINITE_DUR) return(FALSE);
|
|
plr[pnum].Hand2Item._iDurability--;
|
|
if (plr[pnum].Hand2Item._iDurability == 0) {
|
|
NetSendCmdDelItem(TRUE, INVLOC_HAND2);
|
|
plr[pnum].Hand2Item._itype = -1;
|
|
CalcPlrInv(pnum,TRUE);
|
|
return(TRUE);
|
|
}
|
|
}
|
|
// Shield only guy
|
|
if ((plr[pnum].Hand1Item._itype == -1) && (plr[pnum].Hand2Item._itype == IT_SHIELD)) {
|
|
if (plr[pnum].Hand2Item._iDurability == INFINITE_DUR) return(FALSE);
|
|
plr[pnum].Hand2Item._iDurability--;
|
|
if (plr[pnum].Hand2Item._iDurability == 0) {
|
|
NetSendCmdDelItem(TRUE, INVLOC_HAND2);
|
|
plr[pnum].Hand2Item._itype = -1;
|
|
CalcPlrInv(pnum,TRUE);
|
|
return(TRUE);
|
|
}
|
|
}
|
|
if ((plr[pnum].Hand2Item._itype == -1) && (plr[pnum].Hand1Item._itype == IT_SHIELD)) {
|
|
if (plr[pnum].Hand1Item._iDurability == INFINITE_DUR) return(FALSE);
|
|
plr[pnum].Hand1Item._iDurability--;
|
|
if (plr[pnum].Hand1Item._iDurability == 0) {
|
|
NetSendCmdDelItem(TRUE, INVLOC_HAND1);
|
|
plr[pnum].Hand1Item._itype = -1;
|
|
CalcPlrInv(pnum,TRUE);
|
|
return(TRUE);
|
|
}
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
BOOL PlrHitMonst(int pnum, int m)
|
|
{
|
|
int hit, hper = 0, mind, maxd;
|
|
long dam, skdam;
|
|
int phanditype;
|
|
int tmac;
|
|
BOOL rv;
|
|
BOOL ret = FALSE;
|
|
BOOL quarterdamage = FALSE;
|
|
|
|
if ((DWORD)m >= MAXMONSTERS)
|
|
app_fatal("PlrHitMonst: illegal monster %d",m);
|
|
|
|
if ((monster[m]._mhitpoints >> HP_SHIFT) <= 0) return(FALSE);
|
|
|
|
if(monster[m].MType->mtype == MT_ILLWEAV && monster[m]._mgoal == MG_RUN_AWAY)
|
|
return FALSE;
|
|
|
|
if (monster[m]._mmode == MM_MISSILE) return(FALSE);
|
|
|
|
if (pnum < 0)
|
|
{
|
|
quarterdamage = TRUE;
|
|
pnum = -pnum;
|
|
if (plr[pnum]._pLevel > 20)
|
|
hper -= 30;
|
|
else
|
|
hper -= 2 * (35 - plr[pnum]._pLevel);
|
|
}
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("PlrHitMonst: illegal player %d",pnum);
|
|
|
|
rv = FALSE;
|
|
// Did I hit?
|
|
hit = random(4, 100);
|
|
if (monster[m]._mmode == MM_STONE) hit = 0;
|
|
tmac = monster[m].mArmorClass;
|
|
if (plr[pnum]._pIEnAc > 0) // like Damage Reduction in Hero --DKT
|
|
{
|
|
int i = plr[pnum]._pIEnAc - 1;
|
|
if (i > 0)
|
|
tmac >>= i; // halved (n-1) times
|
|
else
|
|
tmac -= tmac >> 2; // three quarters
|
|
|
|
if (plr[pnum]._pClass == CLASS_BARBARIAN)
|
|
{
|
|
tmac -= (monster[m].mArmorClass)/8; // Barbarians have a slight advantage using these weapons.
|
|
}
|
|
|
|
// limit it to a zero.
|
|
if (tmac < 0)
|
|
{
|
|
tmac = 0;
|
|
}
|
|
}
|
|
|
|
// note: modified this to += so quarterdamage shots are at minus to hit
|
|
// by giving negative initial value to hper.
|
|
hper += BASE_TO_HIT + plr[pnum]._pLevel - tmac + (plr[pnum]._pDexterity >> 1);
|
|
if (plr[pnum]._pClass == CLASS_WARRIOR)
|
|
hper += 20;
|
|
hper += plr[pnum]._pIBonusToHit;
|
|
if (hper < 5) hper = 5;
|
|
if (hper > 95) hper = 95;
|
|
if (CheckMonsterHit(m, ret)) // ret passed by &reference!!
|
|
return(ret);
|
|
#if CHEATS
|
|
else if((hit < hper) || cheatflag || simplecheat) {
|
|
#else
|
|
else if (hit < hper) {
|
|
#endif
|
|
if ((plr[pnum]._pIFlags & IAF_FIREHIT &&
|
|
plr[pnum]._pIFlags & IAF_LIGHTHIT))
|
|
{
|
|
int dmg = plr[pnum]._pIFMinDam + random(3, (plr[pnum]._pIFMaxDam - plr[pnum]._pIFMinDam));
|
|
AddMissile(plr[pnum]._px, plr[pnum]._py, plr[pnum]._pVar1, plr[pnum]._pVar2, plr[pnum]._pdir, MIT_SPECARROW, MI_ENEMYMONST, pnum, dmg, 0);
|
|
}
|
|
mind = plr[pnum]._pIMinDam;
|
|
maxd = plr[pnum]._pIMaxDam;
|
|
dam = random(5, maxd - mind + 1) + mind;
|
|
dam += (dam * plr[pnum]._pIBonusDam) / 100;
|
|
dam += plr[pnum]._pIBonusDamMod;
|
|
|
|
int perildam = dam << HP_SHIFT;
|
|
|
|
dam += plr[pnum]._pDamageMod;
|
|
if (plr[pnum]._pClass == CLASS_WARRIOR
|
|
|| plr[pnum]._pClass == CLASS_BARBARIAN) {
|
|
//ddp = (plr[pnum]._pDexterity + plr[pnum]._pLevel) >> 3;
|
|
int ddp = plr[pnum]._pLevel;
|
|
int doubledam = random(6, 100);
|
|
if (doubledam < ddp) dam = dam << 1;
|
|
}
|
|
phanditype = -1;
|
|
if ((plr[pnum].Hand1Item._itype == IT_SWORD) || (plr[pnum].Hand2Item._itype == IT_SWORD)) phanditype = IT_SWORD;
|
|
if ((plr[pnum].Hand1Item._itype == IT_MACE) || (plr[pnum].Hand2Item._itype == IT_MACE)) phanditype = IT_MACE;
|
|
switch (monster[m].MData->mMonstClass) {
|
|
case MC_UNDEAD:
|
|
if (phanditype == IT_SWORD) dam -= (dam >> 1);
|
|
else if (phanditype == IT_MACE) dam += (dam >> 1);
|
|
break;
|
|
case MC_ANIMAL:
|
|
if (phanditype == IT_MACE) dam -= (dam >> 1);
|
|
else if (phanditype == IT_SWORD) dam += (dam >> 1);
|
|
break;
|
|
}
|
|
if ((plr[pnum]._pIFlags & IAF_DAMDEMON) && (monster[m].MData->mMonstClass == MC_DEMON)) dam += (dam << 1);
|
|
|
|
if (plr[pnum]._pIFlags2 & IAF2_DEVASTATION)
|
|
{
|
|
int tdp = 5;
|
|
int tripledamage = random(6, 100);
|
|
if (tripledamage < tdp) dam += dam << 1;
|
|
}
|
|
|
|
if (plr[pnum]._pIFlags2 & IAF2_CLONE) // doppelganger
|
|
{
|
|
if (monster[m].MType->mtype != MT_DIABLO)
|
|
{
|
|
if ((monster[m]._uniqtype == 0) && (random(6, 100) < 10))
|
|
CloneMonster(m);
|
|
}
|
|
}
|
|
|
|
dam = dam << HP_SHIFT;
|
|
|
|
// after shift, to increase resolution
|
|
if (plr[pnum]._pIFlags2 & IAF2_JESTER)
|
|
{
|
|
int dammult = random(6, 201);
|
|
if (dammult >= 100)
|
|
dammult = 100 + (dammult-100) * 5;
|
|
dam = (dam * dammult) / 100;
|
|
}
|
|
|
|
if (quarterdamage)
|
|
dam >>= 2;
|
|
|
|
|
|
// can only be damaged by me
|
|
if (pnum == myplr) {
|
|
if (plr[pnum]._pIFlags2 & IAF2_PERIL)
|
|
{
|
|
perildam += plr[pnum]._pIGetHit << HP_SHIFT;
|
|
if (perildam < 0)
|
|
{
|
|
// do nothing
|
|
}
|
|
else if (plr[pnum]._pHitPoints > perildam)
|
|
{
|
|
plr[pnum]._pHitPoints -= perildam;
|
|
plr[pnum]._pHPBase -= perildam;
|
|
}
|
|
else
|
|
{
|
|
plr[pnum]._pHPBase -= plr[pnum]._pHitPoints - (1 << HP_SHIFT);
|
|
plr[pnum]._pHitPoints = 1 << HP_SHIFT;
|
|
}
|
|
dam <<= 1;
|
|
}
|
|
monster[m]._mhitpoints -= dam;
|
|
}
|
|
if (plr[pnum]._pIFlags & IAF_SKING) {
|
|
skdam = random(7, dam >> 3);
|
|
plr[pnum]._pHitPoints += skdam;
|
|
if (plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) plr[pnum]._pHitPoints = plr[pnum]._pMaxHP;
|
|
plr[pnum]._pHPBase += skdam;
|
|
if (plr[pnum]._pHPBase > plr[pnum]._pMaxHPBase) plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase;
|
|
drawhpflag = TRUE;
|
|
}
|
|
if ((plr[pnum]._pIFlags & IAF_ALLBAT) && (!(plr[pnum]._pIFlags & IAF_LMANA))) {
|
|
if (plr[pnum]._pIFlags & IAF_BAT10) skdam = (dam * 3) / 100;
|
|
if (plr[pnum]._pIFlags & IAF_BAT20) skdam = (dam * 5) / 100;
|
|
plr[pnum]._pMana += skdam;
|
|
if (plr[pnum]._pMana > plr[pnum]._pMaxMana) plr[pnum]._pMana = plr[pnum]._pMaxMana;
|
|
plr[pnum]._pManaBase += skdam;
|
|
if (plr[pnum]._pManaBase > plr[pnum]._pMaxManaBase) plr[pnum]._pManaBase = plr[pnum]._pMaxManaBase;
|
|
drawmanaflag = TRUE;
|
|
}
|
|
if (plr[pnum]._pIFlags & IAF_ALLLEECH) {
|
|
if (plr[pnum]._pIFlags & IAF_LEECH10) skdam = (dam * 3) / 100;
|
|
if (plr[pnum]._pIFlags & IAF_LEECH20) skdam = (dam * 5) / 100;
|
|
plr[pnum]._pHitPoints += skdam;
|
|
if (plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) plr[pnum]._pHitPoints = plr[pnum]._pMaxHP;
|
|
plr[pnum]._pHPBase += skdam;
|
|
if (plr[pnum]._pHPBase > plr[pnum]._pMaxHPBase) plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase;
|
|
drawhpflag = TRUE;
|
|
}
|
|
if (plr[pnum]._pIFlags & IAF_NOHEAL) monster[m]._mFlags |= MFLAG_NOHEAL;
|
|
#if CHEATS
|
|
if (simplecheat || cheatflag) monster[m]._mhitpoints = 0;
|
|
// if (cheatflag) monster[m]._mhitpoints = 1 << HP_SHIFT;
|
|
#endif
|
|
//rjs - was doing double dam if stone - 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);
|
|
} else {
|
|
if (monster[m]._mmode == MM_STONE) {
|
|
M_StartHit(m, pnum, dam);
|
|
monster[m]._mmode = MM_STONE;
|
|
} else {
|
|
if (plr[pnum]._pIFlags & IAF_KNOCKBACK) M_GetKnockback(m);
|
|
M_StartHit(m, pnum, dam);
|
|
}
|
|
}
|
|
rv = TRUE;
|
|
}
|
|
return(rv);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
BOOL PlrHitPlr(int pnum, char p)
|
|
{
|
|
int hit, hper, mind, maxd;
|
|
int doubledam, ddp;
|
|
long dam, skdam;
|
|
int tac;
|
|
int blk, blkper, blkdir;
|
|
BOOL rv;
|
|
|
|
if ((DWORD)p >= MAX_PLRS)
|
|
app_fatal("PlrHitPlr: illegal target player %d",p);
|
|
|
|
rv = FALSE;
|
|
if (plr[p]._pInvincible) return(rv);
|
|
if ((plr[p]._pSpellFlags & SF_ETHER) != 0) return(rv);
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("PlrHitPlr: illegal attacking player %d",pnum);
|
|
|
|
// Did I hit?
|
|
hit = random(4, 100);
|
|
//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 + (plr[pnum]._pDexterity >> 1);
|
|
if (plr[pnum]._pClass == CLASS_WARRIOR)
|
|
hper += 20;
|
|
hper += plr[pnum]._pIBonusToHit;
|
|
if (hper < 5) hper = 5;
|
|
if (hper > 95) hper = 95;
|
|
if (((plr[p]._pmode == PM_STAND) || (plr[p]._pmode == PM_ATTACK)) && (plr[p]._pBlockFlag)) blk = random(5, 100);
|
|
else blk = 100;
|
|
blkper = plr[p]._pBaseToBlk + plr[p]._pDexterity - ((plr[pnum]._pLevel - plr[p]._pLevel) << 1);
|
|
if (blkper < 0) blkper = 0;
|
|
if (blkper > 100) blkper = 100;
|
|
if (hit < hper) {
|
|
if (blk < blkper) {
|
|
blkdir = GetDirection(plr[p]._px, plr[p]._py, plr[pnum]._px, plr[pnum]._py);
|
|
StartPlrBlock(p, blkdir);
|
|
} else {
|
|
mind = plr[pnum]._pIMinDam;
|
|
maxd = plr[pnum]._pIMaxDam;
|
|
dam = random(5, maxd - mind + 1) + mind;
|
|
dam += (dam * plr[pnum]._pIBonusDam) / 100;
|
|
dam += plr[pnum]._pIBonusDamMod + plr[pnum]._pDamageMod;
|
|
if (plr[pnum]._pClass == CLASS_WARRIOR
|
|
|| plr[pnum]._pClass == CLASS_BARBARIAN) {
|
|
//ddp = (plr[pnum]._pDexterity + plr[pnum]._pLevel) >> 3;
|
|
ddp = plr[pnum]._pLevel;
|
|
doubledam = random(6, 100);
|
|
if (doubledam < ddp) dam = dam << 1;
|
|
}
|
|
dam = dam << HP_SHIFT;
|
|
if (plr[pnum]._pIFlags & IAF_SKING) {
|
|
skdam = random(7, dam >> 3);
|
|
plr[pnum]._pHitPoints += skdam;
|
|
if (plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) plr[pnum]._pHitPoints = plr[pnum]._pMaxHP;
|
|
plr[pnum]._pHPBase += skdam;
|
|
if (plr[pnum]._pHPBase > plr[pnum]._pMaxHPBase) plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase;
|
|
drawhpflag = TRUE;
|
|
}
|
|
if (pnum == myplr) NetSendCmdDamage(TRUE, p, dam);
|
|
StartPlrHit(p, dam, FALSE);
|
|
}
|
|
rv = TRUE;
|
|
}
|
|
return(rv);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
BOOL PlrHitObj(int pnum, int mx, int my)
|
|
{
|
|
int oi;
|
|
|
|
if (dObject[mx][my] > 0) oi = dObject[mx][my] - 1;
|
|
else oi = -(dObject[mx][my] + 1);
|
|
if (object[oi]._oBreak == OBJ_BREAKABLE) {
|
|
BreakObject(pnum, oi);
|
|
return(TRUE);
|
|
} else return(FALSE);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int PM_DoAttack(int pnum)
|
|
{
|
|
int dx,dy,m;
|
|
char p;
|
|
BOOL didhit = FALSE;
|
|
int frame;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("PM_DoAttack: illegal player %d",pnum);
|
|
|
|
frame = plr[pnum]._pAnimFrame;
|
|
|
|
if ((plr[pnum]._pIFlags & IAF_ATANIM1) && (frame == 1))
|
|
plr[pnum]._pAnimFrame++;
|
|
|
|
if ((plr[pnum]._pIFlags & IAF_ATANIM2) && (frame == 1 || frame == 3))
|
|
plr[pnum]._pAnimFrame++;
|
|
|
|
if ((plr[pnum]._pIFlags & IAF_ATANIM3) && (frame == 1 || frame == 3 || frame == 5))
|
|
plr[pnum]._pAnimFrame++;
|
|
|
|
if ((plr[pnum]._pIFlags & IAF_ATANIM4) && (frame == 1 || frame == 4))
|
|
plr[pnum]._pAnimFrame += 2;
|
|
|
|
if (plr[pnum]._pAnimFrame == (plr[pnum]._pAFNum-1))
|
|
PlaySfxLoc(PS_SWING, plr[pnum]._px, plr[pnum]._py);
|
|
|
|
if (plr[pnum]._pAnimFrame == plr[pnum]._pAFNum) {
|
|
dx = plr[pnum]._px + offset_x[plr[pnum]._pdir];
|
|
dy = plr[pnum]._py + offset_y[plr[pnum]._pdir];
|
|
|
|
if (dMonster[dx][dy] != 0) {
|
|
if (dMonster[dx][dy] > 0) m = dMonster[dx][dy] - 1;
|
|
else m = -(dMonster[dx][dy] + 1);
|
|
if (CanTalkToMonst(m)) {
|
|
plr[pnum]._pVar1 = 0;
|
|
return(RUN_DONE);
|
|
}
|
|
}
|
|
|
|
if ((plr[pnum]._pIFlags & IAF_FIREHIT &&
|
|
plr[pnum]._pIFlags & IAF_LIGHTHIT))
|
|
{
|
|
}
|
|
else if (plr[pnum]._pIFlags & IAF_FIREHIT)
|
|
AddMissile(dx, dy, 1, 0, 0, MIT_WEAPEXP, MI_ENEMYMONST, pnum, 0, 0);
|
|
else if (plr[pnum]._pIFlags & IAF_LIGHTHIT)
|
|
AddMissile(dx, dy, 2, 0, 0, MIT_WEAPEXP, MI_ENEMYMONST, pnum, 0, 0);
|
|
|
|
if (dMonster[dx][dy] != 0) {
|
|
if (dMonster[dx][dy] > 0)
|
|
m = dMonster[dx][dy] - 1;
|
|
else
|
|
m = -(dMonster[dx][dy] + 1);
|
|
didhit = PlrHitMonst(pnum, m);
|
|
} else {
|
|
if ((dPlayer[dx][dy] != 0) && (!FriendlyMode)) {
|
|
if (dPlayer[dx][dy] > 0) p = dPlayer[dx][dy] - 1;
|
|
else p = -(dPlayer[dx][dy] + 1);
|
|
didhit = PlrHitPlr(pnum, p);
|
|
} else {
|
|
if (dObject[dx][dy] > 0) didhit = PlrHitObj(pnum,dx,dy);
|
|
}
|
|
}
|
|
|
|
if ((plr[pnum]._pClass == CLASS_MONK &&
|
|
(plr[pnum].Hand1Item._itype == IT_STAFF ||
|
|
plr[pnum].Hand2Item._itype == IT_STAFF)
|
|
)
|
|
|| (plr[pnum]._pClass == CLASS_BARD &&
|
|
(plr[pnum].Hand1Item._itype == IT_SWORD &&
|
|
plr[pnum].Hand2Item._itype == IT_SWORD)
|
|
)
|
|
// Axes, 2handed Maces or 2handed swords with no shield used.
|
|
|| (plr[pnum]._pClass == CLASS_BARBARIAN &&
|
|
(plr[pnum].Hand1Item._itype == IT_AXE ||
|
|
plr[pnum].Hand2Item._itype == IT_AXE ||
|
|
((((plr[pnum].Hand1Item._itype == IT_MACE && plr[pnum].Hand1Item._iLoc == IL_2HAND) ||
|
|
(plr[pnum].Hand2Item._itype == IT_MACE && plr[pnum].Hand2Item._iLoc == IL_2HAND) ||
|
|
(plr[pnum].Hand1Item._itype == IT_SWORD && plr[pnum].Hand1Item._iLoc == IL_2HAND) ||
|
|
(plr[pnum].Hand2Item._itype == IT_SWORD && plr[pnum].Hand2Item._iLoc == IL_2HAND)
|
|
)
|
|
&& !(plr[pnum].Hand1Item._itype == IT_SHIELD || plr[pnum].Hand2Item._itype == IT_SHIELD)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
// check right-hand opponent, then left
|
|
// note that we temporarily redeclare dx, dy, and m here
|
|
int dx = plr[pnum]._px + offset_x[(plr[pnum]._pdir+1)%8];
|
|
int dy = plr[pnum]._py + offset_y[(plr[pnum]._pdir+1)%8];
|
|
int m = ((dMonster[dx][dy] > 0) ?
|
|
dMonster[dx][dy] : -dMonster[dx][dy])
|
|
- 1;
|
|
if (dMonster[dx][dy] != 0 && !CanTalkToMonst(m) &&
|
|
monster[m]._moldx == dx && monster[m]._moldy == dy)
|
|
{
|
|
if (PlrHitMonst(-pnum, m))
|
|
didhit = TRUE;
|
|
}
|
|
dx = plr[pnum]._px + offset_x[(plr[pnum]._pdir+7)%8];
|
|
dy = plr[pnum]._py + offset_y[(plr[pnum]._pdir+7)%8];
|
|
m = ((dMonster[dx][dy] > 0) ?
|
|
dMonster[dx][dy] : -dMonster[dx][dy])
|
|
- 1;
|
|
if (dMonster[dx][dy] != 0 && !CanTalkToMonst(m) &&
|
|
monster[m]._moldx == dx && monster[m]._moldy == dy)
|
|
{
|
|
if (PlrHitMonst(-pnum, m))
|
|
didhit = TRUE;
|
|
}
|
|
}
|
|
if (didhit) {
|
|
if (WeaponDur(pnum, 30)) { // 1 in 30 dur hit if plr hit monst/obj
|
|
StartStand(pnum, plr[pnum]._pdir);
|
|
ClearPlrPVars(pnum);
|
|
return(RUN_AGAIN);
|
|
}
|
|
}
|
|
}
|
|
if (plr[pnum]._pAnimFrame == plr[pnum]._pAFrames) {
|
|
StartStand(pnum, plr[pnum]._pdir);
|
|
ClearPlrPVars(pnum);
|
|
return(RUN_AGAIN);
|
|
} else return(RUN_DONE);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int PM_DoRangeAttack(int pnum)
|
|
{
|
|
int mistype;
|
|
int numshots = 0;
|
|
int shottype = 0;
|
|
int deltaX = 0, deltaY = 0;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("PM_DoRangeAttack: illegal player %d",pnum);
|
|
|
|
if (plr[pnum]._pAnimFrame == plr[pnum]._pAFNum)
|
|
numshots = 1;
|
|
|
|
if ((plr[pnum]._pIFlags & IAF_RABID) &&
|
|
(plr[pnum]._pAnimFrame == plr[pnum]._pAFNum + 2))
|
|
{
|
|
numshots = 2;
|
|
shottype = 1; // framing shots
|
|
}
|
|
|
|
for (int shotnum = 0; shotnum < numshots; shotnum++)
|
|
{
|
|
switch(shottype)
|
|
{
|
|
case 0: break;
|
|
case 1:
|
|
{
|
|
int fanoffset = (shotnum == 0) ? -1 : 1;
|
|
int xoffset = plr[pnum]._pVar1 - plr[pnum]._px;
|
|
int yoffset = plr[pnum]._pVar2 - plr[pnum]._py;
|
|
if (xoffset < 0)
|
|
deltaY = fanoffset;
|
|
if (xoffset > 0)
|
|
deltaY = -fanoffset;
|
|
if (yoffset < 0)
|
|
deltaX = -fanoffset;
|
|
if (yoffset > 0)
|
|
deltaX = fanoffset;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
mistype = MIT_ARROW;
|
|
if (plr[pnum]._pIFlags & IAF_FIREARROW) mistype = MIT_FARROW;
|
|
if (plr[pnum]._pIFlags & IAF_LARROW) mistype = MIT_LARROW;
|
|
|
|
// both flags means a special arrow, doing (firedamage) damage.
|
|
// a bit of a hack. --donald
|
|
if ((plr[pnum]._pIFlags & IAF_FIREARROW) &&
|
|
(plr[pnum]._pIFlags & IAF_LARROW))
|
|
{
|
|
int dmg = plr[pnum]._pIFMinDam + random(3, (plr[pnum]._pIFMaxDam - plr[pnum]._pIFMinDam));
|
|
mistype = MIT_SPECARROW;
|
|
|
|
AddMissile(plr[pnum]._px, plr[pnum]._py, plr[pnum]._pVar1 + deltaX, plr[pnum]._pVar2 + deltaY, plr[pnum]._pdir, mistype, MI_ENEMYMONST, pnum, dmg, 0);
|
|
}
|
|
else
|
|
{
|
|
AddMissile(plr[pnum]._px, plr[pnum]._py, plr[pnum]._pVar1 + deltaX, plr[pnum]._pVar2 + deltaY, plr[pnum]._pdir, mistype, MI_ENEMYMONST, pnum, 4, 0);
|
|
if (shotnum == 0)
|
|
{
|
|
if (shottype == 0)
|
|
PlaySfxLoc(PS_BFIRE, plr[pnum]._px, plr[pnum]._py);
|
|
else
|
|
PlaySfxLoc(PS_NEW_BFIRE, plr[pnum]._px, plr[pnum]._py);
|
|
}
|
|
}
|
|
|
|
if (WeaponDur(pnum, 40)) { // 1 in 40 bow dur hit
|
|
StartStand(pnum, plr[pnum]._pdir);
|
|
ClearPlrPVars(pnum);
|
|
return(RUN_AGAIN);
|
|
}
|
|
}
|
|
if (plr[pnum]._pAnimFrame >= plr[pnum]._pAFrames) {
|
|
StartStand(pnum, plr[pnum]._pdir);
|
|
ClearPlrPVars(pnum);
|
|
return(RUN_AGAIN);
|
|
} else return(RUN_DONE);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void ShieldDur(int pnum)
|
|
{
|
|
if (pnum != myplr) return;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("ShieldDur: illegal player %d",pnum);
|
|
|
|
// Item used, so change durability
|
|
if (plr[pnum].Hand1Item._itype == IT_SHIELD) {
|
|
if (plr[pnum].Hand1Item._iDurability == INFINITE_DUR) return;
|
|
plr[pnum].Hand1Item._iDurability--;
|
|
if (plr[pnum].Hand1Item._iDurability == 0) {
|
|
NetSendCmdDelItem(TRUE, INVLOC_HAND1);
|
|
plr[pnum].Hand1Item._itype = -1;
|
|
CalcPlrInv(pnum,TRUE);
|
|
}
|
|
}
|
|
if (plr[pnum].Hand2Item._itype == IT_SHIELD) {
|
|
if (plr[pnum].Hand2Item._iDurability == INFINITE_DUR) return;
|
|
plr[pnum].Hand2Item._iDurability--;
|
|
if (plr[pnum].Hand2Item._iDurability == 0) {
|
|
NetSendCmdDelItem(TRUE, INVLOC_HAND2);
|
|
plr[pnum].Hand2Item._itype = -1;
|
|
CalcPlrInv(pnum,TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int PM_DoBlock(int pnum)
|
|
{
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("PM_DoBlock: illegal player %d",pnum);
|
|
|
|
if ((plr[pnum]._pIFlags & IAF_BLANIM) && (plr[pnum]._pAnimFrame != 1)) {
|
|
plr[pnum]._pAnimFrame = plr[pnum]._pBFrames;
|
|
}
|
|
if (plr[pnum]._pAnimFrame >= plr[pnum]._pBFrames) {
|
|
StartStand(pnum, plr[pnum]._pdir);
|
|
ClearPlrPVars(pnum);
|
|
if (random(3,10) == 0) ShieldDur(pnum);
|
|
return(RUN_AGAIN);
|
|
} else return(RUN_DONE);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int PM_DoSpell(int pnum)
|
|
{
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("PM_DoSpell: illegal player %d",pnum);
|
|
|
|
if (plr[pnum]._pVar8 == plr[pnum]._pSFNum) {
|
|
CastSpell(pnum, plr[pnum]._pSpell, plr[pnum]._px, plr[pnum]._py, plr[pnum]._pVar1, plr[pnum]._pVar2, MI_PLR, plr[pnum]._pVar4);
|
|
if (plr[pnum]._pSplFrom == SPL_FROMR) {
|
|
if (plr[pnum]._pRSplType == SPT_SCROLL) {
|
|
if ((plr[pnum]._pScrlSpells & (((__int64)1) << (plr[pnum]._pRSpell-1))) == 0) {
|
|
plr[pnum]._pRSpell = -1;
|
|
plr[pnum]._pRSplType = SPT_NONE;
|
|
force_redraw = FULLDRAW;
|
|
}
|
|
}
|
|
if (plr[pnum]._pRSplType == SPT_ITEM) {
|
|
if (((plr[pnum]._pISpells & (((__int64)1) << (plr[pnum]._pRSpell-1)))) == 0) {
|
|
plr[pnum]._pRSpell = -1;
|
|
plr[pnum]._pRSplType = SPT_NONE;
|
|
force_redraw = FULLDRAW;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
plr[pnum]._pVar8++;
|
|
if (leveltype == 0) {
|
|
if (plr[pnum]._pVar8 > plr[pnum]._pSFrames) {
|
|
StartWalkStand(pnum);
|
|
ClearPlrPVars(pnum);
|
|
return(RUN_AGAIN);
|
|
} else return(RUN_DONE);
|
|
} else {
|
|
if (plr[pnum]._pAnimFrame == plr[pnum]._pSFrames) {
|
|
StartStand(pnum, plr[pnum]._pdir);
|
|
ClearPlrPVars(pnum);
|
|
return(RUN_AGAIN);
|
|
} else return(RUN_DONE);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
static void ArmorDur(int pnum) {
|
|
if (pnum != myplr) return;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("ArmorDur: illegal player %d",pnum);
|
|
|
|
PlayerStruct * p = &plr[pnum];
|
|
if (p->BodyItem._itype == -1 && p->HeadItem._itype == -1) return;
|
|
|
|
// Head or body hit?
|
|
int a = random(8, 3);
|
|
if (p->BodyItem._itype != -1 && p->HeadItem._itype == -1) a = 1;
|
|
if (p->BodyItem._itype == -1 && p->HeadItem._itype != -1) a = 0;
|
|
|
|
ItemStruct * pi = a ? &p->BodyItem : &p->HeadItem;
|
|
if (pi->_iDurability == INFINITE_DUR) return;
|
|
|
|
// lose some durability
|
|
pi->_iDurability--;
|
|
if (pi->_iDurability == 0) {
|
|
if (a) NetSendCmdDelItem(TRUE, INVLOC_BODY);
|
|
else NetSendCmdDelItem(TRUE, INVLOC_HEAD);
|
|
pi->_itype = -1;
|
|
CalcPlrInv(pnum,TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
int PM_DoGotHit(int pnum)
|
|
{
|
|
int rv;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("PM_DoGotHit: illegal player %d",pnum);
|
|
|
|
if (plr[pnum]._pIFlags & IAF_ALLHTANIM)
|
|
{
|
|
int htanimframes = 3;
|
|
if (plr[pnum]._pIFlags & IAF_HTANIM2)
|
|
htanimframes = 4;
|
|
if (plr[pnum]._pIFlags & IAF_HTANIM3)
|
|
htanimframes = 5;
|
|
|
|
if (plr[pnum]._pVar8 > 1 && plr[pnum]._pVar8 < htanimframes)
|
|
plr[pnum]._pVar8 = htanimframes;
|
|
|
|
// make sure we didn't go too far
|
|
if (plr[pnum]._pVar8 > plr[pnum]._pHFrames)
|
|
plr[pnum]._pVar8 = plr[pnum]._pHFrames;
|
|
}
|
|
if (plr[pnum]._pVar8 == plr[pnum]._pHFrames) {
|
|
StartStand(pnum, plr[pnum]._pdir);
|
|
ClearPlrPVars(pnum);
|
|
if (random(3,4)) ArmorDur(pnum);
|
|
rv = RUN_AGAIN;
|
|
} else {
|
|
plr[pnum]._pVar8++;
|
|
rv = RUN_DONE;
|
|
}
|
|
|
|
return(rv);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int PM_DoDeath(int pnum)
|
|
{
|
|
int rv;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("PM_DoDeath: illegal player %d",pnum);
|
|
|
|
// Hold last frame
|
|
if (plr[pnum]._pVar8 >= (plr[pnum]._pDFrames << 1)) {
|
|
if ((deathdelay > 1) && (pnum == myplr)) {
|
|
deathdelay--;
|
|
if (deathdelay == 1) {
|
|
deathflag = TRUE;
|
|
if (gbMaxPlayers == 1) gamemenu_on();
|
|
}
|
|
}
|
|
plr[pnum]._pAnimDelay = 10000;
|
|
plr[pnum]._pAnimFrame = plr[pnum]._pAnimLen;
|
|
dFlags[plr[pnum]._px][plr[pnum]._py] |= BFLAG_DEADPLR;
|
|
}
|
|
if (plr[pnum]._pVar8 < 100) plr[pnum]._pVar8++;
|
|
rv = RUN_DONE;
|
|
|
|
return(rv);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int PM_DoNewLvl(int pnum)
|
|
{
|
|
return(RUN_DONE);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void CheckNewPath(int pnum)
|
|
{
|
|
int i, dx, dy, d, oi;
|
|
int v1,v2,v3;
|
|
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("CheckNewPath: illegal player %d",pnum);
|
|
|
|
if (plr[pnum].destAction == PCMD_ATTACKID) {
|
|
i = plr[pnum].destParam1;
|
|
MakePlrPath(pnum, monster[i]._mfutx, monster[i]._mfuty, FALSE);
|
|
}
|
|
if (plr[pnum].destAction == PCMD_ATTACKPID) {
|
|
i = plr[pnum].destParam1;
|
|
MakePlrPath(pnum, plr[i]._pfutx, plr[i]._pfuty, FALSE);
|
|
}
|
|
if (plr[pnum].walkpath[0] != PCMD_NOTHING) {
|
|
if (plr[pnum]._pmode == PM_STAND) {
|
|
// Special case for attack
|
|
if (pnum == myplr) {
|
|
if ((plr[pnum].destAction == PCMD_ATTACKID) || (plr[pnum].destAction == PCMD_ATTACKPID)) {
|
|
i = plr[pnum].destParam1;
|
|
if (plr[pnum].destAction == PCMD_ATTACKID) {
|
|
dx = abs(plr[pnum]._pfutx - monster[i]._mfutx);
|
|
dy = abs(plr[pnum]._pfuty - monster[i]._mfuty);
|
|
d = GetDirection(plr[pnum]._pfutx, plr[pnum]._pfuty, monster[i]._mfutx, monster[i]._mfuty);
|
|
} else {
|
|
dx = abs(plr[pnum]._pfutx - plr[i]._pfutx);
|
|
dy = abs(plr[pnum]._pfuty - plr[i]._pfuty);
|
|
d = GetDirection(plr[pnum]._pfutx, plr[pnum]._pfuty, plr[i]._pfutx, plr[i]._pfuty);
|
|
}
|
|
if ((dx < 2) && (dy < 2)) {
|
|
ClrPlrPath(pnum);
|
|
if ((monster[i].mtalkmsg !=0) && (monster[i].mtalkmsg != TXT_VB2)) TalktoMonster(i);
|
|
else StartAttack(pnum, d);
|
|
plr[pnum].destAction = PCMD_NOTHING;
|
|
}
|
|
}
|
|
}
|
|
if (currlevel != 0) {
|
|
v1 = PlrWalkTbl[plr[pnum]._pClass][0];
|
|
v2 = PlrWalkTbl[plr[pnum]._pClass][1];
|
|
v3 = PlrWalkTbl[plr[pnum]._pClass][2];
|
|
} else {
|
|
v1 = 2048;
|
|
v2 = 1024;
|
|
v3 = 512;
|
|
}
|
|
switch(plr[pnum].walkpath[0]) {
|
|
case PCMD_WALKU :
|
|
StartWalk(pnum, 0, -v2, -1, -1, DIR_U, SCRL_U);
|
|
break;
|
|
case PCMD_WALKUR :
|
|
StartWalk(pnum, v2, -v3, 0, -1, DIR_UR, SCRL_UR);
|
|
break;
|
|
case PCMD_WALKR :
|
|
StartWalk3(pnum, v1, 0, -32, -16, 1, -1, 1, 0, DIR_R, SCRL_R);
|
|
break;
|
|
case PCMD_WALKDR :
|
|
StartWalk2(pnum, v2, v3, -32, -16, 1, 0, DIR_DR, SCRL_DR);
|
|
break;
|
|
case PCMD_WALKD :
|
|
StartWalk2(pnum, 0, v2, 0, -32, 1, 1, DIR_D, SCRL_D);
|
|
break;
|
|
case PCMD_WALKDL :
|
|
StartWalk2(pnum, -v2, v3, 32, -16, 0, 1, DIR_DL, SCRL_DL);
|
|
break;
|
|
case PCMD_WALKL :
|
|
StartWalk3(pnum, -v1, 0, 32, -16, -1, 1, 0, 1, DIR_L, SCRL_L);
|
|
break;
|
|
case PCMD_WALKUL :
|
|
StartWalk(pnum, -v2, -v3, -1 ,0, DIR_UL, SCRL_UL);
|
|
break;
|
|
}
|
|
for (i = 1; i < MAXPATHLEN; i++) plr[pnum].walkpath[i-1] = plr[pnum].walkpath[i];
|
|
plr[pnum].walkpath[MAXPATHLEN-1] = PCMD_NOTHING;
|
|
// if walk fails then start standing
|
|
if (plr[pnum]._pmode == PM_STAND) {
|
|
StartStand(pnum, plr[pnum]._pdir);
|
|
plr[pnum].destAction = PCMD_NOTHING;
|
|
}
|
|
}
|
|
} else {
|
|
if (plr[pnum].destAction != PCMD_NOTHING) {
|
|
if (plr[pnum]._pmode == PM_STAND) {
|
|
switch (plr[pnum].destAction) {
|
|
case PCMD_ATTACK :
|
|
d = GetDirection(plr[pnum]._px, plr[pnum]._py, plr[pnum].destParam1, plr[pnum].destParam2);
|
|
StartAttack(pnum, d);
|
|
break;
|
|
case PCMD_ATTACKID :
|
|
i = plr[pnum].destParam1;
|
|
dx = abs(plr[pnum]._px - monster[i]._mfutx);
|
|
dy = abs(plr[pnum]._py - monster[i]._mfuty);
|
|
if ((dx <= 1) && (dy <= 1)) {
|
|
d = GetDirection(plr[pnum]._pfutx, plr[pnum]._pfuty, monster[i]._mfutx, monster[i]._mfuty);
|
|
if ((monster[i].mtalkmsg !=0) && (monster[i].mtalkmsg != TXT_VB2)) TalktoMonster(i);
|
|
else StartAttack(pnum, d);
|
|
}
|
|
break;
|
|
case PCMD_ATTACKPID:
|
|
i = plr[pnum].destParam1;
|
|
dx = abs(plr[pnum]._px - plr[i]._pfutx);
|
|
dy = abs(plr[pnum]._py - plr[i]._pfuty);
|
|
if ((dx <= 1) && (dy <= 1)) {
|
|
d = GetDirection(plr[pnum]._pfutx, plr[pnum]._pfuty, plr[i]._pfutx, plr[i]._pfuty);
|
|
StartAttack(pnum, d);
|
|
}
|
|
break;
|
|
case PCMD_RATTACK:
|
|
d = GetDirection(plr[pnum]._px, plr[pnum]._py, plr[pnum].destParam1, plr[pnum].destParam2);
|
|
StartRangeAttack(pnum, d, plr[pnum].destParam1, plr[pnum].destParam2);
|
|
break;
|
|
case PCMD_RATTACKID:
|
|
i = plr[pnum].destParam1;
|
|
d = GetDirection(plr[pnum]._pfutx, plr[pnum]._pfuty, monster[i]._mfutx, monster[i]._mfuty);
|
|
if ((monster[i].mtalkmsg !=0) && (monster[i].mtalkmsg != TXT_VB2)) TalktoMonster(i);
|
|
else StartRangeAttack(pnum, d, monster[i]._mfutx, monster[i]._mfuty);
|
|
break;
|
|
case PCMD_RATTACKPID:
|
|
i = plr[pnum].destParam1;
|
|
d = GetDirection(plr[pnum]._pfutx, plr[pnum]._pfuty, plr[i]._pfutx, plr[i]._pfuty);
|
|
StartRangeAttack(pnum, d, plr[i]._pfutx, plr[i]._pfuty);
|
|
break;
|
|
case PCMD_SPELL:
|
|
d = GetDirection(plr[pnum]._px, plr[pnum]._py, plr[pnum].destParam1, plr[pnum].destParam2);
|
|
StartSpell(pnum, d, plr[pnum].destParam1, plr[pnum].destParam2);
|
|
plr[pnum]._pVar4 = plr[pnum].destParam3;
|
|
break;
|
|
case PCMD_SPELLXYD:
|
|
StartSpell(pnum, plr[pnum].destParam3, plr[pnum].destParam1, plr[pnum].destParam2);
|
|
plr[pnum]._pVar3 = plr[pnum].destParam3;
|
|
plr[pnum]._pVar4 = plr[pnum].destParam4;
|
|
break;
|
|
case PCMD_SPELLID:
|
|
i = plr[pnum].destParam1;
|
|
d = GetDirection(plr[pnum]._px, plr[pnum]._py, monster[i]._mfutx, monster[i]._mfuty);
|
|
StartSpell(pnum, d, monster[i]._mfutx, monster[i]._mfuty);
|
|
plr[pnum]._pVar4 = plr[pnum].destParam2;
|
|
break;
|
|
case PCMD_SPELLPID:
|
|
i = plr[pnum].destParam1;
|
|
d = GetDirection(plr[pnum]._px, plr[pnum]._py, plr[i]._pfutx, plr[i]._pfuty);
|
|
StartSpell(pnum, d, plr[i]._pfutx, plr[i]._pfuty);
|
|
plr[pnum]._pVar4 = plr[pnum].destParam2;
|
|
break;
|
|
case PCMD_OPOBJ:
|
|
oi = plr[pnum].destParam1;
|
|
dx = abs(plr[pnum]._px - object[oi]._ox);
|
|
dy = abs(plr[pnum]._py - object[oi]._oy);
|
|
if ((dy > 1) && (dObject[object[oi]._ox][object[oi]._oy-1] == (-1 - oi)))
|
|
dy = abs(plr[pnum]._py - object[oi]._oy + 1);
|
|
|
|
if ((dx <= 1) && (dy <= 1)) {
|
|
if (object[oi]._oBreak == OBJ_BREAKABLE) {
|
|
d = GetDirection(plr[pnum]._px, plr[pnum]._py, object[oi]._ox, object[oi]._oy);
|
|
StartAttack(pnum, d);
|
|
} else OperateObject(pnum, oi, FALSE);
|
|
}
|
|
break;
|
|
case PCMD_DISARM:
|
|
oi = plr[pnum].destParam1;
|
|
dx = abs(plr[pnum]._px - object[oi]._ox);
|
|
dy = abs(plr[pnum]._py - object[oi]._oy);
|
|
if ((dy > 1) && (dObject[object[oi]._ox][object[oi]._oy-1] == (-1 - oi)))
|
|
dy = abs(plr[pnum]._py - object[oi]._oy + 1);
|
|
if ((dx <= 1) && (dy <= 1)) {
|
|
if (object[oi]._oBreak == OBJ_BREAKABLE) {
|
|
d = GetDirection(plr[pnum]._px, plr[pnum]._py, object[oi]._ox, object[oi]._oy);
|
|
StartAttack(pnum, d);
|
|
} else {
|
|
TryDisarm(pnum, oi);
|
|
OperateObject(pnum, oi, FALSE);
|
|
}
|
|
}
|
|
break;
|
|
case PCMD_TELEK:
|
|
oi = plr[pnum].destParam1;
|
|
if (object[oi]._oBreak != OBJ_BREAKABLE) OperateObject(pnum, oi, TRUE);
|
|
break;
|
|
case PCMD_REQGETITEM :
|
|
if (pnum == myplr) {
|
|
i = plr[pnum].destParam1;
|
|
dx = abs(plr[pnum]._px - item[i]._ix);
|
|
dy = abs(plr[pnum]._py - item[i]._iy);
|
|
// PATCH1.JMM
|
|
//if ((dx <= 1) && (dy <= 1) && (curs == GLOVE_CURS) && (!item[i]._iRequest) && (!item[i]._iDelFlag)) {
|
|
if ((dx <= 1) && (dy <= 1) && (curs == GLOVE_CURS) && (!item[i]._iRequest)) {
|
|
// ENDPATCH1.JMM
|
|
NetSendCmdGItem(TRUE, CMD_REQUESTGITEM, myplr, myplr, i);
|
|
item[i]._iRequest = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
case PCMD_REQAGETITEM :
|
|
if (pnum == myplr) {
|
|
i = plr[pnum].destParam1;
|
|
dx = abs(plr[pnum]._px - item[i]._ix);
|
|
dy = abs(plr[pnum]._py - item[i]._iy);
|
|
if ((dx <= 1) && (dy <= 1) && (curs == GLOVE_CURS))
|
|
NetSendCmdGItem(TRUE, CMD_REQUESTAGITEM, myplr, myplr, i);
|
|
}
|
|
break;
|
|
case PCMD_TALK:
|
|
if (pnum == myplr) TalkToTowner(pnum, plr[pnum].destParam1);
|
|
break;
|
|
}
|
|
FixPlayerLocation(pnum,plr[pnum]._pdir);
|
|
plr[pnum].destAction = PCMD_NOTHING;
|
|
} else {
|
|
if ((plr[pnum]._pmode == PM_ATTACK) && (plr[pnum]._pAnimFrame > plr[myplr]._pAFNum)) {
|
|
if (plr[pnum].destAction == PCMD_ATTACK) {
|
|
d = GetDirection(plr[pnum]._pfutx, plr[pnum]._pfuty, plr[pnum].destParam1, plr[pnum].destParam2);
|
|
StartAttack(pnum, d);
|
|
plr[pnum].destAction = PCMD_NOTHING;
|
|
}
|
|
else if (plr[pnum].destAction == PCMD_ATTACKID) {
|
|
i = plr[pnum].destParam1;
|
|
dx = abs(plr[pnum]._px - monster[i]._mfutx);
|
|
dy = abs(plr[pnum]._py - monster[i]._mfuty);
|
|
if ((dx <= 1) && (dy <= 1)) {
|
|
d = GetDirection(plr[pnum]._pfutx, plr[pnum]._pfuty, monster[i]._mfutx, monster[i]._mfuty);
|
|
StartAttack(pnum, d);
|
|
}
|
|
plr[pnum].destAction = PCMD_NOTHING;
|
|
}
|
|
else if (plr[pnum].destAction == PCMD_ATTACKPID) {
|
|
i = plr[pnum].destParam1;
|
|
dx = abs(plr[pnum]._px - plr[i]._pfutx);
|
|
dy = abs(plr[pnum]._py - plr[i]._pfuty);
|
|
if ((dx <= 1) && (dy <= 1)) {
|
|
d = GetDirection(plr[pnum]._pfutx, plr[pnum]._pfuty, plr[i]._pfutx, plr[i]._pfuty);
|
|
StartAttack(pnum, d);
|
|
}
|
|
plr[pnum].destAction = PCMD_NOTHING;
|
|
}
|
|
else if (plr[pnum].destAction == PCMD_OPOBJ)
|
|
{
|
|
oi = plr[pnum].destParam1;
|
|
dx = abs(plr[pnum]._px - object[oi]._ox);
|
|
dy = abs(plr[pnum]._py - object[oi]._oy);
|
|
if ((dy > 1) && (dObject[object[oi]._ox][object[oi]._oy-1] == (-1 - oi)))
|
|
dy = abs(plr[pnum]._py - object[oi]._oy + 1);
|
|
if ((dx <= 1) && (dy <= 1)) {
|
|
if (object[oi]._oBreak == OBJ_BREAKABLE) {
|
|
d = GetDirection(plr[pnum]._px, plr[pnum]._py, object[oi]._ox, object[oi]._oy);
|
|
StartAttack(pnum, d);
|
|
} else OperateObject(pnum, oi, FALSE);
|
|
}
|
|
}
|
|
}
|
|
if ((plr[pnum]._pmode == PM_RATTACK) && (plr[pnum]._pAnimFrame > plr[myplr]._pAFNum)) {
|
|
if (plr[pnum].destAction == PCMD_RATTACK) {
|
|
d = GetDirection(plr[pnum]._px, plr[pnum]._py, plr[pnum].destParam1, plr[pnum].destParam2);
|
|
StartRangeAttack(pnum, d, plr[pnum].destParam1, plr[pnum].destParam2);
|
|
plr[pnum].destAction = PCMD_NOTHING;
|
|
}
|
|
else if (plr[pnum].destAction == PCMD_RATTACKID) {
|
|
i = plr[pnum].destParam1;
|
|
d = GetDirection(plr[pnum]._px, plr[pnum]._py, monster[i]._mfutx, monster[i]._mfuty);
|
|
StartRangeAttack(pnum, d, monster[i]._mfutx, monster[i]._mfuty);
|
|
plr[pnum].destAction = PCMD_NOTHING;
|
|
}
|
|
else if (plr[pnum].destAction == PCMD_RATTACKPID) {
|
|
i = plr[pnum].destParam1;
|
|
d = GetDirection(plr[pnum]._px, plr[pnum]._py, plr[i]._pfutx, plr[i]._pfuty);
|
|
StartRangeAttack(pnum, d, plr[i]._pfutx, plr[i]._pfuty);
|
|
plr[pnum].destAction = PCMD_NOTHING;
|
|
}
|
|
}
|
|
if ((plr[pnum]._pmode == PM_SPELL) && (plr[pnum]._pAnimFrame > plr[pnum]._pSFNum)) {
|
|
if (plr[pnum].destAction == PCMD_SPELL) {
|
|
d = GetDirection(plr[pnum]._px, plr[pnum]._py, plr[pnum].destParam1, plr[pnum].destParam2);
|
|
StartSpell(pnum, d, plr[pnum].destParam1, plr[pnum].destParam2);
|
|
plr[pnum].destAction = PCMD_NOTHING;
|
|
}
|
|
else if (plr[pnum].destAction == PCMD_SPELLID) {
|
|
i = plr[pnum].destParam1;
|
|
d = GetDirection(plr[pnum]._px, plr[pnum]._py, monster[i]._mfutx, monster[i]._mfuty);
|
|
StartSpell(pnum, d, monster[i]._mfutx, monster[i]._mfuty);
|
|
plr[pnum].destAction = PCMD_NOTHING;
|
|
}
|
|
else if (plr[pnum].destAction == PCMD_SPELLPID) {
|
|
i = plr[pnum].destParam1;
|
|
d = GetDirection(plr[pnum]._px, plr[pnum]._py, plr[i]._pfutx, plr[i]._pfuty);
|
|
StartSpell(pnum, d, plr[i]._pfutx, plr[i]._pfuty);
|
|
plr[pnum].destAction = PCMD_NOTHING;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
BOOL PlrDeathModeOK(int p)
|
|
{
|
|
if (p != myplr) return(TRUE);
|
|
if ((DWORD)p >= MAX_PLRS)
|
|
app_fatal("PlrDeathModeOK: illegal player %d",p);
|
|
if (plr[p]._pmode == PM_DEATH) return(TRUE);
|
|
if (plr[p]._pmode == PM_QUIT) return(TRUE);
|
|
if (plr[p]._pmode == PM_NEWLVL) return(TRUE);
|
|
return(FALSE);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void ValidatePlayer()
|
|
{
|
|
int i, gt, pc;
|
|
//jam.patch1.start.1/23/97
|
|
//__int64 msk;
|
|
__int64 msk = 0;
|
|
//jam.patch1.end.1/23/97
|
|
__int64 b = 1;
|
|
|
|
if ((DWORD)myplr >= MAX_PLRS)
|
|
app_fatal("ValidatePlayer: illegal player %d",myplr);
|
|
if (plr[myplr]._pLevel > 50) plr[myplr]._pLevel = 50;
|
|
if (plr[myplr]._pExperience > plr[myplr]._pNextExper)
|
|
plr[myplr]._pExperience = plr[myplr]._pNextExper;
|
|
gt = 0;
|
|
for (i = 0; i < plr[myplr]._pNumInv; i++) {
|
|
if (plr[myplr].InvList[i]._itype == IT_GOLD) {
|
|
if (plr[myplr].InvList[i]._ivalue > GOLD_DOUBLE_VMAX) plr[myplr].InvList[i]._ivalue = GOLD_DOUBLE_VMAX;
|
|
gt += plr[myplr].InvList[i]._ivalue;
|
|
}
|
|
}
|
|
if (gt != plr[myplr]._pGold) plr[myplr]._pGold = gt;
|
|
pc = plr[myplr]._pClass;
|
|
if (plr[myplr]._pBaseStr > MaxStats[pc][0]) plr[myplr]._pBaseStr = MaxStats[pc][0];
|
|
if (plr[myplr]._pBaseMag > MaxStats[pc][1]) plr[myplr]._pBaseMag = MaxStats[pc][1];
|
|
if (plr[myplr]._pBaseDex > MaxStats[pc][2]) plr[myplr]._pBaseDex = MaxStats[pc][2];
|
|
if (plr[myplr]._pBaseVit > MaxStats[pc][3]) plr[myplr]._pBaseVit = MaxStats[pc][3];
|
|
|
|
for (i = SPL_FIREBOLT; i < SPL_LAST; i++) {
|
|
if (spelldata[i].sBookLvl != -1) {
|
|
msk |= (b << (i-1));
|
|
if (plr[myplr]._pSplLvl[i] > SPELLCAP) plr[myplr]._pSplLvl[i] = SPELLCAP;
|
|
}
|
|
}
|
|
plr[myplr]._pMemSpells &= msk;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*
|
|
|
|
int pdoppely = DIRTEDGED2;
|
|
|
|
void PlayerDoppel()
|
|
{
|
|
int pdoppelx, pidx;
|
|
PlayerStruct *p;
|
|
BOOL forceclear;
|
|
|
|
if (gbMaxPlayers == 1) return;
|
|
|
|
for (pdoppelx = DIRTEDGED2; pdoppelx < (DIRTEDGED2+80); pdoppelx++) {
|
|
if (dPlayer[pdoppelx][pdoppely]) {
|
|
if (dPlayer[pdoppelx][pdoppely] > 0)
|
|
pidx = dPlayer[pdoppelx][pdoppely] - 1;
|
|
else
|
|
pidx = -(dPlayer[pdoppelx][pdoppely] + 1);
|
|
p = &plr[pidx];
|
|
forceclear = FALSE;
|
|
if (p->plrlevel != currlevel) forceclear = TRUE;
|
|
if (!p->plractive) forceclear = TRUE;
|
|
if (!forceclear) {
|
|
if ((p->_pmode >= PM_WALK) && (p->_pmode <= PM_WALK3)) continue;
|
|
if (p->_pmode >= PM_NEWLVL) continue;
|
|
if ((p->_px == pdoppelx) && (p->_py == pdoppely)) continue;
|
|
forceclear = TRUE;
|
|
}
|
|
if (forceclear) {
|
|
dFlags[pdoppelx+1][pdoppely+0] &= BFMASK_PLRLR;
|
|
dFlags[pdoppelx+0][pdoppely+1] &= BFMASK_PLRLR;
|
|
dPlayer[pdoppelx][pdoppely] = 0;
|
|
}
|
|
}
|
|
}
|
|
pdoppely++;
|
|
if (pdoppely == DIRTEDGED2+80) pdoppely = DIRTEDGED2;
|
|
}
|
|
// PATCH2.JMM.3/5/97
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
#define MAX_STAT 750
|
|
#define MAX_HP (2000<<HP_SHIFT)
|
|
#define MAX_MANA (2000<<MANA_SHIFT)
|
|
static void CheckCheatStats( int pnum ) {
|
|
if ( plr[pnum]._pStrength > MAX_STAT )
|
|
plr[pnum]._pStrength = MAX_STAT;
|
|
|
|
if ( plr[pnum]._pDexterity > MAX_STAT )
|
|
plr[pnum]._pDexterity = MAX_STAT;
|
|
|
|
if ( plr[pnum]._pMagic > MAX_STAT )
|
|
plr[pnum]._pMagic = MAX_STAT;
|
|
|
|
if ( plr[pnum]._pVitality > MAX_STAT )
|
|
plr[pnum]._pVitality = MAX_STAT;
|
|
|
|
if ( plr[pnum]._pHitPoints > MAX_HP )
|
|
plr[pnum]._pHitPoints = MAX_HP;
|
|
|
|
if ( plr[pnum]._pMana > MAX_MANA )
|
|
plr[pnum]._pMana = MAX_MANA;
|
|
|
|
}
|
|
// ENDPATCH2
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void ProcessPlayers()
|
|
{
|
|
int raflag; // Run again flag
|
|
int pnum;
|
|
|
|
if ((DWORD)myplr >= MAX_PLRS)
|
|
app_fatal("ProcessPlayers: illegal player %d",myplr);
|
|
|
|
// TEMP! debugging
|
|
for (int i = 0; i < MAXINV; i++) {
|
|
if (plr[myplr].InvGrid[i] > 0)
|
|
app_assert(plr[myplr].InvGrid[i] <= plr[myplr]._pNumInv);
|
|
}
|
|
|
|
if (plr[myplr].pLvlLoad > 0) plr[myplr].pLvlLoad--;
|
|
|
|
if (sfxdelay > 0) {
|
|
sfxdelay--;
|
|
if (sfxdelay == 0)
|
|
{
|
|
switch (sfxdnum)
|
|
{
|
|
case HSFX_DEFILER1:
|
|
InitQTextMsg(TXT_DEFILER1);
|
|
break;
|
|
case HSFX_DEFILER2:
|
|
InitQTextMsg(TXT_DEFILER2);
|
|
break;
|
|
case HSFX_DEFILER3:
|
|
InitQTextMsg(TXT_DEFILER3);
|
|
break;
|
|
case HSFX_DEFILER4:
|
|
InitQTextMsg(TXT_DEFILER4);
|
|
break;
|
|
default:
|
|
PlaySFX(sfxdnum);
|
|
}
|
|
}
|
|
}
|
|
|
|
ValidatePlayer();
|
|
|
|
for (pnum = 0; pnum < MAX_PLRS; pnum++) {
|
|
if (!plr[pnum].plractive) continue;
|
|
if (currlevel != plr[pnum].plrlevel) continue;
|
|
if ((pnum != myplr) && (plr[pnum]._pLvlChanging)) continue;
|
|
|
|
// PATCH2.JMM.3/5/97
|
|
CheckCheatStats( pnum );
|
|
// PATCH2.JMM.3/5/97
|
|
|
|
|
|
|
|
|
|
if ((!PlrDeathModeOK(pnum)) && ((plr[pnum]._pHitPoints >> HP_SHIFT) <= 0)) {
|
|
// rjs - manashld fix? - SetPlayerHitPoints(pnum, 0);
|
|
StartPlrKill(pnum, KILL_UNKNOWN);
|
|
}
|
|
|
|
if (pnum == myplr) {
|
|
// Constricting item
|
|
if ((plr[pnum]._pIFlags & IAF_CONSTRICT) && (currlevel != 0)) {
|
|
plr[pnum]._pHitPoints -= 4;
|
|
plr[pnum]._pHPBase -= 4;
|
|
if ((plr[pnum]._pHitPoints >> HP_SHIFT) <= 0) {
|
|
// rjs - manashld fix? - SetPlayerHitPoints(pnum, 0);
|
|
StartPlrKill(pnum, FALSE);
|
|
}
|
|
drawhpflag = TRUE;
|
|
}
|
|
|
|
// lose mana item
|
|
if (plr[pnum]._pIFlags & IAF_LMANA) {
|
|
if (plr[pnum]._pManaBase > 0 ) {
|
|
plr[pnum]._pManaBase -= plr[pnum]._pMana;
|
|
plr[pnum]._pMana = 0;
|
|
drawmanaflag = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
raflag = RUN_DONE;
|
|
do {
|
|
// Run Player Mode
|
|
switch (plr[pnum]._pmode) {
|
|
case PM_STAND :
|
|
raflag = PM_DoStand(pnum);
|
|
break;
|
|
case PM_WALK :
|
|
raflag = PM_DoWalk(pnum);
|
|
break;
|
|
case PM_WALK2 :
|
|
raflag = PM_DoWalk2(pnum);
|
|
break;
|
|
case PM_WALK3:
|
|
raflag = PM_DoWalk3(pnum);
|
|
break;
|
|
case PM_ATTACK:
|
|
raflag = PM_DoAttack(pnum);
|
|
break;
|
|
case PM_RATTACK:
|
|
raflag = PM_DoRangeAttack(pnum);
|
|
break;
|
|
case PM_BLOCK :
|
|
raflag = PM_DoBlock(pnum);
|
|
break;
|
|
case PM_SPELL:
|
|
raflag = PM_DoSpell(pnum);
|
|
break;
|
|
case PM_GOTHIT:
|
|
raflag = PM_DoGotHit(pnum);
|
|
break;
|
|
case PM_DEATH:
|
|
raflag = PM_DoDeath(pnum);
|
|
break;
|
|
case PM_NEWLVL:
|
|
raflag = PM_DoNewLvl(pnum);
|
|
break;
|
|
}
|
|
|
|
// Check for new command
|
|
CheckNewPath(pnum);
|
|
|
|
} while (raflag != RUN_DONE);
|
|
|
|
// Animate Player
|
|
plr[pnum]._pAnimCnt++;
|
|
if (plr[pnum]._pAnimCnt > plr[pnum]._pAnimDelay) {
|
|
plr[pnum]._pAnimCnt = 0;
|
|
plr[pnum]._pAnimFrame++;
|
|
if (plr[pnum]._pAnimFrame > plr[pnum]._pAnimLen) plr[pnum]._pAnimFrame = 1;
|
|
}
|
|
}
|
|
|
|
//PlayerDoppel();
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void ClrPlrPath(int pnum) {
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("ClrPlrPath: illegal player %d",pnum);
|
|
FillMemory(plr[pnum].walkpath,MAXPATHLEN,PCMD_NOTHING);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
BOOL PosOkPlayer(int pnum, int px, int py)
|
|
{
|
|
int mi, p, pn;
|
|
char bv;
|
|
|
|
if (dPiece[px][py] == 0) return FALSE;
|
|
pn = dPiece[px][py];
|
|
if (SolidLoc(px, py)) return FALSE;
|
|
if (dPlayer[px][py]) {
|
|
if (dPlayer[px][py] > 0) p = dPlayer[px][py] - 1;
|
|
else p = -(dPlayer[px][py] + 1);
|
|
if ((p != pnum) && (plr[p]._pHitPoints != 0)) return FALSE;
|
|
}
|
|
if (dMonster[px][py]) {
|
|
if (currlevel == 0) return FALSE;
|
|
if (dMonster[px][py] > 0) {
|
|
mi = dMonster[px][py] - 1;
|
|
if ((monster[mi]._mhitpoints >> HP_SHIFT) > 0) return FALSE;
|
|
} else return FALSE;
|
|
}
|
|
if (dObject[px][py]) {
|
|
if (dObject[px][py] > 0) bv = dObject[px][py] - 1;
|
|
else bv = -(dObject[px][py] + 1);
|
|
if (object[bv]._oSolidFlag) return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void MakePlrPath(int pnum, int xx, int yy, BOOL endspace)
|
|
{
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("MakePlrPath: illegal player %d",pnum);
|
|
|
|
// set target position
|
|
plr[pnum]._ptargx = xx;
|
|
plr[pnum]._ptargy = yy;
|
|
|
|
if (plr[pnum]._pfutx == xx && plr[pnum]._pfuty == yy)
|
|
return;
|
|
|
|
int pathlen = FindPath(PosOkPlayer, pnum, plr[pnum]._pfutx, plr[pnum]._pfuty, xx, yy, plr[pnum].walkpath);
|
|
if(pathlen) {
|
|
if (!endspace) {
|
|
pathlen--;
|
|
switch (plr[pnum].walkpath[pathlen]) {
|
|
case PCMD_WALKUR:
|
|
yy++;
|
|
break;
|
|
case PCMD_WALKUL:
|
|
xx++;
|
|
break;
|
|
case PCMD_WALKDR:
|
|
xx--;
|
|
break;
|
|
case PCMD_WALKDL:
|
|
yy--;
|
|
break;
|
|
case PCMD_WALKU:
|
|
xx++;
|
|
yy++;
|
|
break;
|
|
case PCMD_WALKR:
|
|
xx--;
|
|
yy++;
|
|
break;
|
|
case PCMD_WALKD:
|
|
xx--;
|
|
yy--;
|
|
break;
|
|
case PCMD_WALKL:
|
|
xx++;
|
|
yy--;
|
|
break;
|
|
}
|
|
plr[pnum]._ptargx = xx;
|
|
plr[pnum]._ptargy = yy;
|
|
}
|
|
plr[pnum].walkpath[pathlen] = PCMD_NOTHING;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------**
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void CheckPlrSpell()
|
|
{
|
|
int sd;
|
|
BOOL addflag = FALSE;
|
|
|
|
if ((DWORD)myplr >= MAX_PLRS)
|
|
app_fatal("CheckPlrSpell: illegal player %d",myplr);
|
|
|
|
int rspell = plr[myplr]._pRSpell;
|
|
|
|
if (rspell == -1) {
|
|
if (plr[myplr]._pClass == CLASS_WARRIOR) PlaySFX(PS_WARR34);
|
|
#if !IS_VERSION(SHAREWARE)
|
|
else if (plr[myplr]._pClass == CLASS_ROGUE) PlaySFX(PS_ROGUE34);
|
|
else if (plr[myplr]._pClass == CLASS_SORCEROR) PlaySFX(PS_MAGE34);
|
|
else if (plr[myplr]._pClass == CLASS_MONK) PlaySFX(PS_MONK34);
|
|
else if (plr[myplr]._pClass == CLASS_BARD) PlaySFX(PS_BARD34);
|
|
else if (plr[myplr]._pClass == CLASS_BARBARIAN) PlaySFX(PS_BARBARIAN34);
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
//rjs if (leveltype == 0) return;
|
|
if (leveltype == 0 && spelldata[plr[myplr]._pRSpell].sTownSpell == FALSE) {
|
|
if (plr[myplr]._pClass == CLASS_WARRIOR) PlaySFX(PS_WARR27);
|
|
#if !IS_VERSION(SHAREWARE)
|
|
else if (plr[myplr]._pClass == CLASS_ROGUE) PlaySFX(PS_ROGUE27);
|
|
else if (plr[myplr]._pClass == CLASS_SORCEROR) PlaySFX(PS_MAGE27);
|
|
else if (plr[myplr]._pClass == CLASS_MONK) PlaySFX(PS_MONK27);
|
|
else if (plr[myplr]._pClass == CLASS_BARD) PlaySFX(PS_BARD27);
|
|
else if (plr[myplr]._pClass == CLASS_BARBARIAN) PlaySFX(PS_BARBARIAN27);
|
|
#endif
|
|
return;
|
|
}
|
|
if (curs != GLOVE_CURS) return;
|
|
|
|
// Check if cursor is in play area, allowing certain spells to be executed anywhere
|
|
if (!(((MouseY < 352)
|
|
&& !(chrflag && MouseX < 320)
|
|
&& !(invflag && MouseX > 320)) ||
|
|
((MouseY < 352) && (rspell == SPL_HEAL
|
|
|| rspell == SPL_IDENTIFY
|
|
|| rspell == SPL_REPAIR
|
|
|| rspell == SPL_INFRA
|
|
|| rspell == SPL_RECHARGE))))
|
|
return;
|
|
|
|
switch (plr[myplr]._pRSplType) {
|
|
case SPT_ABILITY :
|
|
case SPT_MEMORIZED :
|
|
addflag = CheckSpell(myplr, plr[myplr]._pRSpell, plr[myplr]._pRSplType, FALSE);
|
|
break;
|
|
case SPT_SCROLL :
|
|
addflag = UseScroll();
|
|
break;
|
|
case SPT_ITEM:
|
|
addflag = UseStaff();
|
|
break;
|
|
}
|
|
if (addflag) {
|
|
if (plr[myplr]._pRSpell == SPL_WALL
|
|
|| plr[myplr]._pRSpell == SPL_LTWALL) {
|
|
sd = GetDirection(plr[myplr]._px, plr[myplr]._py, cursmx, cursmy);
|
|
NetSendCmdLocParam3(TRUE, CMD_SPELLXYD, cursmx, cursmy, plr[myplr]._pRSpell, sd, GetSpellLevel(myplr, plr[myplr]._pRSpell));
|
|
} else {
|
|
if (cursmonst != -1) NetSendCmdParam3(TRUE, CMD_SPELLID, cursmonst, plr[myplr]._pRSpell,GetSpellLevel(myplr, plr[myplr]._pRSpell));
|
|
else {
|
|
if (cursplr != -1) NetSendCmdParam3(TRUE, CMD_SPELLPID, cursplr, plr[myplr]._pRSpell,GetSpellLevel(myplr, plr[myplr]._pRSpell));
|
|
else NetSendCmdLocParam2(TRUE, CMD_SPELLXY, cursmx, cursmy, plr[myplr]._pRSpell,GetSpellLevel(myplr, plr[myplr]._pRSpell));
|
|
}
|
|
}
|
|
} else {
|
|
if (plr[myplr]._pRSplType == SPT_MEMORIZED) {
|
|
if (plr[myplr]._pClass == CLASS_WARRIOR) PlaySFX(PS_WARR35);
|
|
#if !IS_VERSION(SHAREWARE)
|
|
else if (plr[myplr]._pClass == CLASS_ROGUE) PlaySFX(PS_ROGUE35);
|
|
else if (plr[myplr]._pClass == CLASS_SORCEROR) PlaySFX(PS_MAGE35);
|
|
else if (plr[myplr]._pClass == CLASS_MONK) PlaySFX(PS_MONK35);
|
|
else if (plr[myplr]._pClass == CLASS_BARD) PlaySFX(PS_BARD35);
|
|
else if (plr[myplr]._pClass == CLASS_BARBARIAN) PlaySFX(PS_BARBARIAN35);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SyncPlrAnim(int p)
|
|
{
|
|
int dir, s;
|
|
|
|
if ((DWORD)p >= MAX_PLRS)
|
|
app_fatal("SyncPlrAnim: illegal player %d",p);
|
|
|
|
dir = plr[p]._pdir;
|
|
switch (plr[p]._pmode) {
|
|
case PM_STAND :
|
|
plr[p]._pAnimData = plr[p]._pNAnim[dir];
|
|
break;
|
|
case PM_WALK :
|
|
plr[p]._pAnimData = plr[p]._pWAnim[dir];
|
|
break;
|
|
case PM_WALK2 :
|
|
plr[p]._pAnimData = plr[p]._pWAnim[dir];
|
|
break;
|
|
case PM_WALK3:
|
|
plr[p]._pAnimData = plr[p]._pWAnim[dir];
|
|
break;
|
|
case PM_ATTACK:
|
|
plr[p]._pAnimData = plr[p]._pAAnim[dir];
|
|
break;
|
|
case PM_RATTACK:
|
|
plr[p]._pAnimData = plr[p]._pAAnim[dir];
|
|
break;
|
|
case PM_BLOCK:
|
|
plr[p]._pAnimData = plr[p]._pBAnim[dir];
|
|
break;
|
|
case PM_SPELL:
|
|
if (p == myplr) s = spelldata[plr[p]._pSpell].sType;
|
|
//jam.patch1.start.1/23/97
|
|
//else s == ST_FIRE;
|
|
else s = ST_FIRE;
|
|
//jam.patch1.end.1/23/97
|
|
if (s == ST_FIRE) plr[p]._pAnimData = plr[p]._pFAnim[dir];
|
|
if (s == ST_LIGHT) plr[p]._pAnimData = plr[p]._pLAnim[dir];
|
|
if (s == ST_MISC) plr[p]._pAnimData = plr[p]._pTAnim[dir];
|
|
break;
|
|
case PM_GOTHIT:
|
|
plr[p]._pAnimData = plr[p]._pHAnim[dir];
|
|
break;
|
|
case PM_DEATH:
|
|
plr[p]._pAnimData = plr[p]._pDAnim[dir];
|
|
break;
|
|
case PM_NEWLVL:
|
|
case PM_QUIT:
|
|
plr[p]._pAnimData = plr[p]._pNAnim[dir];
|
|
break;
|
|
default:
|
|
app_fatal("SyncPlrAnim");
|
|
break;
|
|
}
|
|
|
|
app_assert(plr[p]._pAnimData);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void SyncInitPlrPos(int pnum)
|
|
{
|
|
// Force the player's target position to be where he wants it to be
|
|
plr[pnum]._ptargx = plr[pnum]._px;
|
|
plr[pnum]._ptargy = plr[pnum]._py;
|
|
|
|
// Don't find a space for single player
|
|
if (gbMaxPlayers == 1) return;
|
|
|
|
// Find a place to put him in the map
|
|
if (plr[pnum].plrlevel == currlevel) {
|
|
for (int i = 0; i < sizeof(plrxoff2)/sizeof(plrxoff2[0]) - 1; i++) {
|
|
if (PosOkPlayer(
|
|
pnum,
|
|
plr[pnum]._px + plrxoff2[i],
|
|
plr[pnum]._py + plryoff2[i]
|
|
)) break;
|
|
}
|
|
|
|
// stuff player into the map
|
|
plr[pnum]._px += plrxoff2[i];
|
|
plr[pnum]._py += plryoff2[i];
|
|
dPlayer[plr[pnum]._px][plr[pnum]._py] = pnum + 1;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void SyncInitPlr(int pnum) {
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("SyncInitPlr: illegal player %d",pnum);
|
|
|
|
SetPlrAnims(pnum);
|
|
SyncInitPlrPos(pnum);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void CheckStats(int p)
|
|
/*-----------------------------------------------------------------------*
|
|
** Description: Checks to see if specified characters base stat value
|
|
** is greater than the max base stat, or less than 0.
|
|
** If characters base stat > max. stat, then set characters base
|
|
** stat = max. stat. If characters base stat < 0, then set
|
|
** characters base stat = 0.
|
|
** Input: p = plr[?] index
|
|
** s = stat to check
|
|
** Return: None
|
|
**-----------------------------------------------------------------------*/
|
|
{
|
|
int c, i;
|
|
|
|
if ((DWORD)p >= MAX_PLRS)
|
|
app_fatal("CheckStats: illegal player %d",p);
|
|
|
|
//Find character class
|
|
if (plr[p]._pClass == CLASS_WARRIOR) c = 0;
|
|
else if (plr[p]._pClass == CLASS_ROGUE) c = 1;
|
|
else if (plr[p]._pClass == CLASS_SORCEROR) c = 2;
|
|
else if (plr[p]._pClass == CLASS_MONK) c = 3;
|
|
else if (plr[p]._pClass == CLASS_BARD) c = 4;
|
|
else if (plr[p]._pClass == CLASS_BARBARIAN) c = 5;
|
|
//Check stats
|
|
for (i = 0; i < 4; i++) {
|
|
switch(i) {
|
|
case 0:
|
|
//Strength
|
|
if (plr[p]._pBaseStr > MaxStats[c][0]) plr[p]._pBaseStr = MaxStats[c][0];
|
|
else if (plr[p]._pBaseStr < 0) plr[p]._pBaseStr = 0;
|
|
break;
|
|
case 1:
|
|
//Magic
|
|
if (plr[p]._pBaseMag > MaxStats[c][1]) plr[p]._pBaseMag = MaxStats[c][1];
|
|
else if (plr[p]._pBaseMag < 0) plr[p]._pBaseMag = 0;
|
|
break;
|
|
case 2:
|
|
//Dexterity
|
|
if (plr[p]._pBaseDex > MaxStats[c][2]) plr[p]._pBaseDex = MaxStats[c][2];
|
|
else if (plr[p]._pBaseDex < 0) plr[p]._pBaseDex = 0;
|
|
break;
|
|
case 3:
|
|
//Vitality
|
|
if (plr[p]._pBaseVit > MaxStats[c][3]) plr[p]._pBaseVit = MaxStats[c][3];
|
|
else if (plr[p]._pBaseVit < 0) plr[p]._pBaseVit = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void ModifyPlrStr(int p, int l)
|
|
{
|
|
if ((DWORD)p >= MAX_PLRS)
|
|
app_fatal("ModifyPlrStr: illegal player %d",p);
|
|
int ms = MaxStats[plr[p]._pClass][0];
|
|
if ((plr[p]._pBaseStr + l) > ms) l = ms - plr[p]._pBaseStr;
|
|
plr[p]._pStrength += l;
|
|
plr[p]._pBaseStr += l;
|
|
// if (plr[p]._pClass == CLASS_ROGUE ||
|
|
// plr[p]._pClass == CLASS_MONK ||
|
|
// plr[p]._pClass == CLASS_BARD)
|
|
// plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 200;
|
|
// else
|
|
// plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 100;
|
|
CalcPlrInv(p,TRUE);
|
|
if (p == myplr) NetSendCmdParam1(FALSE, CMD_SETSTR, plr[p]._pBaseStr);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void ModifyPlrMag(int p, int l)
|
|
{
|
|
if ((DWORD)p >= MAX_PLRS)
|
|
app_fatal("ModifyPlrMag: illegal player %d",p);
|
|
int ms = MaxStats[plr[p]._pClass][1];
|
|
if ((plr[p]._pBaseMag + l) > ms) l = ms - plr[p]._pBaseMag;
|
|
plr[p]._pMagic += l;
|
|
plr[p]._pBaseMag += l;
|
|
l = l << MANA_SHIFT;
|
|
if (plr[p]._pClass == CLASS_SORCEROR) l = l << 1; // 2x
|
|
else if (plr[p]._pClass == CLASS_BARD) l += l >> 1; // 1.5x
|
|
plr[p]._pMaxManaBase += l;
|
|
plr[p]._pMaxMana += l;
|
|
|
|
if (!(plr[p]._pIFlags & IAF_LMANA)) {
|
|
plr[p]._pManaBase += l;
|
|
plr[p]._pMana += l;
|
|
}
|
|
CalcPlrInv(p,TRUE);
|
|
if (p == myplr) NetSendCmdParam1(FALSE, CMD_SETMAG, plr[p]._pBaseMag);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void ModifyPlrDex(int p, int l)
|
|
{
|
|
if ((DWORD)p >= MAX_PLRS)
|
|
app_fatal("ModifyPlrDex: illegal player %d",p);
|
|
int ms = MaxStats[plr[p]._pClass][2];
|
|
if ((plr[p]._pBaseDex + l) > ms) l = ms - plr[p]._pBaseDex;
|
|
plr[p]._pDexterity += l;
|
|
plr[p]._pBaseDex += l;
|
|
CalcPlrInv(p,TRUE);
|
|
// if (plr[p]._pClass == CLASS_ROGUE ||
|
|
// plr[p]._pClass == CLASS_MONK ||
|
|
// plr[p]._pClass == CLASS_BARD)
|
|
// {
|
|
// plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 200;
|
|
// }
|
|
if (p == myplr) NetSendCmdParam1(FALSE, CMD_SETDEX, plr[p]._pBaseDex);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void ModifyPlrVit(int p, int l)
|
|
{
|
|
if ((DWORD)p >= MAX_PLRS)
|
|
app_fatal("ModifyPlrVit: illegal player %d",p);
|
|
int ms = MaxStats[plr[p]._pClass][3];
|
|
if ((plr[p]._pBaseVit + l) > ms) l = ms - plr[p]._pBaseVit;
|
|
plr[p]._pVitality += l;
|
|
plr[p]._pBaseVit += l;
|
|
l = l << HP_SHIFT;
|
|
if (plr[p]._pClass == CLASS_WARRIOR
|
|
|| plr[p]._pClass == CLASS_BARBARIAN) l = l << 1;
|
|
plr[p]._pHPBase += l;
|
|
plr[p]._pMaxHPBase += l;
|
|
plr[p]._pHitPoints += l;
|
|
plr[p]._pMaxHP += l;
|
|
CalcPlrInv(p,TRUE);
|
|
if (p == myplr) NetSendCmdParam1(FALSE, CMD_SETVIT, plr[p]._pBaseVit);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SetPlayerHitPoints(int pnum, int newhp)
|
|
{
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("SetPlayerHitPoints: illegal player %d",pnum);
|
|
plr[pnum]._pHitPoints = newhp;
|
|
plr[pnum]._pHPBase = newhp - (plr[pnum]._pMaxHP - plr[pnum]._pMaxHPBase);
|
|
if (pnum == myplr) drawhpflag = TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SetPlrStr(int p, int v)
|
|
{
|
|
if ((DWORD)p >= MAX_PLRS)
|
|
app_fatal("SetPlrStr: illegal player %d",p);
|
|
plr[p]._pBaseStr = v;
|
|
CalcPlrInv(p,TRUE);
|
|
/* this stuff is done in CalcPlrInv */
|
|
// if (plr[p]._pClass == CLASS_ROGUE ||
|
|
// plr[p]._pClass == CLASS_MONK ||
|
|
// plr[p]._pClass == CLASS_BARD)
|
|
// {
|
|
// plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 200;
|
|
// }
|
|
// else
|
|
// plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 100;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SetPlrMag(int p, int v)
|
|
{
|
|
if ((DWORD)p >= MAX_PLRS)
|
|
app_fatal("SetPlrMag: illegal player %d",p);
|
|
plr[p]._pBaseMag = v;
|
|
v = v << MANA_SHIFT;
|
|
if (plr[p]._pClass == CLASS_SORCEROR) v = v << 1; // 2x
|
|
else if (plr[p]._pClass == CLASS_BARD) v += v >> 1; // 1.5x
|
|
plr[p]._pMaxManaBase = v;
|
|
plr[p]._pMaxMana = v;
|
|
CalcPlrInv(p,TRUE);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SetPlrDex(int p, int v)
|
|
{
|
|
if ((DWORD)p >= MAX_PLRS)
|
|
app_fatal("SetPlrDex: illegal player %d",p);
|
|
plr[p]._pBaseDex = v;
|
|
CalcPlrInv(p,TRUE);
|
|
/* this stuff is done in CalcPlrInv */
|
|
// if (plr[p]._pClass == CLASS_ROGUE ||
|
|
// plr[p]._pClass == CLASS_MONK ||
|
|
// plr[p]._pClass == CLASS_BARD)
|
|
// {
|
|
// plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 200;
|
|
// }
|
|
// else
|
|
// plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 100;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SetPlrVit(int p, int v)
|
|
{
|
|
if ((DWORD)p >= MAX_PLRS)
|
|
app_fatal("SetPlrVit: illegal player %d",p);
|
|
plr[p]._pBaseVit = v;
|
|
v = v << HP_SHIFT;
|
|
if (plr[p]._pClass == CLASS_WARRIOR
|
|
|| plr[p]._pClass == CLASS_BARBARIAN) v = v << 1;
|
|
plr[p]._pHPBase = v;
|
|
plr[p]._pMaxHPBase = v;
|
|
CalcPlrInv(p,TRUE);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void InitDungMsgs(int pnum)
|
|
{
|
|
if ((DWORD)pnum >= MAX_PLRS)
|
|
app_fatal("InitDungMsgs: illegal player %d",pnum);
|
|
plr[pnum].pDungMsgs = 0;
|
|
plr[pnum].pHellfireMsgs = 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void PlayDungMsgs()
|
|
{
|
|
if ((DWORD)myplr >= MAX_PLRS)
|
|
app_fatal("PlayDungMsgs: illegal player %d",myplr);
|
|
if ((currlevel == 1) && (!plr[myplr]._pLvlVisited[1]) && (gbMaxPlayers == 1) && (!(plr[myplr].pDungMsgs & DUNGMSG_1))) {
|
|
// play "The sancity of this place" speech
|
|
sfxdelay = 40;
|
|
#if !IS_VERSION(SHAREWARE)
|
|
if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR97;
|
|
else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE97;
|
|
else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE97;
|
|
else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK97;
|
|
else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD97;
|
|
else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN97;
|
|
#else
|
|
if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR97;
|
|
#endif
|
|
plr[myplr].pDungMsgs |= DUNGMSG_1;
|
|
}
|
|
|
|
else if ((currlevel == 5) && (!plr[myplr]._pLvlVisited[5]) && (gbMaxPlayers == 1) && (!(plr[myplr].pDungMsgs & DUNGMSG_2))) {
|
|
// play "smells of death" speech
|
|
sfxdelay = 40;
|
|
#if !IS_VERSION(SHAREWARE)
|
|
if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR96B;
|
|
else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE96;
|
|
else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE96;
|
|
else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK96;
|
|
else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD96;
|
|
else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN96;
|
|
#else
|
|
if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR96B;
|
|
#endif
|
|
plr[myplr].pDungMsgs |= DUNGMSG_2;
|
|
}
|
|
|
|
else if ((currlevel == 9) && (!plr[myplr]._pLvlVisited[9]) && (gbMaxPlayers == 1) && (!(plr[myplr].pDungMsgs & DUNGMSG_3))) {
|
|
// play "It's hot down here" speech
|
|
sfxdelay = 40;
|
|
#if !IS_VERSION(SHAREWARE)
|
|
if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR98;
|
|
else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE98;
|
|
else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE98;
|
|
else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK98;
|
|
else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD98;
|
|
else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN98;
|
|
#else
|
|
if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR98;
|
|
#endif
|
|
plr[myplr].pDungMsgs |= DUNGMSG_3;
|
|
}
|
|
|
|
else if ((currlevel == 13) && (!plr[myplr]._pLvlVisited[13]) && (gbMaxPlayers == 1) && (!(plr[myplr].pDungMsgs & DUNGMSG_4))) {
|
|
// play "I must be getting close" speech
|
|
sfxdelay = 40;
|
|
#if !IS_VERSION(SHAREWARE)
|
|
if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR99;
|
|
else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE99;
|
|
else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE99;
|
|
else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK99;
|
|
else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD99;
|
|
else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN99;
|
|
#else
|
|
if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR99;
|
|
#endif
|
|
plr[myplr].pDungMsgs |= DUNGMSG_4;
|
|
}
|
|
|
|
else if ((currlevel == 16) && (!plr[myplr]._pLvlVisited[15]) && (gbMaxPlayers == 1) && (!(plr[myplr].pDungMsgs & DUNGMSG_5))) {
|
|
// play "Diablo's Wrath"
|
|
sfxdelay = 40;
|
|
#if !IS_VERSION(SHAREWARE)
|
|
if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_DIABLVLINT;
|
|
else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_DIABLVLINT;
|
|
else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_DIABLVLINT;
|
|
else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_DIABLVLINT;
|
|
else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_DIABLVLINT;
|
|
else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_DIABLVLINT;
|
|
#endif
|
|
plr[myplr].pDungMsgs |= DUNGMSG_5;
|
|
}
|
|
else if ((currlevel == HIVESTART) && (!plr[myplr]._pLvlVisited[HIVESTART]) && (gbMaxPlayers == 1) && (!(plr[myplr].pHellfireMsgs & DUNGMSG_1)))
|
|
{
|
|
// play Defiler 1 JKE
|
|
sfxdelay = 10;
|
|
sfxdnum = HSFX_DEFILER1;
|
|
quests[Q_DEFILER]._qactive = QUEST_NOTDONE;
|
|
quests[Q_DEFILER]._qlog = TRUE;
|
|
quests[Q_DEFILER]._qmsg = TXT_DEFILER1;
|
|
plr[myplr].pHellfireMsgs |= DUNGMSG_1;
|
|
}
|
|
/* else if ((currlevel == (HIVESTART+1)) && (!plr[myplr]._pLvlVisited[(HIVESTART+1)]) && (gbMaxPlayers == 1) && (!(plr[myplr].pHellfireMsgs & DUNGMSG_2))) {
|
|
// play Defiler 2 JKE
|
|
sfxdelay = 10;
|
|
sfxdnum = HSFX_DEFILER2;
|
|
plr[myplr].pHellfireMsgs |= DUNGMSG_2;
|
|
} */
|
|
else if ((currlevel == (HIVESTART+2)) && (!plr[myplr]._pLvlVisited[(HIVESTART+2)]) && (gbMaxPlayers == 1) && (!(plr[myplr].pHellfireMsgs & DUNGMSG_3))) {
|
|
// play Defiler 3 JKE
|
|
sfxdelay = 10;
|
|
sfxdnum = HSFX_DEFILER3;
|
|
plr[myplr].pHellfireMsgs |= DUNGMSG_3;
|
|
}
|
|
/* else if ((currlevel == (HIVESTART+3)) && (!plr[myplr]._pLvlVisited[(HIVESTART+3)]) && (gbMaxPlayers == 1) && (!(plr[myplr].pHellfireMsgs & DUNGMSG_4))) {
|
|
// play Defiler 4 JKE
|
|
sfxdelay = 10;
|
|
sfxdnum = HSFX_DEFILER4;
|
|
plr[myplr].pHellfireMsgs |= DUNGMSG_4;
|
|
} */
|
|
else if ((currlevel == CRYPTSTART) && (!plr[myplr]._pLvlVisited[CRYPTSTART]) && (gbMaxPlayers == 1) && (!(plr[myplr].pDungMsgs & DUNGMSG_6))) {
|
|
// play "great power " JKE
|
|
sfxdelay = 30;
|
|
|
|
// sfxdnum = HSFX_CORNERSTONE1;
|
|
/* quests[Q_CORNERSTONE]._qactive = QUEST_NOTDONE;
|
|
quests[Q_CORNERSTONE]._qlog = TRUE;
|
|
quests[Q_CORNERSTONE]._qmsg = TXT_CORNERSTONE1;
|
|
InitQTextMsg(TXT_CORNERSTONE1); */
|
|
|
|
#if !IS_VERSION(SHAREWARE)
|
|
if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR92;
|
|
else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE92;
|
|
else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE92;
|
|
else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK92;
|
|
else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD92;
|
|
else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN92;
|
|
#else
|
|
if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR92;
|
|
#endif
|
|
|
|
plr[myplr].pDungMsgs |= DUNGMSG_6;
|
|
}
|
|
|
|
else sfxdelay = 0;
|
|
}
|
|
|
|
|
|
int GetMaxStr(int Plrclass)
|
|
{
|
|
return MaxStats[Plrclass][0];
|
|
}
|
|
|
|
int GetMaxMag(int Plrclass)
|
|
{
|
|
return MaxStats[Plrclass][1];
|
|
}
|
|
|
|
int GetMaxDex(int Plrclass)
|
|
{
|
|
return MaxStats[Plrclass][2];
|
|
}
|