You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4063 lines
94 KiB
4063 lines
94 KiB
#include "diablo.h" |
|
|
|
int itemactive[MAXITEMS]; |
|
int uitemflag; |
|
int itemavail[MAXITEMS]; |
|
ItemStruct curruitem; |
|
ItemGetRecordStruct itemrecord[MAXITEMS]; |
|
ItemStruct item[MAXITEMS + 1]; |
|
BOOL itemhold[3][3]; |
|
BYTE *itemanims[35]; |
|
BOOL UniqueItemFlag[128]; |
|
int numitems; |
|
int gnNumGetRecords; |
|
|
|
/* data */ |
|
|
|
BYTE ItemCAnimTbl[169] = { |
|
20, 16, 16, 16, 4, 4, 4, 12, 12, 12, |
|
12, 12, 12, 12, 12, 21, 21, 25, 12, 28, |
|
28, 28, 0, 0, 0, 32, 0, 0, 0, 24, |
|
24, 26, 2, 25, 22, 23, 24, 25, 27, 27, |
|
29, 0, 0, 0, 12, 12, 12, 12, 12, 0, |
|
8, 8, 0, 8, 8, 8, 8, 8, 8, 6, |
|
8, 8, 8, 6, 8, 8, 6, 8, 8, 6, |
|
6, 6, 8, 8, 8, 5, 9, 13, 13, 13, |
|
5, 5, 5, 15, 5, 5, 18, 18, 18, 30, |
|
5, 5, 14, 5, 14, 13, 16, 18, 5, 5, |
|
7, 1, 3, 17, 1, 15, 10, 14, 3, 11, |
|
8, 0, 1, 7, 0, 7, 15, 7, 3, 3, |
|
3, 6, 6, 11, 11, 11, 31, 14, 14, 14, |
|
6, 6, 7, 3, 8, 14, 0, 14, 14, 0, |
|
33, 1, 1, 1, 1, 1, 7, 7, 7, 14, |
|
14, 17, 17, 17, 0, 34, 1, 0, 3, 17, |
|
8, 8, 6, 1, 3, 3, 11, 3, 4 |
|
}; |
|
char *ItemDropStrs[35] = { |
|
"Armor2", |
|
"Axe", |
|
"FBttle", |
|
"Bow", |
|
"GoldFlip", |
|
"Helmut", |
|
"Mace", |
|
"Shield", |
|
"SwrdFlip", |
|
"Rock", |
|
"Cleaver", |
|
"Staff", |
|
"Ring", |
|
"CrownF", |
|
"LArmor", |
|
"WShield", |
|
"Scroll", |
|
"FPlateAr", |
|
"FBook", |
|
"Food", |
|
"FBttleBB", |
|
"FBttleDY", |
|
"FBttleOR", |
|
"FBttleBR", |
|
"FBttleBL", |
|
"FBttleBY", |
|
"FBttleWH", |
|
"FBttleDB", |
|
"FEar", |
|
"FBrain", |
|
"FMush", |
|
"Innsign", |
|
"Bldstn", |
|
"Fanvil", |
|
"FLazStaf" |
|
}; |
|
BYTE ItemAnimLs[35] = { |
|
15u, |
|
13u, |
|
16u, |
|
13u, |
|
10u, |
|
13u, |
|
13u, |
|
13u, |
|
13u, |
|
10u, |
|
13u, |
|
13u, |
|
13u, |
|
13u, |
|
13u, |
|
13u, |
|
13u, |
|
13u, |
|
13u, |
|
1u, |
|
16u, |
|
16u, |
|
16u, |
|
16u, |
|
16u, |
|
16u, |
|
16u, |
|
16u, |
|
13u, |
|
12u, |
|
12u, |
|
13u, |
|
13u, |
|
13u, |
|
8u |
|
}; |
|
int ItemDropSnds[35] = { |
|
IS_FHARM, |
|
IS_FAXE, |
|
IS_FPOT, |
|
IS_FBOW, |
|
IS_GOLD, |
|
IS_FCAP, |
|
IS_FSWOR, |
|
IS_FSHLD, |
|
IS_FSWOR, |
|
IS_FROCK, |
|
IS_FAXE, |
|
IS_FSTAF, |
|
IS_FRING, |
|
IS_FCAP, |
|
IS_FLARM, |
|
IS_FSHLD, |
|
IS_FSCRL, |
|
IS_FHARM, |
|
IS_FBOOK, |
|
IS_FLARM, |
|
IS_FPOT, |
|
IS_FPOT, |
|
IS_FPOT, |
|
IS_FPOT, |
|
IS_FPOT, |
|
IS_FPOT, |
|
IS_FPOT, |
|
IS_FPOT, |
|
IS_FBODY, |
|
IS_FBODY, |
|
IS_FMUSH, |
|
IS_ISIGN, |
|
IS_FBLST, |
|
IS_FANVL, |
|
IS_FSTAF |
|
}; |
|
int ItemInvSnds[35] = { |
|
IS_IHARM, |
|
IS_IAXE, |
|
IS_IPOT, |
|
IS_IBOW, |
|
IS_GOLD, |
|
IS_ICAP, |
|
IS_ISWORD, |
|
IS_ISHIEL, |
|
IS_ISWORD, |
|
IS_IROCK, |
|
IS_IAXE, |
|
IS_ISTAF, |
|
IS_IRING, |
|
IS_ICAP, |
|
IS_ILARM, |
|
IS_ISHIEL, |
|
IS_ISCROL, |
|
IS_IHARM, |
|
IS_IBOOK, |
|
IS_IHARM, |
|
IS_IPOT, |
|
IS_IPOT, |
|
IS_IPOT, |
|
IS_IPOT, |
|
IS_IPOT, |
|
IS_IPOT, |
|
IS_IPOT, |
|
IS_IPOT, |
|
IS_IBODY, |
|
IS_IBODY, |
|
IS_IMUSH, |
|
IS_ISIGN, |
|
IS_IBLST, |
|
IS_IANVL, |
|
IS_ISTAF |
|
}; |
|
int idoppely = 16; |
|
int premiumlvladd[6] = { -1, -1, 0, 0, 1, 2 }; |
|
|
|
void InitItemGFX() |
|
{ |
|
int i; |
|
char arglist[64]; |
|
|
|
for (i = 0; i < 35; i++) { |
|
sprintf(arglist, "Items\\%s.CEL", ItemDropStrs[i]); |
|
itemanims[i] = LoadFileInMem(arglist, 0); |
|
} |
|
memset(UniqueItemFlag, 0, sizeof(UniqueItemFlag)); |
|
} |
|
|
|
BOOL ItemPlace(int xp, int yp) |
|
{ |
|
if (dMonster[xp][yp]) |
|
return FALSE; |
|
if (dPlayer[xp][yp]) |
|
return FALSE; |
|
if (dItem[xp][yp]) |
|
return FALSE; |
|
if (dObject[xp][yp]) |
|
return FALSE; |
|
if (dFlags[xp][yp] & BFLAG_POPULATED) |
|
return FALSE; |
|
if (nSolidTable[dPiece[xp][yp]]) |
|
return FALSE; |
|
|
|
return TRUE; |
|
} |
|
|
|
void AddInitItems() |
|
{ |
|
int x, y, i, j, rnd; |
|
|
|
rnd = random(11, 3) + 3; |
|
for (j = 0; j < rnd; j++) { |
|
i = itemavail[0]; |
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1]; |
|
itemactive[numitems] = i; |
|
x = random(12, 80) + 16; |
|
y = random(12, 80) + 16; |
|
while (!ItemPlace(x, y)) { |
|
x = random(12, 80) + 16; |
|
y = random(12, 80) + 16; |
|
} |
|
item[i]._ix = x; |
|
item[i]._iy = y; |
|
dItem[x][y] = i + 1; |
|
item[i]._iSeed = GetRndSeed(); |
|
SetRndSeed(item[i]._iSeed); |
|
if (random(12, 2)) |
|
GetItemAttrs(i, IDI_HEAL, currlevel); |
|
else |
|
GetItemAttrs(i, IDI_MANA, currlevel); |
|
item[i]._iCreateInfo = currlevel - 32768; |
|
SetupItem(i); |
|
item[i]._iAnimFrame = item[i]._iAnimLen; |
|
item[i]._iAnimFlag = 0; |
|
item[i]._iSelFlag = 1; |
|
DeltaAddItem(i); |
|
numitems++; |
|
} |
|
} |
|
|
|
void InitItems() |
|
{ |
|
int i; |
|
|
|
GetItemAttrs(0, IDI_GOLD, 1); |
|
golditem = item[0]; |
|
golditem._iStatFlag = 1; |
|
numitems = 0; |
|
|
|
for (i = 0; i < MAXITEMS; i++) { |
|
item[i]._itype = ITYPE_MISC; |
|
item[i]._ix = 0; |
|
item[i]._iy = 0; |
|
item[i]._isin = 0; |
|
item[i]._iSelFlag = 0; |
|
item[i]._iIdentified = FALSE; |
|
item[i]._iPostDraw = 0; |
|
} |
|
|
|
for (i = 0; i < MAXITEMS; i++) { |
|
itemavail[i] = i; |
|
itemactive[i] = 0; |
|
} |
|
|
|
if (!setlevel) { |
|
GetRndSeed(); |
|
if (QuestStatus(QTYPE_INFRA)) |
|
SpawnRock(); |
|
if (QuestStatus(QTYPE_ANVIL)) |
|
SpawnQuestItem(IDI_ANVIL, 2 * setpc_x + 27, 2 * setpc_y + 27, 0, 1); |
|
if (currlevel > 0u && currlevel < 0x10u) |
|
AddInitItems(); |
|
} |
|
|
|
uitemflag = 0; |
|
} |
|
|
|
void CalcPlrItemVals(int p, BOOL Loadgfx) |
|
{ |
|
int pvid, d; |
|
|
|
int mind = 0; // min damage |
|
int maxd = 0; // max damage |
|
int tac = 0; // accuracy |
|
|
|
int g; |
|
int i; |
|
int mi; |
|
|
|
int bdam = 0; // bonus damage |
|
int btohit = 0; // bonus chance to hit |
|
int bac = 0; // bonus accuracy |
|
|
|
int iflgs = 0; // item_special_effect flags |
|
|
|
int sadd = 0; // added stregth |
|
int madd = 0; // added magic |
|
int dadd = 0; // added dexterity |
|
int vadd = 0; // added vitality |
|
|
|
unsigned __int64 spl = 0; // bitarray for all enabled/active spells |
|
|
|
signed int fr = 0; // fire resistance |
|
signed int lr = 0; // lightning resistance |
|
signed int mr = 0; // magic resistance |
|
|
|
int dmod = 0; // bonus damage mod? |
|
int ghit = 0; // (reduced) chance to get hit |
|
|
|
signed int lrad = 10; // light radius |
|
|
|
int ihp = 0; // increased HP |
|
int imana = 0; // increased mana |
|
|
|
int spllvladd = 0; // increased spell level |
|
int enac = 0; // enhanced accuracy |
|
|
|
int fmin = 0; // minimum fire damage |
|
int fmax = 0; // maximum fire damage |
|
int lmin = 0; // minimum lightning damage |
|
int lmax = 0; // maximum lightning damage |
|
|
|
for (i = 0; i < NUM_INVLOC; i++) { |
|
ItemStruct *itm = &plr[p].InvBody[i]; |
|
if (itm->_itype != ITYPE_NONE && itm->_iStatFlag) { |
|
|
|
mind += itm->_iMinDam; |
|
tac += itm->_iAC; |
|
maxd += itm->_iMaxDam; |
|
|
|
if (itm->_iSpell != SPL_NULL) { |
|
spl |= (unsigned __int64)1 << (itm->_iSpell - 1); |
|
} |
|
|
|
if (itm->_iMagical == ITEM_QUALITY_NORMAL || itm->_iIdentified) { |
|
bdam += itm->_iPLDam; |
|
btohit += itm->_iPLToHit; |
|
if (itm->_iPLAC) { |
|
int tmpac = itm->_iPLAC * itm->_iAC / 100; |
|
if (tmpac == 0) |
|
tmpac = 1; |
|
bac += tmpac; |
|
} |
|
dmod += itm->_iPLDamMod; |
|
iflgs |= itm->_iFlags; |
|
sadd += itm->_iPLStr; |
|
madd += itm->_iPLMag; |
|
dadd += itm->_iPLDex; |
|
vadd += itm->_iPLVit; |
|
fr += itm->_iPLFR; |
|
lr += itm->_iPLLR; |
|
mr += itm->_iPLMR; |
|
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 (mind == 0 && maxd == 0) { |
|
mind = 1; |
|
maxd = 1; |
|
|
|
if (plr[p].InvBody[INVLOC_HAND_LEFT]._itype == ITYPE_SHIELD && plr[p].InvBody[INVLOC_HAND_LEFT]._iStatFlag) { |
|
maxd = 3; |
|
} |
|
|
|
if (plr[p].InvBody[INVLOC_HAND_RIGHT]._itype == ITYPE_SHIELD && plr[p].InvBody[INVLOC_HAND_RIGHT]._iStatFlag) { |
|
maxd = 3; |
|
} |
|
} |
|
|
|
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]._pIGetHit = ghit; |
|
plr[p]._pIMinDam = mind; |
|
plr[p]._pIBonusDamMod = dmod; |
|
|
|
if (lrad < 2) { |
|
lrad = 2; |
|
} |
|
if (lrad > 15) { |
|
lrad = 15; |
|
} |
|
|
|
if (plr[p]._pLightRad != lrad && p == myplr) { |
|
ChangeLightRadius(plr[p]._plid, lrad); |
|
|
|
pvid = plr[p]._pvid; |
|
if (lrad >= 10) { |
|
ChangeVisionRadius(pvid, lrad); |
|
} else { |
|
ChangeVisionRadius(pvid, 10); |
|
} |
|
|
|
plr[p]._pLightRad = lrad; |
|
} |
|
|
|
plr[p]._pStrength = sadd + plr[p]._pBaseStr; |
|
if (plr[myplr]._pStrength <= 0) { |
|
plr[myplr]._pStrength = 0; |
|
} |
|
|
|
plr[p]._pMagic = madd + plr[p]._pBaseMag; |
|
if (plr[myplr]._pMagic <= 0) { |
|
plr[myplr]._pMagic = 0; |
|
} |
|
|
|
plr[p]._pDexterity = dadd + plr[p]._pBaseDex; |
|
if (plr[myplr]._pDexterity <= 0) { |
|
plr[myplr]._pDexterity = 0; |
|
} |
|
|
|
plr[p]._pVitality = vadd + plr[p]._pBaseVit; |
|
if (plr[myplr]._pVitality <= 0) { |
|
plr[myplr]._pVitality = 0; |
|
} |
|
|
|
if (plr[p]._pClass == PC_ROGUE) { |
|
plr[p]._pDamageMod = plr[p]._pLevel * (plr[p]._pStrength + plr[p]._pDexterity) / 200; |
|
} else { |
|
plr[p]._pDamageMod = plr[p]._pLevel * plr[p]._pStrength / 100; |
|
} |
|
|
|
plr[p]._pISpells = spl; |
|
|
|
// check if the current RSplType is a valid/allowed spell |
|
if (plr[p]._pRSplType == RSPLTYPE_CHARGES |
|
&& !(spl & ((unsigned __int64)1 << (plr[p]._pRSpell - 1)))) { |
|
plr[p]._pRSpell = SPL_INVALID; |
|
plr[p]._pRSplType = RSPLTYPE_INVALID; |
|
drawpanflag = 255; |
|
} |
|
|
|
plr[p]._pISplLvlAdd = spllvladd; |
|
plr[p]._pIEnAc = enac; |
|
|
|
if (iflgs & ISPL_ALLRESZERO) { |
|
// reset resistances to zero if the respective special effect is active |
|
mr = 0; |
|
fr = 0; |
|
lr = 0; |
|
} |
|
|
|
if (mr > 75) { |
|
mr = 75; |
|
} |
|
plr[p]._pMagResist = mr; |
|
|
|
if (fr > 75) { |
|
fr = 75; |
|
} |
|
plr[p]._pFireResist = fr; |
|
|
|
if (lr > 75) { |
|
lr = 75; |
|
} |
|
plr[p]._pLghtResist = lr; |
|
|
|
if (plr[p]._pClass == PC_WARRIOR) { |
|
vadd *= 2; |
|
} |
|
if (plr[p]._pClass == PC_ROGUE) { |
|
vadd += vadd >> 1; |
|
} |
|
ihp += (vadd << 6); |
|
|
|
if (plr[p]._pClass == PC_SORCERER) { |
|
madd *= 2; |
|
} |
|
if (plr[p]._pClass == PC_ROGUE) { |
|
madd += madd >> 1; |
|
} |
|
imana += (madd << 6); |
|
|
|
plr[p]._pHitPoints = ihp + plr[p]._pHPBase; |
|
plr[p]._pMaxHP = ihp + plr[p]._pMaxHPBase; |
|
|
|
if (p == myplr && (plr[p]._pHitPoints >> 6) <= 0) { |
|
SetPlayerHitPoints(p, 0); |
|
} |
|
|
|
plr[p]._pMana = imana + plr[p]._pManaBase; |
|
plr[p]._pMaxMana = imana + plr[p]._pMaxManaBase; |
|
|
|
plr[p]._pIFMinDam = fmin; |
|
plr[p]._pIFMaxDam = fmax; |
|
plr[p]._pILMinDam = lmin; |
|
plr[p]._pILMaxDam = lmax; |
|
|
|
if (iflgs & ISPL_INFRAVISION) { |
|
plr[p]._pInfraFlag = 1; |
|
} else { |
|
plr[p]._pInfraFlag = 0; |
|
} |
|
|
|
plr[p]._pBlockFlag = 0; |
|
plr[p]._pwtype = WT_MELEE; |
|
|
|
g = 0; |
|
|
|
if (plr[p].InvBody[INVLOC_HAND_LEFT]._itype != ITYPE_NONE |
|
&& plr[p].InvBody[INVLOC_HAND_LEFT]._iClass == ICLASS_WEAPON |
|
&& plr[p].InvBody[INVLOC_HAND_LEFT]._iStatFlag) { |
|
g = plr[p].InvBody[INVLOC_HAND_LEFT]._itype; |
|
} |
|
|
|
if (plr[p].InvBody[INVLOC_HAND_RIGHT]._itype != ITYPE_NONE |
|
&& plr[p].InvBody[INVLOC_HAND_RIGHT]._iClass == ICLASS_WEAPON |
|
&& plr[p].InvBody[INVLOC_HAND_RIGHT]._iStatFlag) { |
|
g = plr[p].InvBody[INVLOC_HAND_RIGHT]._itype; |
|
} |
|
|
|
switch (g) { |
|
case ITYPE_SWORD: |
|
g = ANIM_ID_SWORD; |
|
break; |
|
case ITYPE_AXE: |
|
g = ANIM_ID_AXE; |
|
break; |
|
case ITYPE_BOW: |
|
plr[p]._pwtype = WT_RANGED; |
|
g = ANIM_ID_BOW; |
|
break; |
|
case ITYPE_MACE: |
|
g = ANIM_ID_MACE; |
|
break; |
|
case ITYPE_STAFF: |
|
g = ANIM_ID_STAFF; |
|
break; |
|
} |
|
|
|
if (plr[p].InvBody[INVLOC_HAND_LEFT]._itype == ITYPE_SHIELD && plr[p].InvBody[INVLOC_HAND_LEFT]._iStatFlag) { |
|
plr[p]._pBlockFlag = 1; |
|
g++; |
|
} |
|
if (plr[p].InvBody[INVLOC_HAND_RIGHT]._itype == ITYPE_SHIELD && plr[p].InvBody[INVLOC_HAND_RIGHT]._iStatFlag) { |
|
plr[p]._pBlockFlag = 1; |
|
g++; |
|
} |
|
|
|
if (plr[p].InvBody[INVLOC_CHEST]._itype == ITYPE_MARMOR && plr[p].InvBody[INVLOC_CHEST]._iStatFlag) { |
|
g += ANIM_ID_MEDIUM_ARMOR; |
|
} |
|
if (plr[p].InvBody[INVLOC_CHEST]._itype == ITYPE_HARMOR && plr[p].InvBody[INVLOC_CHEST]._iStatFlag) { |
|
g += ANIM_ID_HEAVY_ARMOR; |
|
} |
|
|
|
if (plr[p]._pgfxnum != g && Loadgfx) { |
|
plr[p]._pgfxnum = g; |
|
plr[p]._pGFXLoad = 0; |
|
LoadPlrGFX(p, PFILE_STAND); |
|
SetPlrAnims(p); |
|
|
|
d = plr[p]._pdir; |
|
|
|
// TODO: Add debug assert here ( plr[p]._pNAnim[d] != NULL ) |
|
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 == MIS_MANASHIELD && missile[mi]._misource == p) { |
|
missile[mi]._miVar1 = plr[p]._pHitPoints; |
|
missile[mi]._miVar2 = plr[p]._pHPBase; |
|
} |
|
} |
|
|
|
drawmanaflag = TRUE; |
|
drawhpflag = TRUE; |
|
} |
|
|
|
void CalcPlrScrolls(int p) |
|
{ |
|
int i, j; |
|
|
|
plr[p]._pScrlSpells = 0; |
|
for (i = 0; i < plr[p]._pNumInv; i++) { |
|
if (plr[p].InvList[i]._itype != ITYPE_NONE && (plr[p].InvList[i]._iMiscId == IMISC_SCROLL || plr[p].InvList[i]._iMiscId == IMISC_SCROLLT)) { |
|
if (plr[p].InvList[i]._iStatFlag) |
|
plr[p]._pScrlSpells |= (__int64)1 << (plr[p].InvList[i]._iSpell - 1); |
|
} |
|
} |
|
|
|
for (j = 0; j < MAXBELTITEMS; j++) { |
|
if (plr[p].SpdList[j]._itype != ITYPE_NONE && (plr[p].SpdList[j]._iMiscId == IMISC_SCROLL || plr[p].SpdList[j]._iMiscId == IMISC_SCROLLT)) { |
|
if (plr[p].SpdList[j]._iStatFlag) |
|
plr[p]._pScrlSpells |= (__int64)1 << (plr[p].SpdList[j]._iSpell - 1); |
|
} |
|
} |
|
if (plr[p]._pRSplType == RSPLTYPE_SCROLL) { |
|
if (!(plr[p]._pScrlSpells & 1 << (plr[p]._pRSpell - 1))) { |
|
plr[p]._pRSpell = SPL_INVALID; |
|
plr[p]._pRSplType = RSPLTYPE_INVALID; |
|
drawpanflag = 255; |
|
} |
|
} |
|
} |
|
|
|
void CalcPlrStaff(int pnum) |
|
{ |
|
plr[pnum]._pISpells = 0; |
|
if (plr[pnum].InvBody[INVLOC_HAND_LEFT]._itype != ITYPE_NONE |
|
&& plr[pnum].InvBody[INVLOC_HAND_LEFT]._iStatFlag |
|
&& plr[pnum].InvBody[INVLOC_HAND_LEFT]._iCharges > 0) { |
|
plr[pnum]._pISpells |= (__int64)1 << (plr[pnum].InvBody[INVLOC_HAND_LEFT]._iSpell - 1); |
|
} |
|
} |
|
|
|
void CalcSelfItems(int pnum) |
|
{ |
|
int i; |
|
PlayerStruct *p; |
|
BOOL sf, changeflag; |
|
int sa, ma, da; |
|
|
|
p = &plr[pnum]; |
|
|
|
sa = 0; |
|
ma = 0; |
|
da = 0; |
|
for (i = 0; i < NUM_INVLOC; i++) { |
|
if (p->InvBody[i]._itype != ITYPE_NONE) { |
|
p->InvBody[i]._iStatFlag = TRUE; |
|
if (p->InvBody[i]._iIdentified) { |
|
sa += p->InvBody[i]._iPLStr; |
|
ma += p->InvBody[i]._iPLMag; |
|
da += p->InvBody[i]._iPLDex; |
|
} |
|
} |
|
} |
|
do { |
|
changeflag = FALSE; |
|
for (i = 0; i < NUM_INVLOC; i++) { |
|
if (p->InvBody[i]._itype != ITYPE_NONE && p->InvBody[i]._iStatFlag) { |
|
sf = TRUE; |
|
if (sa + p->_pBaseStr < p->InvBody[i]._iMinStr) |
|
sf = FALSE; |
|
if (ma + p->_pBaseMag < p->InvBody[i]._iMinMag) |
|
sf = FALSE; |
|
if (da + p->_pBaseDex < p->InvBody[i]._iMinDex) |
|
sf = FALSE; |
|
if (!sf) { |
|
changeflag = TRUE; |
|
p->InvBody[i]._iStatFlag = FALSE; |
|
if (p->InvBody[i]._iIdentified) { |
|
sa -= p->InvBody[i]._iPLStr; |
|
ma -= p->InvBody[i]._iPLMag; |
|
da -= p->InvBody[i]._iPLDex; |
|
} |
|
} |
|
} |
|
} |
|
} while (changeflag); |
|
} |
|
|
|
void CalcPlrItemMin(int pnum) |
|
{ |
|
PlayerStruct *p; |
|
ItemStruct *pi; |
|
int i; |
|
|
|
p = &plr[pnum]; |
|
pi = p->InvList; |
|
|
|
for (i = p->_pNumInv; i; i--) { |
|
pi->_iStatFlag = ItemMinStats(p, pi); |
|
pi++; |
|
} |
|
|
|
pi = p->SpdList; |
|
for (i = MAXBELTITEMS; i != 0; i--) { |
|
if (pi->_itype != ITYPE_NONE) { |
|
pi->_iStatFlag = ItemMinStats(p, pi); |
|
} |
|
pi++; |
|
} |
|
} |
|
|
|
BOOL ItemMinStats(PlayerStruct *p, ItemStruct *x) |
|
{ |
|
if (p->_pMagic < x->_iMinMag) |
|
return FALSE; |
|
|
|
if (p->_pStrength < x->_iMinStr) |
|
return FALSE; |
|
|
|
if (p->_pDexterity < x->_iMinDex) |
|
return FALSE; |
|
|
|
return TRUE; |
|
} |
|
|
|
void CalcPlrBookVals(int p) |
|
{ |
|
int i, slvl; |
|
|
|
if (!currlevel) { |
|
for (i = 1; witchitem[i]._itype != ITYPE_NONE; i++) { |
|
WitchBookLevel(i); |
|
witchitem[i]._iStatFlag = StoreStatOk(&witchitem[i]); |
|
} |
|
} |
|
|
|
for (i = 0; i < plr[p]._pNumInv; i++) { |
|
if (plr[p].InvList[i]._itype == ITYPE_MISC && plr[p].InvList[i]._iMiscId == IMISC_BOOK) { |
|
plr[p].InvList[i]._iMinMag = spelldata[plr[p].InvList[i]._iSpell].sMinInt; |
|
slvl = plr[p]._pSplLvl[plr[p].InvList[i]._iSpell]; |
|
|
|
while (slvl) { |
|
plr[p].InvList[i]._iMinMag += 20 * plr[p].InvList[i]._iMinMag / 100; |
|
slvl--; |
|
if (plr[p].InvList[i]._iMinMag + 20 * plr[p].InvList[i]._iMinMag / 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) |
|
RecalcStoreStats(); |
|
} |
|
} |
|
|
|
void SetPlrHandItem(ItemStruct *h, int idata) |
|
{ |
|
ItemDataStruct *pAllItem; |
|
|
|
pAllItem = &AllItemsList[idata]; |
|
|
|
// zero-initialize struct |
|
memset(h, 0, sizeof(*h)); |
|
|
|
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 == IMISC_STAFF) { |
|
h->_iCharges = 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->_iMagical = ITEM_QUALITY_NORMAL; |
|
h->IDidx = idata; |
|
} |
|
|
|
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_MEDIUM_LIMIT) |
|
h->_iCurs = ICURS_GOLD_LARGE; |
|
else if (h->_ivalue <= GOLD_SMALL_LIMIT) |
|
h->_iCurs = ICURS_GOLD_SMALL; |
|
else |
|
h->_iCurs = ICURS_GOLD_MEDIUM; |
|
} |
|
|
|
void CreatePlrItems(int p) |
|
{ |
|
int i; |
|
ItemStruct *pi = plr[p].InvBody; |
|
|
|
for (i = 0; i < NUM_INVLOC; i++) { |
|
pi[i]._itype = ITYPE_NONE; |
|
} |
|
|
|
// converting this to a for loop creates a `rep stosd` instruction, |
|
// so this probably actually was a memset |
|
memset(&plr[p].InvGrid, 0, sizeof(plr[p].InvGrid)); |
|
|
|
pi = plr[p].InvList; |
|
for (i = 0; i < NUM_INV_GRID_ELEM; i++) { |
|
pi[i]._itype = ITYPE_NONE; |
|
} |
|
|
|
plr[p]._pNumInv = 0; |
|
|
|
pi = plr[p].SpdList; |
|
for (i = 0; i < MAXBELTITEMS; i++) { |
|
pi[i]._itype = ITYPE_NONE; |
|
} |
|
|
|
switch (plr[p]._pClass) { |
|
case PC_WARRIOR: |
|
SetPlrHandItem(&plr[p].InvBody[INVLOC_HAND_LEFT], IDI_WARRIOR); |
|
GetPlrHandSeed(&plr[p].InvBody[INVLOC_HAND_LEFT]); |
|
|
|
SetPlrHandItem(&plr[p].InvBody[INVLOC_HAND_RIGHT], IDI_WARRSHLD); |
|
GetPlrHandSeed(&plr[p].InvBody[INVLOC_HAND_RIGHT]); |
|
|
|
#ifdef _DEBUG |
|
if (!debug_mode_key_w) { |
|
#endif |
|
SetPlrHandItem(&plr[p].HoldItem, IDI_WARRCLUB); |
|
GetPlrHandSeed(&plr[p].HoldItem); |
|
AutoPlace(p, 0, 1, 3, TRUE); |
|
#ifdef _DEBUG |
|
} |
|
#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 PC_ROGUE: |
|
SetPlrHandItem(&plr[p].InvBody[INVLOC_HAND_LEFT], IDI_ROGUE); |
|
GetPlrHandSeed(&plr[p].InvBody[INVLOC_HAND_LEFT]); |
|
|
|
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 PC_SORCERER: |
|
SetPlrHandItem(&plr[p].InvBody[INVLOC_HAND_LEFT], IDI_SORCEROR); |
|
GetPlrHandSeed(&plr[p].InvBody[INVLOC_HAND_LEFT]); |
|
|
|
SetPlrHandItem(&plr[p].SpdList[0], IDI_MANA); |
|
GetPlrHandSeed(&plr[p].SpdList[0]); |
|
|
|
SetPlrHandItem(&plr[p].SpdList[1], IDI_MANA); |
|
GetPlrHandSeed(&plr[p].SpdList[1]); |
|
break; |
|
} |
|
|
|
SetPlrHandItem(&plr[p].HoldItem, IDI_GOLD); |
|
GetPlrHandSeed(&plr[p].HoldItem); |
|
|
|
#ifdef _DEBUG |
|
if (!debug_mode_key_w) { |
|
#endif |
|
plr[p].HoldItem._ivalue = 100; |
|
plr[p].HoldItem._iCurs = ICURS_GOLD_SMALL; |
|
plr[p]._pGold = plr[p].HoldItem._ivalue; |
|
plr[p].InvList[plr[p]._pNumInv++] = plr[p].HoldItem; |
|
plr[p].InvGrid[30] = plr[p]._pNumInv; |
|
#ifdef _DEBUG |
|
} else { |
|
plr[p].HoldItem._ivalue = GOLD_MAX_LIMIT; |
|
plr[p].HoldItem._iCurs = ICURS_GOLD_LARGE; |
|
plr[p]._pGold = plr[p].HoldItem._ivalue * 40; |
|
for (i = 0; i < 40; i++) { |
|
GetPlrHandSeed(&plr[p].HoldItem); |
|
plr[p].InvList[plr[p]._pNumInv++] = plr[p].HoldItem; |
|
plr[p].InvGrid[i] = plr[p]._pNumInv; |
|
} |
|
} |
|
#endif |
|
|
|
CalcPlrItemVals(p, FALSE); |
|
} |
|
|
|
BOOL ItemSpaceOk(int i, int j) |
|
{ |
|
int oi; |
|
|
|
if (i < 0 || i >= MAXDUNX || j < 0 || j >= MAXDUNY) |
|
return FALSE; |
|
|
|
if (dMonster[i][j]) |
|
return FALSE; |
|
|
|
if (dPlayer[i][j]) |
|
return FALSE; |
|
|
|
if (dItem[i][j]) |
|
return FALSE; |
|
|
|
if (dObject[i][j]) { |
|
oi = dObject[i][j] > 0 ? dObject[i][j] - 1 : -(dObject[i][j] + 1); |
|
if (object[oi]._oSolidFlag) |
|
return FALSE; |
|
} |
|
|
|
if (dObject[i + 1][j + 1] > 0 && object[dObject[i + 1][j + 1] - 1]._oSelFlag != 0) |
|
return FALSE; |
|
|
|
if (dObject[i + 1][j + 1] < 0 && object[-(dObject[i + 1][j + 1] + 1)]._oSelFlag != 0) |
|
return FALSE; |
|
|
|
if (dObject[i + 1][j] > 0 |
|
&& dObject[i][j + 1] > 0 |
|
&& object[dObject[i + 1][j] - 1]._oSelFlag != 0 |
|
&& object[dObject[i][j + 1] - 1]._oSelFlag != 0) { |
|
return FALSE; |
|
} |
|
|
|
return !nSolidTable[dPiece[i][j]]; |
|
} |
|
|
|
BOOL GetItemSpace(int x, int y, char inum) |
|
{ |
|
int i, j, rs; |
|
int xx, yy; |
|
BOOL savail; |
|
|
|
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 (j = 0; j < 3; j++) { |
|
for (i = 0; i < 3; i++) { |
|
if (itemhold[i][j]) |
|
savail = TRUE; |
|
} |
|
} |
|
|
|
rs = random(13, 15) + 1; |
|
|
|
if (!savail) |
|
return FALSE; |
|
|
|
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 += x - 1; |
|
yy += y - 1; |
|
item[inum]._ix = xx; |
|
item[inum]._iy = yy; |
|
dItem[xx][yy] = inum + 1; |
|
|
|
return TRUE; |
|
} |
|
|
|
void GetSuperItemSpace(int x, int y, char inum) |
|
{ |
|
int xx, yy; |
|
int i, j, k; |
|
|
|
if (!GetItemSpace(x, y, inum)) { |
|
for (k = 2; k < 50; k++) { |
|
for (j = -k; j <= k; j++) { |
|
yy = y + j; |
|
for (i = -k; i <= k; i++) { |
|
xx = i + x; |
|
if (ItemSpaceOk(xx, yy)) { |
|
item[inum]._ix = xx; |
|
item[inum]._iy = yy; |
|
dItem[xx][yy] = inum + 1; |
|
return; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
void GetSuperItemLoc(int x, int y, int *xx, int *yy) |
|
{ |
|
int i, j, k; |
|
|
|
for (k = 1; k < 50; k++) { |
|
for (j = -k; j <= k; j++) { |
|
*yy = y + j; |
|
for (i = -k; i <= k; i++) { |
|
*xx = i + x; |
|
if (ItemSpaceOk(*xx, *yy)) { |
|
return; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
void CalcItemValue(int i) |
|
{ |
|
int v; |
|
|
|
v = item[i]._iVMult1 + item[i]._iVMult2; |
|
if (v > 0) { |
|
v *= item[i]._ivalue; |
|
} |
|
if (v < 0) { |
|
v = item[i]._ivalue / v; |
|
} |
|
v = item[i]._iVAdd1 + item[i]._iVAdd2 + v; |
|
if (v <= 0) { |
|
v = 1; |
|
} |
|
item[i]._iIvalue = v; |
|
} |
|
|
|
void GetBookSpell(int i, int lvl) |
|
{ |
|
int rv, s, bs; |
|
|
|
if (!lvl) |
|
lvl = 1; |
|
rv = random(14, MAX_SPELLS) + 1; |
|
s = 1; |
|
while (rv > 0) { |
|
if (spelldata[s].sBookLvl != -1 && lvl >= spelldata[s].sBookLvl) { |
|
rv--; |
|
bs = s; |
|
} |
|
s++; |
|
if (gbMaxPlayers == 1) { |
|
if (s == SPL_RESURRECT) |
|
s = SPL_TELEKINESIS; |
|
if (s == SPL_HEALOTHER) |
|
s = SPL_FLARE; |
|
} |
|
if (s == MAX_SPELLS) |
|
s = 1; |
|
} |
|
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 == STYPE_FIRE) |
|
item[i]._iCurs = ICURS_BOOK_RED; |
|
if (spelldata[bs].sType == STYPE_LIGHTNING) |
|
item[i]._iCurs = ICURS_BOOK_BLUE; |
|
if (spelldata[bs].sType == STYPE_MAGIC) |
|
item[i]._iCurs = ICURS_BOOK_GREY; |
|
} |
|
|
|
void GetStaffPower(int i, int lvl, int bs, BOOL onlygood) |
|
{ |
|
int l[256]; |
|
char istr[128]; |
|
int nl, j, preidx; |
|
BYTE addok; |
|
|
|
preidx = -1; |
|
if (random(15, 10) == 0 || onlygood) { |
|
nl = 0; |
|
for (j = 0; PL_Prefix[j].PLPower != -1; j++) { |
|
if (PL_Prefix[j].PLIType & PLT_STAFF && 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 = ITEM_QUALITY_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 (!control_WriteStringToBuffer((BYTE *)item[i]._iIName)) { |
|
strcpy(item[i]._iIName, AllItemsList[item[i].IDidx].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 == ITEM_QUALITY_NORMAL) |
|
strcpy(item[i]._iName, item[i]._iIName); |
|
} |
|
CalcItemValue(i); |
|
} |
|
|
|
void GetStaffSpell(int i, int lvl, BOOL onlygood) |
|
{ |
|
int l, rv, s, minc, maxc, v, bs; |
|
char istr[64]; |
|
|
|
if (!random(17, 4)) { |
|
GetItemPower(i, lvl >> 1, lvl, 256, onlygood); |
|
} else { |
|
l = lvl >> 1; |
|
if (!l) |
|
l = 1; |
|
rv = random(18, MAX_SPELLS) + 1; |
|
s = 1; |
|
while (rv > 0) { |
|
if (spelldata[s].sStaffLvl != -1 && l >= spelldata[s].sStaffLvl) { |
|
rv--; |
|
bs = s; |
|
} |
|
s++; |
|
if (gbMaxPlayers == 1 && s == SPL_RESURRECT) |
|
s = SPL_TELEKINESIS; |
|
if (gbMaxPlayers == 1 && s == SPL_HEALOTHER) |
|
s = SPL_FLARE; |
|
if (s == MAX_SPELLS) |
|
s = 1; |
|
} |
|
sprintf(istr, "%s of %s", item[i]._iName, spelldata[bs].sNameText); |
|
if (!control_WriteStringToBuffer((BYTE *)istr)) |
|
sprintf(istr, "Staff of %s", spelldata[bs].sNameText); |
|
strcpy(item[i]._iName, istr); |
|
strcpy(item[i]._iIName, istr); |
|
|
|
minc = spelldata[bs].sStaffMin; |
|
maxc = spelldata[bs].sStaffMax - minc + 1; |
|
item[i]._iSpell = bs; |
|
item[i]._iCharges = minc + random(19, maxc); |
|
item[i]._iMaxCharges = item[i]._iCharges; |
|
|
|
item[i]._iMinMag = spelldata[bs].sMinInt; |
|
v = item[i]._iCharges * spelldata[bs].sStaffCost / 5; |
|
item[i]._ivalue += v; |
|
item[i]._iIvalue += v; |
|
GetStaffPower(i, lvl, bs, onlygood); |
|
} |
|
} |
|
|
|
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 = AllItemsList[idata].iMinAC + random(20, AllItemsList[idata].iMaxAC - AllItemsList[idata].iMinAC + 1); |
|
item[i]._iFlags = AllItemsList[idata].iFlags; |
|
item[i]._iMiscId = AllItemsList[idata].iMiscId; |
|
item[i]._iSpell = AllItemsList[idata].iSpell; |
|
item[i]._iMagical = ITEM_QUALITY_NORMAL; |
|
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; |
|
|
|
if (AllItemsList[idata].iMiscId == IMISC_BOOK) |
|
GetBookSpell(i, lvl); |
|
|
|
if (item[i]._itype == ITYPE_GOLD) { |
|
if (gnDifficulty == DIFF_NORMAL) |
|
rndv = 5 * currlevel + random(21, 10 * currlevel); |
|
else |
|
rndv = lvl; |
|
|
|
if (gnDifficulty == DIFF_NIGHTMARE) |
|
rndv = 5 * (currlevel + 16) + random(21, 10 * (currlevel + 16)); |
|
if (gnDifficulty == DIFF_HELL) |
|
rndv = 5 * (currlevel + 32) + random(21, 10 * (currlevel + 32)); |
|
|
|
if (leveltype == DTYPE_HELL) |
|
rndv += rndv >> 3; |
|
if (rndv > GOLD_MAX_LIMIT) |
|
rndv = GOLD_MAX_LIMIT; |
|
|
|
item[i]._ivalue = rndv; |
|
|
|
if (rndv >= GOLD_MEDIUM_LIMIT) |
|
item[i]._iCurs = ICURS_GOLD_LARGE; |
|
else |
|
item[i]._iCurs = (rndv > GOLD_SMALL_LIMIT) + 4; |
|
} |
|
} |
|
|
|
int RndPL(int param1, int param2) |
|
{ |
|
return param1 + random(22, param2 - param1 + 1); |
|
} |
|
|
|
int PLVal(int pv, int p1, int p2, int minv, int maxv) |
|
{ |
|
if (p1 == p2) |
|
return minv; |
|
if (minv == maxv) |
|
return minv; |
|
return minv + (maxv - minv) * (100 * (pv - p1) / (p2 - p1)) / 100; |
|
} |
|
|
|
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 IPL_TOHIT: |
|
item[i]._iPLToHit += r; |
|
break; |
|
case IPL_TOHIT_CURSE: |
|
item[i]._iPLToHit -= r; |
|
break; |
|
case IPL_DAMP: |
|
item[i]._iPLDam += r; |
|
break; |
|
case IPL_DAMP_CURSE: |
|
item[i]._iPLDam -= r; |
|
break; |
|
case IPL_TOHIT_DAMP: |
|
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 IPL_TOHIT_DAMP_CURSE: |
|
item[i]._iPLDam -= r; |
|
if (param1 == 25) |
|
r2 = RndPL(1, 5); |
|
if (param1 == 50) |
|
r2 = RndPL(6, 10); |
|
item[i]._iPLToHit -= r2; |
|
break; |
|
case IPL_ACP: |
|
item[i]._iPLAC += r; |
|
break; |
|
case IPL_ACP_CURSE: |
|
item[i]._iPLAC -= r; |
|
break; |
|
case IPL_SETAC: |
|
item[i]._iAC = r; |
|
break; |
|
case IPL_AC_CURSE: |
|
item[i]._iAC -= r; |
|
break; |
|
case IPL_FIRERES: |
|
item[i]._iPLFR += r; |
|
break; |
|
case IPL_LIGHTRES: |
|
item[i]._iPLLR += r; |
|
break; |
|
case IPL_MAGICRES: |
|
item[i]._iPLMR += r; |
|
break; |
|
case IPL_ALLRES: |
|
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 IPL_SPLLVLADD: |
|
item[i]._iSplLvlAdd = r; |
|
break; |
|
case IPL_CHARGES: |
|
item[i]._iCharges *= param1; |
|
item[i]._iMaxCharges = item[i]._iCharges; |
|
break; |
|
case IPL_SPELL: |
|
item[i]._iSpell = param1; |
|
item[i]._iCharges = param1; |
|
item[i]._iMaxCharges = param2; |
|
break; |
|
case IPL_FIREDAM: |
|
item[i]._iFlags |= ISPL_FIREDAM; |
|
item[i]._iFMinDam = param1; |
|
item[i]._iFMaxDam = param2; |
|
break; |
|
case IPL_LIGHTDAM: |
|
item[i]._iFlags |= ISPL_LIGHTDAM; |
|
item[i]._iLMinDam = param1; |
|
item[i]._iLMaxDam = param2; |
|
break; |
|
case IPL_STR: |
|
item[i]._iPLStr += r; |
|
break; |
|
case IPL_STR_CURSE: |
|
item[i]._iPLStr -= r; |
|
break; |
|
case IPL_MAG: |
|
item[i]._iPLMag += r; |
|
break; |
|
case IPL_MAG_CURSE: |
|
item[i]._iPLMag -= r; |
|
break; |
|
case IPL_DEX: |
|
item[i]._iPLDex += r; |
|
break; |
|
case IPL_DEX_CURSE: |
|
item[i]._iPLDex -= r; |
|
break; |
|
case IPL_VIT: |
|
item[i]._iPLVit += r; |
|
break; |
|
case IPL_VIT_CURSE: |
|
item[i]._iPLVit -= r; |
|
break; |
|
case IPL_ATTRIBS: |
|
item[i]._iPLStr += r; |
|
item[i]._iPLMag += r; |
|
item[i]._iPLDex += r; |
|
item[i]._iPLVit += r; |
|
break; |
|
case IPL_ATTRIBS_CURSE: |
|
item[i]._iPLStr -= r; |
|
item[i]._iPLMag -= r; |
|
item[i]._iPLDex -= r; |
|
item[i]._iPLVit -= r; |
|
break; |
|
case IPL_GETHIT_CURSE: |
|
item[i]._iPLGetHit += r; |
|
break; |
|
case IPL_GETHIT: |
|
item[i]._iPLGetHit -= r; |
|
break; |
|
case IPL_LIFE: |
|
item[i]._iPLHP += r << 6; |
|
break; |
|
case IPL_LIFE_CURSE: |
|
item[i]._iPLHP -= r << 6; |
|
break; |
|
case IPL_MANA: |
|
item[i]._iPLMana += r << 6; |
|
drawmanaflag = TRUE; |
|
break; |
|
case IPL_MANA_CURSE: |
|
item[i]._iPLMana -= r << 6; |
|
drawmanaflag = TRUE; |
|
break; |
|
case IPL_DUR: |
|
r2 = r * item[i]._iMaxDur / 100; |
|
item[i]._iMaxDur += r2; |
|
item[i]._iDurability += r2; |
|
break; |
|
case IPL_DUR_CURSE: |
|
item[i]._iMaxDur -= r * item[i]._iMaxDur / 100; |
|
if (item[i]._iMaxDur < 1) |
|
item[i]._iMaxDur = 1; |
|
item[i]._iDurability = item[i]._iMaxDur; |
|
break; |
|
case IPL_INDESTRUCTIBLE: |
|
item[i]._iDurability = 255; |
|
item[i]._iMaxDur = 255; |
|
break; |
|
case IPL_LIGHT: |
|
item[i]._iPLLight += param1; |
|
break; |
|
case IPL_LIGHT_CURSE: |
|
item[i]._iPLLight -= param1; |
|
break; |
|
case IPL_FIRE_ARROWS: |
|
item[i]._iFlags |= ISPL_FIRE_ARROWS; |
|
item[i]._iFMinDam = param1; |
|
item[i]._iFMaxDam = param2; |
|
break; |
|
case IPL_LIGHT_ARROWS: |
|
item[i]._iFlags |= ISPL_LIGHT_ARROWS; |
|
item[i]._iLMinDam = param1; |
|
item[i]._iLMaxDam = param2; |
|
break; |
|
case IPL_THORNS: |
|
item[i]._iFlags |= ISPL_THORNS; |
|
break; |
|
case IPL_NOMANA: |
|
item[i]._iFlags |= ISPL_NOMANA; |
|
drawmanaflag = TRUE; |
|
break; |
|
case IPL_NOHEALPLR: |
|
item[i]._iFlags |= ISPL_NOHEALPLR; |
|
break; |
|
case IPL_ABSHALFTRAP: |
|
item[i]._iFlags |= ISPL_ABSHALFTRAP; |
|
break; |
|
case IPL_KNOCKBACK: |
|
item[i]._iFlags |= ISPL_KNOCKBACK; |
|
break; |
|
case IPL_3XDAMVDEM: |
|
item[i]._iFlags |= ISPL_3XDAMVDEM; |
|
break; |
|
case IPL_ALLRESZERO: |
|
item[i]._iFlags |= ISPL_ALLRESZERO; |
|
break; |
|
case IPL_NOHEALMON: |
|
item[i]._iFlags |= ISPL_NOHEALMON; |
|
break; |
|
case IPL_STEALMANA: |
|
if (param1 == 3) |
|
item[i]._iFlags |= ISPL_STEALMANA_3; |
|
if (param1 == 5) |
|
item[i]._iFlags |= ISPL_STEALMANA_5; |
|
drawmanaflag = TRUE; |
|
break; |
|
case IPL_STEALLIFE: |
|
if (param1 == 3) |
|
item[i]._iFlags |= ISPL_STEALLIFE_3; |
|
if (param1 == 5) |
|
item[i]._iFlags |= ISPL_STEALLIFE_5; |
|
drawhpflag = TRUE; |
|
break; |
|
case IPL_TARGAC: |
|
item[i]._iPLEnAc += r; |
|
break; |
|
case IPL_FASTATTACK: |
|
if (param1 == 1) |
|
item[i]._iFlags |= ISPL_QUICKATTACK; |
|
if (param1 == 2) |
|
item[i]._iFlags |= ISPL_FASTATTACK; |
|
if (param1 == 3) |
|
item[i]._iFlags |= ISPL_FASTERATTACK; |
|
if (param1 == 4) |
|
item[i]._iFlags |= ISPL_FASTESTATTACK; |
|
break; |
|
case IPL_FASTRECOVER: |
|
if (param1 == 1) |
|
item[i]._iFlags |= ISPL_FASTRECOVER; |
|
if (param1 == 2) |
|
item[i]._iFlags |= ISPL_FASTERRECOVER; |
|
if (param1 == 3) |
|
item[i]._iFlags |= ISPL_FASTESTRECOVER; |
|
break; |
|
case IPL_FASTBLOCK: |
|
item[i]._iFlags |= ISPL_FASTBLOCK; |
|
break; |
|
case IPL_DAMMOD: |
|
item[i]._iPLDamMod += r; |
|
break; |
|
case IPL_RNDARROWVEL: |
|
item[i]._iFlags |= ISPL_RNDARROWVEL; |
|
break; |
|
case IPL_SETDAM: |
|
item[i]._iMinDam = param1; |
|
item[i]._iMaxDam = param2; |
|
break; |
|
case IPL_SETDUR: |
|
item[i]._iDurability = param1; |
|
item[i]._iMaxDur = param1; |
|
break; |
|
case IPL_FASTSWING: |
|
item[i]._iFlags |= ISPL_FASTERATTACK; |
|
break; |
|
case IPL_ONEHAND: |
|
item[i]._iLoc = ILOC_ONEHAND; |
|
break; |
|
case IPL_DRAINLIFE: |
|
item[i]._iFlags |= ISPL_DRAINLIFE; |
|
break; |
|
case IPL_RNDSTEALLIFE: |
|
item[i]._iFlags |= ISPL_RNDSTEALLIFE; |
|
break; |
|
case IPL_INFRAVISION: |
|
item[i]._iFlags |= ISPL_INFRAVISION; |
|
break; |
|
case IPL_NOMINSTR: |
|
item[i]._iMinStr = 0; |
|
break; |
|
case IPL_INVCURS: |
|
item[i]._iCurs = param1; |
|
break; |
|
case IPL_ADDACLIFE: |
|
item[i]._iPLHP = (plr[myplr]._pIBonusAC + plr[myplr]._pIAC + plr[myplr]._pDexterity / 5) << 6; |
|
break; |
|
case IPL_ADDMANAAC: |
|
item[i]._iAC += (plr[myplr]._pMaxManaBase >> 6) / 10; |
|
break; |
|
case IPL_FIRERESCLVL: |
|
item[i]._iPLFR = 30 - plr[myplr]._pLevel; |
|
if (item[i]._iPLFR < 0) |
|
item[i]._iPLFR = 0; |
|
break; |
|
} |
|
if (item[i]._iVAdd1 || item[i]._iVMult1) { |
|
item[i]._iVAdd2 = PLVal(r, param1, param2, minval, maxval); |
|
item[i]._iVMult2 = multval; |
|
} else { |
|
item[i]._iVAdd1 = PLVal(r, param1, param2, minval, maxval); |
|
item[i]._iVMult1 = multval; |
|
} |
|
} |
|
|
|
void GetItemPower(int i, int minlvl, int maxlvl, int flgs, BOOL onlygood) |
|
{ |
|
int pre, post, nt, nl, j, preidx, sufidx; |
|
int l[256]; |
|
char istr[128]; |
|
BYTE goe; |
|
|
|
pre = random(23, 4); |
|
post = random(23, 3); |
|
if (pre != 0 && post == 0) { |
|
if (random(23, 2)) |
|
post = 1; |
|
else |
|
pre = 0; |
|
} |
|
preidx = -1; |
|
sufidx = -1; |
|
goe = 0; |
|
if (!onlygood && random(0, 3)) |
|
onlygood = TRUE; |
|
if (!pre) { |
|
nt = 0; |
|
for (j = 0; PL_Prefix[j].PLPower != -1; j++) { |
|
if (flgs & PL_Prefix[j].PLIType) { |
|
if (PL_Prefix[j].PLMinLvl >= minlvl && PL_Prefix[j].PLMinLvl <= maxlvl && (!onlygood || PL_Prefix[j].PLOk) && (flgs != 256 || PL_Prefix[j].PLPower != 15)) { |
|
l[nt] = j; |
|
nt++; |
|
if (PL_Prefix[j].PLDouble) { |
|
l[nt] = j; |
|
nt++; |
|
} |
|
} |
|
} |
|
} |
|
if (nt) { |
|
preidx = l[random(23, nt)]; |
|
sprintf(istr, "%s %s", PL_Prefix[preidx].PLName, item[i]._iIName); |
|
strcpy(item[i]._iIName, istr); |
|
item[i]._iMagical = ITEM_QUALITY_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 |
|
&& PL_Suffix[j].PLMinLvl >= minlvl && PL_Suffix[j].PLMinLvl <= maxlvl |
|
&& (goe | LOBYTE(PL_Suffix[j].PLGOE)) != 17 |
|
&& (!onlygood || PL_Suffix[j].PLOk)) { |
|
l[nl] = j; |
|
nl++; |
|
} |
|
} |
|
if (nl) { |
|
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 = 1; |
|
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 (!control_WriteStringToBuffer((BYTE *)item[i]._iIName)) { |
|
strcpy(item[i]._iIName, AllItemsList[item[i].IDidx].iSName); |
|
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, int onlygood) |
|
{ |
|
if (item[i]._iClass != ICLASS_GOLD) { |
|
if (minlvl > 25) |
|
minlvl = 25; |
|
|
|
switch (item[i]._itype) { |
|
case ITYPE_SWORD: |
|
case ITYPE_AXE: |
|
case ITYPE_MACE: |
|
GetItemPower(i, minlvl, maxlvl, 0x1000, onlygood); |
|
break; |
|
case ITYPE_BOW: |
|
GetItemPower(i, minlvl, maxlvl, 0x10, onlygood); |
|
break; |
|
case ITYPE_SHIELD: |
|
GetItemPower(i, minlvl, maxlvl, 0x10000, onlygood); |
|
break; |
|
case ITYPE_LARMOR: |
|
case ITYPE_HELM: |
|
case ITYPE_MARMOR: |
|
case ITYPE_HARMOR: |
|
GetItemPower(i, minlvl, maxlvl, 0x100000, onlygood); |
|
break; |
|
case ITYPE_STAFF: |
|
GetStaffSpell(i, maxlvl, onlygood); |
|
break; |
|
case ITYPE_RING: |
|
case ITYPE_AMULET: |
|
GetItemPower(i, minlvl, maxlvl, 1, onlygood); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
void SetupItem(int i) |
|
{ |
|
int it, il; |
|
|
|
it = ItemCAnimTbl[item[i]._iCurs]; |
|
item[i]._iAnimWidth = 96; |
|
item[i]._iAnimWidth2 = 16; |
|
item[i]._iAnimData = itemanims[it]; |
|
il = ItemAnimLs[it]; |
|
item[i]._iAnimLen = il; |
|
item[i]._iIdentified = FALSE; |
|
item[i]._iPostDraw = FALSE; |
|
|
|
if (!plr[myplr].pLvlLoad) { |
|
item[i]._iSelFlag = 0; |
|
il = 1; |
|
item[i]._iAnimFlag = TRUE; |
|
} else { |
|
item[i]._iAnimFlag = FALSE; |
|
item[i]._iSelFlag = 1; |
|
} |
|
|
|
item[i]._iAnimFrame = il; |
|
} |
|
|
|
int RndItem(int m) |
|
{ |
|
int i, ri; |
|
int ril[512]; |
|
|
|
if ((monster[m].MData->mTreasure & 0x8000) != 0) |
|
return -1 - (monster[m].MData->mTreasure & 0xFFF); |
|
|
|
if (monster[m].MData->mTreasure & 0x4000) |
|
return 0; |
|
|
|
if (random(24, 100) > 40) |
|
return 0; |
|
|
|
if (random(24, 100) > 25) |
|
return 1; |
|
|
|
ri = 0; |
|
for (i = 0; AllItemsList[i].iLoc != ILOC_INVALID; i++) { |
|
if (AllItemsList[i].iRnd == 2 && monster[m].mLevel >= AllItemsList[i].iMinMLvl) { |
|
ril[ri] = i; |
|
ri++; |
|
} |
|
if (AllItemsList[i].iRnd && monster[m].mLevel >= AllItemsList[i].iMinMLvl) { |
|
ril[ri] = i; |
|
ri++; |
|
} |
|
if (AllItemsList[i].iSpell == SPL_RESURRECT && gbMaxPlayers == 1) |
|
ri--; |
|
if (AllItemsList[i].iSpell == SPL_HEALOTHER && gbMaxPlayers == 1) |
|
ri--; |
|
} |
|
|
|
return ril[random(24, ri)] + 1; |
|
} |
|
|
|
int RndUItem(int m) |
|
{ |
|
int i, ri; |
|
int ril[512]; |
|
BOOL okflag; |
|
|
|
if (m != -1 && (monster[m].MData->mTreasure & 0x8000) != 0 && gbMaxPlayers == 1) |
|
return -1 - (monster[m].MData->mTreasure & 0xFFF); |
|
|
|
ri = 0; |
|
for (i = 0; AllItemsList[i].iLoc != ILOC_INVALID; i++) { |
|
okflag = TRUE; |
|
if (!AllItemsList[i].iRnd) |
|
okflag = FALSE; |
|
if (m != -1) { |
|
if (monster[m].mLevel < AllItemsList[i].iMinMLvl) |
|
okflag = FALSE; |
|
} else { |
|
if (2 * currlevel < AllItemsList[i].iMinMLvl) |
|
okflag = FALSE; |
|
} |
|
if (AllItemsList[i].itype == ITYPE_MISC) |
|
okflag = FALSE; |
|
if (AllItemsList[i].itype == ITYPE_GOLD) |
|
okflag = FALSE; |
|
if (AllItemsList[i].itype == ITYPE_0E) |
|
okflag = FALSE; |
|
if (AllItemsList[i].iMiscId == IMISC_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) { |
|
ril[ri] = i; |
|
ri++; |
|
} |
|
} |
|
|
|
return ril[random(25, ri)]; |
|
} |
|
|
|
int RndAllItems() |
|
{ |
|
int i, ri; |
|
int ril[512]; |
|
|
|
if (random(26, 100) > 25) |
|
return 0; |
|
|
|
ri = 0; |
|
for (i = 0; AllItemsList[i].iLoc != ILOC_INVALID; i++) { |
|
if (AllItemsList[i].iRnd && 2 * currlevel >= AllItemsList[i].iMinMLvl) { |
|
ril[ri] = i; |
|
ri++; |
|
} |
|
if (AllItemsList[i].iSpell == SPL_RESURRECT && gbMaxPlayers == 1) |
|
ri--; |
|
if (AllItemsList[i].iSpell == SPL_HEALOTHER && gbMaxPlayers == 1) |
|
ri--; |
|
} |
|
|
|
return ril[random(26, ri)]; |
|
} |
|
|
|
int RndTypeItems(int itype, int imid) |
|
{ |
|
int i, ri; |
|
BOOL okflag; |
|
int ril[512]; |
|
|
|
ri = 0; |
|
for (i = 0; AllItemsList[i].iLoc != ILOC_INVALID; i++) { |
|
okflag = TRUE; |
|
if (!AllItemsList[i].iRnd) |
|
okflag = FALSE; |
|
if (currlevel << 1 < AllItemsList[i].iMinMLvl) |
|
okflag = FALSE; |
|
if (AllItemsList[i].itype != itype) |
|
okflag = FALSE; |
|
if (imid != -1 && AllItemsList[i].iMiscId != imid) |
|
okflag = FALSE; |
|
if (okflag) { |
|
ril[ri] = i; |
|
ri++; |
|
} |
|
} |
|
|
|
return ril[random(27, ri)]; |
|
} |
|
|
|
int CheckUnique(int i, int lvl, int uper, BOOL recreate) |
|
{ |
|
int j, idata, numu; |
|
BOOLEAN uok[128]; |
|
|
|
if (random(28, 100) > uper) |
|
return -1; |
|
|
|
numu = 0; |
|
memset(uok, 0, sizeof(uok)); |
|
for (j = 0; UniqueItemList[j].UIItemId != UITYPE_INVALID; j++) { |
|
if (UniqueItemList[j].UIItemId == AllItemsList[item[i].IDidx].iItemId |
|
&& lvl >= UniqueItemList[j].UIMinLvl |
|
&& (recreate || !UniqueItemFlag[j] || gbMaxPlayers != 1)) { |
|
uok[j] = TRUE; |
|
numu++; |
|
} |
|
} |
|
|
|
if (!numu) |
|
return -1; |
|
|
|
random(29, 10); |
|
idata = 0; |
|
while (numu > 0) { |
|
if (uok[idata]) |
|
numu--; |
|
if (numu > 0) { |
|
idata++; |
|
if (idata == 128) |
|
idata = 0; |
|
} |
|
} |
|
|
|
return idata; |
|
} |
|
|
|
void GetUniqueItem(int i, int uid) |
|
{ |
|
UniqueItemFlag[uid] = TRUE; |
|
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); |
|
|
|
strcpy(item[i]._iIName, UniqueItemList[uid].UIName); |
|
item[i]._iIvalue = UniqueItemList[uid].UIValue; |
|
|
|
if (item[i]._iMiscId == IMISC_UNIQUE) |
|
item[i]._iSeed = uid; |
|
|
|
item[i]._iCreateInfo |= 0x0200; |
|
item[i]._iUid = uid; |
|
item[i]._iMagical = ITEM_QUALITY_UNIQUE; |
|
} |
|
|
|
void SpawnUnique(int uid, int x, int y) |
|
{ |
|
int ii, itype; |
|
|
|
if (numitems >= MAXITEMS) |
|
return; |
|
|
|
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, currlevel); |
|
GetUniqueItem(ii, uid); |
|
SetupItem(ii); |
|
numitems++; |
|
} |
|
|
|
void ItemRndDur(int ii) |
|
{ |
|
if (item[ii]._iDurability && item[ii]._iDurability != DUR_INDESTRUCTIBLE) |
|
item[ii]._iDurability = random(0, item[ii]._iMaxDur >> 1) + (item[ii]._iMaxDur >> 2) + 1; |
|
} |
|
|
|
void SetupAllItems(int ii, int idx, int iseed, int lvl, int uper, int onlygood, int recreate, int pregen) |
|
{ |
|
int iblvl, uid; |
|
|
|
item[ii]._iSeed = iseed; |
|
SetRndSeed(iseed); |
|
GetItemAttrs(ii, idx, lvl >> 1); |
|
item[ii]._iCreateInfo = lvl; |
|
|
|
if (pregen) |
|
item[ii]._iCreateInfo = lvl | 0x8000; |
|
if (onlygood) |
|
item[ii]._iCreateInfo |= 0x40; |
|
|
|
if (uper == 15) |
|
item[ii]._iCreateInfo |= 0x80; |
|
else if (uper == 1) |
|
item[ii]._iCreateInfo |= 0x0100; |
|
|
|
if (item[ii]._iMiscId != IMISC_UNIQUE) { |
|
iblvl = -1; |
|
if (random(32, 100) > 10 && random(33, 100) > lvl || (iblvl = lvl, lvl == -1)) { |
|
|
|
if (item[ii]._iMiscId != IMISC_STAFF || (iblvl = lvl, lvl == -1)) { |
|
if (item[ii]._iMiscId != IMISC_RING || (iblvl = lvl, lvl == -1)) { |
|
if (item[ii]._iMiscId == IMISC_AMULET) |
|
iblvl = lvl; |
|
} |
|
} |
|
} |
|
if (onlygood) |
|
iblvl = lvl; |
|
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); |
|
} else { |
|
GetUniqueItem(ii, uid); |
|
item[ii]._iCreateInfo |= 0x0200; |
|
} |
|
} |
|
if (item[ii]._iMagical != ITEM_QUALITY_UNIQUE) |
|
ItemRndDur(ii); |
|
} else { |
|
if (item[ii]._iLoc != ILOC_UNEQUIPABLE) |
|
GetUniqueItem(ii, iseed); |
|
} |
|
SetupItem(ii); |
|
} |
|
|
|
void SpawnItem(int m, int x, int y, BOOL sendmsg) |
|
{ |
|
int ii, onlygood, idx; |
|
|
|
if (monster[m]._uniqtype || ((monster[m].MData->mTreasure & 0x8000) && gbMaxPlayers != 1)) { |
|
idx = RndUItem(m); |
|
if (idx < 0) { |
|
SpawnUnique(-(idx + 1), x, y); |
|
return; |
|
} |
|
onlygood = 1; |
|
} else if (quests[QTYPE_BLKM]._qactive != 2 || quests[QTYPE_BLKM]._qvar1 != QS_MUSHGIVEN) { |
|
idx = RndItem(m); |
|
if (!idx) |
|
return; |
|
if (idx > 0) { |
|
idx--; |
|
onlygood = 0; |
|
} else { |
|
SpawnUnique(-(idx + 1), x, y); |
|
return; |
|
} |
|
} else { |
|
idx = IDI_BRAIN; |
|
quests[QTYPE_BLKM]._qvar1 = QS_BRAINSPAWNED; |
|
} |
|
|
|
if (numitems < MAXITEMS) { |
|
ii = itemavail[0]; |
|
GetSuperItemSpace(x, y, ii); |
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1]; |
|
itemactive[numitems] = ii; |
|
if (monster[m]._uniqtype) { |
|
SetupAllItems(ii, idx, GetRndSeed(), monster[m].MData->mLevel, 15, onlygood, 0, 0); |
|
} else { |
|
SetupAllItems(ii, idx, GetRndSeed(), monster[m].MData->mLevel, 1, onlygood, 0, 0); |
|
} |
|
numitems++; |
|
if (sendmsg) |
|
NetSendCmdDItem(FALSE, ii); |
|
} |
|
} |
|
|
|
void CreateItem(int uid, int x, int y) |
|
{ |
|
int ii, idx; |
|
|
|
if (numitems < MAXITEMS) { |
|
ii = itemavail[0]; |
|
GetSuperItemSpace(x, y, ii); |
|
idx = 0; |
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1]; |
|
itemactive[numitems] = ii; |
|
|
|
while (AllItemsList[idx].iItemId != UniqueItemList[uid].UIItemId) { |
|
idx++; |
|
} |
|
|
|
GetItemAttrs(ii, idx, currlevel); |
|
GetUniqueItem(ii, uid); |
|
SetupItem(ii); |
|
item[ii]._iMagical = ITEM_QUALITY_UNIQUE; |
|
numitems++; |
|
} |
|
} |
|
|
|
void CreateRndItem(int x, int y, BOOL onlygood, BOOL sendmsg, int delta) |
|
{ |
|
int idx, ii; |
|
|
|
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; |
|
SetupAllItems(ii, idx, GetRndSeed(), 2 * currlevel, 1, onlygood, 0, 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 (random(34, 2)) |
|
idx = IDI_HEAL; |
|
else |
|
idx = IDI_MANA; |
|
|
|
if (lvl > 1 && !random(34, 3)) |
|
idx = IDI_PORTAL; |
|
|
|
GetItemAttrs(ii, idx, lvl); |
|
item[ii]._iCreateInfo = lvl + 384; |
|
SetupItem(ii); |
|
} |
|
|
|
void CreateRndUseful(int pnum, int x, int y, BOOL sendmsg) |
|
{ |
|
int ii; |
|
|
|
if (numitems < MAXITEMS) { |
|
ii = itemavail[0]; |
|
GetSuperItemSpace(x, y, ii); |
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1]; |
|
itemactive[numitems] = ii; |
|
SetupAllUseful(ii, GetRndSeed(), currlevel); |
|
if (sendmsg) { |
|
NetSendCmdDItem(FALSE, ii); |
|
} |
|
numitems++; |
|
} |
|
} |
|
|
|
void CreateTypeItem(int x, int y, BOOL onlygood, int itype, int imisc, BOOL sendmsg, int delta) |
|
{ |
|
int idx, ii; |
|
|
|
if (itype != ITYPE_GOLD) |
|
idx = RndTypeItems(itype, imisc); |
|
else |
|
idx = 0; |
|
|
|
if (numitems < MAXITEMS) { |
|
ii = itemavail[0]; |
|
GetSuperItemSpace(x, y, ii); |
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1]; |
|
itemactive[numitems] = ii; |
|
SetupAllItems(ii, idx, GetRndSeed(), 2 * currlevel, 1, onlygood, 0, delta); |
|
|
|
if (sendmsg) |
|
NetSendCmdDItem(FALSE, ii); |
|
if (delta) |
|
DeltaAddItem(ii); |
|
|
|
numitems++; |
|
} |
|
} |
|
|
|
void RecreateItem(int ii, int idx, WORD ic, int iseed, int ivalue) |
|
{ |
|
int uper, onlygood, recreate, pregen; |
|
|
|
if (!idx) { |
|
SetPlrHandItem(&item[ii], IDI_GOLD); |
|
item[ii]._iSeed = iseed; |
|
item[ii]._iCreateInfo = ic; |
|
item[ii]._ivalue = ivalue; |
|
if (ivalue >= GOLD_MEDIUM_LIMIT) |
|
item[ii]._iCurs = ICURS_GOLD_LARGE; |
|
else if (ivalue <= GOLD_SMALL_LIMIT) |
|
item[ii]._iCurs = ICURS_GOLD_SMALL; |
|
else |
|
item[ii]._iCurs = ICURS_GOLD_MEDIUM; |
|
} else { |
|
if (!ic) { |
|
SetPlrHandItem(&item[ii], idx); |
|
SetPlrHandSeed(&item[ii], iseed); |
|
} else { |
|
if (ic & 0x7C00) { |
|
RecreateTownItem(ii, idx, ic, iseed, ivalue); |
|
} else if ((ic & 0x0180) == 0x0180) { |
|
SetupAllUseful(ii, iseed, ic & 0x3F); |
|
} else { |
|
uper = 0; |
|
onlygood = 0; |
|
recreate = 0; |
|
pregen = 0; |
|
if (ic & 0x0100) |
|
uper = 1; |
|
if (ic & 0x80) |
|
uper = 15; |
|
if (ic & 0x40) |
|
onlygood = 1; |
|
if (ic & 0x0200) |
|
recreate = 1; |
|
if (ic & 0x8000) |
|
pregen = 1; |
|
SetupAllItems(ii, idx, iseed, ic & 0x3F, uper, onlygood, recreate, pregen); |
|
} |
|
} |
|
} |
|
} |
|
|
|
void RecreateEar(int ii, WORD ic, int iseed, int 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) & 3) + 19; |
|
item[ii]._iCreateInfo = ic; |
|
item[ii]._ivalue = ivalue & 0x3F; |
|
item[ii]._iSeed = iseed; |
|
} |
|
|
|
void SpawnQuestItem(int itemid, int x, int y, int randarea, int selflag) |
|
{ |
|
BOOL failed; |
|
int i, j, tries; |
|
|
|
if (randarea) { |
|
tries = 0; |
|
while (1) { |
|
tries++; |
|
if (tries > 1000 && randarea > 1) |
|
randarea--; |
|
x = random(0, MAXDUNX); |
|
y = random(0, MAXDUNY); |
|
failed = FALSE; |
|
for (i = 0; i < randarea && !failed; i++) { |
|
for (j = 0; j < randarea && !failed; j++) { |
|
failed = !ItemSpaceOk(i + x, j + y); |
|
} |
|
} |
|
if (!failed) |
|
break; |
|
} |
|
} |
|
|
|
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, currlevel); |
|
SetupItem(i); |
|
item[i]._iPostDraw = TRUE; |
|
if (selflag) { |
|
item[i]._iAnimFlag = FALSE; |
|
item[i]._iSelFlag = selflag; |
|
item[i]._iAnimFrame = item[i]._iAnimLen; |
|
} |
|
numitems++; |
|
} |
|
} |
|
|
|
void SpawnRock() |
|
{ |
|
int i, ii; |
|
int xx, yy; |
|
int ostand; |
|
|
|
ostand = FALSE; |
|
for (i = 0; i < nobjects && !ostand; i++) { |
|
ii = objectactive[i]; |
|
ostand = object[ii]._otype == OBJ_STAND; |
|
} |
|
if (ostand) { |
|
i = itemavail[0]; |
|
itemavail[0] = itemavail[127 - numitems - 1]; |
|
itemactive[numitems] = i; |
|
xx = object[ii]._ox; |
|
yy = object[ii]._oy; |
|
item[i]._ix = xx; |
|
item[i]._iy = yy; |
|
dItem[xx][item[i]._iy] = i + 1; |
|
GetItemAttrs(i, IDI_ROCK, currlevel); |
|
SetupItem(i); |
|
item[i]._iSelFlag = 2; |
|
item[i]._iPostDraw = 1; |
|
item[i]._iAnimFrame = 11; |
|
numitems++; |
|
} |
|
} |
|
|
|
void RespawnItem(int i, BOOL FlipFlag) |
|
{ |
|
int it; |
|
|
|
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 = 0; |
|
} else { |
|
item[i]._iAnimFrame = item[i]._iAnimLen; |
|
item[i]._iAnimFlag = FALSE; |
|
item[i]._iSelFlag = 1; |
|
} |
|
|
|
if (item[i]._iCurs == ICURS_MAGIC_ROCK) { |
|
item[i]._iSelFlag = 1; |
|
PlaySfxLoc(ItemDropSnds[it], item[i]._ix, item[i]._iy); |
|
} |
|
if (item[i]._iCurs == ICURS_TAVERN_SIGN) |
|
item[i]._iSelFlag = 1; |
|
if (item[i]._iCurs == ICURS_ANVIL_OF_FURY) |
|
item[i]._iSelFlag = 1; |
|
} |
|
|
|
void DeleteItem(int ii, int i) |
|
{ |
|
itemavail[MAXITEMS - numitems] = ii; |
|
numitems--; |
|
if (numitems > 0 && i != numitems) |
|
itemactive[i] = itemactive[numitems]; |
|
} |
|
|
|
void ItemDoppel() |
|
{ |
|
int idoppelx; |
|
ItemStruct *i; |
|
|
|
if (gbMaxPlayers != 1) { |
|
for (idoppelx = 16; idoppelx < 96; 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 == 96) |
|
idoppely = 16; |
|
} |
|
} |
|
|
|
void ProcessItems() |
|
{ |
|
int i, ii; |
|
|
|
for (i = 0; i < numitems; i++) { |
|
ii = itemactive[i]; |
|
if (item[ii]._iAnimFlag) { |
|
item[ii]._iAnimFrame++; |
|
if (item[ii]._iCurs == ICURS_MAGIC_ROCK) { |
|
if (item[ii]._iSelFlag == 1 && item[ii]._iAnimFrame == 11) |
|
item[ii]._iAnimFrame = 1; |
|
if (item[ii]._iSelFlag == 2 && item[ii]._iAnimFrame == 21) |
|
item[ii]._iAnimFrame = 11; |
|
} else { |
|
if (item[ii]._iAnimFrame == item[ii]._iAnimLen >> 1) |
|
PlaySfxLoc(ItemDropSnds[ItemCAnimTbl[item[ii]._iCurs]], item[ii]._ix, item[ii]._iy); |
|
|
|
if (item[ii]._iAnimFrame >= item[ii]._iAnimLen) { |
|
item[ii]._iAnimFlag = FALSE; |
|
item[ii]._iAnimFrame = item[ii]._iAnimLen; |
|
item[ii]._iSelFlag = 1; |
|
} |
|
} |
|
} |
|
} |
|
ItemDoppel(); |
|
} |
|
|
|
void FreeItemGFX() |
|
{ |
|
int i; |
|
|
|
for (i = 0; i < 35; i++) { |
|
MemFreeDbg(itemanims[i]); |
|
} |
|
} |
|
|
|
void GetItemFrm(int i) |
|
{ |
|
item[i]._iAnimData = itemanims[ItemCAnimTbl[item[i]._iCurs]]; |
|
} |
|
|
|
void GetItemStr(int i) |
|
{ |
|
int nGold; |
|
|
|
if (item[i]._itype != ITYPE_GOLD) { |
|
if (item[i]._iIdentified) |
|
strcpy(infostr, item[i]._iIName); |
|
else |
|
strcpy(infostr, item[i]._iName); |
|
|
|
if (item[i]._iMagical == ITEM_QUALITY_MAGIC) |
|
infoclr = COL_BLUE; |
|
if (item[i]._iMagical == ITEM_QUALITY_UNIQUE) |
|
infoclr = COL_GOLD; |
|
} else { |
|
nGold = item[i]._ivalue; |
|
sprintf(infostr, "%i gold %s", nGold, get_pieces_str(nGold)); |
|
} |
|
} |
|
|
|
void CheckIdentify(int pnum, int cii) |
|
{ |
|
ItemStruct *pi; |
|
|
|
if (cii >= 7) |
|
pi = &plr[pnum].InvList[cii - 7]; |
|
else |
|
pi = &plr[pnum].InvBody[cii]; |
|
|
|
pi->_iIdentified = TRUE; |
|
CalcPlrInv(pnum, TRUE); |
|
|
|
if (pnum == myplr) |
|
SetCursor_(CURSOR_HAND); |
|
} |
|
|
|
void DoRepair(int pnum, int cii) |
|
{ |
|
PlayerStruct *p; |
|
ItemStruct *pi; |
|
|
|
p = &plr[pnum]; |
|
pi = &p->InvBody[cii]; |
|
|
|
PlaySfxLoc(IS_REPAIR, p->WorldX, p->WorldY); |
|
RepairItem(pi, p->_pLevel); |
|
CalcPlrInv(pnum, TRUE); |
|
|
|
if (pnum == myplr) |
|
SetCursor_(CURSOR_HAND); |
|
} |
|
|
|
void RepairItem(ItemStruct *i, int lvl) |
|
{ |
|
int rep, d; |
|
|
|
if (i->_iDurability == i->_iMaxDur) { |
|
return; |
|
} |
|
|
|
if (i->_iMaxDur <= 0) { |
|
i->_itype = ITYPE_NONE; |
|
return; |
|
} |
|
|
|
rep = 0; |
|
do { |
|
rep += lvl + random(37, lvl); |
|
d = i->_iMaxDur / (lvl + 9); |
|
if (d < 1) |
|
d = 1; |
|
i->_iMaxDur = i->_iMaxDur - d; |
|
if (!i->_iMaxDur) { |
|
i->_itype = ITYPE_NONE; |
|
return; |
|
} |
|
} while (rep + i->_iDurability < i->_iMaxDur); |
|
|
|
i->_iDurability += rep; |
|
if (i->_iDurability > i->_iMaxDur) |
|
i->_iDurability = i->_iMaxDur; |
|
} |
|
|
|
void DoRecharge(int pnum, int cii) |
|
{ |
|
PlayerStruct *p; |
|
ItemStruct *pi; |
|
int r; |
|
|
|
p = &plr[pnum]; |
|
pi = &p->InvBody[cii]; |
|
if (pi->_itype == ITYPE_STAFF && pi->_iSpell) { |
|
r = spelldata[pi->_iSpell].sBookLvl; |
|
r = random(38, p->_pLevel / r) + 1; |
|
RechargeItem(pi, r); |
|
CalcPlrInv(pnum, TRUE); |
|
} |
|
|
|
if (pnum == myplr) |
|
SetCursor_(CURSOR_HAND); |
|
} |
|
|
|
void RechargeItem(ItemStruct *i, int r) |
|
{ |
|
while (i->_iCharges != i->_iMaxCharges) { |
|
i->_iMaxCharges--; |
|
if (i->_iMaxCharges == 0) { |
|
break; |
|
} |
|
i->_iCharges += r; |
|
if (i->_iCharges >= i->_iMaxCharges) { |
|
if (i->_iCharges > i->_iMaxCharges) |
|
i->_iCharges = i->_iMaxCharges; |
|
return; |
|
} |
|
} |
|
} |
|
|
|
void PrintItemOil(char IDidx) |
|
{ |
|
switch (IDidx) { |
|
case IMISC_FULLHEAL: |
|
strcpy(tempstr, "fully recover life"); |
|
AddPanelString(tempstr, TRUE); |
|
break; |
|
case IMISC_HEAL: |
|
strcpy(tempstr, "recover partial life"); |
|
AddPanelString(tempstr, TRUE); |
|
break; |
|
case IMISC_OLDHEAL: |
|
strcpy(tempstr, "recover life"); |
|
AddPanelString(tempstr, TRUE); |
|
break; |
|
case IMISC_DEADHEAL: |
|
strcpy(tempstr, "deadly heal"); |
|
AddPanelString(tempstr, TRUE); |
|
break; |
|
case IMISC_MANA: |
|
strcpy(tempstr, "recover mana"); |
|
AddPanelString(tempstr, TRUE); |
|
break; |
|
case IMISC_FULLMANA: |
|
strcpy(tempstr, "fully recover mana"); |
|
AddPanelString(tempstr, TRUE); |
|
break; |
|
case IMISC_ELIXSTR: |
|
strcpy(tempstr, "increase strength"); |
|
AddPanelString(tempstr, TRUE); |
|
break; |
|
case IMISC_ELIXMAG: |
|
strcpy(tempstr, "increase magic"); |
|
AddPanelString(tempstr, TRUE); |
|
break; |
|
case IMISC_ELIXDEX: |
|
strcpy(tempstr, "increase dexterity"); |
|
AddPanelString(tempstr, TRUE); |
|
break; |
|
case IMISC_ELIXVIT: |
|
strcpy(tempstr, "increase vitality"); |
|
AddPanelString(tempstr, TRUE); |
|
break; |
|
case IMISC_ELIXWEAK: |
|
strcpy(tempstr, "decrease strength"); |
|
AddPanelString(tempstr, TRUE); |
|
break; |
|
case IMISC_ELIXDIS: |
|
strcpy(tempstr, "decrease strength"); |
|
AddPanelString(tempstr, TRUE); |
|
break; |
|
case IMISC_ELIXCLUM: |
|
strcpy(tempstr, "decrease dexterity"); |
|
AddPanelString(tempstr, TRUE); |
|
break; |
|
case IMISC_ELIXSICK: |
|
strcpy(tempstr, "decrease vitality"); |
|
AddPanelString(tempstr, TRUE); |
|
break; |
|
case IMISC_REJUV: |
|
strcpy(tempstr, "recover life and mana"); |
|
AddPanelString(tempstr, TRUE); |
|
break; |
|
case IMISC_FULLREJUV: |
|
strcpy(tempstr, "fully recover life and mana"); |
|
AddPanelString(tempstr, TRUE); |
|
break; |
|
} |
|
} |
|
|
|
void PrintItemPower(char plidx, ItemStruct *x) |
|
{ |
|
switch (plidx) { |
|
case IPL_TOHIT: |
|
case IPL_TOHIT_CURSE: |
|
sprintf(tempstr, "chance to hit : %+i%%", x->_iPLToHit); |
|
break; |
|
case IPL_DAMP: |
|
case IPL_DAMP_CURSE: |
|
sprintf(tempstr, "%+i%% damage", x->_iPLDam); |
|
break; |
|
case IPL_TOHIT_DAMP: |
|
case IPL_TOHIT_DAMP_CURSE: |
|
sprintf(tempstr, "to hit: %+i%%, %+i%% damage", x->_iPLToHit, x->_iPLDam); |
|
break; |
|
case IPL_ACP: |
|
case IPL_ACP_CURSE: |
|
sprintf(tempstr, "%+i%% armor", x->_iPLAC); |
|
break; |
|
case IPL_SETAC: |
|
sprintf(tempstr, "armor class: %i", x->_iAC); |
|
break; |
|
case IPL_AC_CURSE: |
|
sprintf(tempstr, "armor class: %i", x->_iAC); |
|
break; |
|
case IPL_FIRERES: |
|
if (x->_iPLFR < 75) |
|
sprintf(tempstr, "Resist Fire : %+i%%", x->_iPLFR); |
|
if (x->_iPLFR >= 75) |
|
sprintf(tempstr, "Resist Fire : 75%% MAX"); |
|
break; |
|
case IPL_LIGHTRES: |
|
if (x->_iPLLR < 75) |
|
sprintf(tempstr, "Resist Lightning : %+i%%", x->_iPLLR); |
|
if (x->_iPLLR >= 75) |
|
sprintf(tempstr, "Resist Lightning : 75%% MAX"); |
|
break; |
|
case IPL_MAGICRES: |
|
if (x->_iPLMR < 75) |
|
sprintf(tempstr, "Resist Magic : %+i%%", x->_iPLMR); |
|
if (x->_iPLMR >= 75) |
|
sprintf(tempstr, "Resist Magic : 75%% MAX"); |
|
break; |
|
case IPL_ALLRES: |
|
if (x->_iPLFR < 75) |
|
sprintf(tempstr, "Resist All : %+i%%", x->_iPLFR); |
|
if (x->_iPLFR >= 75) |
|
sprintf(tempstr, "Resist All : 75%% MAX"); |
|
break; |
|
case IPL_SPLLVLADD: |
|
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"); |
|
break; |
|
case IPL_CHARGES: |
|
strcpy(tempstr, "Extra charges"); |
|
break; |
|
case IPL_SPELL: |
|
sprintf(tempstr, "%i %s charges", x->_iMaxCharges, spelldata[x->_iSpell].sNameText); |
|
break; |
|
case IPL_FIREDAM: |
|
sprintf(tempstr, "Fire hit damage: %i-%i", x->_iFMinDam, x->_iFMaxDam); |
|
break; |
|
case IPL_LIGHTDAM: |
|
sprintf(tempstr, "Lightning hit damage: %i-%i", x->_iLMinDam, x->_iLMaxDam); |
|
break; |
|
case IPL_STR: |
|
case IPL_STR_CURSE: |
|
sprintf(tempstr, "%+i to strength", x->_iPLStr); |
|
break; |
|
case IPL_MAG: |
|
case IPL_MAG_CURSE: |
|
sprintf(tempstr, "%+i to magic", x->_iPLMag); |
|
break; |
|
case IPL_DEX: |
|
case IPL_DEX_CURSE: |
|
sprintf(tempstr, "%+i to dexterity", x->_iPLDex); |
|
break; |
|
case IPL_VIT: |
|
case IPL_VIT_CURSE: |
|
sprintf(tempstr, "%+i to vitality", x->_iPLVit); |
|
break; |
|
case IPL_ATTRIBS: |
|
case IPL_ATTRIBS_CURSE: |
|
sprintf(tempstr, "%+i to all attributes", x->_iPLStr); |
|
break; |
|
case IPL_GETHIT_CURSE: |
|
case IPL_GETHIT: |
|
sprintf(tempstr, "%+i damage from enemies", x->_iPLGetHit); |
|
break; |
|
case IPL_LIFE: |
|
case IPL_LIFE_CURSE: |
|
sprintf(tempstr, "Hit Points : %+i", x->_iPLHP >> 6); |
|
break; |
|
case IPL_MANA: |
|
case IPL_MANA_CURSE: |
|
sprintf(tempstr, "Mana : %+i", x->_iPLMana >> 6); |
|
break; |
|
case IPL_DUR: |
|
strcpy(tempstr, "high durability"); |
|
break; |
|
case IPL_DUR_CURSE: |
|
strcpy(tempstr, "decreased durability"); |
|
break; |
|
case IPL_INDESTRUCTIBLE: |
|
strcpy(tempstr, "indestructible"); |
|
break; |
|
case IPL_LIGHT: |
|
sprintf(tempstr, "+%i%% light radius", 10 * x->_iPLLight); |
|
break; |
|
case IPL_LIGHT_CURSE: |
|
sprintf(tempstr, "-%i%% light radius", -10 * x->_iPLLight); |
|
break; |
|
case IPL_FIRE_ARROWS: |
|
sprintf(tempstr, "fire arrows damage: %i-%i", x->_iFMinDam, x->_iFMaxDam); |
|
break; |
|
case IPL_LIGHT_ARROWS: |
|
sprintf(tempstr, "lightning arrows damage %i-%i", x->_iLMinDam, x->_iLMaxDam); |
|
break; |
|
case IPL_THORNS: |
|
strcpy(tempstr, "attacker takes 1-3 damage"); |
|
break; |
|
case IPL_NOMANA: |
|
strcpy(tempstr, "user loses all mana"); |
|
break; |
|
case IPL_NOHEALPLR: |
|
strcpy(tempstr, "you can't heal"); |
|
break; |
|
case IPL_ABSHALFTRAP: |
|
strcpy(tempstr, "absorbs half of trap damage"); |
|
break; |
|
case IPL_KNOCKBACK: |
|
strcpy(tempstr, "knocks target back"); |
|
break; |
|
case IPL_3XDAMVDEM: |
|
strcpy(tempstr, "+200% damage vs. demons"); |
|
break; |
|
case IPL_ALLRESZERO: |
|
strcpy(tempstr, "All Resistance equals 0"); |
|
break; |
|
case IPL_NOHEALMON: |
|
strcpy(tempstr, "hit monster doesn't heal"); |
|
break; |
|
case IPL_STEALMANA: |
|
if (x->_iFlags & ISPL_STEALMANA_3) |
|
strcpy(tempstr, "hit steals 3% mana"); |
|
if (x->_iFlags & ISPL_STEALMANA_5) |
|
strcpy(tempstr, "hit steals 5% mana"); |
|
break; |
|
case IPL_STEALLIFE: |
|
if (x->_iFlags & ISPL_STEALLIFE_3) |
|
strcpy(tempstr, "hit steals 3% life"); |
|
if (x->_iFlags & ISPL_STEALLIFE_5) |
|
strcpy(tempstr, "hit steals 5% life"); |
|
break; |
|
case IPL_TARGAC: |
|
strcpy(tempstr, "damages target's armor"); |
|
break; |
|
case IPL_FASTATTACK: |
|
if (x->_iFlags & 0x20000) |
|
strcpy(tempstr, "quick attack"); |
|
if (x->_iFlags & 0x40000) |
|
strcpy(tempstr, "fast attack"); |
|
if (x->_iFlags & 0x80000) |
|
strcpy(tempstr, "faster attack"); |
|
if (x->_iFlags & 0x100000) |
|
strcpy(tempstr, "fastest attack"); |
|
break; |
|
case IPL_FASTRECOVER: |
|
if (x->_iFlags & 0x200000) |
|
strcpy(tempstr, "fast hit recovery"); |
|
if (x->_iFlags & 0x400000) |
|
strcpy(tempstr, "faster hit recovery"); |
|
if (x->_iFlags & 0x800000) |
|
strcpy(tempstr, "fastest hit recovery"); |
|
break; |
|
case IPL_FASTBLOCK: |
|
strcpy(tempstr, "fast block"); |
|
break; |
|
case IPL_DAMMOD: |
|
sprintf(tempstr, "adds %i points to damage", x->_iPLDamMod); |
|
break; |
|
case IPL_RNDARROWVEL: |
|
strcpy(tempstr, "fires random speed arrows"); |
|
break; |
|
case IPL_SETDAM: |
|
sprintf(tempstr, "unusual item damage"); |
|
break; |
|
case IPL_SETDUR: |
|
strcpy(tempstr, "altered durability"); |
|
break; |
|
case IPL_FASTSWING: |
|
strcpy(tempstr, "Faster attack swing"); |
|
break; |
|
case IPL_ONEHAND: |
|
strcpy(tempstr, "one handed sword"); |
|
break; |
|
case IPL_DRAINLIFE: |
|
strcpy(tempstr, "constantly lose hit points"); |
|
break; |
|
case IPL_RNDSTEALLIFE: |
|
strcpy(tempstr, "life stealing"); |
|
break; |
|
case IPL_NOMINSTR: |
|
strcpy(tempstr, "no strength requirement"); |
|
break; |
|
case IPL_INFRAVISION: |
|
strcpy(tempstr, "see with infravision"); |
|
break; |
|
case IPL_INVCURS: |
|
strcpy(tempstr, " "); |
|
break; |
|
case IPL_ADDACLIFE: |
|
strcpy(tempstr, "Armor class added to life"); |
|
break; |
|
case IPL_ADDMANAAC: |
|
strcpy(tempstr, "10% of mana added to armor"); |
|
break; |
|
case IPL_FIRERESCLVL: |
|
if (x->_iPLFR <= 0) |
|
sprintf(tempstr, " "); |
|
else if (x->_iPLFR >= 1) |
|
sprintf(tempstr, "Resist Fire : %+i%%", x->_iPLFR); |
|
break; |
|
default: |
|
strcpy(tempstr, "Another ability (NW)"); |
|
break; |
|
} |
|
} |
|
|
|
void DrawUTextBack() |
|
{ |
|
CelDecodeOnly(88, 487, (BYTE *)pSTextBoxCels, 1, 271); |
|
|
|
#define TRANS_RECT_X 27 |
|
#define TRANS_RECT_Y 28 |
|
#define TRANS_RECT_WIDTH 265 |
|
#define TRANS_RECT_HEIGHT 297 |
|
#include "asm_trans_rect.inc" |
|
} |
|
|
|
void PrintUString(int x, int y, BOOL cjustflag, char *str, int col) |
|
{ |
|
int len, width, off, i, k; |
|
BYTE c; |
|
|
|
off = x + PitchTbl[SStringY[y] + 204] + 96; |
|
len = strlen(str); |
|
k = 0; |
|
if (cjustflag) { |
|
width = 0; |
|
for (i = 0; i < len; i++) |
|
width += fontkern[fontframe[gbFontTransTbl[(BYTE)str[i]]]] + 1; |
|
if (width < 257) |
|
k = (257 - width) >> 1; |
|
off += k; |
|
} |
|
|
|
for (i = 0; i < len; i++) { |
|
c = fontframe[gbFontTransTbl[(BYTE)str[i]]]; |
|
k += fontkern[c] + 1; |
|
if (c && k <= 257) { |
|
CPrintString(off, c, col); |
|
} |
|
off += fontkern[c] + 1; |
|
} |
|
} |
|
|
|
void DrawULine(int y) |
|
{ |
|
/// ASSERT: assert(gpBuffer); |
|
|
|
#ifdef USE_ASM |
|
int yy; |
|
|
|
yy = PitchTbl[SStringY[y] + 198] + 26 + 64; |
|
|
|
__asm { |
|
mov esi, gpBuffer |
|
mov edi, esi |
|
add esi, SCREENXY(26, 25) |
|
add edi, yy |
|
mov ebx, BUFFER_WIDTH - 266 |
|
mov edx, 3 |
|
copyline: |
|
mov ecx, 266 / 4 |
|
rep movsd |
|
movsw |
|
add esi, ebx |
|
add edi, ebx |
|
dec edx |
|
jnz copyline |
|
} |
|
#else |
|
int i; |
|
BYTE *src, *dst; |
|
|
|
src = &gpBuffer[SCREENXY(26, 25)]; |
|
dst = &gpBuffer[PitchTbl[SStringY[y] + 198] + 26 + 64]; |
|
|
|
for (i = 0; i < 3; i++, src += BUFFER_WIDTH, dst += BUFFER_WIDTH) |
|
memcpy(dst, src, 266); |
|
#endif |
|
} |
|
|
|
void DrawUniqueInfo() |
|
{ |
|
int uid, y; |
|
|
|
if (!chrflag && !questlog) { |
|
uid = curruitem._iUid; |
|
DrawUTextBack(); |
|
PrintUString(0, 2, 1, UniqueItemList[uid].UIName, 3); |
|
DrawULine(5); |
|
PrintItemPower(UniqueItemList[uid].UIPower1, &curruitem); |
|
y = 14 - UniqueItemList[uid].UINumPL; |
|
PrintUString(0, y, 1, tempstr, 0); |
|
if (UniqueItemList[uid].UINumPL > 1) { |
|
PrintItemPower(UniqueItemList[uid].UIPower2, &curruitem); |
|
PrintUString(0, y + 2, 1, tempstr, 0); |
|
} |
|
if (UniqueItemList[uid].UINumPL > 2) { |
|
PrintItemPower(UniqueItemList[uid].UIPower3, &curruitem); |
|
PrintUString(0, y + 4, 1, tempstr, 0); |
|
} |
|
if (UniqueItemList[uid].UINumPL > 3) { |
|
PrintItemPower(UniqueItemList[uid].UIPower4, &curruitem); |
|
PrintUString(0, y + 6, 1, tempstr, 0); |
|
} |
|
if (UniqueItemList[uid].UINumPL > 4) { |
|
PrintItemPower(UniqueItemList[uid].UIPower5, &curruitem); |
|
PrintUString(0, y + 8, 1, tempstr, 0); |
|
} |
|
if (UniqueItemList[uid].UINumPL > 5) { |
|
PrintItemPower(UniqueItemList[uid].UIPower6, &curruitem); |
|
PrintUString(0, y + 10, 1, tempstr, 0); |
|
} |
|
} |
|
} |
|
|
|
void PrintItemMisc(ItemStruct *x) |
|
{ |
|
if (x->_iMiscId == IMISC_SCROLL) { |
|
strcpy(tempstr, "Right-click to read"); |
|
AddPanelString(tempstr, TRUE); |
|
} |
|
if (x->_iMiscId == IMISC_SCROLLT) { |
|
strcpy(tempstr, "Right-click to read, then"); |
|
AddPanelString(tempstr, TRUE); |
|
strcpy(tempstr, "left-click to target"); |
|
AddPanelString(tempstr, TRUE); |
|
} |
|
if (x->_iMiscId >= IMISC_USEFIRST && x->_iMiscId <= IMISC_USELAST) { |
|
PrintItemOil(x->_iMiscId); |
|
strcpy(tempstr, "Right click to use"); |
|
AddPanelString(tempstr, TRUE); |
|
} |
|
if (x->_iMiscId == IMISC_BOOK) { |
|
strcpy(tempstr, "Right click to read"); |
|
AddPanelString(tempstr, TRUE); |
|
} |
|
if (x->_iMiscId == IMISC_MAPOFDOOM) { |
|
strcpy(tempstr, "Right click to view"); |
|
AddPanelString(tempstr, TRUE); |
|
} |
|
if (x->_iMiscId == IMISC_EAR) { |
|
sprintf(tempstr, "Level : %i", x->_ivalue); |
|
AddPanelString(tempstr, TRUE); |
|
} |
|
} |
|
|
|
void PrintItemDetails(ItemStruct *x) |
|
{ |
|
if (x->_iClass == ICLASS_WEAPON) { |
|
if (x->_iMaxDur == 255) |
|
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, TRUE); |
|
} |
|
if (x->_iClass == ICLASS_ARMOR) { |
|
if (x->_iMaxDur == 255) |
|
sprintf(tempstr, "armor: %i Indestructible", x->_iAC); |
|
else |
|
sprintf(tempstr, "armor: %i Dur: %i/%i", x->_iAC, x->_iDurability, x->_iMaxDur); |
|
AddPanelString(tempstr, TRUE); |
|
} |
|
if (x->_iMiscId == IMISC_STAFF && x->_iMaxCharges) { |
|
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, TRUE); |
|
} |
|
if (x->_iPrePower != -1) { |
|
PrintItemPower(x->_iPrePower, x); |
|
AddPanelString(tempstr, TRUE); |
|
} |
|
if (x->_iSufPower != -1) { |
|
PrintItemPower(x->_iSufPower, x); |
|
AddPanelString(tempstr, TRUE); |
|
} |
|
if (x->_iMagical == ITEM_QUALITY_UNIQUE) { |
|
AddPanelString("unique item", TRUE); |
|
uitemflag = 1; |
|
curruitem = *x; |
|
} |
|
PrintItemMisc(x); |
|
if (x->_iMinMag + x->_iMinDex + x->_iMinStr) { |
|
strcpy(tempstr, "Required:"); |
|
if (x->_iMinStr) |
|
sprintf(tempstr, "%s %i Str", tempstr, x->_iMinStr); |
|
if (x->_iMinMag) |
|
sprintf(tempstr, "%s %i Mag", tempstr, x->_iMinMag); |
|
if (x->_iMinDex) |
|
sprintf(tempstr, "%s %i Dex", tempstr, x->_iMinDex); |
|
AddPanelString(tempstr, TRUE); |
|
} |
|
pinfoflag = TRUE; |
|
} |
|
|
|
void PrintItemDur(ItemStruct *x) |
|
{ |
|
if (x->_iClass == ICLASS_WEAPON) { |
|
if (x->_iMaxDur == 255) |
|
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, TRUE); |
|
if (x->_iMiscId == IMISC_STAFF && x->_iMaxCharges) { |
|
sprintf(tempstr, "Charges: %i/%i", x->_iCharges, x->_iMaxCharges); |
|
AddPanelString(tempstr, TRUE); |
|
} |
|
if (x->_iMagical != ITEM_QUALITY_NORMAL) |
|
AddPanelString("Not Identified", TRUE); |
|
} |
|
if (x->_iClass == ICLASS_ARMOR) { |
|
if (x->_iMaxDur == 255) |
|
sprintf(tempstr, "armor: %i Indestructible", x->_iAC); |
|
else |
|
sprintf(tempstr, "armor: %i Dur: %i/%i", x->_iAC, x->_iDurability, x->_iMaxDur); |
|
AddPanelString(tempstr, TRUE); |
|
if (x->_iMagical != ITEM_QUALITY_NORMAL) |
|
AddPanelString("Not Identified", TRUE); |
|
if (x->_iMiscId == IMISC_STAFF && x->_iMaxCharges) { |
|
sprintf(tempstr, "Charges: %i/%i", x->_iCharges, x->_iMaxCharges); |
|
AddPanelString(tempstr, TRUE); |
|
} |
|
} |
|
if (x->_itype == ITYPE_RING || x->_itype == ITYPE_AMULET) |
|
AddPanelString("Not Identified", TRUE); |
|
PrintItemMisc(x); |
|
if (x->_iMinMag + x->_iMinDex + x->_iMinStr) { |
|
strcpy(tempstr, "Required:"); |
|
if (x->_iMinStr) |
|
sprintf(tempstr, "%s %i Str", tempstr, x->_iMinStr); |
|
if (x->_iMinMag) |
|
sprintf(tempstr, "%s %i Mag", tempstr, x->_iMinMag); |
|
if (x->_iMinDex) |
|
sprintf(tempstr, "%s %i Dex", tempstr, x->_iMinDex); |
|
AddPanelString(tempstr, TRUE); |
|
} |
|
pinfoflag = TRUE; |
|
} |
|
|
|
void UseItem(int p, int Mid, int spl) |
|
{ |
|
int l, j; |
|
|
|
switch (Mid) { |
|
case IMISC_HEAL: |
|
case IMISC_HEAL_1C: |
|
j = plr[p]._pMaxHP >> 8; |
|
l = ((j >> 1) + random(39, j)) << 6; |
|
if (plr[p]._pClass == PC_WARRIOR) |
|
l *= 2; |
|
if (plr[p]._pClass == PC_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; |
|
break; |
|
case IMISC_FULLHEAL: |
|
plr[p]._pHitPoints = plr[p]._pMaxHP; |
|
plr[p]._pHPBase = plr[p]._pMaxHPBase; |
|
drawhpflag = TRUE; |
|
break; |
|
case IMISC_MANA: |
|
j = plr[p]._pMaxMana >> 8; |
|
l = ((j >> 1) + random(40, j)) << 6; |
|
if (plr[p]._pClass == PC_SORCERER) |
|
l *= 2; |
|
if (plr[p]._pClass == PC_ROGUE) |
|
l += l >> 1; |
|
if (!(plr[p]._pIFlags & ISPL_NOMANA)) { |
|
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 IMISC_FULLMANA: |
|
if (!(plr[p]._pIFlags & ISPL_NOMANA)) { |
|
plr[p]._pMana = plr[p]._pMaxMana; |
|
plr[p]._pManaBase = plr[p]._pMaxManaBase; |
|
drawmanaflag = TRUE; |
|
} |
|
break; |
|
case IMISC_ELIXSTR: |
|
ModifyPlrStr(p, 1); |
|
break; |
|
case IMISC_ELIXMAG: |
|
ModifyPlrMag(p, 1); |
|
break; |
|
case IMISC_ELIXDEX: |
|
ModifyPlrDex(p, 1); |
|
break; |
|
case IMISC_ELIXVIT: |
|
ModifyPlrVit(p, 1); |
|
break; |
|
case IMISC_REJUV: |
|
j = plr[p]._pMaxHP >> 8; |
|
l = ((j >> 1) + random(39, j)) << 6; |
|
if (plr[p]._pClass == PC_WARRIOR) |
|
l *= 2; |
|
if (plr[p]._pClass == PC_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; |
|
j = plr[p]._pMaxMana >> 8; |
|
l = ((j >> 1) + random(40, j)) << 6; |
|
if (plr[p]._pClass == PC_SORCERER) |
|
l *= 2; |
|
if (plr[p]._pClass == PC_ROGUE) |
|
l += l >> 1; |
|
if (!(plr[p]._pIFlags & ISPL_NOMANA)) { |
|
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 IMISC_FULLREJUV: |
|
plr[p]._pHitPoints = plr[p]._pMaxHP; |
|
plr[p]._pHPBase = plr[p]._pMaxHPBase; |
|
drawhpflag = TRUE; |
|
if (!(plr[p]._pIFlags & ISPL_NOMANA)) { |
|
plr[p]._pMana = plr[p]._pMaxMana; |
|
plr[p]._pManaBase = plr[p]._pMaxManaBase; |
|
drawmanaflag = TRUE; |
|
} |
|
break; |
|
case IMISC_SCROLL: |
|
if (spelldata[spl].sTargeted) { |
|
plr[p]._pTSpell = spl; |
|
plr[p]._pTSplType = RSPLTYPE_INVALID; |
|
if (p == myplr) |
|
NewCursor(CURSOR_TELEPORT); |
|
} else { |
|
ClrPlrPath(p); |
|
plr[p]._pSpell = spl; |
|
plr[p]._pSplType = RSPLTYPE_INVALID; |
|
plr[p]._pSplFrom = 3; |
|
plr[p].destAction = ACTION_SPELL; |
|
plr[p].destParam1 = cursmx; |
|
plr[p].destParam2 = cursmy; |
|
if (p == myplr && spl == SPL_NOVA) |
|
NetSendCmdLoc(TRUE, CMD_NOVA, cursmx, cursmy); |
|
} |
|
break; |
|
case IMISC_SCROLLT: |
|
if (spelldata[spl].sTargeted) { |
|
plr[p]._pTSpell = spl; |
|
plr[p]._pTSplType = RSPLTYPE_INVALID; |
|
if (p == myplr) |
|
NewCursor(CURSOR_TELEPORT); |
|
} else { |
|
ClrPlrPath(p); |
|
plr[p]._pSpell = spl; |
|
plr[p]._pSplType = RSPLTYPE_INVALID; |
|
plr[p]._pSplFrom = 3; |
|
plr[p].destAction = ACTION_SPELL; |
|
plr[p].destParam1 = cursmx; |
|
plr[p].destParam2 = cursmy; |
|
} |
|
break; |
|
case IMISC_BOOK: |
|
plr[p]._pMemSpells |= (__int64)1 << (spl - 1); |
|
if (plr[p]._pSplLvl[spl] < 15) |
|
plr[p]._pSplLvl[spl]++; |
|
plr[p]._pMana += spelldata[spl].sManaCost << 6; |
|
if (plr[p]._pMana > plr[p]._pMaxMana) |
|
plr[p]._pMana = plr[p]._pMaxMana; |
|
plr[p]._pManaBase += spelldata[spl].sManaCost << 6; |
|
if (plr[p]._pManaBase > plr[p]._pMaxManaBase) |
|
plr[p]._pManaBase = plr[p]._pMaxManaBase; |
|
if (p == myplr) |
|
CalcPlrBookVals(p); |
|
drawmanaflag = TRUE; |
|
break; |
|
case IMISC_MAPOFDOOM: |
|
doom_init(); |
|
break; |
|
case IMISC_SPECELIX: |
|
ModifyPlrStr(p, 3); |
|
ModifyPlrMag(p, 3); |
|
ModifyPlrDex(p, 3); |
|
ModifyPlrVit(p, 3); |
|
break; |
|
} |
|
} |
|
|
|
BOOL StoreStatOk(ItemStruct *h) |
|
{ |
|
BOOL sf; |
|
|
|
sf = TRUE; |
|
if (plr[myplr]._pStrength < h->_iMinStr) |
|
sf = FALSE; |
|
if (plr[myplr]._pMagic < h->_iMinMag) |
|
sf = FALSE; |
|
if (plr[myplr]._pDexterity < h->_iMinDex) |
|
sf = FALSE; |
|
|
|
return sf; |
|
} |
|
|
|
BOOL SmithItemOk(int i) |
|
{ |
|
BOOL rv; |
|
|
|
rv = TRUE; |
|
if (AllItemsList[i].itype == ITYPE_MISC) |
|
rv = FALSE; |
|
if (AllItemsList[i].itype == ITYPE_GOLD) |
|
rv = FALSE; |
|
if (AllItemsList[i].itype == ITYPE_0E) |
|
rv = FALSE; |
|
if (AllItemsList[i].itype == ITYPE_STAFF) |
|
rv = FALSE; |
|
if (AllItemsList[i].itype == ITYPE_RING) |
|
rv = FALSE; |
|
if (AllItemsList[i].itype == ITYPE_AMULET) |
|
rv = FALSE; |
|
|
|
return rv; |
|
} |
|
|
|
int RndSmithItem(int lvl) |
|
{ |
|
int i, ri; |
|
int ril[512]; |
|
|
|
ri = 0; |
|
for (i = 1; AllItemsList[i].iLoc != ILOC_INVALID; i++) { |
|
if (AllItemsList[i].iRnd && SmithItemOk(i) && lvl >= AllItemsList[i].iMinMLvl) { |
|
ril[ri] = i; |
|
ri++; |
|
if (AllItemsList[i].iRnd == 2) { |
|
ril[ri] = i; |
|
ri++; |
|
} |
|
} |
|
} |
|
|
|
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; |
|
|
|
j = 0; |
|
while (smithitem[j + 1]._itype != ITYPE_NONE) { |
|
j++; |
|
} |
|
|
|
sorted = FALSE; |
|
while (j > 0 && !sorted) { |
|
sorted = TRUE; |
|
if (j > 0) { |
|
for (k = 0; k < j; k++) { |
|
if (smithitem[k].IDidx > smithitem[k + 1].IDidx) { |
|
BubbleSwapItem(&smithitem[k], &smithitem[k + 1]); |
|
sorted = FALSE; |
|
} |
|
} |
|
} |
|
j--; |
|
} |
|
} |
|
|
|
void SpawnSmith(int lvl) |
|
{ |
|
int i, iCnt, idata; |
|
|
|
iCnt = random(50, 10) + 10; |
|
for (i = 0; i < iCnt; i++) { |
|
do { |
|
item[0]._iSeed = GetRndSeed(); |
|
SetRndSeed(item[0]._iSeed); |
|
idata = RndSmithItem(lvl) - 1; |
|
GetItemAttrs(0, idata, lvl); |
|
} while (item[0]._iIvalue > 140000); |
|
smithitem[i] = item[0]; |
|
smithitem[i]._iCreateInfo = lvl | 0x400; |
|
smithitem[i]._iIdentified = TRUE; |
|
smithitem[i]._iStatFlag = StoreStatOk(&smithitem[i]); |
|
} |
|
for (i = iCnt; i < 20; i++) |
|
smithitem[i]._itype = ITYPE_NONE; |
|
|
|
SortSmith(); |
|
} |
|
|
|
BOOL PremiumItemOk(int i) |
|
{ |
|
BOOL rv; |
|
|
|
rv = TRUE; |
|
if (AllItemsList[i].itype == ITYPE_MISC) |
|
rv = FALSE; |
|
if (AllItemsList[i].itype == ITYPE_GOLD) |
|
rv = FALSE; |
|
if (AllItemsList[i].itype == ITYPE_0E) |
|
rv = FALSE; |
|
if (AllItemsList[i].itype == ITYPE_STAFF) |
|
rv = FALSE; |
|
|
|
if (gbMaxPlayers != 1) { |
|
if (AllItemsList[i].itype == ITYPE_RING) |
|
rv = FALSE; |
|
if (AllItemsList[i].itype == ITYPE_AMULET) |
|
rv = FALSE; |
|
} |
|
|
|
return rv; |
|
} |
|
|
|
int RndPremiumItem(int minlvl, int maxlvl) |
|
{ |
|
int i, ri; |
|
int ril[512]; |
|
|
|
ri = 0; |
|
for (i = 1; AllItemsList[i].iLoc != ILOC_INVALID; i++) { |
|
if (AllItemsList[i].iRnd) { |
|
if (PremiumItemOk(i)) { |
|
if (AllItemsList[i].iMinMLvl >= minlvl && AllItemsList[i].iMinMLvl <= maxlvl) { |
|
ril[ri] = i; |
|
ri++; |
|
} |
|
} |
|
} |
|
} |
|
|
|
return ril[random(50, ri)] + 1; |
|
} |
|
|
|
void SpawnOnePremium(int i, int plvl) |
|
{ |
|
int itype; |
|
ItemStruct holditem; |
|
|
|
holditem = item[0]; |
|
if (plvl > 30) |
|
plvl = 30; |
|
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, 1); |
|
} while (item[0]._iIvalue > 140000); |
|
premiumitem[i] = item[0]; |
|
premiumitem[i]._iCreateInfo = plvl | 0x800; |
|
premiumitem[i]._iIdentified = TRUE; |
|
premiumitem[i]._iStatFlag = StoreStatOk(&premiumitem[i]); |
|
item[0] = holditem; |
|
} |
|
|
|
void SpawnPremium(int lvl) |
|
{ |
|
int i; |
|
|
|
if (numpremium < 6) { |
|
for (i = 0; i < 6; i++) { |
|
if (premiumitem[i]._itype == ITYPE_NONE) |
|
SpawnOnePremium(i, premiumlevel + premiumlvladd[i]); |
|
} |
|
numpremium = 6; |
|
} |
|
while (premiumlevel < lvl) { |
|
premiumlevel++; |
|
premiumitem[0] = premiumitem[2]; |
|
premiumitem[1] = premiumitem[3]; |
|
premiumitem[2] = premiumitem[4]; |
|
SpawnOnePremium(3, premiumlevel + premiumlvladd[3]); |
|
premiumitem[4] = premiumitem[5]; |
|
SpawnOnePremium(5, premiumlevel + premiumlvladd[5]); |
|
} |
|
} |
|
|
|
BOOL WitchItemOk(int i) |
|
{ |
|
BOOL rv; |
|
|
|
rv = FALSE; |
|
if (AllItemsList[i].itype == ITYPE_MISC) |
|
rv = TRUE; |
|
if (AllItemsList[i].itype == ITYPE_STAFF) |
|
rv = TRUE; |
|
if (AllItemsList[i].iMiscId == IMISC_MANA) |
|
rv = FALSE; |
|
if (AllItemsList[i].iMiscId == IMISC_FULLMANA) |
|
rv = FALSE; |
|
if (AllItemsList[i].iSpell == SPL_TOWN) |
|
rv = FALSE; |
|
if (AllItemsList[i].iMiscId == IMISC_FULLHEAL) |
|
rv = FALSE; |
|
if (AllItemsList[i].iMiscId == IMISC_HEAL) |
|
rv = FALSE; |
|
if (AllItemsList[i].iSpell == SPL_RESURRECT && gbMaxPlayers == 1) |
|
rv = FALSE; |
|
if (AllItemsList[i].iSpell == SPL_HEALOTHER && gbMaxPlayers == 1) |
|
rv = FALSE; |
|
|
|
return rv; |
|
} |
|
|
|
int RndWitchItem(int lvl) |
|
{ |
|
int i, ri; |
|
int ril[512]; |
|
|
|
ri = 0; |
|
for (i = 1; AllItemsList[i].iLoc != ILOC_INVALID; i++) { |
|
if (AllItemsList[i].iRnd && WitchItemOk(i) && lvl >= AllItemsList[i].iMinMLvl) { |
|
ril[ri] = i; |
|
ri++; |
|
} |
|
} |
|
|
|
return ril[random(51, ri)] + 1; |
|
} |
|
|
|
void SortWitch() |
|
{ |
|
int j, k; |
|
BOOL sorted; |
|
|
|
j = 3; |
|
while (witchitem[j + 1]._itype != ITYPE_NONE) { |
|
j++; |
|
} |
|
|
|
sorted = FALSE; |
|
while (j > 3 && !sorted) { |
|
sorted = TRUE; |
|
if (j > 3) { |
|
for (k = 3; k < j; k++) { |
|
if (witchitem[k].IDidx > witchitem[k + 1].IDidx) { |
|
BubbleSwapItem(&witchitem[k], &witchitem[k + 1]); |
|
sorted = FALSE; |
|
} |
|
} |
|
} |
|
j--; |
|
} |
|
} |
|
|
|
void WitchBookLevel(int ii) |
|
{ |
|
int slvl; |
|
|
|
if (witchitem[ii]._iMiscId == IMISC_BOOK) { |
|
witchitem[ii]._iMinMag = spelldata[witchitem[ii]._iSpell].sMinInt; |
|
slvl = plr[myplr]._pSplLvl[witchitem[ii]._iSpell]; |
|
while (slvl) { |
|
witchitem[ii]._iMinMag += 20 * witchitem[ii]._iMinMag / 100; |
|
slvl--; |
|
if (witchitem[ii]._iMinMag + 20 * witchitem[ii]._iMinMag / 100 > 255) { |
|
witchitem[ii]._iMinMag = 255; |
|
slvl = 0; |
|
} |
|
} |
|
} |
|
} |
|
|
|
void SpawnWitch(int lvl) |
|
{ |
|
int i, iCnt; |
|
int idata, maxlvl; |
|
|
|
GetItemAttrs(0, IDI_MANA, 1); |
|
witchitem[0] = item[0]; |
|
witchitem[0]._iCreateInfo = lvl; |
|
witchitem[0]._iStatFlag = 1; |
|
GetItemAttrs(0, IDI_FULLMANA, 1); |
|
witchitem[1] = item[0]; |
|
witchitem[1]._iCreateInfo = lvl; |
|
witchitem[1]._iStatFlag = 1; |
|
GetItemAttrs(0, IDI_PORTAL, 1); |
|
witchitem[2] = item[0]; |
|
witchitem[2]._iCreateInfo = lvl; |
|
witchitem[2]._iStatFlag = 1; |
|
iCnt = random(51, 8) + 10; |
|
|
|
for (i = 3; i < iCnt; i++) { |
|
do { |
|
item[0]._iSeed = GetRndSeed(); |
|
SetRndSeed(item[0]._iSeed); |
|
idata = RndWitchItem(lvl) - 1; |
|
GetItemAttrs(0, idata, lvl); |
|
maxlvl = -1; |
|
if (random(51, 100) <= 5) |
|
maxlvl = 2 * lvl; |
|
if (maxlvl == -1 && item[0]._iMiscId == IMISC_STAFF) |
|
maxlvl = 2 * lvl; |
|
if (maxlvl != -1) |
|
GetItemBonus(0, idata, maxlvl >> 1, maxlvl, 1); |
|
} while (item[0]._iIvalue > 140000); |
|
witchitem[i] = item[0]; |
|
witchitem[i]._iCreateInfo = lvl | 0x2000; |
|
witchitem[i]._iIdentified = TRUE; |
|
WitchBookLevel(i); |
|
witchitem[i]._iStatFlag = StoreStatOk(&witchitem[i]); |
|
} |
|
|
|
for (i = iCnt; i < 20; i++) |
|
witchitem[i]._itype = ITYPE_NONE; |
|
|
|
SortWitch(); |
|
} |
|
|
|
int RndBoyItem(int lvl) |
|
{ |
|
int i, ri; |
|
int ril[512]; |
|
|
|
ri = 0; |
|
for (i = 1; AllItemsList[i].iLoc != ILOC_INVALID; i++) { |
|
if (AllItemsList[i].iRnd && PremiumItemOk(i) && lvl >= AllItemsList[i].iMinMLvl) { |
|
ril[ri] = i; |
|
ri++; |
|
} |
|
} |
|
|
|
return ril[random(49, ri)] + 1; |
|
} |
|
|
|
void SpawnBoy(int lvl) |
|
{ |
|
int itype; |
|
|
|
if (boylevel<lvl>> 1 || boyitem._itype == ITYPE_NONE) { |
|
do { |
|
item[0]._iSeed = GetRndSeed(); |
|
SetRndSeed(item[0]._iSeed); |
|
itype = RndBoyItem(lvl) - 1; |
|
GetItemAttrs(0, itype, lvl); |
|
GetItemBonus(0, itype, lvl, 2 * lvl, 1); |
|
} while (item[0]._iIvalue > 90000); |
|
boyitem = item[0]; |
|
boyitem._iCreateInfo = lvl | 0x1000; |
|
boyitem._iIdentified = TRUE; |
|
boyitem._iStatFlag = StoreStatOk(&boyitem); |
|
boylevel = lvl >> 1; |
|
} |
|
} |
|
|
|
BOOL HealerItemOk(int i) |
|
{ |
|
BOOL result; |
|
|
|
result = FALSE; |
|
if (AllItemsList[i].itype != ITYPE_MISC) |
|
return FALSE; |
|
|
|
if (AllItemsList[i].iMiscId == IMISC_SCROLL && AllItemsList[i].iSpell == SPL_HEAL) |
|
result = TRUE; |
|
if (AllItemsList[i].iMiscId == IMISC_SCROLLT && AllItemsList[i].iSpell == SPL_RESURRECT && gbMaxPlayers != 1) |
|
result = FALSE; |
|
if (AllItemsList[i].iMiscId == IMISC_SCROLLT && AllItemsList[i].iSpell == SPL_HEALOTHER && gbMaxPlayers != 1) |
|
result = TRUE; |
|
|
|
if (gbMaxPlayers == 1) { |
|
if (AllItemsList[i].iMiscId == IMISC_ELIXSTR) |
|
result = TRUE; |
|
if (AllItemsList[i].iMiscId == IMISC_ELIXMAG) |
|
result = TRUE; |
|
if (AllItemsList[i].iMiscId == IMISC_ELIXDEX) |
|
result = TRUE; |
|
if (AllItemsList[i].iMiscId == IMISC_ELIXVIT) |
|
result = TRUE; |
|
} |
|
|
|
if (AllItemsList[i].iMiscId == IMISC_FULLHEAL) // BUGFIX this is a duplicate with the wrong case |
|
result = TRUE; |
|
|
|
if (AllItemsList[i].iMiscId == IMISC_REJUV) |
|
result = TRUE; |
|
if (AllItemsList[i].iMiscId == IMISC_FULLREJUV) |
|
result = TRUE; |
|
if (AllItemsList[i].iMiscId == IMISC_HEAL) |
|
result = FALSE; |
|
if (AllItemsList[i].iMiscId == IMISC_FULLHEAL) |
|
result = FALSE; |
|
if (AllItemsList[i].iMiscId == IMISC_MANA) |
|
result = FALSE; |
|
if (AllItemsList[i].iMiscId == IMISC_FULLMANA) |
|
result = FALSE; |
|
|
|
return result; |
|
} |
|
|
|
int RndHealerItem(int lvl) |
|
{ |
|
int i, ri; |
|
int ril[512]; |
|
|
|
ri = 0; |
|
for (i = 1; AllItemsList[i].iLoc != ILOC_INVALID; i++) { |
|
if (AllItemsList[i].iRnd && HealerItemOk(i) && lvl >= AllItemsList[i].iMinMLvl) { |
|
ril[ri] = i; |
|
ri++; |
|
} |
|
} |
|
|
|
return ril[random(50, ri)] + 1; |
|
} |
|
|
|
void SortHealer() |
|
{ |
|
int j, k; |
|
BOOL sorted; |
|
|
|
j = 2; |
|
while (healitem[j + 1]._itype != ITYPE_NONE) { |
|
j++; |
|
} |
|
|
|
sorted = FALSE; |
|
while (j > 2 && !sorted) { |
|
sorted = TRUE; |
|
if (j > 2) { |
|
for (k = 2; k < j; k++) { |
|
if (healitem[k].IDidx > healitem[k + 1].IDidx) { |
|
BubbleSwapItem(&healitem[k], &healitem[k + 1]); |
|
sorted = FALSE; |
|
} |
|
} |
|
} |
|
j--; |
|
} |
|
} |
|
|
|
void SpawnHealer(int lvl) |
|
{ |
|
int i, nsi, srnd; |
|
|
|
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; |
|
|
|
i = 3; |
|
} else { |
|
i = 2; |
|
} |
|
nsi = random(50, 8) + 10; |
|
for (; i < nsi; i++) { |
|
item[0]._iSeed = GetRndSeed(); |
|
SetRndSeed(item[0]._iSeed); |
|
srnd = RndHealerItem(lvl) - 1; |
|
GetItemAttrs(0, srnd, lvl); |
|
healitem[i] = item[0]; |
|
healitem[i]._iCreateInfo = lvl | 0x4000; |
|
healitem[i]._iIdentified = TRUE; |
|
healitem[i]._iStatFlag = StoreStatOk(&healitem[i]); |
|
} |
|
for (i = nsi; i < 20; i++) { |
|
healitem[i]._itype = ITYPE_NONE; |
|
} |
|
SortHealer(); |
|
} |
|
|
|
void SpawnStoreGold() |
|
{ |
|
GetItemAttrs(0, IDI_GOLD, 1); |
|
golditem = item[0]; |
|
golditem._iStatFlag = TRUE; |
|
} |
|
|
|
void RecreateSmithItem(int ii, int idx, int plvl, int iseed) |
|
{ |
|
int itype; |
|
|
|
SetRndSeed(iseed); |
|
itype = RndSmithItem(plvl) - 1; |
|
GetItemAttrs(ii, itype, plvl); |
|
|
|
item[ii]._iCreateInfo = plvl | 0x400; |
|
item[ii]._iSeed = iseed; |
|
item[ii]._iIdentified = TRUE; |
|
} |
|
|
|
void RecreatePremiumItem(int ii, int idx, int lvl, int iseed) |
|
{ |
|
int itype; |
|
|
|
SetRndSeed(iseed); |
|
itype = RndPremiumItem(lvl >> 2, lvl) - 1; |
|
GetItemAttrs(ii, itype, lvl); |
|
GetItemBonus(ii, itype, lvl >> 1, lvl, 1); |
|
|
|
item[ii]._iCreateInfo = lvl | 0x800; |
|
item[ii]._iSeed = iseed; |
|
item[ii]._iIdentified = TRUE; |
|
} |
|
|
|
void RecreateBoyItem(int ii, int idx, int lvl, int iseed) |
|
{ |
|
int itype; |
|
|
|
SetRndSeed(iseed); |
|
itype = RndBoyItem(lvl) - 1; |
|
GetItemAttrs(ii, itype, lvl); |
|
GetItemBonus(ii, itype, lvl, 2 * lvl, 1); |
|
|
|
item[ii]._iCreateInfo = lvl | 0x1000; |
|
item[ii]._iSeed = iseed; |
|
item[ii]._iIdentified = TRUE; |
|
} |
|
|
|
void RecreateWitchItem(int ii, int idx, int lvl, int iseed) |
|
{ |
|
int iblvl, itype; |
|
|
|
if (idx == IDI_MANA || idx == IDI_FULLMANA || idx == IDI_PORTAL) { |
|
GetItemAttrs(ii, idx, lvl); |
|
} else { |
|
SetRndSeed(iseed); |
|
iblvl = -1; |
|
itype = RndWitchItem(lvl) - 1; |
|
GetItemAttrs(ii, itype, lvl); |
|
if (random(51, 100) <= 5) |
|
iblvl = 2 * lvl; |
|
if (iblvl == -1 && item[ii]._iMiscId == IMISC_STAFF) |
|
iblvl = 2 * lvl; |
|
if (iblvl != -1) |
|
GetItemBonus(ii, itype, iblvl >> 1, iblvl, 1); |
|
} |
|
|
|
item[ii]._iCreateInfo = lvl | 0x2000; |
|
item[ii]._iSeed = iseed; |
|
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); |
|
idx = RndHealerItem(lvl) - 1; |
|
GetItemAttrs(ii, idx, lvl); |
|
} |
|
|
|
item[ii]._iCreateInfo = lvl | 0x4000; |
|
item[ii]._iSeed = iseed; |
|
item[ii]._iIdentified = TRUE; |
|
} |
|
|
|
void RecreateTownItem(int ii, int idx, WORD icreateinfo, int iseed, int ivalue) |
|
{ |
|
if (icreateinfo & 0x400) |
|
RecreateSmithItem(ii, idx, icreateinfo & 0x3F, iseed); |
|
else if (icreateinfo & 0x800) |
|
RecreatePremiumItem(ii, idx, icreateinfo & 0x3F, iseed); |
|
else if (icreateinfo & 0x1000) |
|
RecreateBoyItem(ii, idx, icreateinfo & 0x3F, iseed); |
|
else if (icreateinfo & 0x2000) |
|
RecreateWitchItem(ii, idx, icreateinfo & 0x3F, iseed); |
|
else if (icreateinfo & 0x4000) |
|
RecreateHealerItem(ii, idx, icreateinfo & 0x3F, iseed); |
|
} |
|
|
|
void RecalcStoreStats() |
|
{ |
|
int i; |
|
|
|
for (i = 0; i < 20; i++) { |
|
if (smithitem[i]._itype != ITYPE_NONE) { |
|
smithitem[i]._iStatFlag = StoreStatOk(&smithitem[i]); |
|
} |
|
} |
|
for (i = 0; i < 6; i++) { |
|
if (premiumitem[i]._itype != ITYPE_NONE) { |
|
premiumitem[i]._iStatFlag = StoreStatOk(&premiumitem[i]); |
|
} |
|
} |
|
for (i = 0; i < 20; i++) { |
|
if (witchitem[i]._itype != ITYPE_NONE) { |
|
witchitem[i]._iStatFlag = StoreStatOk(&witchitem[i]); |
|
} |
|
} |
|
for (i = 0; i < 20; i++) { |
|
if (healitem[i]._itype != ITYPE_NONE) { |
|
healitem[i]._iStatFlag = StoreStatOk(&healitem[i]); |
|
} |
|
} |
|
boyitem._iStatFlag = StoreStatOk(&boyitem); |
|
} |
|
|
|
int ItemNoFlippy() |
|
{ |
|
int r; |
|
|
|
r = itemactive[numitems - 1]; |
|
item[r]._iAnimFlag = FALSE; |
|
item[r]._iAnimFrame = item[r]._iAnimLen; |
|
item[r]._iSelFlag = 1; |
|
|
|
return r; |
|
} |
|
|
|
void CreateSpellBook(int x, int y, int ispell, BOOL sendmsg, int delta) |
|
{ |
|
int ii, idx; |
|
BOOL done; |
|
|
|
done = FALSE; |
|
idx = RndTypeItems(0, 24); |
|
if (numitems < MAXITEMS) { |
|
ii = itemavail[0]; |
|
GetSuperItemSpace(x, y, ii); |
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1]; |
|
itemactive[numitems] = ii; |
|
while (!done) { |
|
SetupAllItems(ii, idx, GetRndSeed(), 2 * currlevel, 1, 1, 0, delta); |
|
if (item[ii]._iMiscId == IMISC_BOOK && item[ii]._iSpell == ispell) |
|
done = TRUE; |
|
} |
|
if (sendmsg) |
|
NetSendCmdDItem(FALSE, ii); |
|
if (delta) |
|
DeltaAddItem(ii); |
|
numitems++; |
|
} |
|
} |
|
|
|
void CreateMagicArmor(int x, int y, int imisc, int icurs, BOOL sendmsg, int delta) |
|
{ |
|
int ii, idx; |
|
BOOL done; |
|
|
|
done = FALSE; |
|
if (numitems < MAXITEMS) { |
|
ii = itemavail[0]; |
|
GetSuperItemSpace(x, y, ii); |
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1]; |
|
itemactive[numitems] = ii; |
|
idx = RndTypeItems(imisc, 0); |
|
while (!done) { |
|
SetupAllItems(ii, idx, GetRndSeed(), 2 * currlevel, 1, 1, 0, delta); |
|
if (item[ii]._iCurs == icurs) |
|
done = TRUE; |
|
else |
|
idx = RndTypeItems(imisc, 0); |
|
} |
|
if (sendmsg) |
|
NetSendCmdDItem(FALSE, ii); |
|
if (delta) |
|
DeltaAddItem(ii); |
|
numitems++; |
|
} |
|
} |
|
|
|
void CreateMagicWeapon(int x, int y, int imisc, int icurs, BOOL sendmsg, int delta) |
|
{ |
|
int ii, idx; |
|
BOOL done; |
|
|
|
done = FALSE; |
|
if (numitems < MAXITEMS) { |
|
ii = itemavail[0]; |
|
GetSuperItemSpace(x, y, ii); |
|
itemavail[0] = itemavail[MAXITEMS - numitems - 1]; |
|
itemactive[numitems] = ii; |
|
idx = RndTypeItems(imisc, 0); |
|
while (!done) { |
|
SetupAllItems(ii, idx, GetRndSeed(), 2 * currlevel, 1, 1, 0, delta); |
|
if (item[ii]._iCurs == icurs) |
|
done = TRUE; |
|
else |
|
idx = RndTypeItems(imisc, 0); |
|
} |
|
if (sendmsg) |
|
NetSendCmdDItem(FALSE, ii); |
|
if (delta) |
|
DeltaAddItem(ii); |
|
numitems++; |
|
} |
|
} |
|
|
|
BOOL GetItemRecord(int nSeed, WORD wCI, int nIndex) |
|
{ |
|
int i; |
|
DWORD dwTicks; |
|
|
|
dwTicks = GetTickCount(); |
|
|
|
for (i = 0; i < gnNumGetRecords; i++) { |
|
if (dwTicks - itemrecord[i].dwTimestamp > 6000) { |
|
NextItemRecord(i); |
|
i--; |
|
} else if (nSeed == itemrecord[i].nSeed && wCI == itemrecord[i].wCI && nIndex == itemrecord[i].nIndex) { |
|
return FALSE; |
|
} |
|
} |
|
|
|
return TRUE; |
|
} |
|
|
|
void NextItemRecord(int i) |
|
{ |
|
gnNumGetRecords--; |
|
|
|
if (gnNumGetRecords == 0) { |
|
return; |
|
} |
|
|
|
itemrecord[i].dwTimestamp = itemrecord[gnNumGetRecords].dwTimestamp; |
|
itemrecord[i].nSeed = itemrecord[gnNumGetRecords].nSeed; |
|
itemrecord[i].wCI = itemrecord[gnNumGetRecords].wCI; |
|
itemrecord[i].nIndex = itemrecord[gnNumGetRecords].nIndex; |
|
} |
|
|
|
void SetItemRecord(int nSeed, WORD wCI, int nIndex) |
|
{ |
|
DWORD dwTicks; |
|
|
|
dwTicks = GetTickCount(); |
|
|
|
if (gnNumGetRecords == MAXITEMS) { |
|
return; |
|
} |
|
|
|
itemrecord[gnNumGetRecords].dwTimestamp = dwTicks; |
|
itemrecord[gnNumGetRecords].nSeed = nSeed; |
|
itemrecord[gnNumGetRecords].wCI = wCI; |
|
itemrecord[gnNumGetRecords].nIndex = nIndex; |
|
gnNumGetRecords++; |
|
} |
|
|
|
void PutItemRecord(int nSeed, WORD wCI, int nIndex) |
|
{ |
|
int i; |
|
DWORD dwTicks; |
|
|
|
dwTicks = GetTickCount(); |
|
|
|
for (i = 0; i < gnNumGetRecords; i++) { |
|
if (dwTicks - itemrecord[i].dwTimestamp > 6000) { |
|
NextItemRecord(i); |
|
i--; |
|
} else if (nSeed == itemrecord[i].nSeed && wCI == itemrecord[i].wCI && nIndex == itemrecord[i].nIndex) { |
|
NextItemRecord(i); |
|
break; |
|
} |
|
} |
|
}
|
|
|