mirror of
https://github.com/jmarshall23/Hellfire.git
synced 2026-08-11 23:40:51 +02:00
5993 lines
158 KiB
C++
5993 lines
158 KiB
C++
/*-----------------------------------------------------------------------**
|
|
** Diablo
|
|
**
|
|
** Items file
|
|
**
|
|
** (C)1995 Condor, Inc. All rights reserved.
|
|
**
|
|
**-----------------------------------------------------------------------**
|
|
** $Header: /Diablo/ITEMS.CPP 4 2/06/97 6:08p Jessmac $
|
|
**-----------------------------------------------------------------------**
|
|
**
|
|
** File Routines
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
#include <limits.h>
|
|
#include "diablo.h"
|
|
#pragma hdrstop
|
|
#include "sound.h"
|
|
#include "objects.h"
|
|
#include "items.h"
|
|
#include "itemdat.h"
|
|
#include "engine.h"
|
|
#include "gendung.h"
|
|
#include "player.h"
|
|
#include "control.h"
|
|
#include "monster.h"
|
|
#include "spells.h"
|
|
#include "quests.h"
|
|
#include "cursor.h"
|
|
#include "effects.h"
|
|
#include "lighting.h"
|
|
#include "stores.h"
|
|
#include "spelldat.h"
|
|
#include "scrollrt.h"
|
|
#include "inv.h"
|
|
#include "msg.h"
|
|
#include "multi.h"
|
|
#include "monstdat.h"
|
|
#include "doom.h"
|
|
#include "missiles.h"
|
|
#include "minitext.h"
|
|
#include "storm/h/storm.h"
|
|
#include "DRLG_l1.h"
|
|
#include "packplr.h"
|
|
#include "textdat.h"
|
|
|
|
|
|
void RecreateTownItem(int ii, int idx, WORD icreateinfo, int iseed, int ivalue);
|
|
void SaveItemPower(int i, int power, int param1, int param2, int minval, int maxval, int multval);
|
|
void GetItemPower(int i, int minlvl, int maxlvl, long flgs, BOOL onlygood);
|
|
void GetItemAttrs(int i, int idata, int lvl);
|
|
void SetupItem(int);
|
|
void RecalcStoreStats();
|
|
void SpawnMap();
|
|
void DeleteItem(int ii, int i);
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** Global Variables
|
|
**-----------------------------------------------------------------------*/
|
|
CornerStoneType CornerStone;
|
|
extern char gszProgKey[];
|
|
|
|
int GOLD_VMAX = 5000;
|
|
const int GOLD_DOUBLE_VMAX = 2 * GOLD_VMAX;
|
|
ItemStruct item[MAXITEMS+1];
|
|
long numitems = 0;
|
|
|
|
int itemactive[MAXITEMS];
|
|
int itemavail[MAXITEMS];
|
|
int tem;
|
|
|
|
//PATCH1.JMM
|
|
ItemGetRecordStruct itemgets[MAXITEMS];
|
|
int gnNumGetRecords = 0;
|
|
//ENDPATCH1.JMM
|
|
|
|
|
|
|
|
BOOL UniqueItemFlag[MAXUITEMS];
|
|
BOOL uitemflag;
|
|
ItemStruct curruitem;
|
|
#if CHEATS
|
|
extern BOOL itemcheat;
|
|
|
|
BOOL davecheat = FALSE;
|
|
#endif
|
|
|
|
BOOL itemhold[3][3];
|
|
|
|
|
|
#define MAXOIL 10
|
|
|
|
int OilLvlTbl[MAXOIL]= { 1, 10, 1, 10, 4, 1, 5, 17, 1, 10 };
|
|
int OilValue[MAXOIL] = { 500, 2500, 500, 2500, 1500, 100, 2500, 15000, 500, 2500 };
|
|
int OilIdVal[MAXOIL] = {
|
|
IMID_OILACC,
|
|
IMID_OILMAST,
|
|
IMID_OILSHRP,
|
|
IMID_OILDEATH,
|
|
IMID_OILSKILL,
|
|
IMID_OILBLKSM,
|
|
IMID_OILFORT,
|
|
IMID_OILPERM,
|
|
IMID_OILHARD,
|
|
IMID_OILIMPER
|
|
};
|
|
char OilStr[MAXOIL][25] = {
|
|
"Oil of Accuracy",
|
|
"Oil of Mastery",
|
|
"Oil of Sharpness",
|
|
"Oil of Death",
|
|
"Oil of Skill",
|
|
"Blacksmith Oil",
|
|
"Oil of Fortitude",
|
|
"Oil of Permanence",
|
|
"Oil of Hardening",
|
|
"Oil of Imperviousness"
|
|
};
|
|
|
|
BYTE ItemCAnimTbl[ITEM_LAST_ID] = {
|
|
// 1x1
|
|
20, // ITEM_BLUEBTL
|
|
16, // ITEM_SCROLL
|
|
16, // ITEM_SCROLL2
|
|
16, // ITEM_SCROLL3
|
|
4, // ITEM_1GOLD
|
|
4, // ITEM_3GOLD
|
|
4, // ITEM_5GOLD
|
|
12, // ITEM_GOLDRING
|
|
12, // ITEM_1JRING
|
|
12, // ITEM_WOODRING
|
|
12, // ITEM_BLUERING
|
|
12, // ITEM_3JRING
|
|
12, // ITEM_SLVRRING
|
|
12, // ITEM_MJRING
|
|
12, // ITEM_BRNRING
|
|
21, // ITEM_SPECTRAL
|
|
21, // ITEM_3COLORPOT
|
|
25, // ITEM_GOLDENELIX
|
|
12, // ITEM_EMPYBAND
|
|
28, // ITEM_EAR1
|
|
28, // ITEM_EAR2
|
|
28, // ITEM_EAR3
|
|
38, // ITEM_SPHERE
|
|
38, // ITEM_CUBE
|
|
38, // ITEM_PYRIMID
|
|
32, // ITEM_BLOODGEM
|
|
38, // ITEM_JSPHERE
|
|
38, // ITEM_JCUBE
|
|
38, // ITEM_JPYRIMID
|
|
24, // ITEM_VILE
|
|
24, // ITEM_BLKBTL
|
|
26, // ITEM_WHTEBTL
|
|
2, // ITEM_REDBTL
|
|
25, // ITEM_YELBTL
|
|
22, // ITEM_ORGBTL
|
|
23, // ITEM_BREDBTL
|
|
24, // ITEM_BLKBTL2
|
|
25, // ITEM_GOLDBTL
|
|
27, // ITEM_LTBLUEBTL
|
|
27, // ITEM_BLUEBTL2
|
|
29, // ITEM_BRAIN
|
|
0, // ITEM_CLAW
|
|
0, // ITEM_FANG
|
|
0, // ITEM_BREAD
|
|
12, // ITEM_AMULET
|
|
12, // ITEM_AMULET1
|
|
12, // ITEM_AMULET2
|
|
12, // ITEM_AMULET3
|
|
12, // ITEM_AMULET4
|
|
0, // ITEM_POUCH1
|
|
// 1x2
|
|
8, // ITEM_DAGGER1
|
|
8, // ITEM_DAGGER2
|
|
0, // ITEM_BIGBOTTLE
|
|
8, // ITEM_DAGGER3
|
|
8, // ITEM_DAGGER4
|
|
8, // ITEM_DAGGER5
|
|
// 1x3
|
|
8, // ITEM_BLADE
|
|
8, // ITEM_BASTSRD
|
|
8, // ITEM_FALCHION
|
|
6, // ITEM_MACE
|
|
8, // ITEM_LONGSRD
|
|
8, // ITEM_BROADSRD
|
|
8, // ITEM_SCIMITAR
|
|
6, // ITEM_MORNSTAR
|
|
8, // ITEM_SHORTSRD
|
|
8, // ITEM_CLAYMORE
|
|
6, // ITEM_CLUB
|
|
8, // ITEM_SABRE
|
|
8, // ITEM_KNTSWORD
|
|
6, // ITEM_CLUB1
|
|
6, // ITEM_CLUB2
|
|
6, // ITEM_CLUB3
|
|
8, // ITEM_SCIMITAR2
|
|
8, // ITEM_MAGSWORD
|
|
8, // ITEM_SKULSWORD
|
|
// 2x2
|
|
5, // ITEM_HELM
|
|
9, // ITEM_ROCK
|
|
13, // ITEM_SKCROWN
|
|
13, // ITEM_CROWN
|
|
13, // ITEM_MCROWN
|
|
5, // ITEM_JESTER
|
|
5, // ITEM_HARLEQ
|
|
5, // ITEM_FHELM
|
|
15, // ITEM_BUCKLER
|
|
5, // ITEM_FHELM2
|
|
5, // ITEM_GRTHELM
|
|
18, // ITEM_BOOK1
|
|
18, // ITEM_BOOK2
|
|
18, // ITEM_BOOK3
|
|
30, // ITEM_MUSHROOM
|
|
5, // ITEM_SKLCAP
|
|
5, // ITEM_LCAP
|
|
14, // ITEM_FLESH
|
|
5, // ITEM_SKLCAP2
|
|
14, // ITEM_CLOTHES
|
|
13, // ITEM_CROWN2
|
|
16, // ITEM_MAP
|
|
18, // ITEM_BOOK4
|
|
5, // ITEM_FHELM3
|
|
5, // ITEM_SAMHELM
|
|
// 2x3
|
|
7, // ITEM_LRGSHIELD
|
|
1, // ITEM_BTLAXE
|
|
3, // ITEM_LONGBOW
|
|
17, // ITEM_PARMOR
|
|
1, // ITEM_AXE
|
|
15, // ITEM_WSHIELD
|
|
10, // ITEM_CLEAVER
|
|
14, // ITEM_STDARMOR
|
|
3, // ITEM_COMPBOW
|
|
11, // ITEM_SHRTSTAFF
|
|
8, // ITEM_2HSWORD
|
|
0, // ITEM_CHARMOR
|
|
1, // ITEM_SMALLAXE
|
|
7, // ITEM_HVYSHIELD
|
|
0, // ITEM_SCLARMOR
|
|
7, // ITEM_SMLSHIELD
|
|
15, // ITEM_SKULLSHLD
|
|
7, // ITEM_WOLFSHLD
|
|
3, // ITEM_SHORTBOW
|
|
3, // ITEM_STLLONGBOW
|
|
3, // ITEM_STLSHRTBOW
|
|
6, // ITEM_SMLWARHAM
|
|
6, // ITEM_MAUL
|
|
11, // ITEM_IRONSTAFF
|
|
11, // ITEM_STLSTAFF
|
|
11, // ITEM_LONGSTAFF
|
|
31, // ITEM_INNSIGN
|
|
14, // ITEM_HLARMOR
|
|
14, // ITEM_RAGS
|
|
14, // ITEM_QARMOR
|
|
6, // ITEM_BALLNCHN
|
|
6, // ITEM_FLAIL
|
|
7, // ITEM_TSHIELD
|
|
3, // ITEM_HNTRBOW
|
|
8, // ITEM_GRTSWORD
|
|
14, // ITEM_LARMOR
|
|
0, // ITEM_SPLTARMOR
|
|
14, // ITEM_ROBE
|
|
14, // ITEM_HVYROBE
|
|
0, // ITEM_RINGARMOR
|
|
33, // ITEM_ANVIL
|
|
1, // ITEM_BROADAXE
|
|
1, // ITEM_LRGAXE
|
|
1, // ITEM_WICKAXE
|
|
1, // ITEM_HANDAXE
|
|
1, // ITEM_GREATAXE
|
|
7, // ITEM_IRONSHLD
|
|
7, // ITEM_KITESHLD
|
|
7, // ITEM_LRGSHLD
|
|
14, // ITEM_CLOAK
|
|
14, // ITEM_CAPE
|
|
17, // ITEM_PARMOR2
|
|
17, // ITEM_PARMOR3
|
|
17, // ITEM_BPLATE
|
|
0, // ITEM_RINGMAIL
|
|
34, // ITEM_BISHOPSTF
|
|
1, // ITEM_GEMGRTAXE
|
|
0, // ITEM_ARKARMOR
|
|
3, // ITEM_CROSBOW
|
|
17, // ITEM_NAJARMOR
|
|
8, // ITEM_GRIZZLY
|
|
8, // ITEM_GRANDPA
|
|
6, // ITEM_PROTECT
|
|
1, // ITEM_REAVER
|
|
3, // ITEM_WINDFOR
|
|
3, // ITEM_SWARBOW
|
|
11, // ITEM_COMPSTF
|
|
3, // ITEM_SBATLBOW
|
|
// Misc
|
|
// 4, // ITEM_GOLD
|
|
|
|
// new 1x1
|
|
12, // ITEM_MERLINRING
|
|
12, // ITEM_MANARING
|
|
12, // ITEM_AMULWARD
|
|
12, // ITEM_NECMAGIC
|
|
12, // ITEM_NECHEALTH
|
|
12, // ITEM_KARIKSRING
|
|
12, // ITEM_RINGGROUND
|
|
12, // ITEM_AMULPROT
|
|
12, // ITEM_MERCRING
|
|
12, // ITEM_RINGTHUND
|
|
12, // ITEM_NECTRUTH
|
|
12, // ITEM_RINGGIANTS
|
|
12, // ITEM_AMULGOLD
|
|
12, // ITEM_RINGMYSTIC
|
|
12, // ITEM_RINGCOPPER
|
|
12, // ITEM_AMULACOLYT
|
|
12, // ITEM_RINGMAGMA
|
|
12, // ITEM_NECPURIFY
|
|
12, // ITEM_RINGGLADTR
|
|
35, // ITEM_RUNEBOMB
|
|
39, // ITEM_THEODORE
|
|
36, // ITEM_TORNPAPER1
|
|
36, // ITEM_TORNPAPER2
|
|
36, // ITEM_TORNPAPER3
|
|
37, // ITEM_WHOLEPAPER
|
|
38, // ITEM_FIRERUNE1
|
|
38, // ITEM_FIRERUNE2
|
|
38, // ITEM_LIGHTRUNE1
|
|
38, // ITEM_LIGHTRUNE2
|
|
38, // ITEM_STONERUNE
|
|
// new 2x2
|
|
41,
|
|
42,
|
|
// new 1x3
|
|
8, // ITEM_SWORDEDGE
|
|
8, // ITEM_SWORDGLAM
|
|
8, // ITEM_SWORDSERR
|
|
// new 2x3
|
|
17, // ITEM_ARMRDARK
|
|
0, // ITEM_ARMRBONECH
|
|
6, // ITEM_HAMRTHUND
|
|
8, // ITEM_SWRDCRYSTL
|
|
11, // ITEM_STAFJESTER
|
|
11, // ITEM_STAFMANA
|
|
3, // ITEM_BOWVULCAN
|
|
3, // ITEM_BOWSPEED
|
|
1, // ITEM_AXEANCIENT
|
|
6, // ITEM_CLUBCARNAG
|
|
6, // ITEM_MACEDARK
|
|
6, // ITEM_CLUBDECAY
|
|
1, // ITEM_AXEDECAY
|
|
8, // ITEM_SWRDDECAY
|
|
6, // ITEM_MACEDECAY
|
|
11, // ITEM_STAFDECAY
|
|
3, // ITEM_BOWDECAY
|
|
6, // ITEM_CLUBOUCH
|
|
8, // ITEM_SWRDDEVAST
|
|
1, // ITEM_AXEDEVAST
|
|
6, // ITEM_MORNDEVAST
|
|
6, // ITEM_MACEDEVAST
|
|
17, // ITEM_ARMRDMNPLT
|
|
40,
|
|
};
|
|
|
|
|
|
char *ItemFiles[] = {
|
|
"Armor2", // 0
|
|
"Axe", // 1
|
|
"FBttle", // 2
|
|
"Bow", // 3
|
|
"GoldFlip", // 4
|
|
"Helmut", // 5
|
|
"Mace", // 6
|
|
"Shield", // 7
|
|
"SwrdFlip", // 8
|
|
"Rock", // 9
|
|
"Cleaver", // 10
|
|
"Staff", // 11
|
|
"Ring", // 12
|
|
"CrownF", // 13
|
|
"LArmor", // 14
|
|
"WShield", // 15
|
|
"Scroll", // 16
|
|
"FPlateAr", // 17
|
|
"FBook", // 18
|
|
"Food", // 19
|
|
"FBttleBB", // 20
|
|
"FBttleDY", // 21
|
|
"FBttleOR", // 22
|
|
"FBttleBR", // 23
|
|
"FBttleBL", // 24
|
|
"FBttleBY", // 25
|
|
"FBttleWH", // 26
|
|
"FBttleDB", // 27
|
|
"FEar", // 28
|
|
"FBrain", // 29
|
|
"FMush", // 30
|
|
"Innsign", // 31
|
|
"Bldstn", // 32
|
|
"Fanvil", // 33
|
|
"FLazStaf", // 34
|
|
"bombs1", // 35
|
|
"halfps1", // 36
|
|
"wholeps1", // 37
|
|
"runes1", // 38
|
|
"teddys1", // 39
|
|
"cows1", // 40
|
|
"donkys1", // 41
|
|
"mooses1", // 42
|
|
};
|
|
#define ITEMFTYPES (sizeof(ItemFiles)/sizeof(char *))
|
|
|
|
BYTE *itemanims[ITEMFTYPES];
|
|
|
|
byte ItemAnimLs[ITEMFTYPES] = {
|
|
15, // Armor2
|
|
13, // Axe
|
|
16, // FBttle
|
|
13, // Bow
|
|
10, // GoldFlip
|
|
13, // Helmut
|
|
13, // Mace
|
|
13, // Shield
|
|
13, // SwrdFlip
|
|
10, // Rock
|
|
13, // Cleaver
|
|
13, // Staff
|
|
13, // Ring
|
|
13, // Crown
|
|
13, // LArmor
|
|
13, // WShield
|
|
13, // Scroll
|
|
13, // FPlateAr
|
|
13, // FBook
|
|
1, // Food
|
|
16, // FBttleBB
|
|
16, // FBttleDY
|
|
16, // FBttleOR
|
|
16, // FBttleBR
|
|
16, // FBttleBL
|
|
16, // FBttleBY
|
|
16, // FBttleWH
|
|
16, // FBttleDB
|
|
13, // FEar
|
|
12, // FBrain
|
|
12, // FMush
|
|
13, // Innsign
|
|
13, // Bldstn
|
|
13, // Fanvil
|
|
8, // FLazStaf
|
|
10, // nest bomb
|
|
16, // half paper
|
|
16, // whole paper
|
|
10, // runes
|
|
10, // teddy bear
|
|
15,
|
|
15,
|
|
15,
|
|
};
|
|
|
|
int ItemAnimSnds[ITEMFTYPES] = {
|
|
IS_FHARM, // Armor2
|
|
IS_FAXE, // Axe
|
|
IS_FPOT, // FBttle
|
|
IS_FBOW, // Bow
|
|
IS_GOLD, // GoldFlip
|
|
IS_FCAP, // Helmet
|
|
IS_FSWOR, // Mace
|
|
IS_FSHLD, // Shield
|
|
IS_FSWOR, // SwrdFlip
|
|
IS_FROCK, // Rock
|
|
IS_FAXE, // Cleaver
|
|
IS_FSTAF, // Staff
|
|
IS_FRING, // Ring
|
|
IS_FCAP, // Crown
|
|
IS_FLARM, // LArmor
|
|
IS_FSHLD, // WShield
|
|
IS_FSCRL, // Scroll
|
|
IS_FHARM, // FPlateAr
|
|
IS_FBOOK, // FBook
|
|
IS_FLARM, // Food
|
|
IS_FPOT, // FBttleBB
|
|
IS_FPOT, // FBttleDY
|
|
IS_FPOT, // FBttleOR
|
|
IS_FPOT, // FBttleBR
|
|
IS_FPOT, // FBttleBL
|
|
IS_FPOT, // FBttleBY
|
|
IS_FPOT, // FBttleWH
|
|
IS_FPOT, // FBttleDB
|
|
IS_FBODY, // FEar
|
|
IS_FBODY, // FBrain
|
|
IS_FMUSH, // FMush
|
|
IS_ISIGN, // Innsign
|
|
IS_FBLST, // Bldstn
|
|
IS_FANVL, // Fanvil
|
|
IS_FSTAF, // FLazStaf
|
|
IS_FROCK, // Bomb
|
|
IS_FSCRL, // Half Paper
|
|
IS_FSCRL, // Whole Paper
|
|
IS_FROCK, // Rune
|
|
IS_FMUSH, // Theo
|
|
IS_FHARM, // Cow Armor
|
|
IS_FLARM, //
|
|
IS_FLARM, //
|
|
};
|
|
|
|
int ItemInvSnds[ITEMFTYPES] = {
|
|
IS_IHARM, // Armor2
|
|
IS_IAXE, // Axe
|
|
IS_IPOT, // FBttle
|
|
IS_IBOW, // Bow
|
|
IS_GOLD, // GoldFlip
|
|
IS_ICAP, // Helmet
|
|
IS_ISWORD, // Mace
|
|
IS_ISHIEL, // Shield
|
|
IS_ISWORD, // SwrdFlip
|
|
IS_IROCK, // Rock
|
|
IS_IAXE, // Cleaver
|
|
IS_ISTAF, // Staff
|
|
IS_IRING, // Ring
|
|
IS_ICAP, // Crown
|
|
IS_ILARM, // LArmor
|
|
IS_ISHIEL, // WShield
|
|
IS_ISCROL, // Scroll
|
|
IS_IHARM, // FPlateAr
|
|
IS_IBOOK, // FBook
|
|
IS_IHARM, // Food
|
|
IS_IPOT, // FBttleBB
|
|
IS_IPOT, // FBttleDY
|
|
IS_IPOT, // FBttleOR
|
|
IS_IPOT, // FBttleBR
|
|
IS_IPOT, // FBttleBL
|
|
IS_IPOT, // FBttleBY
|
|
IS_IPOT, // FBttleWH
|
|
IS_IPOT, // FBttleDB
|
|
IS_IBODY, // FEar
|
|
IS_IBODY, // FBrain
|
|
IS_IMUSH, // FMush
|
|
IS_ISIGN, // Innsign
|
|
IS_IBLST, // Bldstn
|
|
IS_IANVL, // Fanvil
|
|
IS_ISTAF, // FLazStaf
|
|
IS_IROCK, // Bomb
|
|
IS_ISCROL, // Half Paper
|
|
IS_ISCROL, // Whole Paper
|
|
IS_IROCK, // Rune
|
|
IS_IMUSH, // Theo
|
|
IS_IHARM, // Cow Armor
|
|
IS_ILARM, //
|
|
IS_ILARM, //
|
|
};
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
int GetEffLevel()
|
|
{
|
|
int efflevel = currlevel;
|
|
if (currlevel >= HIVESTART && currlevel <= HIVEEND)
|
|
efflevel = currlevel - HIVESTART + 9;
|
|
if (currlevel >= CRYPTSTART && currlevel <= CRYPTEND)
|
|
efflevel = currlevel - CRYPTSTART + 14;
|
|
|
|
return efflevel;
|
|
}
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void InitItemGFX() {
|
|
for (int i = 0; i < ITEMFTYPES; i++) {
|
|
char filestr[64];
|
|
sprintf(filestr, "Items\\%s.CEL", ItemFiles[i]);
|
|
app_assert(! itemanims[i]);
|
|
itemanims[i] = LoadFileInMemSig(filestr,NULL,'IGFX');
|
|
}
|
|
|
|
ZeroMemory(UniqueItemFlag,sizeof(UniqueItemFlag));
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
BOOL ItemPlace(int xp, int yp) {
|
|
if (dMonster[xp][yp] != 0) return FALSE;
|
|
if (dPlayer[xp][yp] != 0) return FALSE;
|
|
if (dItem[xp][yp] != 0) return FALSE;
|
|
if (dObject[xp][yp] != 0) return FALSE;
|
|
if (dFlags[xp][yp] & BFLAG_SETPC) return FALSE;
|
|
if (nSolidTable[dPiece[xp][yp]]) return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------**
|
|
**-----------------------------------------------------------------------*/
|
|
void AddInitItems() {
|
|
|
|
int efflevel = GetEffLevel();
|
|
int j = random(11, 3) + 3;
|
|
for (int i = 0; i < j; i++) {
|
|
int ii = itemavail[0];
|
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1];
|
|
itemactive[numitems] = ii;
|
|
|
|
int xx = random(12, DMAXX - DIRTEDGE) + (DIRTEDGED2);
|
|
int yy = random(12, DMAXY - DIRTEDGE) + (DIRTEDGED2);
|
|
while (! ItemPlace(xx, yy)) {
|
|
xx = random(12, DMAXX - DIRTEDGE) + (DIRTEDGED2);
|
|
yy = random(12, DMAXY - DIRTEDGE) + (DIRTEDGED2);
|
|
}
|
|
|
|
item[ii]._ix = xx;
|
|
item[ii]._iy = yy;
|
|
dItem[xx][yy] = ii + 1;
|
|
item[ii]._iSeed = GetRndSeed();
|
|
SetRndSeed(item[ii]._iSeed);
|
|
if (random(12, 2)) GetItemAttrs(ii, IDI_HEAL, efflevel);
|
|
else GetItemAttrs(ii, IDI_MANA, efflevel);
|
|
item[ii]._iCreateInfo = efflevel + ICI_PREGEN;
|
|
SetupItem(ii);
|
|
item[ii]._iAnimFrame = item[ii]._iAnimLen;
|
|
item[ii]._iAnimFlag = FALSE;
|
|
item[ii]._iSelFlag = ISEL_FLR;
|
|
DeltaAddItem(ii);
|
|
numitems++;
|
|
}
|
|
}
|
|
|
|
static void AddNote()
|
|
{
|
|
int xx, yy;
|
|
|
|
do
|
|
{
|
|
xx = random(12, DMAXX - DIRTEDGE) + (DIRTEDGED2);
|
|
yy = random(12, DMAXY - DIRTEDGE) + (DIRTEDGED2);
|
|
} while (! ItemPlace(xx, yy));
|
|
|
|
int idi;
|
|
switch(currlevel)
|
|
{
|
|
case CRYPTSTART+2:
|
|
idi = IDI_NOTE3;
|
|
break;
|
|
case CRYPTSTART+1:
|
|
idi = IDI_NOTE2;
|
|
break;
|
|
default:
|
|
idi = IDI_NOTE1;
|
|
break;
|
|
}
|
|
SpawnQuestItem(idi, xx, yy, FALSE, ISEL_FLR);
|
|
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void InitItems() {
|
|
int i;
|
|
|
|
DROPLOG("Initing items...\n");
|
|
// Setup a gold item
|
|
GetItemAttrs(0, 0, 1);
|
|
golditem = item[0];
|
|
golditem._iStatFlag = TRUE;
|
|
|
|
numitems = 0;
|
|
for (i = 0; i < MAXITEMS; i++) {
|
|
item[i]._itype = 0;
|
|
item[i]._ix = 0;
|
|
item[i]._iy = 0;
|
|
item[i]._iAnimFlag = FALSE;
|
|
item[i]._iSelFlag = ISEL_NONE;
|
|
item[i]._iIdentified = FALSE;
|
|
item[i]._iPostDraw = FALSE;
|
|
}
|
|
|
|
for (i = 0; i < MAXITEMS; i++) {
|
|
itemavail[i] = i;
|
|
itemactive[i] = 0;
|
|
}
|
|
|
|
if (!setlevel) {
|
|
|
|
int rs = GetRndSeed();
|
|
|
|
if (QuestStatus(Q_ROCK)) {
|
|
SpawnRock();
|
|
}
|
|
if (QuestStatus(Q_ANVIL)) {
|
|
SpawnQuestItem(IDI_ANVIL, (setpc_x << 1) + 11 + DIRTEDGED2, (setpc_y << 1) + 11 + DIRTEDGED2, FALSE, ISEL_FLR);
|
|
}
|
|
if (gbCowsuit)
|
|
if (currlevel == HIVEEND)
|
|
SpawnQuestItem(IDI_SUITBRWN, 25, 25, 3, ISEL_FLR);
|
|
if (gbCowsuit)
|
|
if (currlevel == HIVESTART+2)
|
|
SpawnQuestItem(IDI_SUITGREY, 25, 25, 3, ISEL_FLR);
|
|
|
|
if (currlevel > 0 && currlevel < 16)
|
|
AddInitItems();
|
|
if (currlevel >= CRYPTSTART && currlevel <= CRYPTSTART+2)
|
|
AddNote();
|
|
}
|
|
|
|
uitemflag = FALSE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void CalcPlrItemVals(int p, BOOL Loadgfx)
|
|
{
|
|
int mind, maxd, tac, g, d, i, mi;
|
|
int bdam, btohit, bac;
|
|
int sadd, madd, dadd, vadd;
|
|
int fr, lr, mr;
|
|
int dmod, ghit, lrad;
|
|
int ihp, imana;
|
|
int spllvladd;
|
|
int enac;
|
|
int fmin, fmax, lmin, lmax;
|
|
long iflgs, iflgs2;
|
|
__int64 spl, t;
|
|
|
|
app_assert((DWORD) p < MAX_PLRS);
|
|
|
|
mind = 0;
|
|
maxd = 0;
|
|
tac = 0;
|
|
bdam = 0;
|
|
btohit = 0;
|
|
bac = 0;
|
|
iflgs = 0;
|
|
iflgs2 = 0;
|
|
sadd = 0;
|
|
madd = 0;
|
|
dadd = 0;
|
|
vadd = 0;
|
|
spl = 0;
|
|
fr = 0;
|
|
lr = 0;
|
|
mr = 0;
|
|
dmod = 0;
|
|
ghit = 0;
|
|
lrad = PLRLRAD;
|
|
ihp = 0;
|
|
imana = 0;
|
|
spllvladd = 0;
|
|
enac = 0;
|
|
fmin = 0;
|
|
fmax = 0;
|
|
lmin = 0;
|
|
lmax = 0;
|
|
for (i = 0; i < 7; i++) {
|
|
const ItemStruct * itm = &plr[p].InvBody[i];
|
|
if (itm->_itype == -1) continue;
|
|
if (! itm->_iStatFlag) continue;
|
|
|
|
mind += itm->_iMinDam;
|
|
maxd += itm->_iMaxDam;
|
|
tac += itm->_iAC;
|
|
|
|
t = 1;
|
|
if (itm->_iSpell != 0)
|
|
spl |= t << (itm->_iSpell - 1);
|
|
|
|
// don't give benefit of unidentified magic items
|
|
if (itm->_iMagical != IMAGIC_NONE && ! itm->_iIdentified)
|
|
continue;
|
|
|
|
bdam += itm->_iPLDam;
|
|
btohit += itm->_iPLToHit;
|
|
|
|
if (itm->_iPLAC) {
|
|
int tmpac = (itm->_iAC * itm->_iPLAC) / 100;
|
|
if (tmpac == 0) tmpac = 1;
|
|
bac += tmpac;
|
|
}
|
|
|
|
iflgs |= itm->_iFlags;
|
|
iflgs2 |= itm->_iFlags2;
|
|
sadd += itm->_iPLStr;
|
|
madd += itm->_iPLMag;
|
|
dadd += itm->_iPLDex;
|
|
vadd += itm->_iPLVit;
|
|
fr += itm->_iPLFR;
|
|
lr += itm->_iPLLR;
|
|
mr += itm->_iPLMR;
|
|
dmod += itm->_iPLDamMod;
|
|
ghit += itm->_iPLGetHit;
|
|
lrad += itm->_iPLLight;
|
|
ihp += itm->_iPLHP;
|
|
imana += itm->_iPLMana;
|
|
spllvladd += itm->_iSplLvlAdd;
|
|
enac += itm->_iPLEnAc;
|
|
fmin += itm->_iFMinDam;
|
|
fmax += itm->_iFMaxDam;
|
|
lmin += itm->_iLMinDam;
|
|
lmax += itm->_iLMaxDam;
|
|
}
|
|
|
|
// If I have no weapons, then make it min of 1-1, if shield only, 1-3
|
|
if (mind == 0 && maxd == 0) {
|
|
mind = 1;
|
|
maxd = 1;
|
|
if ((plr[p].Hand1Item._itype == IT_SHIELD) && (plr[p].Hand1Item._iStatFlag))
|
|
maxd = 3;
|
|
if ((plr[p].Hand2Item._itype == IT_SHIELD) && (plr[p].Hand2Item._iStatFlag))
|
|
maxd = 3;
|
|
|
|
// monks have fists of fury.
|
|
if (plr[p]._pClass == CLASS_MONK)
|
|
{
|
|
mind = max(mind,plr[p]._pLevel >> 1);
|
|
maxd = max(maxd,plr[p]._pLevel);
|
|
}
|
|
}
|
|
|
|
if ((plr[p]._pSpellFlags & SF_RAGE) == SF_RAGE) {
|
|
sadd += 2 * plr[p]._pLevel;
|
|
dadd += plr[p]._pLevel + (plr[p]._pLevel/2);
|
|
vadd += 2 * plr[p]._pLevel;
|
|
}
|
|
|
|
if ((plr[p]._pSpellFlags & SF_LETHERGY) == SF_LETHERGY) {
|
|
sadd -= 2 * plr[p]._pLevel;
|
|
dadd -= plr[p]._pLevel + (plr[p]._pLevel/2);
|
|
vadd -= 2 * plr[p]._pLevel;
|
|
}
|
|
|
|
plr[p]._pIMinDam = mind;
|
|
plr[p]._pIMaxDam = maxd;
|
|
plr[p]._pIAC = tac;
|
|
plr[p]._pIBonusDam = bdam;
|
|
plr[p]._pIBonusToHit = btohit;
|
|
plr[p]._pIBonusAC = bac;
|
|
plr[p]._pIFlags = iflgs;
|
|
plr[p]._pIFlags2 = iflgs2;
|
|
plr[p]._pIBonusDamMod = dmod;
|
|
plr[p]._pIGetHit = ghit;
|
|
if (lrad < 2) lrad = 2;
|
|
if (lrad > 15) lrad = 15;
|
|
if ((plr[p]._pLightRad != lrad ) && (p == myplr)) {
|
|
ChangeLightRadius(plr[p]._plid, lrad);
|
|
if (lrad < 10) ChangeVisionRadius(plr[p]._pvid, 10);
|
|
else ChangeVisionRadius(plr[p]._pvid, lrad);
|
|
plr[p]._pLightRad = lrad;
|
|
}
|
|
|
|
plr[p]._pStrength = plr[p]._pBaseStr + sadd;
|
|
if (plr[myplr]._pStrength <= 0) plr[myplr]._pStrength = 0;
|
|
plr[p]._pMagic = plr[p]._pBaseMag + madd;
|
|
if (plr[myplr]._pMagic <= 0) plr[myplr]._pMagic = 0;
|
|
plr[p]._pDexterity = plr[p]._pBaseDex + dadd;
|
|
if (plr[myplr]._pDexterity <= 0) plr[myplr]._pDexterity = 0;
|
|
plr[p]._pVitality = plr[p]._pBaseVit + vadd;
|
|
if (plr[myplr]._pVitality <= 0) plr[myplr]._pVitality = 0;
|
|
|
|
if (plr[p]._pClass == CLASS_ROGUE)
|
|
plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 200;
|
|
else if (plr[p]._pClass == CLASS_MONK)
|
|
{
|
|
if (plr[p].Hand1Item._itype == IT_STAFF || // bonus for staff
|
|
plr[p].Hand2Item._itype == IT_STAFF ||
|
|
(plr[p].Hand1Item._itype == -1 && // bonus for no weapons.
|
|
plr[p].Hand2Item._itype == -1)
|
|
)
|
|
{
|
|
plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 150;
|
|
}
|
|
else
|
|
{
|
|
plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 300;
|
|
}
|
|
}
|
|
else if (plr[p]._pClass == CLASS_BARD)
|
|
{
|
|
if (plr[p].Hand1Item._itype == IT_SWORD // bonus for using a sword.
|
|
|| plr[p].Hand2Item._itype == IT_SWORD)
|
|
{
|
|
plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 150;
|
|
}
|
|
else if (plr[p].Hand1Item._itype == IT_BOW
|
|
|| plr[p].Hand2Item._itype == IT_BOW)
|
|
{
|
|
// Better than a monk or warrior with a bow but not as good as a rogue.
|
|
plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 250;
|
|
}
|
|
else
|
|
{
|
|
plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 100;
|
|
}
|
|
}
|
|
else if (plr[p]._pClass == CLASS_BARBARIAN)
|
|
{
|
|
if (plr[p].Hand1Item._itype == IT_AXE
|
|
|| plr[p].Hand2Item._itype == IT_AXE)
|
|
{
|
|
plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 75;
|
|
}
|
|
else if (plr[p].Hand1Item._itype == IT_MACE
|
|
|| plr[p].Hand2Item._itype == IT_MACE)
|
|
{
|
|
plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 75;
|
|
}
|
|
else if (plr[p].Hand1Item._itype == IT_BOW
|
|
|| plr[p].Hand2Item._itype == IT_BOW)
|
|
{
|
|
// As bad as it gets
|
|
plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 300;
|
|
}
|
|
else
|
|
{
|
|
plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 100;
|
|
}
|
|
|
|
if (plr[p].Hand1Item._itype == IT_SHIELD || plr[p].Hand2Item._itype == IT_SHIELD)
|
|
{
|
|
// remove 1/2 the AC for the shield.
|
|
if (plr[p].Hand1Item._itype == IT_SHIELD)
|
|
{
|
|
plr[p]._pIAC -= plr[p].Hand1Item._iAC / 2;
|
|
}
|
|
else if (plr[p].Hand2Item._itype == IT_SHIELD)
|
|
{
|
|
plr[p]._pIAC -= plr[p].Hand2Item._iAC / 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Bonus for not using a shield.
|
|
if ( !(plr[p].Hand1Item._itype == IT_STAFF || plr[p].Hand2Item._itype == IT_STAFF ||
|
|
plr[p].Hand1Item._itype == IT_BOW || plr[p].Hand2Item._itype == IT_BOW)
|
|
)
|
|
{
|
|
plr[p]._pDamageMod += (plr[p]._pVitality * plr[p]._pLevel) / 100;
|
|
}
|
|
}
|
|
// Barbarians have a natural armor (Thick skin)
|
|
plr[p]._pIAC += plr[p]._pLevel/4;
|
|
}
|
|
else
|
|
plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 100;
|
|
|
|
plr[p]._pISpells = spl;
|
|
if ((plr[p]._pRSplType == SPT_ITEM) /*|| plr[p]._pRSplType == SPT_SCROLL)*/
|
|
&& ((plr[p]._pISpells & (((__int64)1) << (plr[p]._pRSpell-1))) == 0)) {
|
|
plr[p]._pRSpell = -1;
|
|
plr[p]._pRSplType = SPT_NONE;
|
|
force_redraw = FULLDRAW;
|
|
}
|
|
plr[p]._pISplLvlAdd = spllvladd;
|
|
|
|
plr[p]._pIEnAc = enac;
|
|
|
|
if (plr[p]._pClass == CLASS_BARBARIAN) // Barbarians have a natural bonus.
|
|
{
|
|
mr += plr[p]._pLevel;
|
|
fr += plr[p]._pLevel;
|
|
lr += plr[p]._pLevel;
|
|
}
|
|
|
|
if ((plr[p]._pSpellFlags & SF_LETHERGY) == SF_LETHERGY) // Lethergy causes a loss of strength
|
|
{
|
|
mr -= plr[p]._pLevel;
|
|
fr -= plr[p]._pLevel;
|
|
lr -= plr[p]._pLevel;
|
|
}
|
|
|
|
if (iflgs & IAF_ZERORES) {
|
|
mr = 0;
|
|
fr = 0;
|
|
lr = 0;
|
|
}
|
|
|
|
if (mr > RESIST_MAX) mr = RESIST_MAX;
|
|
else if (mr < 0) mr = 0;
|
|
plr[p]._pMagResist = mr;
|
|
|
|
if (fr > RESIST_MAX) fr = RESIST_MAX;
|
|
else if (fr < 0) fr = 0;
|
|
plr[p]._pFireResist = fr;
|
|
|
|
if (lr > RESIST_MAX) lr = RESIST_MAX;
|
|
else if (lr < 0) lr = 0;
|
|
plr[p]._pLghtResist = lr;
|
|
|
|
if (plr[p]._pClass == CLASS_WARRIOR)
|
|
{
|
|
vadd = vadd << 1;
|
|
}
|
|
else if (plr[p]._pClass == CLASS_BARBARIAN)
|
|
{
|
|
vadd *= 2;
|
|
vadd += (vadd >> 2);
|
|
}
|
|
else if (plr[p]._pClass == CLASS_ROGUE ||
|
|
plr[p]._pClass == CLASS_MONK ||
|
|
plr[p]._pClass == CLASS_BARD )
|
|
{
|
|
vadd += (vadd >> 1);
|
|
}
|
|
ihp += (vadd << HP_SHIFT);
|
|
if (plr[p]._pClass == CLASS_SORCEROR)
|
|
madd = madd << 1; // 2 * madd
|
|
if (plr[p]._pClass == CLASS_ROGUE ||
|
|
plr[p]._pClass == CLASS_MONK )
|
|
madd += (madd >> 1); // 1.5 * madd
|
|
else if ( plr[p]._pClass == CLASS_BARD )
|
|
madd += (madd >> 1) + (madd >> 2); // 1.75 * madd
|
|
|
|
imana += (madd << MANA_SHIFT);
|
|
|
|
plr[p]._pHitPoints = plr[p]._pHPBase + ihp;
|
|
plr[p]._pMaxHP = plr[p]._pMaxHPBase + ihp;
|
|
|
|
if (plr[p]._pHitPoints > plr[p]._pMaxHP)
|
|
plr[p]._pHitPoints = plr[p]._pMaxHP;
|
|
|
|
if ((p == myplr) && (plr[p]._pHitPoints >> HP_SHIFT) <= 0)
|
|
SetPlayerHitPoints(p, 0);
|
|
|
|
plr[p]._pMana = plr[p]._pManaBase + imana;
|
|
plr[p]._pMaxMana = plr[p]._pMaxManaBase + imana;
|
|
|
|
if (plr[p]._pMana > plr[p]._pMaxMana)
|
|
plr[p]._pMana = plr[p]._pMaxMana;
|
|
|
|
plr[p]._pIFMinDam = fmin;
|
|
plr[p]._pIFMaxDam = fmax;
|
|
plr[p]._pILMinDam = lmin;
|
|
plr[p]._pILMaxDam = lmax;
|
|
|
|
|
|
if (iflgs & IAF_INFRAVISION) plr[p]._pInfraFlag = TRUE;
|
|
else plr[p]._pInfraFlag = FALSE;
|
|
|
|
plr[p]._pBlockFlag = FALSE;
|
|
if (plr[p]._pClass == CLASS_MONK)
|
|
{
|
|
if ((plr[p].Hand1Item._itype == IT_STAFF) &&
|
|
(plr[p].Hand1Item._iStatFlag))
|
|
{
|
|
plr[p]._pBlockFlag = TRUE;
|
|
plr[p]._pIFlags |= IAF_BLANIM;
|
|
}
|
|
|
|
if ((plr[p].Hand2Item._itype == IT_STAFF) &&
|
|
(plr[p].Hand2Item._iStatFlag))
|
|
{
|
|
plr[p]._pBlockFlag = TRUE;
|
|
plr[p]._pIFlags |= IAF_BLANIM;
|
|
}
|
|
|
|
if ((plr[p].Hand1Item._itype == -1) &&
|
|
(plr[p].Hand2Item._itype == -1))
|
|
{
|
|
plr[p]._pBlockFlag = TRUE;
|
|
}
|
|
|
|
if ((plr[p].Hand1Item._iClass == IC_WEAP) &&
|
|
(plr[p].Hand1Item._iLoc != IL_2HAND) &&
|
|
(plr[p].Hand2Item._itype == -1))
|
|
{
|
|
plr[p]._pBlockFlag = TRUE;
|
|
}
|
|
|
|
if ((plr[p].Hand2Item._iClass == IC_WEAP) &&
|
|
(plr[p].Hand2Item._iLoc != IL_2HAND) &&
|
|
(plr[p].Hand1Item._itype == -1))
|
|
{
|
|
plr[p]._pBlockFlag = TRUE;
|
|
}
|
|
}
|
|
#if 0
|
|
// No Block art
|
|
else if (plr[p]._pClass == CLASS_BARD)
|
|
{
|
|
if ((plr[p].Hand1Item._itype == IT_SWORD) &&
|
|
(plr[p].Hand1Item._iStatFlag))
|
|
{
|
|
plr[p]._pBlockFlag = TRUE;
|
|
plr[p]._pIFlags |= IAF_BLANIM;
|
|
}
|
|
|
|
if ((plr[p].Hand2Item._itype == IT_SWORD) &&
|
|
(plr[p].Hand2Item._iStatFlag))
|
|
{
|
|
plr[p]._pBlockFlag = TRUE;
|
|
plr[p]._pIFlags |= IAF_BLANIM;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
plr[p]._pwtype = WEAP_H2H;
|
|
// Determine which graphics to use
|
|
g = PGFX_NGUY;
|
|
if ((plr[p].Hand1Item._itype != -1) &&
|
|
(plr[p].Hand1Item._iClass == IC_WEAP) &&
|
|
(plr[p].Hand1Item._iStatFlag)) g = plr[p].Hand1Item._itype;
|
|
if ((plr[p].Hand2Item._itype != -1) &&
|
|
(plr[p].Hand2Item._iClass == IC_WEAP) &&
|
|
(plr[p].Hand2Item._iStatFlag)) g = plr[p].Hand2Item._itype;
|
|
switch (g) {
|
|
case IT_SWORD:
|
|
g = PGFX_XGUY;
|
|
break;
|
|
case IT_MACE:
|
|
g = PGFX_ZGUY;
|
|
break;
|
|
case IT_BOW:
|
|
plr[p]._pwtype = WEAP_RANGE;
|
|
g = PGFX_BGUY;
|
|
break;
|
|
case IT_AXE:
|
|
g = PGFX_FGUY;
|
|
break;
|
|
case IT_STAFF:
|
|
g = PGFX_TGUY;
|
|
break;
|
|
}
|
|
if ((plr[p].Hand1Item._itype == IT_SHIELD) && (plr[p].Hand1Item._iStatFlag)) {
|
|
plr[p]._pBlockFlag = TRUE;
|
|
g++;
|
|
}
|
|
if ((plr[p].Hand2Item._itype == IT_SHIELD) && (plr[p].Hand2Item._iStatFlag)) {
|
|
plr[p]._pBlockFlag = TRUE;
|
|
g++;
|
|
}
|
|
|
|
#if IS_VERSION(RETAIL) || IS_VERSION(BETA)
|
|
if ((plr[p].BodyItem._itype == IT_HARMOR) && (plr[p].BodyItem._iStatFlag))
|
|
{
|
|
if ((plr[p]._pClass == CLASS_MONK) &&
|
|
(plr[p].BodyItem._iMagical == IMAGIC_UNIQUE))
|
|
plr[p]._pIAC += plr[p]._pLevel >> 1; // Monks get 1/2 level bonus while wearing medium armor.
|
|
g += 32;
|
|
}
|
|
else if ((plr[p].BodyItem._itype == IT_MARMOR) && (plr[p].BodyItem._iStatFlag))
|
|
{
|
|
if (plr[p]._pClass == CLASS_MONK)
|
|
{
|
|
if (plr[p].BodyItem._iMagical == IMAGIC_UNIQUE)
|
|
plr[p]._pIAC += plr[p]._pLevel << 1; // Monks get 2x level bonus while wearing light armor.
|
|
else
|
|
plr[p]._pIAC += plr[p]._pLevel >> 1; // Monks get 1/2 level bonus while wearing medium armor.
|
|
}
|
|
g += 16;
|
|
}
|
|
else
|
|
{
|
|
if (plr[p]._pClass == CLASS_MONK)
|
|
{
|
|
plr[p]._pIAC += plr[p]._pLevel << 1; // Monks get 2x level bonus for light/no armor.
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if ((plr[p]._pgfxnum != g) && (Loadgfx)) {
|
|
plr[p]._pgfxnum = g;
|
|
plr[p]._pGFXLoad = 0; // Clear all graphics loaded flag
|
|
LoadPlrGFX(p, PGL_STAND);
|
|
SetPlrAnims(p);
|
|
d = plr[p]._pdir;
|
|
|
|
app_assert(plr[p]._pNAnim[d]);
|
|
plr[p]._pAnimData = plr[p]._pNAnim[d];
|
|
plr[p]._pAnimLen = plr[p]._pNFrames;
|
|
plr[p]._pAnimFrame = 1;
|
|
plr[p]._pAnimCnt = 0;
|
|
plr[p]._pAnimDelay = 3;
|
|
plr[p]._pAnimWidth = plr[p]._pNWidth;
|
|
plr[p]._pAnimWidth2 = (plr[p]._pNWidth - 64) >> 1;
|
|
}
|
|
else {
|
|
plr[p]._pgfxnum = g;
|
|
}
|
|
|
|
for (i = 0; i < nummissiles; i++) {
|
|
mi = missileactive[i];
|
|
if (missile[mi]._mitype == MIT_MANASHIELD && missile[mi]._misource == p) {
|
|
missile[mi]._miVar1 = plr[p]._pHitPoints;
|
|
missile[mi]._miVar2 = plr[p]._pHPBase;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (plr[p].NeckItem._itype != -1 && plr[p].NeckItem.IDidx == IDI_AURIC)
|
|
{
|
|
GOLD_VMAX = GOLD_DOUBLE_VMAX;
|
|
}
|
|
else
|
|
{
|
|
int const old_vmax = GOLD_VMAX;
|
|
|
|
GOLD_VMAX = GOLD_DOUBLE_VMAX/2;
|
|
|
|
if (old_vmax != GOLD_VMAX)
|
|
StripTopGold(p);
|
|
}
|
|
|
|
drawmanaflag = TRUE;
|
|
drawhpflag = TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void CalcPlrScrolls(int p) {
|
|
int i;
|
|
__int64 t;
|
|
|
|
plr[p]._pScrlSpells = 0;
|
|
for (i = 0; i < plr[p]._pNumInv; i++) {
|
|
if (plr[p].InvList[i]._itype != -1) {
|
|
if (((plr[p].InvList[i]._iMiscId == IMID_SCROLL) ||
|
|
(plr[p].InvList[i]._iMiscId == IMID_TSCROLL)) &&
|
|
(plr[p].InvList[i]._iStatFlag)) {
|
|
t = 1;
|
|
plr[p]._pScrlSpells |= (t << plr[p].InvList[i]._iSpell-1);
|
|
}
|
|
}
|
|
}
|
|
for (i = 0; i < MAXSPD; i++) {
|
|
if (plr[p].SpdList[i]._itype != -1) {
|
|
if (((plr[p].SpdList[i]._iMiscId == IMID_SCROLL) ||
|
|
(plr[p].SpdList[i]._iMiscId == IMID_TSCROLL)) &&
|
|
(plr[p].SpdList[i]._iStatFlag)) {
|
|
t = 1;
|
|
plr[p]._pScrlSpells |= (t << plr[p].SpdList[i]._iSpell-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((plr[p]._pRSplType == SPT_SCROLL)
|
|
&& ((plr[p]._pScrlSpells & (1 << (plr[p]._pRSpell-1))) == 0)) {
|
|
plr[p]._pRSpell = -1;
|
|
plr[p]._pRSplType = SPT_NONE;
|
|
force_redraw = FULLDRAW;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void CalcPlrStaff(int p) {
|
|
plr[p]._pISpells = 0;
|
|
if (plr[p].Hand1Item._itype == -1) return;
|
|
if (!plr[p].Hand1Item._iStatFlag) return;
|
|
if (plr[p].Hand1Item._iCharges > 0) {
|
|
__int64 t = 1;
|
|
plr[p]._pISpells |= t << (plr[p].Hand1Item._iSpell - 1);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void CalcSelfItems(int pnum) {
|
|
int i;
|
|
ItemStruct * pi;
|
|
PlayerStruct * p = &plr[pnum];
|
|
BOOL sf, changeflag;
|
|
int sa = 0;
|
|
int ma = 0;
|
|
int da = 0;
|
|
|
|
// assume everything works, and calc potential + to str, mag, dex
|
|
pi = &p->InvBody[0];
|
|
for (i = NUM_INVLOC; i--; pi++) {
|
|
if (pi->_itype == -1) continue;
|
|
pi->_iStatFlag = TRUE;
|
|
if (!pi->_iIdentified) continue;
|
|
sa += pi->_iPLStr;
|
|
ma += pi->_iPLMag;
|
|
da += pi->_iPLDex;
|
|
}
|
|
|
|
do {
|
|
changeflag = FALSE;
|
|
pi = &p->InvBody[0];
|
|
for (i = NUM_INVLOC; i--; pi++) {
|
|
if (pi->_itype == -1) continue;
|
|
if (!pi->_iStatFlag) continue;
|
|
sf = TRUE;
|
|
if ((p->_pBaseStr + sa) < pi->_iMinStr) sf = FALSE;
|
|
if ((p->_pBaseMag + ma) < pi->_iMinMag) sf = FALSE;
|
|
if ((p->_pBaseDex + da) < pi->_iMinDex) sf = FALSE;
|
|
if (!sf) {
|
|
changeflag = TRUE;
|
|
pi->_iStatFlag = FALSE;
|
|
if (pi->_iIdentified) {
|
|
sa -= pi->_iPLStr;
|
|
ma -= pi->_iPLMag;
|
|
da -= pi->_iPLDex;
|
|
}
|
|
}
|
|
}
|
|
} while (changeflag);
|
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
static BOOL ItemMinStats(const PlayerStruct * p,const ItemStruct * x) {
|
|
if (p->_pMagic < (byte)x->_iMinMag) return FALSE;
|
|
if (p->_pStrength < x->_iMinStr) return FALSE;
|
|
if (p->_pDexterity < x->_iMinDex) return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void CalcPlrItemMin(int pnum) {
|
|
int i;
|
|
ItemStruct * pi;
|
|
PlayerStruct * p = &plr[pnum];
|
|
|
|
// handle inventory
|
|
pi = &p->InvList[0];
|
|
for (i = p->_pNumInv; i--; pi++)
|
|
pi->_iStatFlag = ItemMinStats(p,pi);
|
|
|
|
// handle speedbar
|
|
pi = &p->SpdList[0];
|
|
for (i = MAXSPD; i--; pi++) {
|
|
if (pi->_itype == -1) continue;
|
|
pi->_iStatFlag = ItemMinStats(p,pi);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void CalcPlrBookVals(int p)
|
|
{
|
|
int i, slvl;
|
|
|
|
void WitchBookLevel(int);
|
|
if (currlevel == 0) {
|
|
for (i = 1; witchitem[i]._itype != -1; i++)
|
|
WitchBookLevel(i);
|
|
}
|
|
|
|
for (i = 0; i < plr[p]._pNumInv; i++) {
|
|
if ((plr[p].InvList[i]._itype == IT_MISC) && (plr[p].InvList[i]._iMiscId == IMID_BOOK)) {
|
|
plr[p].InvList[i]._iMinMag = spelldata[plr[p].InvList[i]._iSpell].sMinInt;
|
|
slvl = plr[p]._pSplLvl[plr[p].InvList[i]._iSpell];
|
|
while (slvl != 0) {
|
|
plr[p].InvList[i]._iMinMag += ((plr[p].InvList[i]._iMinMag * 20) / 100);
|
|
slvl--;
|
|
if ((plr[p].InvList[i]._iMinMag + ((plr[p].InvList[i]._iMinMag * 20) / 100)) > 255) {
|
|
plr[p].InvList[i]._iMinMag = 255;
|
|
slvl = 0;
|
|
}
|
|
}
|
|
plr[p].InvList[i]._iStatFlag = ItemMinStats(&plr[p], &plr[p].InvList[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void CalcPlrInv(int p, BOOL Loadgfx) {
|
|
CalcPlrItemMin(p);
|
|
CalcSelfItems(p);
|
|
CalcPlrItemVals(p, Loadgfx);
|
|
CalcPlrItemMin(p);
|
|
if (p == myplr) {
|
|
CalcPlrBookVals(p);
|
|
CalcPlrScrolls(p);
|
|
CalcPlrStaff(p);
|
|
}
|
|
if ((p == myplr) && (currlevel == 0)) RecalcStoreStats();
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void SetPlrHandItem(ItemStruct *h, int idata) {
|
|
const ItemDataStruct * pAllItem = &AllItemsList[idata];
|
|
|
|
ZeroMemory(h,sizeof(ItemStruct));
|
|
h->_itype = pAllItem->itype;
|
|
h->_iCurs = pAllItem->iCurs;
|
|
strcpy(h->_iName, pAllItem->iName);
|
|
strcpy(h->_iIName, pAllItem->iName);
|
|
h->_iLoc = pAllItem->iLoc;
|
|
h->_iClass = pAllItem->iClass;
|
|
h->_iMinDam = pAllItem->iMinDam;
|
|
h->_iMaxDam = pAllItem->iMaxDam;
|
|
h->_iAC = pAllItem->iMinAC;
|
|
h->_iMiscId = pAllItem->iMiscId;
|
|
h->_iSpell = pAllItem->iSpell;
|
|
if (pAllItem->iMiscId == IMID_STAFF) h->_iCharges = 18; // was 40
|
|
h->_iMaxCharges = h->_iCharges;
|
|
h->_iDurability = pAllItem->iDurability;
|
|
h->_iMaxDur = pAllItem->iDurability;
|
|
h->_iMinStr = pAllItem->iMinStr;
|
|
h->_iMinMag = pAllItem->iMinMag;
|
|
h->_iMinDex = pAllItem->iMinDex;
|
|
h->_ivalue = pAllItem->iValue;
|
|
h->_iIvalue = pAllItem->iValue;
|
|
h->_iPrePower = -1;
|
|
h->_iSufPower = -1;
|
|
h->IDidx = idata;
|
|
h->_iMagical = IMAGIC_NONE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void GetPlrHandSeed(ItemStruct *h)
|
|
{
|
|
h->_iSeed = GetRndSeed();
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void GetGoldSeed(int pnum, ItemStruct *h)
|
|
{
|
|
int i, ii, s;
|
|
BOOL doneflag;
|
|
|
|
do {
|
|
doneflag = TRUE;
|
|
s = GetRndSeed();
|
|
for (i = 0; i < numitems; i++) {
|
|
ii = itemactive[i];
|
|
if (item[ii]._iSeed == s) doneflag = FALSE;
|
|
}
|
|
if (pnum == myplr) {
|
|
for (i = 0; i < plr[pnum]._pNumInv; i++)
|
|
if (plr[pnum].InvList[i]._iSeed == s) doneflag = FALSE;
|
|
}
|
|
} while (!doneflag);
|
|
h->_iSeed = s;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void SetPlrHandSeed(ItemStruct *h, int iseed)
|
|
{
|
|
h->_iSeed = iseed;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void SetPlrHandGoldCurs(ItemStruct *h)
|
|
{
|
|
if (h->_ivalue >= GOLD_VT2) {
|
|
h->_iCurs = ITEM_5GOLD;
|
|
} else {
|
|
if (h->_ivalue <= GOLD_VT1) h->_iCurs = ITEM_1GOLD;
|
|
else h->_iCurs = ITEM_3GOLD;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void CreatePlrItems(int p) {
|
|
int i;
|
|
ItemStruct * pi;
|
|
|
|
// zero out carried items
|
|
pi = &plr[p].InvBody[0];
|
|
for (i = NUM_INVLOC; i--; pi++)
|
|
pi->_itype = -1;
|
|
|
|
// zero inventory
|
|
ZeroMemory(plr[p].InvGrid,sizeof(plr[p].InvGrid));
|
|
pi = &plr[p].InvList[0];
|
|
for (i = MAXINV; i--; pi++)
|
|
pi->_itype = -1;
|
|
plr[p]._pNumInv = 0;
|
|
|
|
// zero speedbar
|
|
pi = &plr[p].SpdList[0];
|
|
for (i = MAXSPD; i--; pi++)
|
|
pi->_itype = -1;
|
|
|
|
switch (plr[p]._pClass) {
|
|
case CLASS_WARRIOR :
|
|
// Sword in left
|
|
SetPlrHandItem(&plr[p].Hand1Item, IDI_WARRIOR);
|
|
GetPlrHandSeed(&plr[p].Hand1Item);
|
|
|
|
// Shield in right
|
|
SetPlrHandItem(&plr[p].Hand2Item, IDI_WARRSHLD);
|
|
GetPlrHandSeed(&plr[p].Hand2Item);
|
|
|
|
#if CHEATS
|
|
if (!davecheat) {
|
|
SetPlrHandItem(&plr[p].HoldItem, IDI_WARRCLUB);
|
|
GetPlrHandSeed(&plr[p].HoldItem);
|
|
AutoPlace(p, 0, 1, 3, TRUE);
|
|
}
|
|
#else
|
|
// Club in inv
|
|
SetPlrHandItem(&plr[p].HoldItem, IDI_WARRCLUB);
|
|
GetPlrHandSeed(&plr[p].HoldItem);
|
|
AutoPlace(p, 0, 1, 3, TRUE);
|
|
#endif
|
|
SetPlrHandItem(&plr[p].SpdList[0], IDI_HEAL);
|
|
GetPlrHandSeed(&plr[p].SpdList[0]);
|
|
SetPlrHandItem(&plr[p].SpdList[1], IDI_HEAL);
|
|
GetPlrHandSeed(&plr[p].SpdList[1]);
|
|
break;
|
|
|
|
case CLASS_ROGUE :
|
|
#if !IS_VERSION(SHAREWARE)
|
|
// Bow in both hands
|
|
SetPlrHandItem(&plr[p].Hand1Item, IDI_ROGUE);
|
|
GetPlrHandSeed(&plr[p].Hand1Item);
|
|
SetPlrHandItem(&plr[p].SpdList[0], IDI_HEAL);
|
|
GetPlrHandSeed(&plr[p].SpdList[0]);
|
|
SetPlrHandItem(&plr[p].SpdList[1], IDI_HEAL);
|
|
GetPlrHandSeed(&plr[p].SpdList[1]);
|
|
#endif
|
|
break;
|
|
|
|
case CLASS_SORCEROR :
|
|
#if !IS_VERSION(SHAREWARE)
|
|
// Staff in both hands
|
|
SetPlrHandItem(&plr[p].Hand1Item, IDI_SORCEROR);
|
|
GetPlrHandSeed(&plr[p].Hand1Item);
|
|
SetPlrHandItem(&plr[p].SpdList[0], IDI_HEAL); // was mana
|
|
GetPlrHandSeed(&plr[p].SpdList[0]);
|
|
SetPlrHandItem(&plr[p].SpdList[1], IDI_HEAL); // was mana
|
|
GetPlrHandSeed(&plr[p].SpdList[1]);
|
|
#endif
|
|
break;
|
|
|
|
case CLASS_MONK :
|
|
#if !IS_VERSION(SHAREWARE)
|
|
// Bow in both hands
|
|
SetPlrHandItem(&plr[p].Hand1Item, IDI_MONK);
|
|
GetPlrHandSeed(&plr[p].Hand1Item);
|
|
SetPlrHandItem(&plr[p].SpdList[0], IDI_HEAL);
|
|
GetPlrHandSeed(&plr[p].SpdList[0]);
|
|
SetPlrHandItem(&plr[p].SpdList[1], IDI_HEAL);
|
|
GetPlrHandSeed(&plr[p].SpdList[1]);
|
|
#endif
|
|
break;
|
|
|
|
case CLASS_BARD :
|
|
#if !IS_VERSION(SHAREWARE)
|
|
// Bow in both hands
|
|
SetPlrHandItem(&plr[p].Hand1Item, IDI_BARD);
|
|
GetPlrHandSeed(&plr[p].Hand1Item);
|
|
SetPlrHandItem(&plr[p].Hand2Item, IDI_BARDDAGGER);
|
|
GetPlrHandSeed(&plr[p].Hand2Item);
|
|
SetPlrHandItem(&plr[p].SpdList[0], IDI_HEAL);
|
|
GetPlrHandSeed(&plr[p].SpdList[0]);
|
|
SetPlrHandItem(&plr[p].SpdList[1], IDI_HEAL);
|
|
GetPlrHandSeed(&plr[p].SpdList[1]);
|
|
#endif
|
|
break;
|
|
|
|
case CLASS_BARBARIAN :
|
|
#if !IS_VERSION(SHAREWARE)
|
|
// Club in left
|
|
SetPlrHandItem(&plr[p].Hand1Item, IDI_BARBARIAN);
|
|
GetPlrHandSeed(&plr[p].Hand1Item);
|
|
|
|
// Shield in right
|
|
SetPlrHandItem(&plr[p].Hand2Item, IDI_BARSHLD);
|
|
GetPlrHandSeed(&plr[p].Hand2Item);
|
|
SetPlrHandItem(&plr[p].SpdList[0], IDI_HEAL);
|
|
GetPlrHandSeed(&plr[p].SpdList[0]);
|
|
SetPlrHandItem(&plr[p].SpdList[1], IDI_HEAL);
|
|
GetPlrHandSeed(&plr[p].SpdList[1]);
|
|
#endif
|
|
break;
|
|
|
|
}
|
|
|
|
SetPlrHandItem(&plr[p].HoldItem, IDI_GOLD);
|
|
GetPlrHandSeed(&plr[p].HoldItem);
|
|
#if CHEATS
|
|
if (!davecheat) {
|
|
// 100 Gold
|
|
plr[p].HoldItem._ivalue = 100;
|
|
plr[p].HoldItem._iCurs = ITEM_1GOLD;
|
|
plr[p]._pGold = plr[p].HoldItem._ivalue;
|
|
i = plr[p]._pNumInv;
|
|
plr[p].InvList[i] = plr[p].HoldItem;
|
|
plr[p]._pNumInv++;
|
|
plr[p].InvGrid[30] = plr[p]._pNumInv;
|
|
}
|
|
else {
|
|
// 200000 Gold
|
|
plr[p].HoldItem._ivalue = 5000;
|
|
plr[p].HoldItem._iCurs = ITEM_5GOLD;
|
|
plr[p]._pGold = 200000;
|
|
for (int j = 0; j < 40; j++) {
|
|
GetGoldSeed(p, &plr[p].HoldItem);
|
|
i = plr[p]._pNumInv;
|
|
plr[p].InvList[i] = plr[p].HoldItem;
|
|
plr[p]._pNumInv++;
|
|
plr[p].InvGrid[j] = plr[p]._pNumInv;
|
|
}
|
|
}
|
|
#else
|
|
// 100 Gold
|
|
plr[p].HoldItem._ivalue = 100;
|
|
plr[p].HoldItem._iCurs = ITEM_1GOLD;
|
|
plr[p]._pGold = plr[p].HoldItem._ivalue;
|
|
i = plr[p]._pNumInv;
|
|
plr[p].InvList[i] = plr[p].HoldItem;
|
|
plr[p]._pNumInv++;
|
|
plr[p].InvGrid[30] = plr[p]._pNumInv;
|
|
#endif
|
|
|
|
CalcPlrItemVals(p,FALSE);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
BOOL ItemSpaceOk(int i, int j)
|
|
{
|
|
int pn, oi;
|
|
|
|
if ((i < 0) || (i >= DMAXX) || (j < 0) || (j >= DMAXY)) return(FALSE);
|
|
if (dMonster[i][j] != 0) return(FALSE);
|
|
if (dPlayer[i][j] != 0) return(FALSE);
|
|
if (dItem[i][j] != 0) return(FALSE);
|
|
if (dObject[i][j] != 0) {
|
|
if (dObject[i][j] > 0) oi = dObject[i][j]-1;
|
|
else oi = -(dObject[i][j]+1);
|
|
if (object[oi]._oSolidFlag) return(FALSE);
|
|
}
|
|
if (dObject[i+1][j+1] > 0) {
|
|
oi = dObject[i+1][j+1]-1;
|
|
if (object[oi]._oSelFlag != OSEL_NONE) return(FALSE);
|
|
}
|
|
if (dObject[i+1][j+1] < 0) {
|
|
oi = -(dObject[i+1][j+1]+1);
|
|
if (object[oi]._oSelFlag != OSEL_NONE) return(FALSE);
|
|
}
|
|
if ((dObject[i+1][j] > 0) && (dObject[i][j+1] > 0)) {
|
|
oi = dObject[i+1][j]-1;
|
|
if (object[oi]._oSelFlag != OSEL_NONE) {
|
|
oi = dObject[i][j+1]-1;
|
|
if (object[oi]._oSelFlag != OSEL_NONE) return(FALSE);
|
|
}
|
|
}
|
|
pn = dPiece[i][j];
|
|
if (nSolidTable[pn]) return(FALSE);
|
|
return(TRUE);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*
|
|
|
|
#if CHEATS
|
|
void DaveISpaceOk(int inum)
|
|
{
|
|
int i,j;
|
|
|
|
for (j = 0; j < MAXDUNY; j++) {
|
|
for (i = 0; i < MAXDUNX; i++) {
|
|
if (dItem[i][j] == inum+1)
|
|
app_fatal("Item in map already");
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
BOOL GetItemSpace(int x, int y, char inum)
|
|
{
|
|
int i,j,xx,yy,rs;
|
|
BOOL savail;
|
|
|
|
// Try surrounding squares
|
|
yy = 0;
|
|
for (j = (y-1); j <= (y+1); j++) {
|
|
xx = 0;
|
|
for (i = (x-1); i <= (x+1); i++) {
|
|
itemhold[xx][yy] = ItemSpaceOk(i,j);
|
|
xx++;
|
|
}
|
|
yy++;
|
|
}
|
|
|
|
savail = FALSE;
|
|
for (yy = 0; yy < 3; yy++) {
|
|
for (xx = 0; xx < 3; xx++) {
|
|
if (itemhold[xx][yy]) savail = TRUE;
|
|
}
|
|
}
|
|
|
|
// Must go here so same number of rnd calls on multiplayer machines
|
|
rs = random(13, 15) + 1;
|
|
|
|
// No fit, no good
|
|
if (!savail) return(FALSE);
|
|
|
|
// Place item
|
|
xx = 0;
|
|
yy = 0;
|
|
while (rs > 0) {
|
|
if (itemhold[xx][yy]) rs--;
|
|
if (rs > 0) {
|
|
xx++;
|
|
if (xx == 3) {
|
|
xx = 0;
|
|
yy++;
|
|
if (yy == 3) yy = 0;
|
|
}
|
|
}
|
|
}
|
|
xx = xx + x - 1;
|
|
yy = yy + y - 1;
|
|
item[inum]._ix = xx;
|
|
item[inum]._iy = yy;
|
|
//DaveISpaceOk(inum);
|
|
dItem[xx][yy] = inum + 1;
|
|
return(TRUE);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void GetSuperItemSpace(int x, int y, char inum)
|
|
{
|
|
// try normal method first
|
|
if (GetItemSpace(x, y, inum)) return;
|
|
|
|
int xx, yy;
|
|
|
|
// radial search outward until a space is found
|
|
for (int l = 2; l < 50; l++) {
|
|
for (int j = -l; j <= l; j++) {
|
|
yy = y + j;
|
|
for (int i = -l; i <= l; i++) {
|
|
xx = x + i;
|
|
if (! ItemSpaceOk(xx,yy)) continue;
|
|
|
|
// drop it
|
|
item[inum]._ix = xx;
|
|
item[inum]._iy = yy;
|
|
//DaveISpaceOk(inum);
|
|
dItem[xx][yy] = inum + 1;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void GetSuperItemLoc(int x, int y, int &xx, int &yy)
|
|
{
|
|
// radial search outward until a space is found
|
|
for (int l = 1; l < 50; l++) {
|
|
for (int j = -l; j <= l; j++) {
|
|
yy = y + j;
|
|
for (int i = -l; i <= l; i++) {
|
|
xx = x + i;
|
|
if (ItemSpaceOk(xx,yy)) // found it
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void CalcItemValue(int i)
|
|
{
|
|
int v = item[i]._iVMult1 + item[i]._iVMult2;
|
|
if (v > 0) v = item[i]._ivalue * v;
|
|
if (v < 0) v = item[i]._ivalue / v;
|
|
v += item[i]._iVAdd1 + item[i]._iVAdd2;
|
|
if (v <= 0) v = 1;
|
|
item[i]._iIvalue = v;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void GetBookSpell(int i, int lvl)
|
|
{
|
|
|
|
if (lvl == 0) lvl = 1;
|
|
int rv = random(14, SPL_LAST) + 1;
|
|
|
|
#if IS_VERSION(SHAREWARE)
|
|
if (lvl > 5) lvl = 5;
|
|
#endif
|
|
|
|
int bs = SPL_FIREBOLT;
|
|
int s = SPL_FIREBOLT;
|
|
while (rv > 0) {
|
|
if ((spelldata[s].sBookLvl != -1) && (lvl >= spelldata[s].sBookLvl)) {
|
|
rv--;
|
|
bs = s;
|
|
}
|
|
|
|
s++;
|
|
if ((gbMaxPlayers == 1) && (s == SPL_RESURRECT)) s++;
|
|
if ((gbMaxPlayers == 1) && (s == SPL_HEALOTHER)) s++;
|
|
if (s == SPL_LAST) s = SPL_FIREBOLT;
|
|
}
|
|
strcat(item[i]._iName, spelldata[bs].sNameText);
|
|
strcat(item[i]._iIName, spelldata[bs].sNameText);
|
|
item[i]._iSpell = bs;
|
|
item[i]._iMinMag = spelldata[bs].sMinInt;
|
|
item[i]._ivalue += spelldata[bs].sBookCost;
|
|
item[i]._iIvalue += spelldata[bs].sBookCost;
|
|
if (spelldata[bs].sType == ST_FIRE) item[i]._iCurs = ITEM_BOOK3;
|
|
else if (spelldata[bs].sType == ST_LIGHT) item[i]._iCurs = ITEM_BOOK;
|
|
else if (spelldata[bs].sType == ST_MISC) item[i]._iCurs = ITEM_BOOK2;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void GetStaffPower(int i, int lvl, int bs, BOOL onlygood)
|
|
{
|
|
int pre;
|
|
int l[256], nl;
|
|
int j, aii;
|
|
int preidx;
|
|
char istr[128];
|
|
BOOL addok;
|
|
|
|
// Prefix only (for a staff w/ spell)
|
|
pre = random(15, 10);
|
|
|
|
preidx = -1;
|
|
|
|
#if CHEATS
|
|
if ((pre == 0) || (cheatflag) || (onlygood)) {
|
|
#else
|
|
if ((pre == 0) || (onlygood)) {
|
|
#endif
|
|
nl = 0;
|
|
for (j = 0; PL_Prefix[j].PLPower != -1; j++) {
|
|
if (((PL_Prefix[j].PLIType & PLF_STAFF) != 0) && (PL_Prefix[j].PLMinLvl <= lvl)) {
|
|
addok = TRUE;
|
|
if ((onlygood) && (!PL_Prefix[j].PLOk)) addok = FALSE;
|
|
|
|
if (addok) {
|
|
l[nl] = j;
|
|
nl++;
|
|
if (PL_Prefix[j].PLDouble) {
|
|
l[nl] = j;
|
|
nl++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (nl != 0) {
|
|
preidx = l[random(16, nl)];
|
|
sprintf(istr, "%s %s", PL_Prefix[preidx].PLName, item[i]._iIName);
|
|
strcpy(item[i]._iIName, istr);
|
|
item[i]._iMagical = IMAGIC_MAGIC;
|
|
SaveItemPower(i, PL_Prefix[preidx].PLPower, PL_Prefix[preidx].PLParam1, PL_Prefix[preidx].PLParam2, PL_Prefix[preidx].PLMinVal, PL_Prefix[preidx].PLMaxVal, PL_Prefix[preidx].PLMultVal);
|
|
item[i]._iPrePower = PL_Prefix[preidx].PLPower;
|
|
}
|
|
}
|
|
if (!InfoFit(item[i]._iIName)) {
|
|
aii = item[i].IDidx;
|
|
strcpy(item[i]._iIName, AllItemsList[aii].iSName);
|
|
if (preidx != -1) {
|
|
sprintf(istr, "%s %s", PL_Prefix[preidx].PLName, item[i]._iIName);
|
|
strcpy(item[i]._iIName, istr);
|
|
}
|
|
sprintf(istr, "%s of %s", item[i]._iIName, spelldata[bs].sNameText);
|
|
strcpy(item[i]._iIName, istr);
|
|
if (!item[i]._iMagical) strcpy(item[i]._iName, item[i]._iIName);
|
|
}
|
|
CalcItemValue(i);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void GetStaffSpell(int i, int lvl, BOOL onlygood)
|
|
{
|
|
int rv, s, bs, l;
|
|
char tstr[64];
|
|
int maxc, minc;
|
|
|
|
//if (random(17, 4) == 0) GetItemPower(i, lvl >> 1, lvl, PLF_STAFF, onlygood);
|
|
//else
|
|
//{
|
|
l = lvl >> 1;
|
|
if (l == 0) l = 1;
|
|
rv = random(18, SPL_LAST) + 1;
|
|
|
|
#if IS_VERSION(SHAREWARE)
|
|
if (lvl > 10) lvl = 10;
|
|
#endif
|
|
|
|
s = SPL_FIREBOLT;
|
|
while (rv > 0) {
|
|
if ((spelldata[s].sStaffLvl != -1) && (l >= spelldata[s].sStaffLvl)) {
|
|
rv--;
|
|
bs = s;
|
|
}
|
|
s++;
|
|
if ((gbMaxPlayers == 1) && (s == SPL_RESURRECT)) s++;
|
|
if ((gbMaxPlayers == 1) && (s == SPL_HEALOTHER)) s++;
|
|
if (s == SPL_LAST) s = SPL_FIREBOLT;
|
|
}
|
|
sprintf(tstr, "%s of %s", item[i]._iName, spelldata[bs].sNameText);
|
|
//Check to see if string will fit
|
|
if (!InfoFit(tstr)) {
|
|
sprintf(tstr, "Staff of %s", spelldata[bs].sNameText);
|
|
}
|
|
strcpy(item[i]._iName, tstr);
|
|
strcpy(item[i]._iIName, tstr);
|
|
item[i]._iSpell = bs;
|
|
minc = spelldata[bs].sStaffMin;
|
|
maxc = spelldata[bs].sStaffMax;
|
|
item[i]._iCharges = random(19, maxc-minc+1) + minc;
|
|
item[i]._iMaxCharges = item[i]._iCharges;
|
|
item[i]._iMinMag = spelldata[bs].sMinInt;
|
|
int v = (spelldata[bs].sStaffCost * item[i]._iCharges) / 5;
|
|
item[i]._ivalue += v;
|
|
item[i]._iIvalue += v;
|
|
GetStaffPower(i, lvl, bs, onlygood);
|
|
//}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void GetOilType(int i, int lvl)
|
|
{
|
|
int n, ro, roi, j;
|
|
char OilIndexList[30];
|
|
|
|
if (gbMaxPlayers == 1) {
|
|
if (lvl == 0) lvl = 1;
|
|
n = 0;
|
|
for (j=0; j < MAXOIL; j++) {
|
|
if (OilLvlTbl[j] <= lvl) {
|
|
OilIndexList[n] = j;
|
|
n++;
|
|
}
|
|
}
|
|
ro = random(165, n);
|
|
roi = OilIndexList[ro];
|
|
} else {
|
|
ro = random(165, 2);
|
|
if (ro == 0) roi = 5;
|
|
else roi = 6;
|
|
}
|
|
|
|
strcpy(item[i]._iName, OilStr[roi]);
|
|
strcpy(item[i]._iIName, OilStr[roi]);
|
|
item[i]._iMiscId = OilIdVal[roi];
|
|
item[i]._ivalue = OilValue[roi];
|
|
item[i]._iIvalue = OilValue[roi];
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void GetItemAttrs(int i, int idata, int lvl)
|
|
{
|
|
int rndv;
|
|
|
|
item[i]._itype = AllItemsList[idata].itype;
|
|
item[i]._iCurs = AllItemsList[idata].iCurs;
|
|
strcpy(item[i]._iName, AllItemsList[idata].iName);
|
|
strcpy(item[i]._iIName, AllItemsList[idata].iName);
|
|
item[i]._iLoc = AllItemsList[idata].iLoc;
|
|
item[i]._iClass = AllItemsList[idata].iClass;
|
|
item[i]._iMinDam = AllItemsList[idata].iMinDam;
|
|
item[i]._iMaxDam = AllItemsList[idata].iMaxDam;
|
|
item[i]._iAC = random(20, AllItemsList[idata].iMaxAC - AllItemsList[idata].iMinAC + 1) + AllItemsList[idata].iMinAC;
|
|
item[i]._iFlags = AllItemsList[idata].iFlags;
|
|
item[i]._iFlags2 = 0;
|
|
item[i]._iMiscId = AllItemsList[idata].iMiscId;
|
|
item[i]._iSpell = AllItemsList[idata].iSpell;
|
|
item[i]._iMagical = IMAGIC_NONE;
|
|
|
|
item[i]._ivalue = AllItemsList[idata].iValue;
|
|
item[i]._iIvalue = AllItemsList[idata].iValue;
|
|
|
|
item[i]._iVAdd1 = 0;
|
|
item[i]._iVMult1 = 0;
|
|
item[i]._iVAdd2 = 0;
|
|
item[i]._iVMult2 = 0;
|
|
|
|
item[i]._iPLDam = 0;
|
|
item[i]._iPLToHit = 0;
|
|
item[i]._iPLAC = 0;
|
|
|
|
item[i]._iPLStr = 0;
|
|
item[i]._iPLMag = 0;
|
|
item[i]._iPLDex = 0;
|
|
item[i]._iPLVit = 0;
|
|
|
|
item[i]._iCharges = 0;
|
|
item[i]._iMaxCharges = 0;
|
|
|
|
item[i]._iDurability = AllItemsList[idata].iDurability;
|
|
item[i]._iMaxDur = AllItemsList[idata].iDurability;
|
|
item[i]._iMinStr = AllItemsList[idata].iMinStr;
|
|
item[i]._iMinMag = AllItemsList[idata].iMinMag;
|
|
item[i]._iMinDex = AllItemsList[idata].iMinDex;
|
|
|
|
item[i]._iPLFR = 0;
|
|
item[i]._iPLLR = 0;
|
|
item[i]._iPLMR = 0;
|
|
|
|
item[i].IDidx = idata;
|
|
|
|
item[i]._iPLDamMod = 0;
|
|
item[i]._iPLGetHit = 0;
|
|
item[i]._iPLLight = 0;
|
|
|
|
item[i]._iSplLvlAdd = 0;
|
|
|
|
item[i]._iRequest = FALSE;
|
|
|
|
item[i]._iFMinDam = 0;
|
|
item[i]._iFMaxDam = 0;
|
|
item[i]._iLMinDam = 0;
|
|
item[i]._iLMaxDam = 0;
|
|
|
|
item[i]._iPLEnAc = 0;
|
|
|
|
item[i]._iPLMana = 0;
|
|
item[i]._iPLHP = 0;
|
|
|
|
item[i]._iPrePower = -1;
|
|
item[i]._iSufPower = -1;
|
|
item[i]._iFlags = 0;
|
|
item[i]._iFlags2 = 0;
|
|
|
|
if (item[i]._iMiscId == IMID_BOOK) GetBookSpell(i, lvl);
|
|
|
|
if (item[i]._iMiscId == IMID_OIL) GetOilType(i, lvl);
|
|
|
|
int efflevel = GetEffLevel();
|
|
|
|
if (item[i]._itype == IT_GOLD) {
|
|
if (gnDifficulty == D_NORMAL)
|
|
rndv = (efflevel * 5) + random(21, efflevel * 10);
|
|
else if (gnDifficulty == D_NIGHTMARE)
|
|
rndv = ((efflevel + 16) * 5) + random(21, (efflevel + 16) * 10);
|
|
else if (gnDifficulty == D_HELL)
|
|
rndv = ((efflevel + 32) * 5) + random(21, (efflevel + 32) * 10);
|
|
|
|
if (leveltype == 4) rndv += (rndv >> 3);
|
|
if (rndv > 5000) rndv = 5000;
|
|
item[i]._ivalue = rndv;
|
|
if (rndv >= GOLD_VT2) {
|
|
item[i]._iCurs = ITEM_5GOLD;
|
|
} else {
|
|
if (rndv <= GOLD_VT1) item[i]._iCurs = ITEM_1GOLD;
|
|
else item[i]._iCurs = ITEM_3GOLD;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int RndPL(int param1, int param2)
|
|
{
|
|
return(random(22, param2 - param1 + 1) + param1);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int PLVal(int pv, int p1, int p2, int minv, int maxv)
|
|
{
|
|
if (p1 == p2) return(minv);
|
|
if (minv == maxv) return(minv);
|
|
return((((((pv - p1) * 100) / (p2 - p1)) * (maxv - minv)) / 100) + minv);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SaveItemPower(int i, int power, int param1, int param2, int minval, int maxval, int multval)
|
|
{
|
|
int r, r2;
|
|
|
|
r = RndPL(param1, param2);
|
|
switch (power) {
|
|
case PL_TOHIT:
|
|
item[i]._iPLToHit += r;
|
|
break;
|
|
case PL_NTOHIT:
|
|
item[i]._iPLToHit -= r;
|
|
break;
|
|
case PL_TODAM:
|
|
item[i]._iPLDam += r;
|
|
break;
|
|
case PL_NTODAM:
|
|
item[i]._iPLDam -= r;
|
|
break;
|
|
case PL_DOPPEL:
|
|
item[i]._iFlags2 |= IAF2_CLONE;
|
|
// fall through
|
|
case PL_DAHT:
|
|
r = RndPL(param1, param2);
|
|
item[i]._iPLDam += r;
|
|
if (param1 == 20) r2 = RndPL(1, 5);
|
|
if (param1 == 36) r2 = RndPL(6, 10);
|
|
if (param1 == 51) r2 = RndPL(11, 15);
|
|
if (param1 == 66) r2 = RndPL(16, 20);
|
|
if (param1 == 81) r2 = RndPL(21, 30);
|
|
if (param1 == 96) r2 = RndPL(31, 40);
|
|
if (param1 == 111) r2 = RndPL(41, 50);
|
|
if (param1 == 126) r2 = RndPL(51, 75);
|
|
if (param1 == 151) r2 = RndPL(76, 100);
|
|
item[i]._iPLToHit += r2;
|
|
break;
|
|
|
|
case PL_NDAHT:
|
|
item[i]._iPLDam -= r;
|
|
if (param1 == 25) r2 = RndPL(1, 5);
|
|
if (param1 == 50) r2 = RndPL(6, 10);
|
|
item[i]._iPLToHit -= r2;
|
|
break;
|
|
case PL_AC:
|
|
item[i]._iPLAC += r;
|
|
break;
|
|
case PL_NAC:
|
|
item[i]._iPLAC -= r;
|
|
break;
|
|
case PL_ACTUALAC:
|
|
item[i]._iAC = r;
|
|
break;
|
|
case PL_NACTULAC:
|
|
item[i]._iAC -= r;
|
|
break;
|
|
case PL_RFIRE:
|
|
item[i]._iPLFR += r;
|
|
break;
|
|
case PL_RLGHT:
|
|
item[i]._iPLLR += r;
|
|
break;
|
|
case PL_RMAG:
|
|
item[i]._iPLMR += r;
|
|
break;
|
|
case PL_RALL:
|
|
item[i]._iPLFR += r;
|
|
item[i]._iPLLR += r;
|
|
item[i]._iPLMR += r;
|
|
if (item[i]._iPLFR < 0) item[i]._iPLFR = 0;
|
|
if (item[i]._iPLLR < 0) item[i]._iPLLR = 0;
|
|
if (item[i]._iPLMR < 0) item[i]._iPLMR = 0;
|
|
break;
|
|
case PL_SLVL:
|
|
item[i]._iSplLvlAdd = r;
|
|
break;
|
|
case PL_CHRG :
|
|
item[i]._iCharges = item[i]._iCharges * param1;
|
|
item[i]._iMaxCharges = item[i]._iCharges;
|
|
break;
|
|
case PL_SPELL :
|
|
item[i]._iSpell = param1;
|
|
item[i]._iCharges = param2;
|
|
item[i]._iMaxCharges = param2;
|
|
break;
|
|
case PL_FHIT:
|
|
item[i]._iFlags |= IAF_FIREHIT;
|
|
item[i]._iFlags &= ~IAF_LIGHTHIT;
|
|
item[i]._iFMinDam = param1;
|
|
item[i]._iFMaxDam = param2;
|
|
item[i]._iLMinDam = 0;
|
|
item[i]._iLMaxDam = 0;
|
|
break;
|
|
case PL_LHIT:
|
|
item[i]._iFlags |= IAF_LIGHTHIT;
|
|
item[i]._iFlags &= ~IAF_FIREHIT;
|
|
item[i]._iLMinDam = param1;
|
|
item[i]._iLMaxDam = param2;
|
|
item[i]._iFMinDam = 0;
|
|
item[i]._iFMaxDam = 0;
|
|
break;
|
|
case PL_STR:
|
|
item[i]._iPLStr += r;
|
|
break;
|
|
case PL_NSTR:
|
|
item[i]._iPLStr -= r;
|
|
break;
|
|
case PL_MAG:
|
|
item[i]._iPLMag += r;
|
|
break;
|
|
case PL_NMAG:
|
|
item[i]._iPLMag -= r;
|
|
break;
|
|
case PL_DEX:
|
|
item[i]._iPLDex += r;
|
|
break;
|
|
case PL_NDEX:
|
|
item[i]._iPLDex -= r;
|
|
break;
|
|
case PL_VIT:
|
|
item[i]._iPLVit += r;
|
|
break;
|
|
case PL_NVIT:
|
|
item[i]._iPLVit -= r;
|
|
break;
|
|
case PL_STATS:
|
|
item[i]._iPLStr += r;
|
|
item[i]._iPLMag += r;
|
|
item[i]._iPLDex += r;
|
|
item[i]._iPLVit += r;
|
|
break;
|
|
case PL_NSTATS:
|
|
item[i]._iPLStr -= r;
|
|
item[i]._iPLMag -= r;
|
|
item[i]._iPLDex -= r;
|
|
item[i]._iPLVit -= r;
|
|
break;
|
|
case PL_GETHIT:
|
|
item[i]._iPLGetHit += r;
|
|
break;
|
|
case PL_NGETHIT:
|
|
item[i]._iPLGetHit -= r;
|
|
break;
|
|
case PL_HP:
|
|
item[i]._iPLHP += (r << HP_SHIFT);
|
|
break;
|
|
case PL_NHP:
|
|
item[i]._iPLHP -= (r << HP_SHIFT);
|
|
break;
|
|
case PL_MANA:
|
|
item[i]._iPLMana += (r << MANA_SHIFT);
|
|
drawmanaflag = TRUE;
|
|
break;
|
|
case PL_NMANA:
|
|
item[i]._iPLMana -= (r << MANA_SHIFT);
|
|
drawmanaflag = TRUE;
|
|
break;
|
|
case PL_DUR:
|
|
r2 = (item[i]._iMaxDur * r) / 100;
|
|
item[i]._iMaxDur += r2;
|
|
item[i]._iDurability += r2;
|
|
break;
|
|
case PL_FRAGILE:
|
|
item[i]._iPLDam += 140 + r * 2;
|
|
// fall through
|
|
case PL_NDUR:
|
|
r2 = (item[i]._iMaxDur * r) / 100;
|
|
item[i]._iMaxDur -= r2;
|
|
if (item[i]._iMaxDur < 1) item[i]._iMaxDur = 1;
|
|
item[i]._iDurability = item[i]._iMaxDur;
|
|
break;
|
|
case PL_IND:
|
|
item[i]._iDurability = INFINITE_DUR;
|
|
item[i]._iMaxDur = INFINITE_DUR;
|
|
break;
|
|
case PL_LIGHT:
|
|
item[i]._iPLLight += param1;
|
|
break;
|
|
case PL_NLIGHT:
|
|
item[i]._iPLLight -= param1;
|
|
break;
|
|
case PL_NUMARWS:
|
|
item[i]._iFlags |= IAF_RABID; // unused -> multimissile --donald
|
|
break;
|
|
case PL_FARROW:
|
|
item[i]._iFlags |= IAF_FIREARROW;
|
|
item[i]._iFlags &= ~IAF_LARROW;
|
|
item[i]._iFMinDam = param1;
|
|
item[i]._iFMaxDam = param2;
|
|
item[i]._iLMinDam = 0;
|
|
item[i]._iLMaxDam = 0;
|
|
break;
|
|
case PL_LARROW:
|
|
item[i]._iFlags |= IAF_LARROW;
|
|
item[i]._iFlags &= ~IAF_FIREARROW;
|
|
item[i]._iLMinDam = param1;
|
|
item[i]._iLMaxDam = param2;
|
|
item[i]._iFMinDam = 0;
|
|
item[i]._iFMaxDam = 0;
|
|
break;
|
|
case PL_HITADD: // usurped for fireball arrows...
|
|
item[i]._iFlags |= (IAF_LARROW | IAF_FIREARROW);
|
|
item[i]._iFMinDam = param1;
|
|
item[i]._iFMaxDam = param2;
|
|
item[i]._iLMinDam = 0;
|
|
item[i]._iLMaxDam = 0;
|
|
break;
|
|
case PL_THORN:
|
|
item[i]._iFlags |= IAF_THORN;
|
|
break;
|
|
case PL_LMANA:
|
|
item[i]._iFlags |= IAF_LMANA;
|
|
drawmanaflag = TRUE;
|
|
break;
|
|
case PL_NOHEAL:
|
|
item[i]._iFlags |= IAF_NOHEAL;
|
|
break;
|
|
case PL_TRAPDAM:
|
|
item[i]._iFlags |= IAF_TRAPDAM;
|
|
break;
|
|
case PL_BEAR:
|
|
item[i]._iFlags |= IAF_KNOCKBACK;
|
|
break;
|
|
case PL_DAMDEMON:
|
|
item[i]._iFlags |= IAF_DAMDEMON;
|
|
break;
|
|
case PL_ZERORES:
|
|
item[i]._iFlags |= IAF_ZERORES;
|
|
break;
|
|
case PL_MNOHEAL:
|
|
item[i]._iFlags |= IAF_MNOHEAL;
|
|
break;
|
|
case PL_BAT:
|
|
if (param1 == 3) item[i]._iFlags |= IAF_BAT10;
|
|
if (param1 == 5) item[i]._iFlags |= IAF_BAT20;
|
|
drawmanaflag = TRUE;
|
|
break;
|
|
case PL_LEECH:
|
|
if (param1 == 3) item[i]._iFlags |= IAF_LEECH10;
|
|
if (param1 == 5) item[i]._iFlags |= IAF_LEECH20;
|
|
drawhpflag = TRUE;
|
|
break;
|
|
case PL_ENAC:
|
|
item[i]._iPLEnAc = param1;
|
|
break;
|
|
case PL_ATANIM:
|
|
if (param1 == 1) item[i]._iFlags |= IAF_ATANIM1;
|
|
if (param1 == 2) item[i]._iFlags |= IAF_ATANIM2;
|
|
if (param1 == 3) item[i]._iFlags |= IAF_ATANIM3;
|
|
if (param1 == 4) item[i]._iFlags |= IAF_ATANIM4;
|
|
break;
|
|
case PL_HTANIM:
|
|
if (param1 == 1) item[i]._iFlags |= IAF_HTANIM1;
|
|
if (param1 == 2) item[i]._iFlags |= IAF_HTANIM2;
|
|
if (param1 == 3) item[i]._iFlags |= IAF_HTANIM3;
|
|
break;
|
|
case PL_BLANIM:
|
|
item[i]._iFlags |= IAF_BLANIM;
|
|
break;
|
|
case PL_DAMADD:
|
|
item[i]._iPLDamMod += r;
|
|
break;
|
|
case PL_RNDARW:
|
|
item[i]._iFlags |= IAF_RNDARROW;
|
|
break;
|
|
case PL_DAMAGE:
|
|
item[i]._iMinDam = param1;
|
|
item[i]._iMaxDam = param2;
|
|
break;
|
|
case PL_DURNUM:
|
|
item[i]._iDurability = param1;
|
|
item[i]._iMaxDur = param1;
|
|
break;
|
|
case PL_FALCON:
|
|
item[i]._iFlags |= IAF_ATANIM3;
|
|
break;
|
|
case PL_ONEHAND:
|
|
item[i]._iLoc = IL_HAND;
|
|
break;
|
|
case PL_CONST:
|
|
item[i]._iFlags |= IAF_CONSTRICT;
|
|
break;
|
|
case PL_SKING:
|
|
item[i]._iFlags |= IAF_SKING;
|
|
break;
|
|
case PL_INFRA:
|
|
item[i]._iFlags |= IAF_INFRAVISION;
|
|
break;
|
|
case PL_NSTRREQ:
|
|
item[i]._iMinStr = 0;
|
|
break;
|
|
case PL_GFX:
|
|
item[i]._iCurs = param1;
|
|
break;
|
|
case PL_HARQUN: // usurped for lightning arrows
|
|
item[i]._iFlags |= (IAF_LARROW | IAF_FIREARROW);
|
|
item[i]._iFMinDam = param1;
|
|
item[i]._iFMaxDam = param2;
|
|
item[i]._iLMinDam = 1;
|
|
item[i]._iLMaxDam = 0;
|
|
#if 0
|
|
//rjs item[i]._iPLHP = (byte)plr[myplr]._pArmorClass + plr[myplr]._pIBonusAC + plr[myplr]._pIAC;
|
|
item[i]._iPLHP = plr[myplr]._pIBonusAC + plr[myplr]._pIAC;
|
|
item[i]._iPLHP += (plr[myplr]._pDexterity / 5);
|
|
item[i]._iPLHP = item[i]._iPLHP << HP_SHIFT;
|
|
#endif
|
|
break;
|
|
case PL_HARQUN2:
|
|
item[i]._iFlags |= (IAF_LIGHTHIT | IAF_FIREHIT);
|
|
item[i]._iFMinDam = param1;
|
|
item[i]._iFMaxDam = param2;
|
|
item[i]._iLMinDam = 2;
|
|
item[i]._iLMaxDam = 0;
|
|
// item[i]._iAC += ((plr[myplr]._pMaxManaBase >> MANA_SHIFT) / 10);
|
|
break;
|
|
case PL_HARQUN3:
|
|
item[i]._iPLFR = 30 - plr[myplr]._pLevel;
|
|
if (item[i]._iPLFR < 0) item[i]._iPLFR = 0;
|
|
break;
|
|
case PL_NRFIRE:
|
|
item[i]._iPLFR -= r;
|
|
break;
|
|
case PL_NRLGHT:
|
|
item[i]._iPLLR -= r;
|
|
break;
|
|
case PL_NRMAG:
|
|
item[i]._iPLMR -= r;
|
|
break;
|
|
case PL_NRALL:
|
|
item[i]._iPLFR -= r;
|
|
item[i]._iPLLR -= r;
|
|
item[i]._iPLMR -= r;
|
|
break;
|
|
case PL_DEVAST:
|
|
item[i]._iFlags2 |= IAF2_DEVASTATION;
|
|
break;
|
|
case PL_DECAY:
|
|
item[i]._iFlags2 |= IAF2_DECAY;
|
|
item[i]._iPLDam += r;
|
|
break;
|
|
case PL_PERIL:
|
|
item[i]._iFlags2 |= IAF2_PERIL;
|
|
break;
|
|
case PL_RNDDAM:
|
|
item[i]._iFlags2 |= IAF2_JESTER;
|
|
break;
|
|
|
|
case PL_DEMONAC:
|
|
item[i]._iFlags2 |= IAF2_DEMONAC;
|
|
break;
|
|
case PL_UNDEADAC:
|
|
item[i]._iFlags2 |= IAF2_UNDEADAC;
|
|
break;
|
|
|
|
case PL_ACOLYTE:
|
|
r2 = ((plr[myplr]._pMaxManaBase >> MANA_SHIFT) * 50 / 100);
|
|
item[i]._iPLMana -= (r2 << MANA_SHIFT);
|
|
item[i]._iPLHP += (r2 << HP_SHIFT);
|
|
break;
|
|
case PL_GLADIATR:
|
|
r2 = ((plr[myplr]._pMaxHPBase >> HP_SHIFT) * 40 / 100);
|
|
item[i]._iPLHP -= (r2 << HP_SHIFT);
|
|
item[i]._iPLMana += (r2 << MANA_SHIFT);
|
|
break;
|
|
}
|
|
if ((item[i]._iVAdd1 == 0) && (item[i]._iVMult1 == 0)) {
|
|
item[i]._iVAdd1 = PLVal(r, param1, param2, minval, maxval);
|
|
item[i]._iVMult1 = multval;
|
|
} else {
|
|
item[i]._iVAdd2 = PLVal(r, param1, param2, minval, maxval);
|
|
item[i]._iVMult2 = multval;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void GetItemPower(int i, int minlvl, int maxlvl, long flgs, BOOL onlygood)
|
|
{
|
|
int pre, post;
|
|
int l[256], nl;
|
|
int j, aii;
|
|
int preidx, sufidx;
|
|
char istr[128];
|
|
byte goe;
|
|
|
|
pre = random(23, 4); // Pre modifier (20%)
|
|
post = random(23, 3); // Post modifirer (66%)
|
|
// if no pre modifier, make sure post modifier
|
|
if ((pre != 0) && (post == 0)) {
|
|
if (random(23, 2)) post = 1;
|
|
else pre = 0;
|
|
}
|
|
|
|
preidx = -1;
|
|
sufidx = -1;
|
|
goe = 0;
|
|
|
|
// if not any only good item, then 67% chance of good, 33% chance of anything
|
|
if ((!onlygood) && (random(0, 3))) onlygood = TRUE;
|
|
|
|
if (pre == 0) {
|
|
nl = 0;
|
|
for (j = 0; PL_Prefix[j].PLPower != -1; j++) {
|
|
if (((PL_Prefix[j].PLIType & flgs) != 0) &&
|
|
(PL_Prefix[j].PLMinLvl >= minlvl) &&
|
|
(PL_Prefix[j].PLMinLvl <= maxlvl)
|
|
) {
|
|
if (onlygood && !PL_Prefix[j].PLOk) continue;
|
|
if ((flgs == PLF_STAFF) && (PL_Prefix[j].PLPower == PL_CHRG)) continue;
|
|
|
|
l[nl] = j;
|
|
nl++;
|
|
if (PL_Prefix[j].PLDouble) {
|
|
l[nl] = j;
|
|
nl++;
|
|
}
|
|
}
|
|
}
|
|
if (nl != 0) {
|
|
preidx = l[random(23, nl)];
|
|
sprintf(istr, "%s %s", PL_Prefix[preidx].PLName, item[i]._iIName);
|
|
strcpy(item[i]._iIName, istr);
|
|
item[i]._iMagical = IMAGIC_MAGIC;
|
|
SaveItemPower(i, PL_Prefix[preidx].PLPower, PL_Prefix[preidx].PLParam1, PL_Prefix[preidx].PLParam2, PL_Prefix[preidx].PLMinVal, PL_Prefix[preidx].PLMaxVal, PL_Prefix[preidx].PLMultVal);
|
|
item[i]._iPrePower = PL_Prefix[preidx].PLPower;
|
|
goe = PL_Prefix[preidx].PLGOE;
|
|
}
|
|
}
|
|
if (post != 0) {
|
|
nl = 0;
|
|
for (j = 0; PL_Suffix[j].PLPower != -1; j++) {
|
|
if (((PL_Suffix[j].PLIType & flgs) != 0) &&
|
|
(PL_Suffix[j].PLMinLvl >= minlvl) &&
|
|
(PL_Suffix[j].PLMinLvl <= maxlvl) &&
|
|
((goe | PL_Suffix[j].PLGOE) != 0x11)
|
|
) {
|
|
if (onlygood && !PL_Suffix[j].PLOk) continue;
|
|
|
|
l[nl] = j;
|
|
nl++;
|
|
}
|
|
}
|
|
if (nl != 0) {
|
|
sufidx = l[random(23, nl)];
|
|
sprintf(istr, "%s of %s", item[i]._iIName, PL_Suffix[sufidx].PLName);
|
|
strcpy(item[i]._iIName, istr);
|
|
item[i]._iMagical = IMAGIC_MAGIC;
|
|
SaveItemPower(i, PL_Suffix[sufidx].PLPower, PL_Suffix[sufidx].PLParam1, PL_Suffix[sufidx].PLParam2, PL_Suffix[sufidx].PLMinVal, PL_Suffix[sufidx].PLMaxVal, PL_Suffix[sufidx].PLMultVal);
|
|
item[i]._iSufPower = PL_Suffix[sufidx].PLPower;
|
|
}
|
|
}
|
|
if (!InfoFit(item[i]._iIName)) {
|
|
aii = item[i].IDidx;
|
|
if (AllItemsList[aii].iSName)
|
|
strcpy(item[i]._iIName, AllItemsList[aii].iSName);
|
|
else
|
|
item[i]._iName[0] = 0;
|
|
|
|
if (preidx != -1) {
|
|
sprintf(istr, "%s %s", PL_Prefix[preidx].PLName, item[i]._iIName);
|
|
strcpy(item[i]._iIName, istr);
|
|
}
|
|
if (sufidx != -1) {
|
|
sprintf(istr, "%s of %s", item[i]._iIName, PL_Suffix[sufidx].PLName);
|
|
strcpy(item[i]._iIName, istr);
|
|
}
|
|
}
|
|
if ((preidx != -1) || (sufidx != -1)) CalcItemValue(i);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void GetItemBonus(int i, int idata, int minlvl, int maxlvl, BOOL onlygood, bool SpellsOk)
|
|
{
|
|
if (item[i]._iClass == IC_GOLD) return;
|
|
if (minlvl > 25) minlvl = 25;
|
|
|
|
switch(item[i]._itype) {
|
|
case IT_SWORD :
|
|
case IT_AXE:
|
|
case IT_MACE:
|
|
GetItemPower(i, minlvl, maxlvl, PLF_WEAPON, onlygood);
|
|
break;
|
|
case IT_BOW:
|
|
GetItemPower(i, minlvl, maxlvl, PLF_BOW, onlygood);
|
|
break;
|
|
case IT_SHIELD:
|
|
GetItemPower(i, minlvl, maxlvl, PLF_SHIELD, onlygood);
|
|
break;
|
|
case IT_ARMOR:
|
|
case IT_HELM:
|
|
case IT_MARMOR:
|
|
case IT_HARMOR:
|
|
GetItemPower(i, minlvl, maxlvl, PLF_ARMOR, onlygood);
|
|
break;
|
|
case IT_STAFF:
|
|
if (SpellsOk)
|
|
GetStaffSpell(i, maxlvl, onlygood);
|
|
else
|
|
GetItemPower(i, minlvl, maxlvl, PLF_STAFF, onlygood);
|
|
break;
|
|
case IT_RING:
|
|
case IT_AMULET:
|
|
GetItemPower(i, minlvl, maxlvl, PLF_RING, onlygood);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SetupItem(int i)
|
|
{
|
|
int it;
|
|
|
|
DROPLOG("SetupItem: setting up object %d!\n",i);
|
|
|
|
it = ItemCAnimTbl[item[i]._iCurs];
|
|
item[i]._iAnimData = itemanims[it];
|
|
item[i]._iAnimLen = ItemAnimLs[it];
|
|
item[i]._iAnimWidth = 96;
|
|
item[i]._iAnimWidth2 = 16;
|
|
item[i]._iIdentified = FALSE;
|
|
item[i]._iPostDraw = FALSE;
|
|
if (plr[myplr].pLvlLoad == LVLCHANGE_OFF) {
|
|
item[i]._iAnimFrame = 1;
|
|
item[i]._iAnimFlag = TRUE;
|
|
item[i]._iSelFlag = ISEL_NONE;
|
|
} else {
|
|
item[i]._iAnimFrame = item[i]._iAnimLen;
|
|
item[i]._iAnimFlag = FALSE;
|
|
item[i]._iSelFlag = ISEL_FLR;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** Choose an item type from a monster
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int RndItem(int m)
|
|
{
|
|
int r;
|
|
int ril[512]; // Max 512 items
|
|
int ri, i;
|
|
|
|
// Unique item?
|
|
if (monster[m].MData->mTreasure & T_U)
|
|
return(-((monster[m].MData->mTreasure & T_MASK) + 1));
|
|
|
|
if (monster[m].MData->mTreasure & T_NONE) return(0);
|
|
|
|
#if CHEATS
|
|
if (davedebug) r = 100;
|
|
else r = random(24, 100);
|
|
if (!cheatflag && (r > 40)) return(0);
|
|
if (!cheatflag && (random(24, 100) > 25)) return(IDI_GOLD+1);
|
|
#else
|
|
r = random(24, 100);
|
|
if (r > 40) return(0);
|
|
// Gold 75% of the time
|
|
if (random(24, 100) > 25) return(IDI_GOLD+1);
|
|
#endif
|
|
|
|
ri = 0;
|
|
for (i = 0; AllItemsList[i].iLoc != -1; i++) {
|
|
if ((AllItemsList[i].iRnd == IRND_DOUBLE) &&
|
|
(monster[m].mLevel >= AllItemsList[i].iMinMLvl)
|
|
&& ri < 512) ril[ri++] = i;
|
|
if (AllItemsList[i].iRnd &&
|
|
(monster[m].mLevel >= AllItemsList[i].iMinMLvl)
|
|
&& ri < 512) ril[ri++] = i;
|
|
if (AllItemsList[i].iSpell == SPL_RESURRECT && gbMaxPlayers == 1) ri--;
|
|
if (AllItemsList[i].iSpell == SPL_HEALOTHER && gbMaxPlayers == 1) ri--;
|
|
}
|
|
r = random(24, ri);
|
|
return(ril[r]+1);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** Choose an item type for a good or unique item
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int RndUItem(int m)
|
|
{
|
|
int ril[512]; // Max 512 items
|
|
int ri, i;
|
|
BOOL okflag;
|
|
|
|
// Unique item?
|
|
if (m != -1) {
|
|
if ((monster[m].MData->mTreasure & T_U) && (gbMaxPlayers == 1))
|
|
return(-((monster[m].MData->mTreasure & T_MASK) + 1));
|
|
}
|
|
int efflevel = GetEffLevel();
|
|
|
|
ri = 0;
|
|
for (i = 0; AllItemsList[i].iLoc != -1; i++) {
|
|
okflag = TRUE;
|
|
if (!AllItemsList[i].iRnd) okflag = FALSE;
|
|
if (m != -1) {
|
|
if (monster[m].mLevel < AllItemsList[i].iMinMLvl) okflag = FALSE;
|
|
} else {
|
|
if ((efflevel << 1) < AllItemsList[i].iMinMLvl) okflag = FALSE;
|
|
}
|
|
if (AllItemsList[i].itype == IT_MISC) okflag = FALSE;
|
|
if (AllItemsList[i].itype == IT_GOLD) okflag = FALSE;
|
|
if (AllItemsList[i].itype == IT_FOOD) okflag = FALSE;
|
|
if (AllItemsList[i].iMiscId == IMID_BOOK) okflag = TRUE;
|
|
if (AllItemsList[i].iSpell == SPL_RESURRECT && gbMaxPlayers == 1) okflag = FALSE;
|
|
if (AllItemsList[i].iSpell == SPL_HEALOTHER && gbMaxPlayers == 1) okflag = FALSE;
|
|
if (okflag && ri < 512) ril[ri++] = i;
|
|
}
|
|
return(ril[random(25, ri)]);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** Choose any type of item
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int RndAllItems()
|
|
{
|
|
int r;
|
|
int ril[512]; // Max 512 items
|
|
int ri, i;
|
|
|
|
#if CHEATS
|
|
if (!cheatflag && !itemcheat && (random(26, 100) > 25)) return(IDI_GOLD);
|
|
#else
|
|
// Gold 75% of the time
|
|
if (random(26, 100) > 25) return(IDI_GOLD);
|
|
#endif
|
|
int efflevel = GetEffLevel();
|
|
|
|
ri = 0;
|
|
for (i = 0; AllItemsList[i].iLoc != -1; i++) {
|
|
if (AllItemsList[i].iRnd && ((efflevel << 1) >= AllItemsList[i].iMinMLvl)
|
|
&& ri < 512) ril[ri++] = i;
|
|
if (AllItemsList[i].iSpell == SPL_RESURRECT && gbMaxPlayers == 1) ri--;
|
|
if (AllItemsList[i].iSpell == SPL_HEALOTHER && gbMaxPlayers == 1) ri--;
|
|
}
|
|
r = random(26, ri);
|
|
return(ril[r]);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** Choose an item of a specific type
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int RndTypeItems(int itype, int imid, int level)
|
|
{
|
|
int ril[512]; // Max 512 items
|
|
int ri, i;
|
|
BOOL okflag;
|
|
|
|
ri = 0;
|
|
for (i = 0; AllItemsList[i].iLoc != -1; i++) {
|
|
okflag = TRUE;
|
|
if (!AllItemsList[i].iRnd) okflag = FALSE;
|
|
if ((level << 1) < AllItemsList[i].iMinMLvl) okflag = FALSE;
|
|
if (AllItemsList[i].itype != itype) okflag = FALSE;
|
|
if ((imid != -1) && (AllItemsList[i].iMiscId != imid)) okflag = FALSE;
|
|
if (okflag && ri < 512)
|
|
ril[ri++] = i;
|
|
}
|
|
return(ril[random(27, ri)]);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int CheckUnique(int i, int lvl, int uper, BOOL recreate)
|
|
{
|
|
int j, idata;
|
|
BYTE uok[MAXUITEMS];
|
|
int numu, u;
|
|
|
|
#if CHEATS
|
|
if (!davedebug || !cheatflag) {
|
|
if (random(28, 100) > uper) return(-1);
|
|
}
|
|
#else
|
|
if (random(28, 100) > uper) return(-1);
|
|
#endif
|
|
|
|
numu = 0;
|
|
ZeroMemory(uok,sizeof(uok));
|
|
for (j = 0; UniqueItemList[j].UIItemId != -1; j++) {
|
|
idata = item[i].IDidx;
|
|
if (UniqueItemList[j].UIItemId != AllItemsList[idata].iItemId) continue;
|
|
if (lvl < UniqueItemList[j].UIMinLvl) continue;
|
|
if (!recreate && UniqueItemFlag[j] && (gbMaxPlayers == 1)) continue;
|
|
uok[j] = TRUE;
|
|
numu++;
|
|
}
|
|
|
|
if (numu == 0) return(-1);
|
|
u = random(29, 10);
|
|
j = 0;
|
|
while (numu > 0) {
|
|
if (uok[j]) numu--;
|
|
if (numu > 0) {
|
|
j++;
|
|
if (j == MAXUITEMS) j = 0;
|
|
}
|
|
}
|
|
return(j);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void GetUniqueItem(int i, int uid)
|
|
{
|
|
// Generated
|
|
UniqueItemFlag[uid] = TRUE;
|
|
// Save abilities
|
|
SaveItemPower(i, UniqueItemList[uid].UIPower1, UniqueItemList[uid].UIParam1, UniqueItemList[uid].UIParam2, 0, 0, 1);
|
|
if (UniqueItemList[uid].UINumPL > 1)
|
|
SaveItemPower(i, UniqueItemList[uid].UIPower2, UniqueItemList[uid].UIParam3, UniqueItemList[uid].UIParam4, 0, 0, 1);
|
|
if (UniqueItemList[uid].UINumPL > 2)
|
|
SaveItemPower(i, UniqueItemList[uid].UIPower3, UniqueItemList[uid].UIParam5, UniqueItemList[uid].UIParam6, 0, 0, 1);
|
|
if (UniqueItemList[uid].UINumPL > 3)
|
|
SaveItemPower(i, UniqueItemList[uid].UIPower4, UniqueItemList[uid].UIParam7, UniqueItemList[uid].UIParam8, 0, 0, 1);
|
|
if (UniqueItemList[uid].UINumPL > 4)
|
|
SaveItemPower(i, UniqueItemList[uid].UIPower5, UniqueItemList[uid].UIParam9, UniqueItemList[uid].UIParam10, 0, 0, 1);
|
|
if (UniqueItemList[uid].UINumPL > 5)
|
|
SaveItemPower(i, UniqueItemList[uid].UIPower6, UniqueItemList[uid].UIParam11, UniqueItemList[uid].UIParam12, 0, 0, 1);
|
|
// Save name
|
|
strcpy(item[i]._iIName, UniqueItemList[uid].UIName);
|
|
item[i]._iIvalue = UniqueItemList[uid].UIValue;
|
|
if (item[i]._iMiscId == IMID_UNIQUE) item[i]._iSeed = uid; // Save index into UniqueItemList
|
|
item[i]._iUid = uid; // Save index into Unique Item List
|
|
item[i]._iMagical = IMAGIC_UNIQUE;
|
|
item[i]._iCreateInfo |= ICI_UNIQUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SpawnUnique(int uid, int x, int y)
|
|
{
|
|
int ii, itype;
|
|
|
|
int efflevel = GetEffLevel();
|
|
|
|
if (numitems < MAXITEMS) {
|
|
ii = itemavail[0];
|
|
GetSuperItemSpace(x,y,ii);
|
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1];
|
|
itemactive[numitems] = ii;
|
|
itype = 0;
|
|
while (AllItemsList[itype].iItemId != UniqueItemList[uid].UIItemId) itype++;
|
|
GetItemAttrs(ii, itype, efflevel);
|
|
GetUniqueItem(ii, uid);
|
|
SetupItem(ii);
|
|
numitems++;
|
|
}
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** Items in dungeon have lower durs
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void ItemRndDur(int ii)
|
|
{
|
|
if (item[ii]._iDurability == 0) return;
|
|
if (item[ii]._iDurability == INFINITE_DUR) return;
|
|
item[ii]._iDurability = random(0, item[ii]._iMaxDur >> 1) + (item[ii]._iMaxDur >> 2) + 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** Setup an item and determine magics
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SetupAllItems(int ii, int idx, int iseed, int lvl, int uper, BOOL onlygood, BOOL recreate, BOOL pregen)
|
|
{
|
|
int iblvl, uid;
|
|
|
|
item[ii]._iSeed = iseed;
|
|
SetRndSeed(iseed);
|
|
GetItemAttrs(ii, idx, lvl >> 1);
|
|
item[ii]._iCreateInfo = lvl;
|
|
if (pregen) item[ii]._iCreateInfo |= ICI_PREGEN;
|
|
if (onlygood) item[ii]._iCreateInfo |= ICI_ONLYGOOD;
|
|
if (uper == 15) item[ii]._iCreateInfo |= ICI_UPER15;
|
|
else if (uper == 1) item[ii]._iCreateInfo |= ICI_UPER1;
|
|
if (item[ii]._iMiscId != IMID_UNIQUE) {
|
|
iblvl = -1;
|
|
if (random(32, 100) <= 10) iblvl = lvl;
|
|
else if (random(33, 100) <= lvl) iblvl = lvl;
|
|
// Force rings, amulets, and staffs to be magical
|
|
if ((iblvl == -1) && (item[ii]._iMiscId == IMID_STAFF)) iblvl = lvl;
|
|
if ((iblvl == -1) && (item[ii]._iMiscId == IMID_RING)) iblvl = lvl;
|
|
if ((iblvl == -1) && (item[ii]._iMiscId == IMID_AMULET)) iblvl = lvl;
|
|
if (onlygood) iblvl = lvl;
|
|
#if CHEATS
|
|
if (cheatflag) iblvl = lvl;
|
|
#endif
|
|
if (uper == 15) iblvl = lvl + 4;
|
|
if (iblvl != -1) {
|
|
uid = CheckUnique(ii, iblvl, uper, recreate);
|
|
if (uid == -1)
|
|
GetItemBonus(ii, idx, iblvl >> 1, iblvl, onlygood, true);
|
|
else {
|
|
GetUniqueItem(ii, uid);
|
|
item[ii]._iCreateInfo |= ICI_UNIQUE;
|
|
}
|
|
}
|
|
if (item[ii]._iMagical != IMAGIC_UNIQUE) ItemRndDur(ii);
|
|
} else {
|
|
// if it is something they wield, then get the attributes
|
|
if (item[ii]._iLoc != IL_INV) GetUniqueItem(ii, iseed);
|
|
}
|
|
SetupItem(ii);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** Create any item from a monster (or unqiue if monster gives one up)
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SpawnItem(int m, int x, int y, BOOL sendmsg)
|
|
{
|
|
int ii, idx;
|
|
BOOL onlygood;
|
|
|
|
if ((monster[m]._uniqtype != 0) ||
|
|
((monster[m].MData->mTreasure & T_U) && (gbMaxPlayers != 1))) {
|
|
// If unique, make sure we get something good
|
|
idx = RndUItem(m);
|
|
if (idx < 0) {
|
|
SpawnUnique(-(idx+1), x, y);
|
|
return;
|
|
}
|
|
onlygood = TRUE;
|
|
} else {
|
|
// special code to pop out brain for Mushroom Quest
|
|
if (quests[Q_BKMUSHRM]._qactive == QUEST_NOTDONE
|
|
&& quests[Q_BKMUSHRM]._qvar1 == QS_MUSHGIVEN) {
|
|
idx = IDI_BRAIN;
|
|
quests[Q_BKMUSHRM]._qvar1 = QS_BRAINSPAWNED;
|
|
}
|
|
else
|
|
{
|
|
idx = RndItem(m);
|
|
if (idx == 0) return;
|
|
if (idx > 0) {
|
|
idx--;
|
|
onlygood = FALSE;
|
|
} else {
|
|
SpawnUnique(-(idx+1), x, y);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
if (numitems < MAXITEMS) {
|
|
ii = itemavail[0];
|
|
GetSuperItemSpace(x,y,ii);
|
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1];
|
|
itemactive[numitems] = ii;
|
|
if (monster[m]._uniqtype != 0) SetupAllItems(ii, idx, GetRndSeed(), monster[m].MData->mLevel, 15, onlygood, FALSE, FALSE);
|
|
#if CHEATS
|
|
else if (itemcheat)
|
|
SetupAllItems(ii, idx, GetRndSeed(), monster[m].MData->mLevel, 15, TRUE, FALSE, FALSE);
|
|
#endif
|
|
else SetupAllItems(ii, idx, GetRndSeed(), monster[m].MData->mLevel, 1, onlygood, FALSE, FALSE);
|
|
|
|
numitems++;
|
|
if (sendmsg) NetSendCmdDItem(FALSE, ii);
|
|
}
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** Only used for quest (single player)
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void CreateItem(int uid, int x, int y)
|
|
{
|
|
int ii, idx;
|
|
|
|
int efflevel = GetEffLevel();
|
|
|
|
if (numitems < MAXITEMS) {
|
|
ii = itemavail[0];
|
|
GetSuperItemSpace(x,y,ii);
|
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1];
|
|
itemactive[numitems] = ii;
|
|
idx = 0;
|
|
while (AllItemsList[idx].iItemId != UniqueItemList[uid].UIItemId) idx++;
|
|
GetItemAttrs(ii, idx, efflevel);
|
|
GetUniqueItem(ii, uid);
|
|
SetupItem(ii);
|
|
item[ii]._iMagical = IMAGIC_UNIQUE;
|
|
numitems++;
|
|
}
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** Create any item from an object, etc (chest, barrel, sarc)
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void CreateRndItem(int x, int y, BOOL onlygood, BOOL sendmsg, BOOL delta)
|
|
{
|
|
int ii, idx;
|
|
|
|
int efflevel = GetEffLevel();
|
|
|
|
if (onlygood) idx = RndUItem(-1);
|
|
else idx = RndAllItems();
|
|
if (numitems < MAXITEMS) {
|
|
ii = itemavail[0];
|
|
GetSuperItemSpace(x,y,ii);
|
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1];
|
|
itemactive[numitems] = ii;
|
|
#if CHEATS
|
|
if (itemcheat)
|
|
SetupAllItems(ii, idx, GetRndSeed(), efflevel << 1, 15, TRUE, FALSE, delta);
|
|
else
|
|
#endif
|
|
SetupAllItems(ii, idx, GetRndSeed(), efflevel << 1, 1, onlygood, FALSE, delta);
|
|
if (sendmsg) NetSendCmdDItem(FALSE, ii);
|
|
if (delta) DeltaAddItem(ii);
|
|
numitems++;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SetupAllUseful(int ii, int iseed, int lvl)
|
|
{
|
|
int idx;
|
|
|
|
item[ii]._iSeed = iseed;
|
|
SetRndSeed(iseed);
|
|
|
|
#if 0
|
|
if (random(34, 2)) idx = IDI_HEAL;
|
|
else idx = IDI_MANA;
|
|
|
|
// added 7/30/97 by donald
|
|
if (!random(34, 8)) idx = IDI_OILACC;
|
|
|
|
if ((lvl > 1) && (random(34, 3) == 0)) idx = IDI_PORTAL;
|
|
#else
|
|
// why call random() so many times?
|
|
|
|
switch(random(34,7))
|
|
{
|
|
case 0: idx = IDI_PORTAL; if (lvl > 1) break; // else fallthrough
|
|
case 1:
|
|
case 2: idx = IDI_HEAL; break;
|
|
case 3: idx = IDI_PORTAL; if (lvl > 1) break; // else fallthrough
|
|
case 4:
|
|
case 5: idx = IDI_MANA; break;
|
|
default:idx = IDI_OILACC; break;
|
|
}
|
|
#endif
|
|
|
|
GetItemAttrs(ii, idx, lvl);
|
|
item[ii]._iCreateInfo = ICI_USEFUL + lvl;
|
|
SetupItem(ii);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** Rnd item, but only health, mana, or id
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void CreateRndUseful(int pnum, int x, int y, BOOL sendmsg)
|
|
{
|
|
int ii;
|
|
|
|
int efflevel = GetEffLevel();
|
|
|
|
if (numitems < MAXITEMS) {
|
|
ii = itemavail[0];
|
|
GetSuperItemSpace(x,y,ii);
|
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1];
|
|
itemactive[numitems] = ii;
|
|
SetupAllUseful(ii, GetRndSeed(), efflevel);
|
|
if (sendmsg) NetSendCmdDItem(FALSE, ii);
|
|
numitems++;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** Create any item of a specific type
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void CreateTypeItem(int x, int y, BOOL onlygood, int itype, int imisc, BOOL sendmsg, BOOL delta)
|
|
{
|
|
int ii, idx;
|
|
|
|
int efflevel = GetEffLevel();
|
|
|
|
if (itype != IT_GOLD) idx = RndTypeItems(itype, imisc, efflevel);
|
|
else idx = 0;
|
|
if (numitems < MAXITEMS) {
|
|
ii = itemavail[0];
|
|
GetSuperItemSpace(x,y,ii);
|
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1];
|
|
itemactive[numitems] = ii;
|
|
#if CHEATS
|
|
if (itemcheat)
|
|
SetupAllItems(ii, idx, GetRndSeed(), efflevel << 1, 15, TRUE, FALSE, delta);
|
|
else
|
|
#endif
|
|
SetupAllItems(ii, idx, GetRndSeed(), efflevel << 1, 1, onlygood, FALSE, delta);
|
|
if (sendmsg) NetSendCmdDItem(FALSE, ii);
|
|
if (delta) DeltaAddItem(ii);
|
|
numitems++;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** Recreate any item with the proper info
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void RecreateItem(int ii, int idx, WORD icreateinfo, int iseed, int ivalue)
|
|
{
|
|
int uper;
|
|
BOOL onlygood, uavail, pregen;
|
|
|
|
// PATCH1.JMM
|
|
#if 0
|
|
int i, nIndex;
|
|
for(i = 0; i < numitems; i++) {
|
|
nIndex = itemactive[i];
|
|
|
|
if(((item[nIndex]._iSeed == iseed) && (item[nIndex]._iCreateInfo == icreateinfo) && (item[nIndex].IDidx == idx)))
|
|
DROPLOG(" Creating dupped item: idx->%8.8x seed->%8.8x ci->%8.8x\n",idx,iseed,icreateinfo);
|
|
|
|
app_assert(!((item[nIndex]._iSeed == iseed) && (item[nIndex]._iCreateInfo == icreateinfo) && (item[nIndex].IDidx == idx)));
|
|
}
|
|
#endif
|
|
// ENDPATCH1.JMM
|
|
|
|
|
|
// Gold
|
|
if (idx == IDI_GOLD) {
|
|
SetPlrHandItem(&item[ii], idx);
|
|
item[ii]._iSeed = iseed;
|
|
item[ii]._iCreateInfo = icreateinfo;
|
|
item[ii]._ivalue = ivalue;
|
|
if (item[ii]._ivalue >= GOLD_VT2) {
|
|
item[ii]._iCurs = ITEM_5GOLD;
|
|
} else {
|
|
if (ivalue <= GOLD_VT1) item[ii]._iCurs = ITEM_1GOLD;
|
|
else item[ii]._iCurs = ITEM_3GOLD;
|
|
}
|
|
} else {
|
|
// One the the players initial items?
|
|
if (icreateinfo == 0) {
|
|
SetPlrHandItem(&item[ii], idx);
|
|
SetPlrHandSeed(&item[ii], iseed);
|
|
} else {
|
|
// From town?
|
|
if (icreateinfo & ICI_TOWNMASK) RecreateTownItem(ii, idx, icreateinfo, iseed, ivalue);
|
|
else {
|
|
// From dungeon
|
|
if ((icreateinfo & ICI_USEFUL) == ICI_USEFUL) {
|
|
SetupAllUseful(ii, iseed, icreateinfo & ICI_LVLMASK);
|
|
} else {
|
|
uper = 0;
|
|
onlygood = FALSE;
|
|
uavail = FALSE;
|
|
pregen = FALSE;
|
|
if (icreateinfo & ICI_UPER1) uper = 1;
|
|
if (icreateinfo & ICI_UPER15) uper = 15;
|
|
if (icreateinfo & ICI_ONLYGOOD) onlygood = TRUE;
|
|
if (icreateinfo & ICI_UNIQUE) uavail = TRUE;
|
|
if (icreateinfo & ICI_PREGEN) pregen = TRUE;
|
|
SetupAllItems(ii, idx, iseed, icreateinfo & ICI_LVLMASK, uper, onlygood, uavail, pregen);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** Recreate any ear with the proper info
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void RecreateEar(int ii, WORD ic, int iseed, BOOL Id, int dur, int mdur, int ch, int mch, int ivalue, int ibuff)
|
|
{
|
|
SetPlrHandItem(&item[ii], IDI_EAR);
|
|
tempstr[0] = (ic >> 8) & 0x7f;
|
|
tempstr[1] = ic & 0x7f;
|
|
tempstr[2] = (iseed >> 24) & 0x7f;
|
|
tempstr[3] = (iseed >> 16) & 0x7f;
|
|
tempstr[4] = (iseed >> 8) & 0x7f;
|
|
tempstr[5] = iseed & 0x7f;
|
|
tempstr[6] = Id & 0x7f;
|
|
tempstr[7] = dur & 0x7f;
|
|
tempstr[8] = mdur & 0x7f;
|
|
tempstr[9] = ch & 0x7f;
|
|
tempstr[10] = mch & 0x7f;
|
|
tempstr[11] = (ivalue >> 8) & 0x7f;
|
|
tempstr[12] = (ibuff >> 24) & 0x7f;
|
|
tempstr[13] = (ibuff >> 16) & 0x7f;
|
|
tempstr[14] = (ibuff >> 8) & 0x7f;
|
|
tempstr[15] = ibuff & 0x7f;
|
|
tempstr[16] = 0;
|
|
sprintf(item[ii]._iName, "Ear of %s", tempstr);
|
|
item[ii]._iCurs = ((ivalue >> 6) & 0x3) + ITEM_EAR1;
|
|
item[ii]._ivalue = ivalue & 0x3f;
|
|
item[ii]._iCreateInfo = ic;
|
|
item[ii]._iSeed = iseed;
|
|
}
|
|
|
|
|
|
const char * sgszCornerstone = "SItem";
|
|
|
|
void CornerstoneSave()
|
|
{
|
|
if (!CornerStone.Initted)
|
|
return;
|
|
|
|
PkItemStruct pki;
|
|
|
|
if (CornerStone.item.IDidx >= 0)
|
|
{
|
|
PackItem(&pki, &(CornerStone.item));
|
|
SRegSaveData(gszProgKey,sgszCornerstone,0, &pki, sizeof(PkItemStruct));
|
|
}
|
|
else
|
|
{
|
|
SRegSaveData(gszProgKey,sgszCornerstone, 0, "", 1);
|
|
}
|
|
}
|
|
|
|
void CornerstoneRestore(int x, int y)
|
|
{
|
|
if (CornerStone.Initted)
|
|
return;
|
|
|
|
// read the info out of the options file
|
|
PkItemStruct pki;
|
|
|
|
if (x == 0 || y == 0)
|
|
return;
|
|
|
|
CornerStone.item.IDidx = 0;
|
|
CornerStone.Initted = TRUE;
|
|
|
|
if (dItem[x][y] != 0)
|
|
{
|
|
// clear the square
|
|
int ii = dItem[x][y] - 1;
|
|
for (int i = 0; i < numitems; ++i)
|
|
if (itemactive[i] == ii)
|
|
{
|
|
DeleteItem(ii, i);
|
|
break;
|
|
}
|
|
dItem[x][y] = 0;
|
|
}
|
|
|
|
DWORD bytesread = 0;
|
|
if (! SRegLoadData(gszProgKey,sgszCornerstone, 0, &pki, sizeof(PkItemStruct), &bytesread))
|
|
return;
|
|
|
|
if (bytesread != sizeof(PkItemStruct))
|
|
return;
|
|
|
|
// create a new item slot
|
|
int ii = itemavail[0];
|
|
dItem[x][y] = ii+1;
|
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1];
|
|
itemactive[numitems] = ii;
|
|
|
|
UnPackItem(&pki, &item[ii]);
|
|
item[ii]._ix = x;
|
|
item[ii]._iy = y;
|
|
|
|
DROPLOG("CornerstoneRestore: respawning object %d!\n",ii);
|
|
RespawnItem(ii, FALSE);
|
|
CornerStone.item = item[ii];
|
|
|
|
numitems++;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SpawnQuestItem(int itemid, int x,int y, int randarea, int selflag)
|
|
{
|
|
int i,j;
|
|
BOOL failed;
|
|
|
|
int efflevel = GetEffLevel();
|
|
|
|
if (randarea) {
|
|
int tries = 0;
|
|
do {
|
|
if (++tries > 1000 && randarea > 1)
|
|
--randarea;
|
|
x = random(0, DMAXX);
|
|
y = random(0, DMAXY);
|
|
failed = FALSE;
|
|
for (i = 0; i < randarea && !failed; i++)
|
|
for (j = 0; j < randarea && !failed; j++)
|
|
failed = !ItemSpaceOk(x + i, y + j);
|
|
} while (failed);
|
|
}
|
|
|
|
if (numitems < MAXITEMS) {
|
|
i = itemavail[0];
|
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1];
|
|
itemactive[numitems] = i;
|
|
item[i]._ix = x;
|
|
item[i]._iy = y;
|
|
dItem[x][y] = i + 1;
|
|
GetItemAttrs(i, itemid, efflevel);
|
|
SetupItem(i);
|
|
item[i]._iPostDraw = TRUE;
|
|
if (selflag != ISEL_NONE) {
|
|
// selflag indicates creation of post-flippy item
|
|
item[i]._iSelFlag = selflag;
|
|
item[i]._iAnimFrame = item[i]._iAnimLen;
|
|
item[i]._iAnimFlag = FALSE;
|
|
}
|
|
|
|
numitems++;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void SpawnRock()
|
|
{
|
|
int i, ii, ostand;
|
|
int xx,yy;
|
|
BOOL done = FALSE;
|
|
|
|
for (i = 0; i < numobjects && !done; i++) {
|
|
ostand = objectactive[i];
|
|
done = (object[ostand]._otype == 23); // OBJ_STAND
|
|
}
|
|
|
|
int efflevel = GetEffLevel();
|
|
|
|
if(done)
|
|
{
|
|
ii = itemavail[0];
|
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1];
|
|
itemactive[numitems] = ii;
|
|
xx = item[ii]._ix = object[ostand]._ox;
|
|
yy = item[ii]._iy = object[ostand]._oy;
|
|
dItem[xx][yy] = ii + 1;
|
|
GetItemAttrs(ii, IDI_ROCK, efflevel);
|
|
SetupItem(ii);
|
|
item[ii]._iSelFlag = ISEL_TOP;
|
|
item[ii]._iPostDraw = TRUE;
|
|
item[ii]._iAnimFrame = 11;
|
|
|
|
numitems++;
|
|
}
|
|
}
|
|
|
|
void SpawnSomething(int what, int xx, int yy)
|
|
{
|
|
int ii = itemavail[0];
|
|
|
|
int efflevel = GetEffLevel();
|
|
|
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1];
|
|
itemactive[numitems] = ii;
|
|
item[ii]._ix = xx;
|
|
item[ii]._iy = yy;
|
|
dItem[xx][yy] = ii + 1;
|
|
GetItemAttrs(ii, what, efflevel);
|
|
SetupItem(ii);
|
|
item[ii]._iSelFlag = ISEL_TOP;
|
|
item[ii]._iPostDraw = TRUE;
|
|
item[ii]._iAnimFrame = 1; // item[ii]._iAnimLen;
|
|
item[ii]._iAnimFlag = TRUE;
|
|
item[ii]._iIdentified = TRUE;
|
|
|
|
numitems++;
|
|
}
|
|
|
|
void SpawnMap(int xx, int yy)
|
|
{
|
|
SpawnSomething(IDI_MAPOFDOOM, xx, yy);
|
|
}
|
|
|
|
void SpawnBomb(int xx, int yy)
|
|
{
|
|
SpawnSomething(IDI_RUNEBOMB, xx, yy);
|
|
}
|
|
|
|
void SpawnBear(int xx, int yy)
|
|
{
|
|
SpawnSomething(IDI_THEODORE, xx, yy);
|
|
}
|
|
|
|
void SpawnCowArmor(int xx, int yy)
|
|
{
|
|
CreateItem(UID_ARMRCOW, xx, yy);
|
|
}
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void RespawnItem(int i, BOOL FlipFlag)
|
|
{
|
|
int it;
|
|
|
|
DROPLOG(" RespawnItem: Respawning item %d!\n",i);
|
|
|
|
it = ItemCAnimTbl[item[i]._iCurs];
|
|
item[i]._iAnimData = itemanims[it];
|
|
item[i]._iAnimLen = ItemAnimLs[it];
|
|
item[i]._iAnimWidth = 96;
|
|
item[i]._iAnimWidth2 = 16;
|
|
item[i]._iPostDraw = FALSE;
|
|
item[i]._iRequest = FALSE;
|
|
if (FlipFlag) {
|
|
item[i]._iAnimFrame = 1;
|
|
item[i]._iAnimFlag = TRUE;
|
|
item[i]._iSelFlag = ISEL_NONE;
|
|
} else {
|
|
item[i]._iAnimFrame = item[i]._iAnimLen;
|
|
item[i]._iAnimFlag = FALSE;
|
|
item[i]._iSelFlag = ISEL_FLR;
|
|
}
|
|
if (item[i]._iCurs == ITEM_ROCK) {
|
|
item[i]._iSelFlag = ISEL_FLR;
|
|
PlaySfxLoc(ItemAnimSnds[it], item[i]._ix, item[i]._iy);
|
|
}
|
|
if (item[i]._iCurs == ITEM_INNSIGN) item[i]._iSelFlag = ISEL_FLR;
|
|
if (item[i]._iCurs == ITEM_ANVIL) item[i]._iSelFlag = ISEL_FLR;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void DeleteItem(int ii, int i)
|
|
{
|
|
itemavail[MAXITEMS - numitems] = ii;
|
|
numitems--;
|
|
if ((numitems > 0) && (i != numitems)) {
|
|
itemactive[i] = itemactive[numitems];
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int idoppely = DIRTEDGED2;
|
|
|
|
void ItemDoppel()
|
|
{
|
|
int idoppelx;
|
|
ItemStruct *i;
|
|
|
|
if (gbMaxPlayers == 1) return;
|
|
|
|
for (idoppelx = DIRTEDGED2; idoppelx < (DIRTEDGED2+80); idoppelx++) {
|
|
if (dItem[idoppelx][idoppely]) {
|
|
i = &item[dItem[idoppelx][idoppely] - 1];
|
|
if ((i->_ix != idoppelx) || (i->_iy != idoppely))
|
|
dItem[idoppelx][idoppely] = 0;
|
|
}
|
|
}
|
|
idoppely++;
|
|
if (idoppely == DIRTEDGED2+80) idoppely = DIRTEDGED2;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void ProcessItems()
|
|
{
|
|
int i, ii, it;
|
|
|
|
VerifyItemActiveList();
|
|
|
|
for (i = 0; i < numitems; i++) {
|
|
ii = itemactive[i];
|
|
|
|
// Animate Spell GFX
|
|
if (item[ii]._iAnimFlag) {
|
|
item[ii]._iAnimFrame++;
|
|
if (item[ii]._iCurs == ITEM_ROCK) {
|
|
if ((item[ii]._iSelFlag == ISEL_FLR) && (item[ii]._iAnimFrame == 11))
|
|
item[ii]._iAnimFrame = 1;
|
|
if ((item[ii]._iSelFlag == ISEL_TOP) && (item[ii]._iAnimFrame == 21))
|
|
item[ii]._iAnimFrame = 11;
|
|
} else {
|
|
if (item[ii]._iAnimFrame == (item[ii]._iAnimLen >> 1)) {
|
|
it = ItemCAnimTbl[item[ii]._iCurs];
|
|
PlaySfxLoc(ItemAnimSnds[it], item[ii]._ix, item[ii]._iy);
|
|
}
|
|
if (item[ii]._iAnimFrame >= item[ii]._iAnimLen) {
|
|
item[ii]._iAnimFrame = item[ii]._iAnimLen;
|
|
item[ii]._iAnimFlag = FALSE;
|
|
item[ii]._iSelFlag = ISEL_FLR;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ItemDoppel();
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void FreeItemGFX()
|
|
{
|
|
for (int i = 0; i < ITEMFTYPES; i++)
|
|
DiabloFreePtr(itemanims[i]);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SyncItemAnim(int ii)
|
|
{
|
|
int a;
|
|
|
|
a = ItemCAnimTbl[item[ii]._iCurs];
|
|
item[ii]._iAnimData = itemanims[a];
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void GetItemStr(int i) {
|
|
|
|
switch (item[i]._itype) {
|
|
case IT_GOLD: {
|
|
int nGold = item[i]._ivalue;
|
|
const char * get_pieces_str(int nGold);
|
|
sprintf(infostr,"%i gold %s",nGold,get_pieces_str(nGold));
|
|
}
|
|
break;
|
|
|
|
default :
|
|
int s = item[i]._itype;
|
|
if (item[i]._iIdentified) strcpy(infostr, item[i]._iIName);
|
|
else strcpy(infostr, item[i]._iName);
|
|
if (item[i]._iMagical == IMAGIC_MAGIC) infoclr = ICOLOR_BLUE;
|
|
if (item[i]._iMagical == IMAGIC_UNIQUE) infoclr = ICOLOR_GOLD;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void CheckIdentify(int pnum, int cii) {
|
|
ItemStruct * pi;
|
|
if (cii < NUM_INVLOC)
|
|
pi = &plr[pnum].InvBody[cii];
|
|
else
|
|
pi = &plr[pnum].InvList[cii - NUM_INVLOC];
|
|
pi->_iIdentified = TRUE;
|
|
CalcPlrInv(pnum,TRUE);
|
|
|
|
if (pnum == myplr)
|
|
NewCursor(GLOVE_CURS);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
static void RepairItem(ItemStruct *i, int lvl) {
|
|
int d, rep;
|
|
|
|
if (i->_iDurability == i->_iMaxDur) return;
|
|
// If item already has zero durability, wipe it out
|
|
if (i->_iMaxDur <= 0) {
|
|
i->_itype = -1;
|
|
return;
|
|
}
|
|
rep = 0;
|
|
do {
|
|
rep += random(37, lvl) + lvl;
|
|
d = i->_iMaxDur / (9 + lvl);
|
|
if (d < 1) d = 1;
|
|
i->_iMaxDur -= d;
|
|
// If I have no max durability, break
|
|
if (i->_iMaxDur == 0) {
|
|
i->_itype = -1;
|
|
return;
|
|
}
|
|
} while ((i->_iDurability + rep) < i->_iMaxDur);
|
|
i->_iDurability += rep;
|
|
if (i->_iDurability > i->_iMaxDur)
|
|
i->_iDurability = i->_iMaxDur;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void DoRepair(int pnum, int cii) {
|
|
PlayerStruct * p = &plr[pnum];
|
|
PlaySfxLoc(IS_REPAIR, p->_px, p->_py);
|
|
|
|
ItemStruct * pi;
|
|
if (cii < NUM_INVLOC)
|
|
pi = &p->InvBody[cii];
|
|
else
|
|
pi = &p->InvList[cii - NUM_INVLOC];
|
|
RepairItem(pi,p->_pLevel);
|
|
CalcPlrInv(pnum,TRUE);
|
|
|
|
if (pnum == myplr)
|
|
NewCursor(GLOVE_CURS);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
static void RechargeItem(ItemStruct *i, int r) {
|
|
if (i->_iCharges == i->_iMaxCharges) return;
|
|
|
|
do {
|
|
i->_iMaxCharges--;
|
|
if (i->_iMaxCharges == 0) {
|
|
//i->_itype = -1;
|
|
return;
|
|
}
|
|
i->_iCharges += r;
|
|
} while (i->_iCharges < i->_iMaxCharges);
|
|
|
|
if (i->_iCharges > i->_iMaxCharges) i->_iCharges = i->_iMaxCharges;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void DoRecharge(int pnum, int cii) {
|
|
PlayerStruct * p = &plr[pnum];
|
|
|
|
ItemStruct * pi;
|
|
if (cii < NUM_INVLOC) pi = &p->InvBody[cii];
|
|
else pi = &p->InvList[cii - NUM_INVLOC];
|
|
// rmw.patch1.start.1/14/97
|
|
// if (pi->_itype == IT_STAFF) {
|
|
if ((pi->_itype == IT_STAFF) && (pi->_iSpell != SPL_NONE)) {
|
|
// rmw.patch1.end.1/14/97
|
|
int sp = pi->_iSpell;
|
|
int r = spelldata[sp].sBookLvl;
|
|
r = random(38, p->_pLevel / r) + 1;
|
|
|
|
RechargeItem(pi, r);
|
|
CalcPlrInv(pnum, TRUE);
|
|
}
|
|
|
|
if (pnum == myplr) NewCursor(GLOVE_CURS);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
static BOOL OilItem(ItemStruct * i,const PlayerStruct * p) {
|
|
int v;
|
|
|
|
if (i->_iClass == IC_ITEM) return(FALSE);
|
|
if (i->_iClass == IC_GOLD) return(FALSE);
|
|
if (i->_iClass == IC_SPECIAL) return(FALSE);
|
|
switch(p->_pOilType) {
|
|
case IMID_OILACC :
|
|
case IMID_OILMAST :
|
|
case IMID_OILSHRP :
|
|
if (i->_iClass == IC_ARMOR) return(FALSE);
|
|
break;
|
|
case IMID_OILDEATH :
|
|
if (i->_iClass == IC_ARMOR) return(FALSE);
|
|
if (i->_itype == IT_BOW) return(FALSE);
|
|
break;
|
|
case IMID_OILHARD :
|
|
case IMID_OILIMPER :
|
|
if (i->_iClass == IC_WEAP) return(FALSE);
|
|
break;
|
|
}
|
|
|
|
switch(p->_pOilType) {
|
|
case IMID_OILACC :
|
|
if (i->_iPLToHit >= 50) break;
|
|
i->_iPLToHit += random(68, 2) + 1;
|
|
break;
|
|
case IMID_OILMAST :
|
|
if (i->_iPLToHit >= 100) break;
|
|
i->_iPLToHit += random(68, 3) + 3;
|
|
break;
|
|
case IMID_OILSHRP :
|
|
if (i->_iMaxDam - i->_iMinDam >= 30) break;
|
|
i->_iMaxDam += 1;
|
|
break;
|
|
case IMID_OILDEATH :
|
|
if (i->_iMaxDam - i->_iMinDam >= 30) break;
|
|
i->_iMinDam += 1;
|
|
i->_iMaxDam += 2;
|
|
break;
|
|
case IMID_OILSKILL :
|
|
v = random(68, 6) + 5;
|
|
|
|
if (i->_iMinStr > v) {
|
|
i->_iMinStr -= v;
|
|
}
|
|
else {
|
|
i->_iMinStr = 0;
|
|
}
|
|
|
|
if (i->_iMinMag > v) {
|
|
i->_iMinMag -= v;
|
|
}
|
|
else {
|
|
i->_iMinMag = 0;
|
|
}
|
|
|
|
if (i->_iMinDex > v) {
|
|
i->_iMinDex -= v;
|
|
}
|
|
else {
|
|
i->_iMinDex = 0;
|
|
}
|
|
break;
|
|
case IMID_OILBLKSM :
|
|
if (i->_iMaxDur == INFINITE_DUR) break;
|
|
// i->_iDurability = (i->_iDurability + (random(68, 5) + 2));
|
|
// i->_iMaxDur = (i->_iMaxDur + (random(68, 9) + 7));
|
|
if (i->_iDurability < i->_iMaxDur)
|
|
{
|
|
// fix by 20%
|
|
int tmp = i->_iDurability + ((i->_iMaxDur + 4) / 5);
|
|
if (tmp > i->_iMaxDur)
|
|
tmp = i->_iMaxDur;
|
|
i->_iDurability = tmp;
|
|
}
|
|
else
|
|
{
|
|
if (i->_iMaxDur >= 100) break;
|
|
i->_iMaxDur += 1;
|
|
i->_iDurability = i->_iMaxDur;
|
|
}
|
|
break;
|
|
case IMID_OILFORT :
|
|
if (i->_iMaxDur == INFINITE_DUR) break;
|
|
if (i->_iMaxDur >= 200) break;
|
|
v = random(68, 41) + 10;
|
|
i->_iMaxDur += v;
|
|
i->_iDurability += v;
|
|
break;
|
|
case IMID_OILPERM :
|
|
i->_iDurability = INFINITE_DUR;
|
|
i->_iMaxDur = INFINITE_DUR;
|
|
break;
|
|
case IMID_OILHARD :
|
|
if (i->_iAC >= 60) break;
|
|
i->_iAC += random(68, 2) + 1;
|
|
break;
|
|
case IMID_OILIMPER :
|
|
if (i->_iAC >= 120) break;
|
|
i->_iAC += random(68, 3) + 3;
|
|
break;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void DoOil(int pnum, int cii) {
|
|
ItemStruct * pi;
|
|
PlayerStruct * p = &plr[pnum];
|
|
if (cii < NUM_INVLOC) switch (cii) {
|
|
case INVLOC_HEAD:
|
|
case INVLOC_HAND1:
|
|
case INVLOC_HAND2:
|
|
case INVLOC_BODY:
|
|
pi = &p->InvBody[cii];
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
else {
|
|
pi = &p->InvList[cii - NUM_INVLOC];
|
|
}
|
|
|
|
if (OilItem(pi,p)) {
|
|
CalcPlrInv(pnum,TRUE);
|
|
if (pnum == myplr) NewCursor(GLOVE_CURS);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void PrintItemOil(char IDidx)
|
|
{
|
|
switch(IDidx) {
|
|
case IMID_OILACC :
|
|
strcpy(tempstr, "increases a weapon's");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
strcpy(tempstr, "chance to hit");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_OILMAST :
|
|
strcpy(tempstr, "greatly increases a");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
strcpy(tempstr, "weapon's chance to hit");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_OILSHRP :
|
|
strcpy(tempstr, "increases a weapon's");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
strcpy(tempstr, "damage potential");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_OILDEATH :
|
|
strcpy(tempstr, "greatly increases a weapon's");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
strcpy(tempstr, "damage potential - not bows");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_OILSKILL :
|
|
strcpy(tempstr, "reduces attributes needed");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
strcpy(tempstr, "to use armor or weapons");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_OILBLKSM :
|
|
strcpy(tempstr, "restores 20% of an");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
strcpy(tempstr, "item's durability");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_OILFORT :
|
|
strcpy(tempstr, "increases an item's");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
strcpy(tempstr, "current and max durability");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_OILPERM :
|
|
strcpy(tempstr, "makes an item indestructible");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_OILHARD :
|
|
strcpy(tempstr, "increases the armor class");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
strcpy(tempstr, "of armor and shields");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_OILIMPER :
|
|
strcpy(tempstr, "greatly increases the armor");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
strcpy(tempstr, "class of armor and shields");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
// potions
|
|
case IMID_PHEAL :
|
|
strcpy(tempstr, "fully recover life");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_PLHEAL :
|
|
strcpy(tempstr, "recover partial life");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_PSHEAL :
|
|
strcpy(tempstr, "recover life");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_PDHEAL :
|
|
strcpy(tempstr, "deadly heal");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_PMANA :
|
|
strcpy(tempstr, "recover mana");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_PFMANA :
|
|
strcpy(tempstr, "fully recover mana");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_ESTR :
|
|
strcpy(tempstr, "increase strength");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_EMAG :
|
|
strcpy(tempstr, "increase magic");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_EDEX :
|
|
strcpy(tempstr, "increase dexterity");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_EVIT :
|
|
strcpy(tempstr, "increase vitality");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_ENSTR :
|
|
strcpy(tempstr, "decrease strength");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_ENMAG :
|
|
strcpy(tempstr, "decrease strength");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_ENDEX :
|
|
strcpy(tempstr, "decrease dexterity");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_ENVIT :
|
|
strcpy(tempstr, "decrease vitality");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_REJUV :
|
|
strcpy(tempstr, "recover life and mana");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_FREJUV :
|
|
strcpy(tempstr, "fully recover life and mana");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_RUNEFIRE:
|
|
case IMID_RUNEIMMOLATE:
|
|
strcpy(tempstr, "sets fire trap");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_RUNELIGHT:
|
|
case IMID_RUNENOVA:
|
|
strcpy(tempstr, "sets lightning trap");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
case IMID_RUNESTONE:
|
|
strcpy(tempstr, "sets petrification trap");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void PrintItemPower(char plidx,const ItemStruct * x) {
|
|
int v;
|
|
|
|
switch(plidx) {
|
|
case PL_TOHIT:
|
|
case PL_NTOHIT:
|
|
sprintf(tempstr, "chance to hit : %+i%%", x->_iPLToHit);
|
|
break;
|
|
case PL_TODAM:
|
|
case PL_NTODAM:
|
|
sprintf(tempstr, "%+i%% damage", x->_iPLDam);
|
|
break;
|
|
case PL_DAHT:
|
|
case PL_NDAHT:
|
|
sprintf(tempstr, "to hit: %+i%%, %+i%% damage", x->_iPLToHit, x->_iPLDam);
|
|
break;
|
|
case PL_AC:
|
|
case PL_NAC:
|
|
sprintf(tempstr, "%+i%% armor", x->_iPLAC);
|
|
break;
|
|
case PL_ACTUALAC:
|
|
sprintf(tempstr, "armor class: %i", x->_iAC);
|
|
break;
|
|
case PL_NACTULAC:
|
|
sprintf(tempstr, "armor class: %i", x->_iAC);
|
|
break;
|
|
case PL_RFIRE:
|
|
case PL_NRFIRE:
|
|
if (x->_iPLFR < 75)
|
|
sprintf(tempstr, "Resist Fire : %+i%%", x->_iPLFR);
|
|
else
|
|
sprintf(tempstr, "Resist Fire : 75%% MAX");
|
|
break;
|
|
case PL_RLGHT:
|
|
case PL_NRLGHT:
|
|
if (x->_iPLLR < 75)
|
|
sprintf(tempstr, "Resist Lightning : %+i%%", x->_iPLLR);
|
|
else
|
|
sprintf(tempstr, "Resist Lightning : 75%% MAX");
|
|
break;
|
|
case PL_RMAG:
|
|
case PL_NRMAG:
|
|
if (x->_iPLMR < 75)
|
|
sprintf(tempstr, "Resist Magic : %+i%%", x->_iPLMR);
|
|
else
|
|
sprintf(tempstr, "Resist Magic : 75%% MAX");
|
|
break;
|
|
case PL_RALL:
|
|
case PL_NRALL:
|
|
if (x->_iPLFR < 75) sprintf(tempstr, "Resist All : %+i%%", x->_iPLFR);
|
|
if (x->_iPLFR >= 75) sprintf(tempstr, "Resist All : 75%% MAX");
|
|
break;
|
|
case PL_SLVL:
|
|
#if 0
|
|
if (x->_iSplLvlAdd == 1 ) strcpy(tempstr, "spells are increased 1 level");
|
|
if (x->_iSplLvlAdd == 2 ) strcpy(tempstr, "spells are increased 2 levels");
|
|
if (x->_iSplLvlAdd < 1 ) strcpy(tempstr, "spells are decreased 1 level");
|
|
#endif
|
|
if (x->_iSplLvlAdd == 1) strcpy(tempstr, "spells are increased 1 level");
|
|
else if (x->_iSplLvlAdd > 1 ) sprintf(tempstr, "spells are increased %i levels", x->_iSplLvlAdd);
|
|
else if (x->_iSplLvlAdd == -1) strcpy(tempstr, "spells are decreased 1 level");
|
|
else if (x->_iSplLvlAdd < -1 ) sprintf(tempstr, "spells are decreased %i levels", x->_iSplLvlAdd);
|
|
else if (x->_iSplLvlAdd == 0 ) strcpy(tempstr, "spell levels unchanged (?)");
|
|
break;
|
|
case PL_CHRG:
|
|
strcpy(tempstr, "Extra charges");
|
|
break;
|
|
case PL_SPELL:
|
|
sprintf(tempstr, "%i %s charges", x->_iMaxCharges, spelldata[x->_iSpell].sNameText);
|
|
break;
|
|
case PL_FHIT:
|
|
if (x->_iFMinDam == x->_iFMaxDam)
|
|
sprintf(tempstr, "Fire hit damage: %i", x->_iFMinDam);
|
|
else
|
|
sprintf(tempstr, "Fire hit damage: %i-%i", x->_iFMinDam, x->_iFMaxDam);
|
|
break;
|
|
case PL_LHIT:
|
|
if (x->_iLMinDam == x->_iLMaxDam)
|
|
sprintf(tempstr, "Lightning hit damage: %i", x->_iLMinDam);
|
|
else
|
|
sprintf(tempstr, "Lightning hit damage: %i-%i", x->_iLMinDam, x->_iLMaxDam);
|
|
break;
|
|
case PL_STR:
|
|
case PL_NSTR:
|
|
sprintf(tempstr, "%+i to strength", x->_iPLStr);
|
|
break;
|
|
case PL_MAG:
|
|
case PL_NMAG:
|
|
sprintf(tempstr, "%+i to magic", x->_iPLMag);
|
|
break;
|
|
case PL_DEX:
|
|
case PL_NDEX:
|
|
sprintf(tempstr, "%+i to dexterity", x->_iPLDex);
|
|
break;
|
|
case PL_VIT:
|
|
case PL_NVIT:
|
|
sprintf(tempstr, "%+i to vitality", x->_iPLVit);
|
|
break;
|
|
case PL_STATS:
|
|
case PL_NSTATS:
|
|
sprintf(tempstr, "%+i to all attributes", x->_iPLStr);
|
|
break;
|
|
case PL_GETHIT:
|
|
case PL_NGETHIT:
|
|
sprintf(tempstr, "%+i damage from enemies", x->_iPLGetHit);
|
|
break;
|
|
case PL_HP:
|
|
case PL_NHP:
|
|
sprintf(tempstr, "Hit Points : %+i", (x->_iPLHP >> HP_SHIFT));
|
|
break;
|
|
case PL_MANA:
|
|
case PL_NMANA:
|
|
sprintf(tempstr, "Mana : %+i", (x->_iPLMana >> MANA_SHIFT));
|
|
break;
|
|
case PL_DUR:
|
|
strcpy(tempstr, "high durability");
|
|
break;
|
|
case PL_NDUR:
|
|
strcpy(tempstr, "decreased durability");
|
|
break;
|
|
case PL_IND:
|
|
strcpy(tempstr, "indestructible");
|
|
break;
|
|
case PL_LIGHT:
|
|
v = x->_iPLLight * 10;
|
|
sprintf(tempstr, "+%i%% light radius", v);
|
|
break;
|
|
case PL_NLIGHT:
|
|
v = -x->_iPLLight * 10;
|
|
sprintf(tempstr, "-%i%% light radius", v);
|
|
break;
|
|
case PL_NUMARWS:
|
|
sprintf(tempstr, "multiple arrows per shot");
|
|
break;
|
|
case PL_FARROW:
|
|
if (x->_iFMinDam == x->_iFMaxDam)
|
|
sprintf(tempstr, "fire arrows damage: %i", x->_iFMinDam);
|
|
else
|
|
sprintf(tempstr, "fire arrows damage: %i-%i", x->_iFMinDam, x->_iFMaxDam);
|
|
break;
|
|
case PL_LARROW:
|
|
if (x->_iLMinDam == x->_iLMaxDam)
|
|
sprintf(tempstr, "lightning arrows damage %i", x->_iLMinDam);
|
|
else
|
|
sprintf(tempstr, "lightning arrows damage %i-%i", x->_iLMinDam, x->_iLMaxDam);
|
|
break;
|
|
case PL_HITADD: // usurped for fireball arrows...
|
|
if (x->_iFMinDam == x->_iFMaxDam)
|
|
sprintf(tempstr, "fireball damage: %i", x->_iFMinDam);
|
|
else
|
|
sprintf(tempstr, "fireball damage: %i-%i", x->_iFMinDam, x->_iFMaxDam);
|
|
break;
|
|
case PL_THORN:
|
|
strcpy(tempstr, "attacker takes 1-3 damage");
|
|
break;
|
|
case PL_LMANA:
|
|
strcpy(tempstr, "user loses all mana");
|
|
break;
|
|
case PL_NOHEAL:
|
|
strcpy(tempstr, "you can't heal");
|
|
break;
|
|
case PL_TRAPDAM:
|
|
strcpy(tempstr, "absorbs half of trap damage");
|
|
break;
|
|
case PL_BEAR:
|
|
strcpy(tempstr, "knocks target back");
|
|
break;
|
|
case PL_DAMDEMON:
|
|
strcpy(tempstr, "+200% damage vs. demons");
|
|
break;
|
|
case PL_ZERORES:
|
|
strcpy(tempstr, "All Resistance equals 0");
|
|
break;
|
|
case PL_MNOHEAL:
|
|
strcpy(tempstr, "hit monster doesn't heal");
|
|
break;
|
|
case PL_BAT:
|
|
if (x->_iFlags & IAF_BAT10) strcpy(tempstr, "hit steals 3% mana");
|
|
if (x->_iFlags & IAF_BAT20) strcpy(tempstr, "hit steals 5% mana");
|
|
break;
|
|
case PL_LEECH:
|
|
if (x->_iFlags & IAF_LEECH10) strcpy(tempstr, "hit steals 3% life");
|
|
if (x->_iFlags & IAF_LEECH20) strcpy(tempstr, "hit steals 5% life");
|
|
break;
|
|
case PL_ENAC:
|
|
strcpy(tempstr, "penetrates target's armor");
|
|
break;
|
|
case PL_ATANIM:
|
|
if (x->_iFlags & IAF_ATANIM1) strcpy(tempstr, "quick attack");
|
|
if (x->_iFlags & IAF_ATANIM2) strcpy(tempstr, "fast attack");
|
|
if (x->_iFlags & IAF_ATANIM3) strcpy(tempstr, "faster attack");
|
|
if (x->_iFlags & IAF_ATANIM4) strcpy(tempstr, "fastest attack");
|
|
break;
|
|
case PL_HTANIM:
|
|
if (x->_iFlags & IAF_HTANIM1) strcpy(tempstr, "fast hit recovery");
|
|
if (x->_iFlags & IAF_HTANIM2) strcpy(tempstr, "faster hit recovery");
|
|
if (x->_iFlags & IAF_HTANIM3) strcpy(tempstr, "fastest hit recovery");
|
|
break;
|
|
case PL_BLANIM:
|
|
strcpy(tempstr, "fast block");
|
|
break;
|
|
case PL_DAMADD:
|
|
sprintf(tempstr, "adds %i points to damage", x->_iPLDamMod);
|
|
break;
|
|
case PL_RNDARW:
|
|
strcpy(tempstr, "fires random speed arrows");
|
|
break;
|
|
case PL_DAMAGE:
|
|
sprintf(tempstr, "unusual item damage");
|
|
break;
|
|
case PL_DURNUM:
|
|
strcpy(tempstr, "altered durability");
|
|
break;
|
|
case PL_FALCON:
|
|
strcpy(tempstr, "Faster attack swing");
|
|
// not used
|
|
break;
|
|
case PL_ONEHAND:
|
|
strcpy(tempstr, "one handed sword");
|
|
break;
|
|
case PL_CONST:
|
|
strcpy(tempstr, "constantly lose hit points");
|
|
break;
|
|
case PL_SKING:
|
|
strcpy(tempstr, "life stealing");
|
|
break;
|
|
case PL_NSTRREQ:
|
|
strcpy(tempstr, "no strength requirement");
|
|
break;
|
|
case PL_INFRA:
|
|
strcpy(tempstr, "see with infravision");
|
|
break;
|
|
case PL_GFX:
|
|
strcpy(tempstr, " ");
|
|
break;
|
|
case PL_HARQUN:
|
|
if (x->_iFMinDam == x->_iFMaxDam)
|
|
sprintf(tempstr, "lightning damage: %i", x->_iFMinDam);
|
|
else
|
|
sprintf(tempstr, "lightning damage: %i-%i", x->_iFMinDam, x->_iFMaxDam);
|
|
// strcpy(tempstr, "Armor class added to life");
|
|
break;
|
|
case PL_HARQUN2:
|
|
strcpy(tempstr, "charged bolts on hits");
|
|
// strcpy(tempstr, "10% of mana added to armor");
|
|
break;
|
|
case PL_HARQUN3:
|
|
if (x->_iPLFR <= 0) sprintf(tempstr, " ");
|
|
else if (x->_iPLFR >= 1) sprintf(tempstr, "Resist Fire : %+i%%", x->_iPLFR);
|
|
break;
|
|
case PL_DEVAST:
|
|
strcpy(tempstr, "occasional triple damage");
|
|
break;
|
|
case PL_DECAY:
|
|
sprintf(tempstr, "decaying %+i%% damage", x->_iPLDam);
|
|
break;
|
|
case PL_PERIL:
|
|
strcpy(tempstr, "2x dmg to monst, 1x to you");
|
|
break;
|
|
case PL_RNDDAM:
|
|
strcpy(tempstr, "Random 0 - 500% damage");
|
|
break;
|
|
case PL_FRAGILE:
|
|
sprintf(tempstr, "low dur, %+i%% damage", x->_iPLDam);
|
|
break;
|
|
case PL_DOPPEL:
|
|
sprintf(tempstr, "to hit: %+i%%, %+i%% damage", x->_iPLToHit, x->_iPLDam);
|
|
break;
|
|
case PL_DEMONAC:
|
|
sprintf(tempstr, "extra AC vs demons");
|
|
break;
|
|
case PL_UNDEADAC:
|
|
sprintf(tempstr, "extra AC vs undead");
|
|
break;
|
|
case PL_ACOLYTE:
|
|
sprintf(tempstr, "50%% Mana moved to Health");
|
|
break;
|
|
case PL_GLADIATR:
|
|
sprintf(tempstr, "40%% Health moved to Mana");
|
|
break;
|
|
|
|
default:
|
|
strcpy(tempstr, "Another ability (NW)");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void DrawUBack()
|
|
{
|
|
DrawCel(88, 487, pSTextBoxCels, 1, 271);
|
|
app_assert(gpBuffer);
|
|
|
|
__asm {
|
|
mov edi,dword ptr [gpBuffer]
|
|
add edi,371803
|
|
|
|
xor eax,eax
|
|
mov edx,148
|
|
_YLp: mov ecx,132
|
|
_XLp1: stosb
|
|
inc edi
|
|
loop _XLp1
|
|
stosb
|
|
sub edi,1033
|
|
mov ecx,132
|
|
_XLp2: inc edi
|
|
stosb
|
|
loop _XLp2
|
|
sub edi,1032
|
|
dec edx
|
|
jnz _YLp
|
|
mov ecx,132
|
|
_XLp3: stosb
|
|
inc edi
|
|
loop _XLp3
|
|
stosb
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------**
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void PrintUString(int x, int y, BOOL cjustflag, char str[], char col)
|
|
{
|
|
long boffset;
|
|
int sl,i,w,tw,yy;
|
|
|
|
yy = SStringY[y];
|
|
boffset = nBuffWTbl[yy + 204] + x + 96;
|
|
sl = strlen(str);
|
|
w = 0;
|
|
if (cjustflag) {
|
|
tw = 0;
|
|
for (i = 0; i < sl; i++) {
|
|
BYTE c = char2print(str[i]);
|
|
c = fonttrans[c];
|
|
tw += fontkern[c]+1;
|
|
}
|
|
if (tw < 257) w = (257 - tw) >> 1;
|
|
boffset += w;
|
|
}
|
|
for (i = 0; i < sl; i++) {
|
|
BYTE c = char2print(str[i]);
|
|
c = fonttrans[c];
|
|
w += fontkern[c]+1;
|
|
if ((c != 0) && (w <= 257)) DrawPanelFont(boffset, c, col);
|
|
boffset += fontkern[c]+1;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------**
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void DrawULine(int y)
|
|
{
|
|
long doffset;
|
|
|
|
app_assert(gpBuffer);
|
|
doffset = nBuffWTbl[SStringY[y] + 198] + 90;
|
|
__asm {
|
|
mov esi,dword ptr [gpBuffer]
|
|
mov edi,esi
|
|
add esi,142170
|
|
add edi,dword ptr [doffset]
|
|
|
|
mov ebx,502
|
|
|
|
mov edx,3
|
|
_YLp: mov ecx,66
|
|
rep movsd
|
|
movsw
|
|
add esi,ebx
|
|
add edi,ebx
|
|
dec edx
|
|
jnz _YLp
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void DrawUniqueInfo()
|
|
{
|
|
int u,y;
|
|
|
|
if (chrflag || questlog) return;
|
|
u = curruitem._iUid;
|
|
DrawUBack();
|
|
PrintUString(0, 2, TRUE, UniqueItemList[u].UIName, ICOLOR_GOLD);
|
|
DrawULine(5);
|
|
PrintItemPower(UniqueItemList[u].UIPower1, &curruitem);
|
|
y = (6 - UniqueItemList[u].UINumPL) + 8;
|
|
PrintUString(0, y, TRUE, tempstr, ICOLOR_WHITE);
|
|
if (UniqueItemList[u].UINumPL > 1) {
|
|
PrintItemPower(UniqueItemList[u].UIPower2, &curruitem);
|
|
PrintUString(0, y+2, TRUE, tempstr, ICOLOR_WHITE);
|
|
}
|
|
if (UniqueItemList[u].UINumPL > 2) {
|
|
PrintItemPower(UniqueItemList[u].UIPower3, &curruitem);
|
|
PrintUString(0, y+4, TRUE, tempstr, ICOLOR_WHITE);
|
|
}
|
|
if (UniqueItemList[u].UINumPL > 3) {
|
|
PrintItemPower(UniqueItemList[u].UIPower4, &curruitem);
|
|
PrintUString(0, y+6, TRUE, tempstr, ICOLOR_WHITE);
|
|
}
|
|
if (UniqueItemList[u].UINumPL > 4) {
|
|
PrintItemPower(UniqueItemList[u].UIPower5, &curruitem);
|
|
PrintUString(0, y+8, TRUE, tempstr, ICOLOR_WHITE);
|
|
}
|
|
if (UniqueItemList[u].UINumPL > 5) {
|
|
PrintItemPower(UniqueItemList[u].UIPower6, &curruitem);
|
|
PrintUString(0, y+10, TRUE, tempstr, ICOLOR_WHITE);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void PrintItemMisc(const ItemStruct * x)
|
|
{
|
|
if (x->_iMiscId == IMID_SCROLL) {
|
|
strcpy(tempstr, "Right-click to read");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
if (x->_iMiscId == IMID_TSCROLL) {
|
|
strcpy(tempstr, "Right-click to read, then");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
strcpy(tempstr, "left-click to target");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
if ((x->_iMiscId >= IMID_FIRSTPOT) && (x->_iMiscId <= IMID_LASTPOT)) {
|
|
PrintItemOil(x->_iMiscId);
|
|
strcpy(tempstr, "Right click to use");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
if ((x->_iMiscId > IMID_FIRSTOIL) && (x->_iMiscId < IMID_LASTOIL)) {
|
|
PrintItemOil(x->_iMiscId);
|
|
strcpy(tempstr, "Right click to use");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
if ((x->_iMiscId > IMID_FIRSTRUNE) && (x->_iMiscId < IMID_LASTRUNE)) {
|
|
PrintItemOil(x->_iMiscId);
|
|
strcpy(tempstr, "Right click to use");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
if (x->_iMiscId == IMID_BOOK) {
|
|
strcpy(tempstr, "Right click to read");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
if (x->_iMiscId == IMID_FULLNOTE)
|
|
{
|
|
strcpy(tempstr, "Right click to read");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
if (x->_iMiscId == IMID_MAPOFDOOM) {
|
|
strcpy(tempstr, "Right click to view");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
if (x->_iMiscId == IMID_EAR) {
|
|
sprintf(tempstr, "Level : %i", x->_ivalue);
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
if (x->_iMiscId == IMID_AURIC) {
|
|
strcpy(tempstr, "Doubles gold capacity");
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void PrintItemDetails(const ItemStruct * x)
|
|
{
|
|
if (x->_iClass == IC_WEAP) {
|
|
if (x->_iMinDam == x->_iMaxDam)
|
|
{
|
|
if (x->_iMaxDur == INFINITE_DUR)
|
|
sprintf(tempstr, "damage: %i Indestructible", x->_iMinDam);
|
|
else
|
|
sprintf(tempstr, "damage: %i Dur: %i/%i", x->_iMinDam, x->_iDurability, x->_iMaxDur);
|
|
}
|
|
else
|
|
{
|
|
if (x->_iMaxDur == INFINITE_DUR)
|
|
sprintf(tempstr, "damage: %i-%i Indestructible", x->_iMinDam, x->_iMaxDam);
|
|
else
|
|
sprintf(tempstr, "damage: %i-%i Dur: %i/%i", x->_iMinDam, x->_iMaxDam, x->_iDurability, x->_iMaxDur);
|
|
}
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
if (x->_iClass == IC_ARMOR) {
|
|
if (x->_iMaxDur == INFINITE_DUR)
|
|
sprintf(tempstr, "armor: %i Indestructible", x->_iAC);
|
|
else
|
|
sprintf(tempstr, "armor: %i Dur: %i/%i", x->_iAC, x->_iDurability, x->_iMaxDur);
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
if ((x->_iMiscId == IMID_STAFF) && (x->_iMaxCharges != 0)) {
|
|
if (x->_iMinDam == x->_iMaxDam)
|
|
sprintf(tempstr, "dam: %i Dur: %i/%i", x->_iMinDam, x->_iDurability, x->_iMaxDur);
|
|
else
|
|
sprintf(tempstr, "dam: %i-%i Dur: %i/%i", x->_iMinDam, x->_iMaxDam, x->_iDurability, x->_iMaxDur);
|
|
sprintf(tempstr, "Charges: %i/%i", x->_iCharges, x->_iMaxCharges);
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
if (x->_iPrePower != -1) {
|
|
PrintItemPower(x->_iPrePower, x);
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
if (x->_iSufPower != -1) {
|
|
PrintItemPower(x->_iSufPower, x);
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
if (x->_iMagical == IMAGIC_UNIQUE) {
|
|
AddPanelString("unique item", TEXT_CENTER);
|
|
uitemflag = TRUE;
|
|
curruitem = *x;
|
|
}
|
|
PrintItemMisc(x);
|
|
if ((x->_iMinStr + x->_iMinMag + x->_iMinDex) != 0) {
|
|
strcpy(tempstr, "Required:");
|
|
if (x->_iMinStr != 0) sprintf(tempstr, "%s %i Str", tempstr, x->_iMinStr);
|
|
if (x->_iMinMag != 0) sprintf(tempstr, "%s %i Mag", tempstr, (byte) x->_iMinMag);
|
|
if (x->_iMinDex != 0) sprintf(tempstr, "%s %i Dex", tempstr, x->_iMinDex);
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
pinfoflag = TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void PrintItemDur(const ItemStruct * x)
|
|
{
|
|
if (x->_iClass == IC_WEAP) {
|
|
if (x->_iMinDam == x->_iMaxDam)
|
|
{
|
|
if (x->_iMaxDur == INFINITE_DUR)
|
|
sprintf(tempstr, "damage: %i Indestructible", x->_iMinDam);
|
|
else
|
|
sprintf(tempstr, "damage: %i Dur: %i/%i", x->_iMinDam, x->_iDurability, x->_iMaxDur);
|
|
}
|
|
else
|
|
{
|
|
if (x->_iMaxDur == INFINITE_DUR)
|
|
sprintf(tempstr, "damage: %i-%i Indestructible", x->_iMinDam, x->_iMaxDam);
|
|
else
|
|
sprintf(tempstr, "damage: %i-%i Dur: %i/%i", x->_iMinDam, x->_iMaxDam, x->_iDurability, x->_iMaxDur);
|
|
}
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
if ((x->_iMiscId == IMID_STAFF) && (x->_iMaxCharges != 0)) {
|
|
sprintf(tempstr, "Charges: %i/%i", x->_iCharges, x->_iMaxCharges);
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
if (x->_iMagical) {
|
|
AddPanelString("Not Identified", TEXT_CENTER);
|
|
}
|
|
}
|
|
if (x->_iClass == IC_ARMOR) {
|
|
if (x->_iMaxDur == INFINITE_DUR)
|
|
sprintf(tempstr, "armor: %i Indestructible", x->_iAC);
|
|
else
|
|
sprintf(tempstr, "armor: %i Dur: %i/%i", x->_iAC, x->_iDurability, x->_iMaxDur);
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
if (x->_iMagical) {
|
|
AddPanelString("Not Identified", TEXT_CENTER);
|
|
}
|
|
if ((x->_iMiscId == IMID_STAFF) && (x->_iMaxCharges != 0)) {
|
|
sprintf(tempstr, "Charges: %i/%i", x->_iCharges, x->_iMaxCharges);
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
}
|
|
if ((x->_itype == IT_RING) || (x->_itype == IT_AMULET)) {
|
|
AddPanelString("Not Identified", TEXT_CENTER);
|
|
}
|
|
PrintItemMisc(x);
|
|
if ((x->_iMinStr + x->_iMinMag + x->_iMinDex) != 0) {
|
|
strcpy(tempstr, "Required:");
|
|
if (x->_iMinStr != 0) sprintf(tempstr, "%s %i Str", tempstr, x->_iMinStr);
|
|
if (x->_iMinMag != 0) sprintf(tempstr, "%s %i Mag", tempstr, (byte) x->_iMinMag);
|
|
if (x->_iMinDex != 0) sprintf(tempstr, "%s %i Dex", tempstr, x->_iMinDex);
|
|
AddPanelString(tempstr, TEXT_CENTER);
|
|
}
|
|
pinfoflag = TRUE;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*
|
|
**-------------------------------------------------------------------------*/
|
|
|
|
void UseItem(int p, int Mid, int spl)
|
|
{
|
|
long l;
|
|
__int64 t;
|
|
|
|
switch(Mid) {
|
|
case IMID_MEAT :
|
|
case IMID_PLHEAL :
|
|
l = plr[p]._pMaxHP >> (HP_SHIFT + 2);
|
|
l = ((random(39, l) + (l >> 1)) << HP_SHIFT);
|
|
if (plr[p]._pClass == CLASS_WARRIOR
|
|
|| plr[p]._pClass == CLASS_BARBARIAN) l = l << 1;
|
|
if (plr[p]._pClass == CLASS_ROGUE ||
|
|
plr[p]._pClass == CLASS_MONK ||
|
|
plr[p]._pClass == CLASS_BARD) l += (l >> 1);
|
|
plr[p]._pHitPoints += l;
|
|
if (plr[p]._pHitPoints > plr[p]._pMaxHP) plr[p]._pHitPoints = plr[p]._pMaxHP;
|
|
plr[p]._pHPBase += l;
|
|
if (plr[p]._pHPBase > plr[p]._pMaxHPBase) plr[p]._pHPBase = plr[p]._pMaxHPBase;
|
|
drawhpflag = TRUE;
|
|
break;
|
|
case IMID_PHEAL :
|
|
plr[p]._pHitPoints = plr[p]._pMaxHP;
|
|
plr[p]._pHPBase = plr[p]._pMaxHPBase;
|
|
drawhpflag = TRUE;
|
|
break;
|
|
case IMID_PMANA :
|
|
l = plr[p]._pMaxMana >> (MANA_SHIFT + 2);
|
|
l = ((random(40, l) + (l >> 1)) << MANA_SHIFT);
|
|
if (plr[p]._pClass == CLASS_SORCEROR) l = l << 1;
|
|
if (plr[p]._pClass == CLASS_ROGUE ||
|
|
plr[p]._pClass == CLASS_MONK ||
|
|
plr[p]._pClass == CLASS_BARD) l += (l >> 1);
|
|
if (!(plr[p]._pIFlags & IAF_LMANA)) {
|
|
plr[p]._pMana += l;
|
|
if (plr[p]._pMana > plr[p]._pMaxMana) plr[p]._pMana = plr[p]._pMaxMana;
|
|
plr[p]._pManaBase += l;
|
|
if (plr[p]._pManaBase > plr[p]._pMaxManaBase) plr[p]._pManaBase = plr[p]._pMaxManaBase;
|
|
drawmanaflag = TRUE;
|
|
}
|
|
break;
|
|
case IMID_PFMANA :
|
|
if (!(plr[p]._pIFlags & IAF_LMANA)) {
|
|
plr[p]._pMana = plr[p]._pMaxMana;
|
|
plr[p]._pManaBase = plr[p]._pMaxManaBase;
|
|
drawmanaflag = TRUE;
|
|
}
|
|
break;
|
|
case IMID_ESTR :
|
|
ModifyPlrStr(p, 1);
|
|
break;
|
|
case IMID_EMAG :
|
|
ModifyPlrMag(p, 1);
|
|
|
|
// also give full mana potion effect
|
|
plr[p]._pMana = plr[p]._pMaxMana;
|
|
plr[p]._pManaBase = plr[p]._pMaxManaBase;
|
|
drawmanaflag = TRUE;
|
|
|
|
break;
|
|
case IMID_EDEX :
|
|
ModifyPlrDex(p, 1);
|
|
break;
|
|
case IMID_EVIT :
|
|
ModifyPlrVit(p, 1);
|
|
|
|
// heal the player, too
|
|
plr[p]._pHitPoints = plr[p]._pMaxHP;
|
|
plr[p]._pHPBase = plr[p]._pMaxHPBase;
|
|
drawhpflag = TRUE;
|
|
|
|
break;
|
|
case IMID_BOOK :
|
|
t = 1;
|
|
plr[p]._pMemSpells |= (t << spl-1);
|
|
if (plr[p]._pSplLvl[spl] < SPELLCAP) plr[p]._pSplLvl[spl]++;
|
|
plr[p]._pMana += spelldata[spl].sManaCost << MANA_SHIFT;
|
|
if (plr[p]._pMana > plr[p]._pMaxMana) plr[p]._pMana = plr[p]._pMaxMana;
|
|
plr[p]._pManaBase += spelldata[spl].sManaCost << MANA_SHIFT;
|
|
if (plr[p]._pManaBase > plr[p]._pMaxManaBase) plr[p]._pManaBase = plr[p]._pMaxManaBase;
|
|
if (p == myplr) CalcPlrBookVals(p);
|
|
drawmanaflag = TRUE;
|
|
break;
|
|
case IMID_REJUV :
|
|
l = plr[p]._pMaxHP >> (HP_SHIFT + 2);
|
|
l = ((random(39, l) + (l >> 1)) << HP_SHIFT);
|
|
if (plr[p]._pClass == CLASS_WARRIOR
|
|
|| plr[p]._pClass == CLASS_BARBARIAN) l = l << 1;
|
|
if (plr[p]._pClass == CLASS_ROGUE) l += (l >> 1);
|
|
plr[p]._pHitPoints += l;
|
|
if (plr[p]._pHitPoints > plr[p]._pMaxHP) plr[p]._pHitPoints = plr[p]._pMaxHP;
|
|
plr[p]._pHPBase += l;
|
|
if (plr[p]._pHPBase > plr[p]._pMaxHPBase) plr[p]._pHPBase = plr[p]._pMaxHPBase;
|
|
drawhpflag = TRUE;
|
|
l = plr[p]._pMaxMana >> (MANA_SHIFT + 2);
|
|
l = ((random(40, l) + (l >> 1)) << MANA_SHIFT);
|
|
if (plr[p]._pClass == CLASS_SORCEROR) l = l << 1;
|
|
if (plr[p]._pClass == CLASS_ROGUE) l += (l >> 1);
|
|
if (!(plr[p]._pIFlags & IAF_LMANA)) {
|
|
plr[p]._pMana += l;
|
|
if (plr[p]._pMana > plr[p]._pMaxMana) plr[p]._pMana = plr[p]._pMaxMana;
|
|
plr[p]._pManaBase += l;
|
|
if (plr[p]._pManaBase > plr[p]._pMaxManaBase) plr[p]._pManaBase = plr[p]._pMaxManaBase;
|
|
drawmanaflag = TRUE;
|
|
}
|
|
break;
|
|
case IMID_FREJUV :
|
|
plr[p]._pHitPoints = plr[p]._pMaxHP;
|
|
plr[p]._pHPBase = plr[p]._pMaxHPBase;
|
|
drawhpflag = TRUE;
|
|
if (!(plr[p]._pIFlags & IAF_LMANA)) {
|
|
plr[p]._pMana = plr[p]._pMaxMana;
|
|
plr[p]._pManaBase = plr[p]._pMaxManaBase;
|
|
drawmanaflag = TRUE;
|
|
}
|
|
break;
|
|
case IMID_OILACC :
|
|
case IMID_OILMAST :
|
|
case IMID_OILSHRP :
|
|
case IMID_OILDEATH :
|
|
case IMID_OILSKILL :
|
|
case IMID_OILBLKSM :
|
|
case IMID_OILFORT :
|
|
case IMID_OILPERM :
|
|
case IMID_OILHARD :
|
|
case IMID_OILIMPER :
|
|
plr[p]._pOilType = Mid;
|
|
if (p == myplr) {
|
|
if (sbookflag) sbookflag = FALSE;
|
|
if (!invflag) invflag = TRUE;
|
|
NewCursor(OIL_CURS);
|
|
}
|
|
break;
|
|
case IMID_SCROLL:
|
|
if (spelldata[spl].sTargeted) {
|
|
plr[p]._pTSpell = spl;
|
|
//plr[p]._pTSplType = SPT_SCROLL;
|
|
plr[p]._pTSplType = SPT_NONE;
|
|
if (p == myplr) {
|
|
NewCursor(TARGET_CURS);
|
|
}
|
|
} else {
|
|
ClrPlrPath(p);
|
|
plr[p]._pSpell = spl;
|
|
//plr[p]._pSplType = SPT_SCROLL;
|
|
plr[p]._pSplType = SPT_NONE;
|
|
plr[p]._pSplFrom = SPL_FROMSB;
|
|
plr[p].destAction = PCMD_SPELL;
|
|
plr[p].destParam1 = cursmx;
|
|
plr[p].destParam2 = cursmy;
|
|
}
|
|
break;
|
|
case IMID_TSCROLL:
|
|
if (spelldata[spl].sTargeted) {
|
|
plr[p]._pTSpell = spl;
|
|
//plr[p]._pTSplType = SPT_SCROLL;
|
|
plr[p]._pTSplType = SPT_NONE;
|
|
if (p == myplr) {
|
|
NewCursor(TARGET_CURS);
|
|
}
|
|
} else {
|
|
ClrPlrPath(p);
|
|
plr[p]._pSpell = spl;
|
|
//plr[p]._pSplType = SPT_SCROLL;
|
|
plr[p]._pSplType = SPT_NONE;
|
|
plr[p]._pSplFrom = SPL_FROMSB;
|
|
plr[p].destAction = PCMD_SPELL;
|
|
plr[p].destParam1 = cursmx;
|
|
plr[p].destParam2 = cursmy;
|
|
}
|
|
break;
|
|
case IMID_MAPOFDOOM:
|
|
InitMapOfDoomView();
|
|
break;
|
|
case IMID_SPECTRAL:
|
|
ModifyPlrStr(p, 3);
|
|
ModifyPlrMag(p, 3);
|
|
ModifyPlrDex(p, 3);
|
|
ModifyPlrVit(p, 3);
|
|
break;
|
|
case IMID_RUNEFIRE:
|
|
plr[p]._pTSpell = SPL_RUNEOFFIRE;
|
|
plr[p]._pTSplType = SPT_NONE;
|
|
if (p == myplr) {
|
|
NewCursor(TARGET_CURS);
|
|
}
|
|
break;
|
|
case IMID_RUNELIGHT:
|
|
plr[p]._pTSpell = SPL_RUNEOFLIGHT;
|
|
plr[p]._pTSplType = SPT_NONE;
|
|
if (p == myplr) {
|
|
NewCursor(TARGET_CURS);
|
|
}
|
|
break;
|
|
case IMID_RUNEIMMOLATE:
|
|
plr[p]._pTSpell = SPL_RUNEOFIMMOLATION;
|
|
plr[p]._pTSplType = SPT_NONE;
|
|
if (p == myplr) {
|
|
NewCursor(TARGET_CURS);
|
|
}
|
|
break;
|
|
case IMID_RUNENOVA:
|
|
plr[p]._pTSpell = SPL_RUNEOFNOVA;
|
|
plr[p]._pTSplType = SPT_NONE;
|
|
if (p == myplr) {
|
|
NewCursor(TARGET_CURS);
|
|
}
|
|
break;
|
|
case IMID_RUNESTONE:
|
|
plr[p]._pTSpell = SPL_RUNEOFSTONE;
|
|
plr[p]._pTSplType = SPT_NONE;
|
|
if (p == myplr) {
|
|
NewCursor(TARGET_CURS);
|
|
}
|
|
break;
|
|
case IMID_FULLNOTE:
|
|
// InitQTextMsg(TXT_SKULLJRNL7);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
#define MAX_STORE_VAL 200000
|
|
#define MAX_WIRT_VAL 200000 // Wirts stuff is 75% of normal
|
|
|
|
BOOL StoreStatOk(ItemStruct *h)
|
|
{
|
|
BOOL sf = TRUE;
|
|
if (plr[myplr]._pStrength < h->_iMinStr) sf = FALSE;
|
|
else if (plr[myplr]._pMagic < (byte)h->_iMinMag) sf = FALSE;
|
|
else if (plr[myplr]._pDexterity < h->_iMinDex) sf = FALSE;
|
|
return(sf);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
BOOL SmithItemOk(int i)
|
|
{
|
|
BOOL rv;
|
|
|
|
rv = TRUE;
|
|
// Selling oil is too powerful for the money received.
|
|
// if (AllItemsList[i].iMiscId > IMID_FIRSTOIL &&
|
|
// AllItemsList[i].iMiscId < IMID_LASTOIL) rv = TRUE;
|
|
// else
|
|
if (AllItemsList[i].itype == IT_MISC) rv = FALSE;
|
|
|
|
if (AllItemsList[i].itype == IT_GOLD) rv = FALSE;
|
|
if (AllItemsList[i].itype == IT_FOOD) rv = FALSE;
|
|
if (AllItemsList[i].itype == IT_STAFF
|
|
&& AllItemsList[i].iSpell != 0) rv = FALSE;
|
|
if (AllItemsList[i].itype == IT_RING) rv = FALSE;
|
|
if (AllItemsList[i].itype == IT_AMULET) rv = FALSE;
|
|
return(rv);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int RndSmithItem(int lvl)
|
|
{
|
|
int ril[512]; // Max 512 items
|
|
int ri, i;
|
|
|
|
ri = 0;
|
|
for (i = 1; AllItemsList[i].iLoc != -1; i++) {
|
|
if (AllItemsList[i].iRnd && SmithItemOk(i) &&
|
|
(lvl >= AllItemsList[i].iMinMLvl)
|
|
&& ri < 512) {
|
|
ril[ri++] = i;
|
|
if (AllItemsList[i].iRnd == IRND_DOUBLE
|
|
&& ri < 512) ril[ri++] = i;
|
|
}
|
|
}
|
|
return(ril[random(50, ri)]+1);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void BubbleSwapItem(ItemStruct * a, ItemStruct * b)
|
|
{
|
|
ItemStruct h;
|
|
|
|
h = *a;
|
|
*a = *b;
|
|
*b = h;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SortSmith()
|
|
{
|
|
int j, k;
|
|
BOOL sorted;
|
|
|
|
for (k = 0; smithitem[k+1]._itype != -1; k++);
|
|
sorted = FALSE;
|
|
while ((k > 0) && (!sorted)) {
|
|
sorted = TRUE;
|
|
for (j = 0; j < k; j++) {
|
|
if (smithitem[j].IDidx > smithitem[j+1].IDidx) {
|
|
BubbleSwapItem(&smithitem[j], &smithitem[j+1]);
|
|
sorted = FALSE;
|
|
}
|
|
}
|
|
k--;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SpawnSmith(int lvl)
|
|
{
|
|
int itype;
|
|
int i,nsi;
|
|
ItemStruct const holditem = item[0];
|
|
|
|
nsi = random(50, (MAXSMITHITEMS - 10)) + 10;
|
|
for (i = 0; i < nsi; i++) {
|
|
do {
|
|
item[0]._iSeed = GetRndSeed();
|
|
SetRndSeed(item[0]._iSeed);
|
|
itype = RndSmithItem(lvl) - 1;
|
|
GetItemAttrs(0, itype, lvl);
|
|
} while (item[0]._iIvalue > MAX_STORE_VAL);
|
|
smithitem[i] = item[0];
|
|
smithitem[i]._iCreateInfo = lvl | ICI_SMITH;
|
|
smithitem[i]._iIdentified = TRUE;
|
|
smithitem[i]._iStatFlag = StoreStatOk(&smithitem[i]);
|
|
}
|
|
for (i = nsi; i < MAXSMITHITEMS; i++) smithitem[i]._itype = -1;
|
|
SortSmith();
|
|
item[0] = holditem;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
BOOL PremiumItemOk(int i)
|
|
{
|
|
BOOL rv;
|
|
|
|
rv = TRUE;
|
|
if (AllItemsList[i].itype == IT_MISC) rv = FALSE;
|
|
else if (AllItemsList[i].itype == IT_GOLD) rv = FALSE;
|
|
else if (AllItemsList[i].itype == IT_FOOD) rv = FALSE;
|
|
if (gbMaxPlayers != 1) {
|
|
if (AllItemsList[i].iMiscId == IMID_OIL) rv = FALSE;
|
|
else if (AllItemsList[i].itype == IT_RING) rv = FALSE;
|
|
else if (AllItemsList[i].itype == IT_AMULET) rv = FALSE;
|
|
}
|
|
return(rv);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int RndPremiumItem(int minlvl, int maxlvl)
|
|
{
|
|
int ril[512]; // Max 512 items
|
|
int ri, i;
|
|
|
|
ri = 0;
|
|
for (i = 1; AllItemsList[i].iLoc != -1; i++) {
|
|
if (AllItemsList[i].iRnd && PremiumItemOk(i) &&
|
|
(AllItemsList[i].iMinMLvl >= minlvl) &&
|
|
(AllItemsList[i].iMinMLvl <= maxlvl) &&
|
|
ri < 512) {
|
|
ril[ri++] = i;
|
|
}
|
|
}
|
|
return(ril[random(50, ri)]+1);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
static void SpawnOnePremium(int i, int plvl, int myplr, bool noSpells)
|
|
{
|
|
int itype;
|
|
ItemStruct const holditem = item[0];
|
|
int const maxval = MAX_STORE_VAL;
|
|
int ivalue;
|
|
int iCount = 0;
|
|
int maxPlrStr = GetMaxStr(plr[myplr]._pClass);
|
|
int maxPlrDex = GetMaxDex(plr[myplr]._pClass);
|
|
int maxPlrMag = GetMaxMag(plr[myplr]._pClass);
|
|
|
|
// Test in case of bonus
|
|
if (maxPlrStr < plr[myplr]._pStrength)
|
|
{
|
|
maxPlrStr = plr[myplr]._pStrength;
|
|
}
|
|
maxPlrStr = (int)(maxPlrStr * 1.2);
|
|
|
|
if (maxPlrDex < plr[myplr]._pDexterity)
|
|
{
|
|
maxPlrDex = plr[myplr]._pDexterity;
|
|
}
|
|
maxPlrDex = (int)(maxPlrDex * 1.2);
|
|
|
|
if (maxPlrMag < plr[myplr]._pMagic)
|
|
{
|
|
maxPlrMag = plr[myplr]._pMagic;
|
|
}
|
|
maxPlrMag = (int)(maxPlrMag * 1.2);
|
|
|
|
|
|
#if CHEATS
|
|
if ((plvl > 30) || (davecheat)) plvl = 30;
|
|
#else
|
|
if (plvl > 30) plvl = 30;
|
|
#endif
|
|
if (plvl < 1) plvl = 1;
|
|
|
|
do {
|
|
item[0]._iSeed = GetRndSeed();
|
|
SetRndSeed(item[0]._iSeed);
|
|
itype = RndPremiumItem(plvl>>2, plvl) - 1;
|
|
GetItemAttrs(0, itype, plvl);
|
|
GetItemBonus(0, itype, plvl>>1, plvl, TRUE, noSpells);
|
|
|
|
ivalue = 0;
|
|
|
|
switch (item[0]._itype)
|
|
{
|
|
case IT_ARMOR:
|
|
case IT_MARMOR:
|
|
case IT_HARMOR:
|
|
ivalue = GetHighArmorValue(myplr);
|
|
break;
|
|
case IT_SHIELD:
|
|
ivalue = GetHighShieldValue(myplr);
|
|
break;
|
|
case IT_AXE:
|
|
ivalue = GetHighAxeValue(myplr);
|
|
break;
|
|
case IT_BOW:
|
|
ivalue = GetHighBowValue(myplr);
|
|
break;
|
|
case IT_MACE:
|
|
ivalue = GetHighMaceValue(myplr);
|
|
break;
|
|
case IT_SWORD:
|
|
ivalue = GetHighSwordValue(myplr);
|
|
break;
|
|
case IT_HELM:
|
|
ivalue = GetHighHelmValue(myplr);
|
|
break;
|
|
case IT_STAFF:
|
|
ivalue = GetHighStaffValue(myplr);
|
|
break;
|
|
case IT_RING:
|
|
ivalue = GetHighRingValue(myplr);
|
|
break;
|
|
case IT_AMULET:
|
|
ivalue = GetHighAmuletValue(myplr);
|
|
break;
|
|
}
|
|
ivalue = (int)(0.8 * ivalue);
|
|
|
|
++iCount;
|
|
|
|
// GWP Make sure we can actually use it.
|
|
} while ((item[0]._iIvalue > maxval
|
|
|| item[0]._iMinStr > maxPlrStr
|
|
|| item[0]._iMinMag > maxPlrMag
|
|
|| item[0]._iMinDex > maxPlrDex
|
|
|| item[0]._iIvalue < ivalue) // already have better.
|
|
&& iCount < 150 // prevent infinite loops.
|
|
);
|
|
|
|
premiumitem[i] = item[0];
|
|
premiumitem[i]._iCreateInfo = plvl | ICI_PREMIUM;
|
|
premiumitem[i]._iIdentified = TRUE;
|
|
premiumitem[i]._iStatFlag = StoreStatOk(&premiumitem[i]);
|
|
item[0] = holditem;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int premiumlvladd[MAXPREMIUM] = { -1, -1, -1, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3 };
|
|
|
|
void SpawnPremium(int myplr)
|
|
{
|
|
int lvl = plr[myplr]._pLevel;
|
|
int i;
|
|
|
|
// Empty slots?
|
|
if (numpremium < MAXPREMIUM) {
|
|
for (i = 0; i < MAXPREMIUM; ++i) {
|
|
if (premiumitem[i]._itype == -1)
|
|
SpawnOnePremium(i, premiumlevel + premiumlvladd[i], myplr, false);
|
|
}
|
|
numpremium = MAXPREMIUM;
|
|
}
|
|
// New items?
|
|
while (premiumlevel < lvl) {
|
|
premiumlevel++;
|
|
premiumitem[0] = premiumitem[3];
|
|
premiumitem[1] = premiumitem[4];
|
|
premiumitem[2] = premiumitem[5];
|
|
premiumitem[3] = premiumitem[6];
|
|
premiumitem[4] = premiumitem[7];
|
|
premiumitem[5] = premiumitem[8];
|
|
premiumitem[6] = premiumitem[9];
|
|
premiumitem[7] = premiumitem[10];
|
|
premiumitem[8] = premiumitem[11];
|
|
premiumitem[9] = premiumitem[12];
|
|
SpawnOnePremium(10, premiumlevel + premiumlvladd[10], myplr, false);
|
|
premiumitem[11] = premiumitem[13];
|
|
SpawnOnePremium(12, premiumlevel + premiumlvladd[12], myplr, false);
|
|
premiumitem[13] = premiumitem[14];
|
|
SpawnOnePremium(14, premiumlevel + premiumlvladd[14], myplr, false);
|
|
}
|
|
|
|
#if 15 != MAXPREMIUM
|
|
#error "Fix code for new MAXPREMIUM"
|
|
#endif
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
BOOL WitchItemOk(int i)
|
|
{
|
|
BOOL rv;
|
|
|
|
rv = FALSE;
|
|
if (AllItemsList[i].itype == IT_MISC) rv = TRUE;
|
|
else if (AllItemsList[i].itype == IT_STAFF) rv = TRUE;
|
|
|
|
// Will already have the next one
|
|
if (AllItemsList[i].iMiscId == IMID_PMANA) rv = FALSE;
|
|
else if (AllItemsList[i].iMiscId == IMID_PFMANA) rv = FALSE;
|
|
|
|
if (AllItemsList[i].iSpell == SPL_TOWN) rv = FALSE;
|
|
// no healing
|
|
if (AllItemsList[i].iMiscId == IMID_PHEAL) rv = FALSE;
|
|
else if (AllItemsList[i].iMiscId == IMID_PLHEAL) rv = FALSE;
|
|
|
|
// no oils
|
|
if (AllItemsList[i].iMiscId > IMID_FIRSTOIL &&
|
|
AllItemsList[i].iMiscId < IMID_LASTOIL)
|
|
rv = FALSE;
|
|
// None of these in single player
|
|
if (AllItemsList[i].iSpell == SPL_RESURRECT && gbMaxPlayers == 1) rv = FALSE;
|
|
else if (AllItemsList[i].iSpell == SPL_HEALOTHER && gbMaxPlayers == 1) rv = FALSE;
|
|
|
|
return(rv);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int RndWitchItem(int lvl)
|
|
{
|
|
int ril[512]; // Max 512 items
|
|
int ri, i;
|
|
|
|
ri = 0;
|
|
for (i = 1; AllItemsList[i].iLoc != -1; ++i) {
|
|
if (AllItemsList[i].iRnd && WitchItemOk(i) &&
|
|
(lvl >= AllItemsList[i].iMinMLvl) &&
|
|
ri < 512)
|
|
{
|
|
ril[ri++] = i;
|
|
}
|
|
}
|
|
return(ril[random(51, ri)]+1);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SortWitch()
|
|
{
|
|
int j, k;
|
|
BOOL sorted;
|
|
|
|
for (k = 3; witchitem[k+1]._itype != -1; k++);
|
|
sorted = FALSE;
|
|
while ((k > 3) && (!sorted)) {
|
|
sorted = TRUE;
|
|
for (j = 3; j < k; j++) {
|
|
if (witchitem[j].IDidx > witchitem[j+1].IDidx) {
|
|
BubbleSwapItem(&witchitem[j], &witchitem[j+1]);
|
|
sorted = FALSE;
|
|
}
|
|
}
|
|
k--;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void WitchBookLevel(int ii)
|
|
{
|
|
if (witchitem[ii]._iMiscId != IMID_BOOK)
|
|
return;
|
|
|
|
witchitem[ii]._iMinMag = spelldata[witchitem[ii]._iSpell].sMinInt;
|
|
int slvl = plr[myplr]._pSplLvl[witchitem[ii]._iSpell];
|
|
|
|
while (slvl != 0) {
|
|
witchitem[ii]._iMinMag += ((witchitem[ii]._iMinMag * 20) / 100);
|
|
slvl--;
|
|
if ((witchitem[ii]._iMinMag + ((witchitem[ii]._iMinMag * 20) / 100)) > 255) {
|
|
witchitem[ii]._iMinMag = 255;
|
|
slvl = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SpawnWitch(int lvl)
|
|
{
|
|
int itype, iblvl;
|
|
int i;
|
|
int start = 3;
|
|
|
|
int const nsi = random(51, (MAXWITCHITEMS - 10)) + 10;
|
|
int const max_number_of_books = random(3, 1 + (IDI_LAST_BOOK - IDI_FIRST_BOOK));
|
|
int number_of_books;
|
|
|
|
// Will always have mana (endless supply)
|
|
GetItemAttrs(0, IDI_MANA, 1);
|
|
witchitem[0] = item[0];
|
|
witchitem[0]._iCreateInfo = lvl;
|
|
witchitem[0]._iStatFlag = TRUE;
|
|
GetItemAttrs(0, IDI_FULLMANA, 1);
|
|
witchitem[1] = item[0];
|
|
witchitem[1]._iCreateInfo = lvl;
|
|
witchitem[1]._iStatFlag = TRUE;
|
|
GetItemAttrs(0, IDI_PORTAL, 1);
|
|
witchitem[2] = item[0];
|
|
witchitem[2]._iCreateInfo = lvl;
|
|
witchitem[2]._iStatFlag = TRUE;
|
|
for (i = IDI_FIRST_BOOK, number_of_books = 0;
|
|
i <= IDI_LAST_BOOK
|
|
&& number_of_books < max_number_of_books;
|
|
++i)
|
|
{
|
|
|
|
if ( WitchItemOk(i)
|
|
&& lvl >= AllItemsList[i].iMinMLvl
|
|
)
|
|
{
|
|
item[0]._iSeed = GetRndSeed();
|
|
SetRndSeed(item[0]._iSeed);
|
|
volatile int dummy = random(0, 1); // to sync with below
|
|
|
|
GetItemAttrs(0, i, lvl);
|
|
witchitem[start] = item[0];
|
|
witchitem[start]._iCreateInfo = lvl | ICI_WITCH;
|
|
witchitem[start]._iIdentified = TRUE;
|
|
WitchBookLevel(start);
|
|
witchitem[start]._iStatFlag = StoreStatOk(&witchitem[start]);
|
|
++start;
|
|
++number_of_books;
|
|
}
|
|
}
|
|
|
|
for (i = start; i < nsi; ++i) {
|
|
do {
|
|
item[0]._iSeed = GetRndSeed();
|
|
SetRndSeed(item[0]._iSeed);
|
|
itype = RndWitchItem(lvl) - 1;
|
|
GetItemAttrs(0, itype, lvl);
|
|
iblvl = -1;
|
|
if (random(51, 100) <= 5) iblvl = lvl << 1;
|
|
// Force staffs to be magical
|
|
if ((iblvl == -1) && (item[0]._iMiscId == IMID_STAFF)) iblvl = lvl << 1;
|
|
#if CHEATS
|
|
if (cheatflag) iblvl = lvl << 1;
|
|
#endif
|
|
if (iblvl != -1) GetItemBonus(0, itype, iblvl >> 1, iblvl, TRUE, true);
|
|
} while (item[0]._iIvalue > MAX_STORE_VAL);
|
|
witchitem[i] = item[0];
|
|
witchitem[i]._iCreateInfo = lvl | ICI_WITCH;
|
|
witchitem[i]._iIdentified = TRUE;
|
|
WitchBookLevel(i);
|
|
witchitem[i]._iStatFlag = StoreStatOk(&witchitem[i]);
|
|
//WitchBookLevel(i);
|
|
}
|
|
for (i = nsi; i < MAXWITCHITEMS; i++) witchitem[i]._itype = -1;
|
|
SortWitch();
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int RndBoyItem(int lvl)
|
|
{
|
|
int ril[512]; // Max 512 items
|
|
int ri, i;
|
|
|
|
ri = 0;
|
|
for (i = 1; AllItemsList[i].iLoc != -1; ++i) {
|
|
if (AllItemsList[i].iRnd && PremiumItemOk(i) &&
|
|
(lvl >= AllItemsList[i].iMinMLvl) &&
|
|
ri < 512) ril[ri++] = i;
|
|
}
|
|
return(ril[random(49, ri)]+1);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SpawnBoy(int lvl)
|
|
{
|
|
int itype;
|
|
int ivalue;
|
|
int iCount = 0;
|
|
int maxPlrStr = GetMaxStr(plr[myplr]._pClass);
|
|
int maxPlrDex = GetMaxDex(plr[myplr]._pClass);
|
|
int maxPlrMag = GetMaxMag(plr[myplr]._pClass);
|
|
int const PlayerClass = plr[myplr]._pClass;
|
|
|
|
// Test in case of bonus
|
|
if (maxPlrStr < plr[myplr]._pStrength)
|
|
{
|
|
maxPlrStr = plr[myplr]._pStrength;
|
|
}
|
|
maxPlrStr = (int)(maxPlrStr * 1.2);
|
|
|
|
if (maxPlrDex < plr[myplr]._pDexterity)
|
|
{
|
|
maxPlrDex = plr[myplr]._pDexterity;
|
|
}
|
|
maxPlrDex = (int)(maxPlrDex * 1.2);
|
|
|
|
if (maxPlrMag < plr[myplr]._pMagic)
|
|
{
|
|
maxPlrMag = plr[myplr]._pMagic;
|
|
}
|
|
maxPlrMag = (int)(maxPlrMag * 1.2);
|
|
|
|
|
|
|
|
if ((boylevel < (lvl >> 1)) || (boyitem._itype == -1)) {
|
|
do {
|
|
item[0]._iSeed = GetRndSeed();
|
|
SetRndSeed(item[0]._iSeed);
|
|
itype = RndBoyItem(lvl) - 1;
|
|
GetItemAttrs(0, itype, lvl);
|
|
// Always magical
|
|
GetItemBonus(0, itype, lvl, lvl << 1, TRUE, true);
|
|
ivalue = 0;
|
|
|
|
int const itemType = item[0]._itype;
|
|
|
|
switch (itemType)
|
|
{
|
|
case IT_ARMOR:
|
|
case IT_MARMOR:
|
|
case IT_HARMOR:
|
|
ivalue = GetHighArmorValue(myplr);
|
|
break;
|
|
case IT_SHIELD:
|
|
ivalue = GetHighShieldValue(myplr);
|
|
break;
|
|
case IT_AXE:
|
|
ivalue = GetHighAxeValue(myplr);
|
|
break;
|
|
case IT_BOW:
|
|
ivalue = GetHighBowValue(myplr);
|
|
break;
|
|
case IT_MACE:
|
|
ivalue = GetHighMaceValue(myplr);
|
|
break;
|
|
case IT_SWORD:
|
|
ivalue = GetHighSwordValue(myplr);
|
|
break;
|
|
case IT_HELM:
|
|
ivalue = GetHighHelmValue(myplr);
|
|
break;
|
|
case IT_STAFF:
|
|
ivalue = GetHighStaffValue(myplr);
|
|
break;
|
|
case IT_RING:
|
|
ivalue = GetHighRingValue(myplr);
|
|
break;
|
|
case IT_AMULET:
|
|
ivalue = GetHighAmuletValue(myplr);
|
|
break;
|
|
}
|
|
ivalue = (int)(0.8 * ivalue);
|
|
|
|
++iCount;
|
|
|
|
if (iCount < 200) // prevent infinite loops.
|
|
{
|
|
switch (PlayerClass)
|
|
{
|
|
case CLASS_WARRIOR:
|
|
if (itemType == IT_BOW
|
|
|| itemType == IT_STAFF)
|
|
ivalue = INT_MAX;
|
|
break;
|
|
case CLASS_ROGUE:
|
|
if (itemType == IT_SWORD
|
|
|| itemType == IT_STAFF
|
|
|| itemType == IT_AXE
|
|
|| itemType == IT_MACE
|
|
|| itemType == IT_SHIELD)
|
|
ivalue = INT_MAX;
|
|
break;
|
|
case CLASS_SORCEROR:
|
|
if (itemType == IT_STAFF
|
|
|| itemType == IT_AXE
|
|
|| itemType == IT_BOW
|
|
|| itemType == IT_MACE)
|
|
ivalue = INT_MAX;
|
|
break;
|
|
case CLASS_MONK:
|
|
if (itemType == IT_BOW
|
|
|| itemType == IT_MARMOR
|
|
|| itemType == IT_SHIELD
|
|
|| itemType == IT_MACE)
|
|
ivalue = INT_MAX;
|
|
break;
|
|
case CLASS_BARD:
|
|
if (itemType == IT_AXE
|
|
|| itemType == IT_MACE
|
|
|| itemType == IT_STAFF)
|
|
ivalue = INT_MAX;
|
|
break;
|
|
case CLASS_BARBARIAN:
|
|
if (itemType == IT_BOW
|
|
|| itemType == IT_STAFF)
|
|
ivalue = INT_MAX;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
} while ((item[0]._iIvalue > MAX_WIRT_VAL
|
|
|| item[0]._iMinStr > maxPlrStr
|
|
|| item[0]._iMinMag > maxPlrMag
|
|
|| item[0]._iMinDex > maxPlrDex
|
|
|| item[0]._iIvalue < ivalue) // already have better.
|
|
&& iCount < 250 // prevent infinite loops.
|
|
);
|
|
boyitem = item[0];
|
|
boyitem._iCreateInfo = lvl | ICI_BOY;
|
|
boyitem._iIdentified = TRUE;
|
|
boyitem._iStatFlag = StoreStatOk(&boyitem);
|
|
boylevel = lvl >> 1;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
BOOL HealerItemOk(int i)
|
|
{
|
|
BOOL rv;
|
|
|
|
rv = FALSE;
|
|
if (AllItemsList[i].itype != IT_MISC) return(FALSE);
|
|
// Heal scrolls
|
|
if ((AllItemsList[i].iMiscId == IMID_SCROLL) && (AllItemsList[i].iSpell == SPL_HEAL)) rv = TRUE;
|
|
// Will always have Resurrect scrolls (multiplayer only)
|
|
if ((AllItemsList[i].iMiscId == IMID_TSCROLL) && (AllItemsList[i].iSpell == SPL_RESURRECT) && (gbMaxPlayers != 1)) rv = FALSE;
|
|
// Heal Other scroll (multiplayer only)
|
|
if ((AllItemsList[i].iMiscId == IMID_TSCROLL) && (AllItemsList[i].iSpell == SPL_HEALOTHER) && (gbMaxPlayers != 1)) rv = TRUE;
|
|
// Elixirs
|
|
if (gbMaxPlayers == 1) {
|
|
if (AllItemsList[i].iMiscId == IMID_ESTR
|
|
&& plr[myplr]._pBaseStr < MaxStats[plr[myplr]._pClass][0]) rv = TRUE;
|
|
else if (AllItemsList[i].iMiscId == IMID_EMAG
|
|
&& plr[myplr]._pBaseMag < MaxStats[plr[myplr]._pClass][1]) rv = TRUE;
|
|
else if (AllItemsList[i].iMiscId == IMID_EDEX
|
|
&& plr[myplr]._pBaseDex < MaxStats[plr[myplr]._pClass][2]) rv = TRUE;
|
|
else if (AllItemsList[i].iMiscId == IMID_EVIT
|
|
&& plr[myplr]._pBaseVit < MaxStats[plr[myplr]._pClass][3]) rv = TRUE;
|
|
}
|
|
// Potions
|
|
if (AllItemsList[i].iMiscId == IMID_PHEAL) rv = TRUE;
|
|
else if (AllItemsList[i].iMiscId == IMID_REJUV) rv = TRUE;
|
|
else if (AllItemsList[i].iMiscId == IMID_FREJUV) rv = TRUE;
|
|
// Will always have these
|
|
else if (AllItemsList[i].iMiscId == IMID_PLHEAL) rv = FALSE;
|
|
else if (AllItemsList[i].iMiscId == IMID_PHEAL) rv = FALSE;
|
|
// No mana
|
|
else if (AllItemsList[i].iMiscId == IMID_PMANA) rv = FALSE;
|
|
else if (AllItemsList[i].iMiscId == IMID_PFMANA) rv = FALSE;
|
|
return(rv);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int RndHealerItem(int lvl)
|
|
{
|
|
int ril[512]; // Max 512 items
|
|
int ri, i;
|
|
|
|
ri = 0;
|
|
for (i = 1; AllItemsList[i].iLoc != -1; i++) {
|
|
if (AllItemsList[i].iRnd && HealerItemOk(i) &&
|
|
(lvl >= AllItemsList[i].iMinMLvl) &&
|
|
ri < 512) ril[ri++] = i;
|
|
}
|
|
return(ril[random(50, ri)]+1);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SortHealer()
|
|
{
|
|
int j, k;
|
|
BOOL sorted;
|
|
|
|
for (k = 2; healitem[k+1]._itype != -1; k++);
|
|
sorted = FALSE;
|
|
while ((k > 2) && (!sorted)) {
|
|
sorted = TRUE;
|
|
for (j = 2; j < k; j++) {
|
|
if (healitem[j].IDidx > healitem[j+1].IDidx) {
|
|
BubbleSwapItem(&healitem[j], &healitem[j+1]);
|
|
sorted = FALSE;
|
|
}
|
|
}
|
|
k--;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SpawnHealer(int lvl)
|
|
{
|
|
int itype;
|
|
int i,nsi,srnd;
|
|
|
|
// Will always have healing (endless supply)
|
|
GetItemAttrs(0, IDI_HEAL, 1);
|
|
healitem[0] = item[0];
|
|
healitem[0]._iCreateInfo = lvl;
|
|
healitem[0]._iStatFlag = TRUE;
|
|
GetItemAttrs(0, IDI_FULLHEAL, 1);
|
|
healitem[1] = item[0];
|
|
healitem[1]._iCreateInfo = lvl;
|
|
healitem[1]._iStatFlag = TRUE;
|
|
if (gbMaxPlayers != 1) {
|
|
GetItemAttrs(0, IDI_RESURRECT, 1);
|
|
healitem[2] = item[0];
|
|
healitem[2]._iCreateInfo = lvl;
|
|
healitem[2]._iStatFlag = TRUE;
|
|
srnd = 3;
|
|
} else srnd = 2;
|
|
|
|
nsi = random(50, (MAXHEALITEMS - 10)) + 10;
|
|
for (i = srnd; i < nsi; i++) {
|
|
item[0]._iSeed = GetRndSeed();
|
|
SetRndSeed(item[0]._iSeed);
|
|
itype = RndHealerItem(lvl) - 1;
|
|
GetItemAttrs(0, itype, lvl);
|
|
healitem[i] = item[0];
|
|
healitem[i]._iCreateInfo = lvl | ICI_HEALER;
|
|
healitem[i]._iIdentified = TRUE;
|
|
healitem[i]._iStatFlag = StoreStatOk(&healitem[i]);
|
|
}
|
|
for (i = nsi; i < MAXHEALITEMS; i++) healitem[i]._itype = -1;
|
|
SortHealer();
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void SpawnStoreGold()
|
|
{
|
|
// Setup a gold item to place in inv if they sell
|
|
GetItemAttrs(0, 0, 1);
|
|
golditem = item[0];
|
|
golditem._iStatFlag = TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void RecreateSmithItem(int ii, int idx, int lvl, int iseed)
|
|
{
|
|
SetRndSeed(iseed);
|
|
int itype = RndSmithItem(lvl) - 1;
|
|
GetItemAttrs(ii, itype, lvl);
|
|
item[ii]._iSeed = iseed;
|
|
item[ii]._iCreateInfo = lvl | ICI_SMITH;
|
|
item[ii]._iIdentified = TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void RecreatePremiumItem(int ii, int idx, int plvl, int iseed)
|
|
{
|
|
SetRndSeed(iseed);
|
|
int itype = RndPremiumItem(plvl>>2, plvl) - 1;
|
|
GetItemAttrs(ii, itype, plvl);
|
|
GetItemBonus(ii, itype, plvl>>1, plvl, TRUE, false);
|
|
item[ii]._iSeed = iseed;
|
|
item[ii]._iCreateInfo = plvl | ICI_PREMIUM;
|
|
item[ii]._iIdentified = TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void RecreateBoyItem(int ii, int idx, int lvl, int iseed)
|
|
{
|
|
SetRndSeed(iseed);
|
|
int itype = RndBoyItem(lvl) - 1;
|
|
GetItemAttrs(ii, itype, lvl);
|
|
// Always magical
|
|
GetItemBonus(ii, itype, lvl, lvl << 1, TRUE, true);
|
|
item[ii]._iSeed = iseed;
|
|
item[ii]._iCreateInfo = lvl | ICI_BOY;
|
|
item[ii]._iIdentified = TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void RecreateWitchItem(int ii, int idx, int lvl, int iseed)
|
|
{
|
|
if ((idx == IDI_MANA)
|
|
|| (idx == IDI_FULLMANA)
|
|
|| (idx == IDI_PORTAL))
|
|
{
|
|
GetItemAttrs(ii, idx, lvl);
|
|
} else if( idx >= IDI_FIRST_BOOK && idx <= IDI_LAST_BOOK) {
|
|
SetRndSeed(iseed);
|
|
volatile int dummy = random(0, 1); // to sync with below
|
|
GetItemAttrs(ii, idx, lvl);
|
|
} else {
|
|
SetRndSeed(iseed);
|
|
int itype = RndWitchItem(lvl) - 1;
|
|
GetItemAttrs(ii, itype, lvl);
|
|
int iblvl = -1;
|
|
if (random(51, 100) <= 5) iblvl = lvl << 1;
|
|
// Force staffs to be magical
|
|
if ((iblvl == -1) && (item[ii]._iMiscId == IMID_STAFF)) iblvl = lvl << 1;
|
|
#if CHEATS
|
|
if (cheatflag) iblvl = lvl << 1;
|
|
#endif
|
|
if (iblvl != -1) GetItemBonus(ii, itype, iblvl >> 1, iblvl, TRUE, true);
|
|
}
|
|
item[ii]._iSeed = iseed;
|
|
item[ii]._iCreateInfo = lvl | ICI_WITCH;
|
|
item[ii]._iIdentified = TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void RecreateHealerItem(int ii, int idx, int lvl, int iseed)
|
|
{
|
|
if ((idx == IDI_HEAL) || (idx == IDI_FULLHEAL) || (idx == IDI_RESURRECT)) {
|
|
GetItemAttrs(ii, idx, lvl);
|
|
} else {
|
|
SetRndSeed(iseed);
|
|
int itype = RndHealerItem(lvl) - 1;
|
|
GetItemAttrs(ii, itype, lvl);
|
|
}
|
|
item[ii]._iSeed = iseed;
|
|
item[ii]._iCreateInfo = lvl | ICI_HEALER;
|
|
item[ii]._iIdentified = TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
** Recreate any item with the proper info
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void RecreateTownItem(int ii, int idx, WORD icreateinfo, int iseed, int ivalue)
|
|
{
|
|
if (icreateinfo & ICI_SMITH) RecreateSmithItem(ii, idx, icreateinfo & ICI_LVLMASK, iseed);
|
|
else if (icreateinfo & ICI_PREMIUM) RecreatePremiumItem(ii, idx, icreateinfo & ICI_LVLMASK, iseed);
|
|
else if (icreateinfo & ICI_BOY) RecreateBoyItem(ii, idx, icreateinfo & ICI_LVLMASK, iseed);
|
|
else if (icreateinfo & ICI_WITCH) RecreateWitchItem(ii, idx, icreateinfo & ICI_LVLMASK, iseed);
|
|
else if (icreateinfo & ICI_HEALER) RecreateHealerItem(ii, idx, icreateinfo & ICI_LVLMASK, iseed);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
#if CHEATS
|
|
void DaveGold()
|
|
{
|
|
int i,j;
|
|
|
|
for (j = 0; j < MAXINV; j++) {
|
|
if (plr[myplr].InvGrid[j] == 0) {
|
|
i = plr[myplr]._pNumInv;
|
|
SetPlrHandItem(&plr[myplr].InvList[i], IDI_GOLD);
|
|
GetGoldSeed(myplr, &plr[myplr].InvList[i]);
|
|
plr[myplr].InvList[i]._ivalue = 5000;
|
|
plr[myplr].InvList[i]._iCurs = ITEM_5GOLD;
|
|
plr[myplr].InvList[i]._iStatFlag = TRUE;
|
|
plr[myplr]._pGold += 5000;
|
|
plr[myplr]._pNumInv++;
|
|
plr[myplr].InvGrid[j] = plr[myplr]._pNumInv;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
#if CHEATS
|
|
void DaveNewPremium()
|
|
{
|
|
numpremium = 0;
|
|
for (int i = 0; i < MAXPREMIUM; i++) premiumitem[i]._itype = -1;
|
|
SpawnPremium(30);
|
|
for (i = 0; i < MAXWITCHITEMS; i++) witchitem[i]._itype = -1;
|
|
SpawnWitch(30);
|
|
}
|
|
#endif
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
#if CHEATS
|
|
void DaveCleanUp()
|
|
{
|
|
int i,j;
|
|
|
|
for (j = 0; j < MAXINV; j++) {
|
|
if (plr[myplr].InvGrid[j] > 0) {
|
|
i = plr[myplr].InvGrid[j]-1;
|
|
if (plr[myplr].InvList[i]._itype == IT_GOLD) RemoveInvItem(myplr, i);
|
|
}
|
|
}
|
|
for (j = 0; j < MAXSPD; j++) {
|
|
if (plr[myplr].SpdList[j]._itype == IT_GOLD) plr[myplr].SpdList[j]._itype = -1;
|
|
}
|
|
plr[myplr]._pGold = 0;
|
|
}
|
|
#endif
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
#if CHEATS
|
|
void DaveSpells()
|
|
{
|
|
for (int i = SPL_FIREBOLT; i < SPL_LAST; i++) {
|
|
if (spelldata[i].sBookLvl != -1) {
|
|
__int64 t = 1;
|
|
plr[myplr]._pMemSpells |= (t << (i-1));
|
|
plr[myplr]._pSplLvl[i] = 10;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
#if CHEATS
|
|
void DaveSetSpell(int spl, int lvl)
|
|
{
|
|
__int64 t = 1;
|
|
plr[myplr]._pMemSpells |= (t << (spl-1));
|
|
plr[myplr]._pSplLvl[spl] = lvl;
|
|
}
|
|
#endif
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
#if CHEATS
|
|
void DaveSpells2()
|
|
{
|
|
DaveSetSpell(SPL_FIREBOLT, 8);
|
|
DaveSetSpell(SPL_CBOLT, 11);
|
|
DaveSetSpell(SPL_HBOLT, 10);
|
|
DaveSetSpell(SPL_HEAL, 7);
|
|
DaveSetSpell(SPL_HEALOTHER, 5);
|
|
DaveSetSpell(SPL_LIGHTNING, 9);
|
|
DaveSetSpell(SPL_WALL, 5);
|
|
DaveSetSpell(SPL_TELEKINESIS, 3);
|
|
DaveSetSpell(SPL_TOWN, 3);
|
|
DaveSetSpell(SPL_FLASH, 3);
|
|
DaveSetSpell(SPL_PHASE, 2);
|
|
DaveSetSpell(SPL_MANASHLD, 2);
|
|
DaveSetSpell(SPL_WAVE, 4);
|
|
DaveSetSpell(SPL_FIREBALL, 3);
|
|
DaveSetSpell(SPL_STONE, 1);
|
|
DaveSetSpell(SPL_CHAIN, 1);
|
|
DaveSetSpell(SPL_GUARDIAN, 4);
|
|
DaveSetSpell(SPL_ELEMENT, 3);
|
|
DaveSetSpell(SPL_NOVA, 1);
|
|
DaveSetSpell(SPL_GOLEM, 2);
|
|
DaveSetSpell(SPL_BSTAR, 1);
|
|
DaveSetSpell(SPL_BONESPIRIT, 1);
|
|
}
|
|
#endif
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void RecalcStoreStats()
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < MAXSMITHITEMS; i++)
|
|
if (smithitem[i]._itype != -1) smithitem[i]._iStatFlag = StoreStatOk(&smithitem[i]);
|
|
for (i = 0; i < MAXPREMIUM; i++)
|
|
if (premiumitem[i]._itype != -1) premiumitem[i]._iStatFlag = StoreStatOk(&premiumitem[i]);
|
|
for (i = 0; i < MAXWITCHITEMS; i++)
|
|
if (witchitem[i]._itype != -1) witchitem[i]._iStatFlag = StoreStatOk(&witchitem[i]);
|
|
for (i = 0; i < MAXHEALITEMS; i++)
|
|
if (healitem[i]._itype != -1) healitem[i]._iStatFlag = StoreStatOk(&healitem[i]);
|
|
boyitem._iStatFlag = StoreStatOk(&boyitem);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
int ItemNoFlippy()
|
|
/*-----------------------------------------------------------------------**
|
|
** DESCRIPTION: Makes it so a newly created item will not have a flippy.
|
|
** INPUT: None
|
|
** RETURN: r = The item number if needed.
|
|
/*-----------------------------------------------------------------------*/
|
|
{
|
|
int r;
|
|
|
|
r = itemactive[numitems-1];
|
|
item[r]._iAnimFrame = item[r]._iAnimLen;
|
|
item[r]._iAnimFlag = FALSE;
|
|
item[r]._iSelFlag = ISEL_FLR;
|
|
|
|
return r;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
#if CHEATS
|
|
void DaveQuestText()
|
|
{
|
|
if (!tstQMsgIndexFlag) {
|
|
tstQMsgFlag = TRUE;
|
|
InitQTextMsg(tstQMsgIndex);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void CreateSpellBook(int x, int y, int ispell, BOOL sendmsg, BOOL delta)
|
|
{
|
|
int ii, idx;
|
|
BOOL done = FALSE;
|
|
|
|
int bookminlevel = spelldata[ispell].sBookLvl + 1;
|
|
|
|
if (bookminlevel < 1) // unavailable
|
|
return;
|
|
|
|
idx = RndTypeItems(IT_MISC, IMID_BOOK, bookminlevel);
|
|
if (numitems < MAXITEMS) {
|
|
ii = itemavail[0];
|
|
GetSuperItemSpace(x,y,ii);
|
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1];
|
|
itemactive[numitems] = ii;
|
|
//Loop until we get the book requested
|
|
do {
|
|
SetupAllItems(ii, idx, GetRndSeed(), /* currlevel */ bookminlevel << 1, 1, TRUE, FALSE, delta);
|
|
if ((item[ii]._iMiscId == IMID_BOOK) &&
|
|
(item[ii]._iSpell == ispell)) {
|
|
done = TRUE;
|
|
}
|
|
} while (!done);
|
|
if (sendmsg) NetSendCmdDItem(FALSE, ii);
|
|
if (delta) DeltaAddItem(ii);
|
|
numitems++;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void CreateMagicArmor(int x, int y, int imisc, int icurs, BOOL sendmsg, BOOL delta)
|
|
{
|
|
int ii, idx;
|
|
BOOL done = FALSE;
|
|
|
|
int efflevel = GetEffLevel();
|
|
|
|
if (numitems < MAXITEMS) {
|
|
ii = itemavail[0];
|
|
GetSuperItemSpace(x,y,ii);
|
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1];
|
|
itemactive[numitems] = ii;
|
|
//Loop until we get the armor requested
|
|
idx = RndTypeItems(imisc, IMID_NONE, efflevel);
|
|
do {
|
|
#if CHEATS
|
|
if (itemcheat)
|
|
SetupAllItems(ii, idx, GetRndSeed(), efflevel << 1, 15, TRUE, FALSE, delta);
|
|
else
|
|
#endif
|
|
SetupAllItems(ii, idx, GetRndSeed(), efflevel << 1, 1, TRUE, FALSE, delta);
|
|
if (item[ii]._iCurs == icurs) {
|
|
done = TRUE;
|
|
} else idx = RndTypeItems(imisc, IMID_NONE, efflevel);
|
|
} while (!done);
|
|
if (sendmsg) NetSendCmdDItem(FALSE, ii);
|
|
if (delta) DeltaAddItem(ii);
|
|
numitems++;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void CreateAmulet(int x, int y, int level, BOOL sendmsg, BOOL delta)
|
|
{
|
|
int ii, idx;
|
|
bool done = false;
|
|
|
|
if (numitems < MAXITEMS) {
|
|
ii = itemavail[0];
|
|
GetSuperItemSpace(x,y,ii);
|
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1];
|
|
itemactive[numitems] = ii;
|
|
//Loop until we get the amulet requested
|
|
idx = RndTypeItems(IT_AMULET, IMID_AMULET, level);
|
|
do {
|
|
#if CHEATS
|
|
if (itemcheat)
|
|
SetupAllItems(ii, idx, GetRndSeed(), level << 1, 15, TRUE, FALSE, delta);
|
|
else
|
|
#endif
|
|
SetupAllItems(ii, idx, GetRndSeed(), level << 1, 1, TRUE, FALSE, delta);
|
|
if (item[ii]._iCurs == ITEM_AMULET1) {
|
|
done = true;
|
|
} else idx = RndTypeItems(IT_AMULET, IMID_AMULET, level);
|
|
} while (!done);
|
|
if (sendmsg) NetSendCmdDItem(FALSE, ii);
|
|
if (delta) DeltaAddItem(ii);
|
|
numitems++;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
|
|
void CreateMagicWeapon(int x, int y, int imisc, int icurs, BOOL sendmsg, BOOL delta)
|
|
{
|
|
int ii, idx;
|
|
BOOL done = FALSE;
|
|
int const imid = (imisc == IT_STAFF) ? IMID_STAFF : IMID_NONE;
|
|
|
|
int efflevel = GetEffLevel();
|
|
|
|
if (numitems < MAXITEMS) {
|
|
ii = itemavail[0];
|
|
GetSuperItemSpace(x,y,ii);
|
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1];
|
|
itemactive[numitems] = ii;
|
|
//Loop until we get the weapon requested
|
|
idx = RndTypeItems(imisc, imid, efflevel);
|
|
do {
|
|
#if CHEATS
|
|
if (itemcheat)
|
|
SetupAllItems(ii, idx, GetRndSeed(), efflevel << 1, 15, TRUE, FALSE, delta);
|
|
else
|
|
#endif
|
|
SetupAllItems(ii, idx, GetRndSeed(), efflevel << 1, 1, TRUE, FALSE, delta);
|
|
if (item[ii]._iCurs == icurs) {
|
|
done = TRUE;
|
|
} else idx = RndTypeItems(imisc, imid, efflevel);
|
|
} while (!done);
|
|
if (sendmsg) NetSendCmdDItem(FALSE, ii);
|
|
if (delta) DeltaAddItem(ii);
|
|
numitems++;
|
|
}
|
|
}
|
|
|
|
|
|
// PATCH1.JMM
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
static void DeleteGetRecord( int nIndex ) {
|
|
app_assert(nIndex < gnNumGetRecords);
|
|
app_assert(gnNumGetRecords > 0);
|
|
|
|
gnNumGetRecords--;
|
|
|
|
if(gnNumGetRecords == 0)
|
|
return;
|
|
|
|
itemgets[nIndex].nIndex = itemgets[gnNumGetRecords].nIndex;
|
|
itemgets[nIndex].nSeed = itemgets[gnNumGetRecords].nSeed;
|
|
itemgets[nIndex].wCI = itemgets[gnNumGetRecords].wCI;
|
|
itemgets[nIndex].dwTimestamp = itemgets[gnNumGetRecords].dwTimestamp;
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
#define RESEND_TIME 6000 // number of milliseconds to keep a getrecord around
|
|
|
|
BOOL CheckGetRecord( int nSeed, WORD wCI, int nIndex ) {
|
|
DWORD dwCurr = GetTickCount();
|
|
int i;
|
|
|
|
for(i = 0; i < gnNumGetRecords; i++) {
|
|
if( (dwCurr - itemgets[i].dwTimestamp) > RESEND_TIME ) {
|
|
DeleteGetRecord( i );
|
|
i--;
|
|
continue;
|
|
}
|
|
|
|
if( (nSeed == itemgets[i].nSeed) && (wCI == itemgets[i].wCI) && (nIndex == itemgets[i].nIndex) )
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void AddGetRecord( int nSeed, WORD wCI, int nIndex ) {
|
|
DWORD dwCurr = GetTickCount();
|
|
|
|
if(gnNumGetRecords == MAXITEMS)
|
|
return;
|
|
|
|
itemgets[gnNumGetRecords].dwTimestamp = dwCurr;
|
|
itemgets[gnNumGetRecords].nSeed = nSeed;
|
|
itemgets[gnNumGetRecords].wCI = wCI;
|
|
itemgets[gnNumGetRecords].nIndex = nIndex;
|
|
|
|
gnNumGetRecords++;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*
|
|
**-----------------------------------------------------------------------*/
|
|
void RemoveGetRecord( int nSeed, WORD wCI, int nIndex ) {
|
|
DWORD dwCurr = GetTickCount();
|
|
int i;
|
|
|
|
for(i = 0; i < gnNumGetRecords; i++) {
|
|
if( (dwCurr - itemgets[i].dwTimestamp) > RESEND_TIME ) {
|
|
DeleteGetRecord( i );
|
|
i--;
|
|
continue;
|
|
}
|
|
|
|
if( (nSeed == itemgets[i].nSeed) && (wCI == itemgets[i].wCI) && (nIndex == itemgets[i].nIndex) ) {
|
|
DeleteGetRecord( i );
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//ENDPATCH1.JMM
|