/*-----------------------------------------------------------------------** ** Diablo ** ** Objects file ** ** (C)1995 Condor, Inc. All rights reserved. ** **-----------------------------------------------------------------------** ** $Header: /Diablo/OBJECTS.CPP 5 2/12/97 10:51a Dbrevik2 $ **-----------------------------------------------------------------------** ** ** File Routines **-----------------------------------------------------------------------*/ #include #include "diablo.h" #pragma hdrstop #include "sound.h" #include "objects.h" #include "objdat.h" #include "engine.h" #include "gendung.h" #include "lighting.h" #include "items.h" #include "player.h" #include "monster.h" #include "monstint.h" #include "control.h" #include "cursor.h" #include "spells.h" #include "minitext.h" #include "textdat.h" #include "quests.h" #include "drlg_l1.h" #include "missiles.h" #include "misdat.h" #include "effects.h" #include "themes.h" #include "itemdat.h" #include "stores.h" #include "monstdat.h" #include "error.h" #include "msg.h" #include "multi.h" #include "automap.h" #include "drlg_l4.h" #include "towners.h" #include "inv.h" #include "setmaps.h" /*-----------------------------------------------------------------------* ** Externs **-----------------------------------------------------------------------*/ int ObjIndex(int x, int y); static bool OperateFountains(int, int); /*-----------------------------------------------------------------------* ** Local Defines **-----------------------------------------------------------------------*/ //#define NO_L5_DOORS // JKE just until I get doors. #define DOOR_CLOSED 0 #define DOOR_OPEN 1 #define DOOR_BLOCKED 2 #define TRAP_NODIR 0 #define TRAP_HORIZ 1 #define TRAP_VERT 2 #define TOTAL_FOUNTAINS 4 /*-----------------------------------------------------------------------* ** Global Variables **-----------------------------------------------------------------------*/ ObjectStruct object[MAXOBJECTS]; long numobjects; static char ObjFileList[MAXLVLOBJS]; static int numobjfiles = 0; static BYTE *pObjCels[MAXLVLOBJS]; int objectactive[MAXOBJECTS]; int objectavail[MAXOBJECTS]; static int trapid; static int trapdir; static int leverid; BOOL InitObjFlag; //True while initing, false otherwise static int const bxadd[] = { -1, 0, 1, -1, 1, -1, 0, 1 }; static int const byadd[] = { -1, -1, -1, 0, 0, 1, 1, 1 }; int SpellProgress; #if CHEATS extern BOOL itemcheat; extern BOOL uniqcheat; #endif /*-----------------------------------------------------------------------* ** Function Prototypes **-----------------------------------------------------------------------*/ void AddMushPatch(); void AddSlainHero(); void AddSkulkenObject(int, int, int, int); static void AddNa_Krul_Stuff(); void OpenNaKrul(); static void AddNaKrulLeverObj(); static bool HCheckSpell(int); /*-----------------------------------------------------------------------*/ // Shrine Data // Shrine names static char const * const shrinestrs[] = { "Mysterious", // 0 "Hidden", // 1 "Gloomy", // 2 "Weird", // 3 "Magical", // 4 "Stone", // 5 "Religious", // 6 "Enchanted", // 7 "Thaumaturgic", // 8 "Fascinating", // 9 "Cryptic", // 10 "Magical", // 11 "Eldritch", // 12 "Eerie", // 13 "Divine", // 14 "Holy", // 15 "Sacred", // 16 "Spiritual", // 17 "Spooky", // 18 "Abandoned", // 19 "Creepy", // 20 "Quiet", // 21 "Secluded", // 22 "Ornate", // 23 "Glimmering", // 24 "Tainted", // 25 "Oily", // 26 "Glowing", // 27 "Mendicant's", // 28 "Sparkling", // 29 "Town", // 30 "Shimmering", // 31 "Solar", // 33 "Murphy's", // 34 }; #define NUMSHRINETYPES (sizeof(shrinestrs)/sizeof(char *)) // Shrine min level it can appear static char const shrineminlvl[NUMSHRINETYPES] = { 1, // 0 Mysterious 1, // 1 Hidden 1, // 2 Gloomy 1, // 3 Weird 1, // 4 Magical 1, // 5 Stone 1, // 6 Religious 1, // 7 Enchanted 1, // 8 Thaumaturgic 1, // 9 Fascinating 1, // 10 Cryptic 1, // 11 Supernatural 1, // 12 Eldritch 1, // 13 Eerie 1, // 14 Divine 1, // 15 Holy 1, // 16 Sacred 1, // 17 Spiritual 1, // 18 Spooky 1, // 19 Abandoned 1, // 20 Creepy 1, // 21 Quiet 1, // 22 Secluded 1, // 23 Ornate 1, // 24 Glimmering 1, // 25 Tainted 1, // 26 Oily 1, // 27 Glowing 1, // 28 Mendicants 1, // 29 Edisons 1, // 30 Town 1, // 31 Energy 1, // 32 Solar 1, // 33 Murphy's }; // Shrine max level it can appear static char const shrinemaxlvl[NUMSHRINETYPES] = { MAX_LEVELS, // 0 Mysterious MAX_LEVELS, // 1 Hidden MAX_LEVELS, // 2 Gloomy MAX_LEVELS, // 3 Weird MAX_LEVELS, // 4 Magical MAX_LEVELS, // 5 Stone MAX_LEVELS, // 6 Religious 8, // 7 Enchanted MAX_LEVELS, // 8 Thaumaturgic MAX_LEVELS, // 9 Fascinating MAX_LEVELS, // 10 Cryptic MAX_LEVELS, // 11 Supernatural MAX_LEVELS, // 12 Eldritch MAX_LEVELS, // 13 Eerie MAX_LEVELS, // 14 Divine MAX_LEVELS, // 15 Holy MAX_LEVELS, // 16 Sacred MAX_LEVELS, // 17 Spiritual MAX_LEVELS, // 18 Spooky MAX_LEVELS, // 19 Abandoned MAX_LEVELS, // 20 Creepy MAX_LEVELS, // 21 Quiet MAX_LEVELS, // 22 Secluded MAX_LEVELS, // 23 Ornate MAX_LEVELS, // 24 Glimmering MAX_LEVELS, // 25 Tainted MAX_LEVELS, // 26 Oily MAX_LEVELS, // 27 Glowing MAX_LEVELS, // 28 Mendicants MAX_LEVELS, // 29 Edisons MAX_LEVELS, // 30 Town MAX_LEVELS, // 31 Energy MAX_LEVELS, // 32 Solar MAX_LEVELS, // 33 Murphy's }; #define SHRINE_ALL 0 #define SHRINE_SINGLE 1 #define SHRINE_MULTI 2 // Shrine available for either, single, or multiplayer? static char const shrineavail[NUMSHRINETYPES] = { SHRINE_ALL, // 0 Mysterious SHRINE_ALL, // 1 Hidden SHRINE_SINGLE, // 2 Gloomy SHRINE_SINGLE, // 3 Weird SHRINE_ALL, // 4 Magical SHRINE_ALL, // 5 Stone SHRINE_ALL, // 6 Religious SHRINE_ALL, // 7 Enchanted SHRINE_SINGLE, // 8 Thaumaturgic SHRINE_ALL, // 9 Fascinating SHRINE_ALL, // 10 Cryptic SHRINE_ALL, // 11 Supernatural SHRINE_ALL, // 12 Eldritch SHRINE_ALL, // 13 Eerie SHRINE_ALL, // 14 Divine SHRINE_ALL, // 15 Holy SHRINE_ALL, // 16 Sacred SHRINE_ALL, // 17 Spiritual SHRINE_MULTI, // 18 Spooky SHRINE_ALL, // 19 Abandoned SHRINE_ALL, // 20 Creepy SHRINE_ALL, // 21 Quiet SHRINE_ALL, // 22 Secluded SHRINE_ALL, // 23 Ornate SHRINE_ALL, // 24 Glimmering SHRINE_MULTI, // 25 Tainted SHRINE_ALL, // 26 Oily SHRINE_ALL, // 27 Glowing SHRINE_ALL, // 28 Mendicants SHRINE_ALL, // 29 Edisons SHRINE_ALL, // 30 Town SHRINE_ALL, // 31 Energy SHRINE_SINGLE, // 32 Solar SHRINE_ALL, // 33 Murphy's }; /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static char const * const StoryBookName[] = { // The Librium of the Horadrim (White Books) "The Great Conflict", "The Wages of Sin are War", "The Tale of the Horadrim", // Grimoire of the Burning Hells (Red Books) "The Dark Exile", "The Sin War", "The Binding of the Three", // The Journals of Lazarus the Betrayer (Normal Book Color) "The Realms Beyond", "Tale of the Three", "The Black King", // The Journals of Skulken the Necromancer JKE "Journal: The Ensorcellment", "Journal: The Meeting", "Journal: The Tirade", "Journal: His Power Grows", "Journal: NA-KRUL", "Journal: The End", "A Spellbook" }; /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void InitObjectGFX() { BYTE fileload[MAXOBJFILES]; int i,j,t; int templevel; //JKE ZeroMemory(fileload,sizeof(fileload)); // temp hack to get object art to appear. JKE templevel = currlevel; if ((currlevel >= CRYPTSTART) && (currlevel <= CRYPTEND)) templevel = templevel - CRYPTSTART + 1; // replace templevel with currlevel when done. else if ((currlevel >= HIVESTART) && (currlevel <= HIVEEND)) templevel = templevel - HIVESTART + 9; for (i = 0; AllObjects[i].oload != -1; ++i) { if ((AllObjects[i].oload == OBJMUST) && (templevel >= AllObjects[i].ominlvl) && (templevel <= AllObjects[i].omaxlvl)) fileload[AllObjects[i].ofindex] = TRUE; if (AllObjects[i].otheme != -1) { for (t = 0; t < numthemes; ++t) { if (theme[t].ttype == AllObjects[i].otheme) fileload[AllObjects[i].ofindex] = TRUE; } } if (AllObjects[i].oquest != -1) { j = AllObjects[i].oquest; if (QuestStatus(j)) fileload[AllObjects[i].ofindex] = TRUE; } } app_assert(numobjfiles == 0); for (i = 0; i < MAXOBJFILES; ++i) { if (fileload[i]) { char filestr[32]; ObjFileList[numobjfiles] = i; sprintf(filestr, "Objects\\%s.CEL", ObjMasterFList[i]); if ((currlevel >= HIVESTART) && (currlevel < CRYPTSTART)) //JKE OBJECTS sprintf(filestr, "Objects\\%s.CEL", HObjMasterFList[i]); else if (currlevel >= CRYPTSTART) sprintf(filestr, "Objects\\%s.CEL", CObjMasterFList[i]); app_assert(! pObjCels[numobjfiles]); pObjCels[numobjfiles] = LoadFileInMemSig(filestr,NULL,'OGFX'); ++numobjfiles; } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void FreeObjectGFX() { for (int i = 0; i < numobjfiles; ++i) { DiabloFreePtr(pObjCels[i]); } numobjfiles = 0; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static bool RndLocOk(int xp, int yp) { if (dMonster[xp][yp] != 0) return FALSE; if (dPlayer[xp][yp] != 0) return FALSE; if (dObject[xp][yp] != 0) return FALSE; if (dFlags[xp][yp] & BFLAG_SETPC) return FALSE; if (nSolidTable[dPiece[xp][yp]]) return FALSE; if (leveltype == 1) { if ((dPiece[xp][yp] > 126) && (dPiece[xp][yp] < 144)) return false; } return true; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static bool TrapLocOk(int xp, int yp) { if (dFlags[xp][yp] & BFLAG_SETPC) return false; if (nSolidTable[dPiece[xp][yp]]) return false; return true; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static bool RoomLocOk(int xp, int yp) { if (dPlayer[xp][yp] != 0) return false; if (dObject[xp][yp] != 0) return false; if (dFlags[xp][yp] & BFLAG_SETPC) return false; if (nSolidTable[dPiece[xp][yp]]) return false; return true; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void InitRndLocObj(int min, int max, int objtype) { int xp, yp; int numobjs = random(139,max - min) + min; for (int i = 0; i < numobjs; ++i) { while (1) { xp = random(139,DMAXX - DIRTEDGE) + (DIRTEDGED2); yp = random(139,DMAXY - DIRTEDGE) + (DIRTEDGED2); if (! RndLocOk(xp-1, yp-1)) continue; if (! RndLocOk(xp+0, yp-1)) continue; if (! RndLocOk(xp+1, yp-1)) continue; if (! RndLocOk(xp-1, yp+0)) continue; if (! RndLocOk(xp+0, yp+0)) continue; if (! RndLocOk(xp+1, yp+0)) continue; if (! RndLocOk(xp-1, yp+1)) continue; if (! RndLocOk(xp+0, yp+1)) continue; if (! RndLocOk(xp+1, yp+1)) continue; break; } AddObject(objtype, xp, yp); } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void InitRndLocBigObj(int min, int max, int objtype) { int xp, yp; int numobjs = random(140,max - min) + min; for (int i = 0; i < numobjs; ++i) { while (1) { xp = random(140,DMAXX - DIRTEDGE) + (DIRTEDGED2); yp = random(140,DMAXY - DIRTEDGE) + (DIRTEDGED2); if (! RndLocOk(xp-1, yp-2)) continue; if (! RndLocOk(xp+0, yp-2)) continue; if (! RndLocOk(xp+1, yp-2)) continue; if (! RndLocOk(xp-1, yp-1)) continue; if (! RndLocOk(xp+0, yp-1)) continue; if (! RndLocOk(xp+1, yp-1)) continue; if (! RndLocOk(xp-1, yp+0)) continue; if (! RndLocOk(xp+0, yp+0)) continue; if (! RndLocOk(xp+1, yp+0)) continue; if (! RndLocOk(xp-1, yp+1)) continue; if (! RndLocOk(xp+0, yp+1)) continue; if (! RndLocOk(xp+1, yp+1)) continue; break; } AddObject(objtype, xp, yp); } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void InitRndLocObj5x5(int min, int max, int objtype) { int xp, yp, xx, yy, cnt; bool done; int numobjs = random(139,max - min) + min; for (int i = 0; i < numobjs; ++i) { cnt = 0; done = false; while (! done) { done = true; xp = random(139,DMAXX - DIRTEDGE) + (DIRTEDGED2); yp = random(139,DMAXY - DIRTEDGE) + (DIRTEDGED2); for (yy = -2; yy <= 2; ++yy) { for (xx = -2; xx <= 2; ++xx) if (! RndLocOk(xp+xx,yp+yy)) done = FALSE; } if (!done) { ++cnt; if (cnt > 20000) return; } } AddObject(objtype, xp, yp); } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void ClrAllObjects () { int i; #if 0 for (i = 0; i < MAXOBJECTS; ++i) { object[i]._ox = 0; object[i]._oy = 0; object[i]._oAnimData = NULL; object[i]._oAnimDelay = 0; object[i]._oAnimCnt = 0; object[i]._oAnimLen = 0; object[i]._oAnimFrame = 0; object[i]._oDelFlag = FALSE; object[i]._oVar1 = 0; object[i]._oVar2 = 0; object[i]._oVar3 = 0; object[i]._oVar4 = 0; } #else memset(object, 0, sizeof(object)); #endif numobjects = 0; for (i = 0; i < MAXOBJECTS; ++i) { objectavail[i] = i; //objectactive[i] = 0; } memset(objectactive, 0, sizeof(objectactive)); trapid = 1; trapdir = TRAP_NODIR; leverid = 1; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddTortures() { int yp, xp; for (yp = 0; yp < DMAXY; ++yp) { for (xp = 0; xp < DMAXX; ++xp) { if (dPiece[xp][yp] == 367) { AddObject(OBJ_TORTURE1, xp, yp+1); AddObject(OBJ_TORTURE3, xp+2, yp-1); AddObject(OBJ_TORTURE2, xp, yp+3); AddObject(OBJ_TORTURE4, xp+4, yp-1); AddObject(OBJ_TORTURE5, xp, yp+5); AddObject(OBJ_TNUDEM1, xp+1, yp+3); AddObject(OBJ_TNUDEM2, xp+4, yp+5); AddObject(OBJ_TNUDEM3, xp+2, yp); AddObject(OBJ_TNUDEM4, xp+3, yp+2); AddObject(OBJ_TNUDEW1, xp+2, yp+4); AddObject(OBJ_TNUDEW2, xp+2, yp+1); AddObject(OBJ_TNUDEW3, xp+4, yp+2); } } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddCandles() { int const xp = quests[Q_PWATER]._qtx; int const yp = quests[Q_PWATER]._qty; AddObject(OBJ_STORYCANDLE, xp-2, yp+1); AddObject(OBJ_STORYCANDLE, xp+3, yp+1); AddObject(OBJ_STORYCANDLE, xp-1, yp+2); AddObject(OBJ_STORYCANDLE, xp+2, yp+2); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddTrapLine(int min, int max, int tobjtype, int lobjtype) { int i, j, xp, yp, numobjs; int sx, sy, xa, ya, t; int lx1, ly1, lx2, ly2; bool found; numobjs = random(0,max - min) + min; for (i = 0; i < numobjs; ++i) { found = false; while (!found) { found = true; xp = random(0,DMAXX - DIRTEDGE) + (DIRTEDGED2); yp = random(0,DMAXY - DIRTEDGE) + (DIRTEDGED2); if (random(0,2)) { while (TrapLocOk(xp, yp-1)) --yp; // Go to bottom sx = xp; sy = yp; xa = 0; ya = 1; t = 0; while (TrapLocOk(xp, yp+1) && found) { found = found && RndLocOk(xp-3, yp); found = found && RndLocOk(xp-2, yp); found = found && RndLocOk(xp-1, yp); found = found && RndLocOk(xp, yp); found = found && RndLocOk(xp+1, yp); found = found && RndLocOk(xp+2, yp); found = found && RndLocOk(xp+3, yp); ++yp; ++t; } lx1 = xp-2; ly1 = random(0,t-1) + sy + 1; lx2 = xp+2; ly2 = random(0,t-1) + sy + 1; trapdir = TRAP_VERT; } else { while (TrapLocOk(xp-1, yp)) --xp; // Go to left sx = xp; sy = yp; xa = 1; ya = 0; t = 0; while (TrapLocOk(xp+1, yp) && found) { found = found && RndLocOk(xp, yp-3); found = found && RndLocOk(xp, yp-2); found = found && RndLocOk(xp, yp-1); found = found && RndLocOk(xp, yp); found = found && RndLocOk(xp, yp+1); found = found && RndLocOk(xp, yp+2); found = found && RndLocOk(xp, yp+3); ++xp; ++t; } lx1 = random(0,t-1) + sx + 1; ly1 = yp-2; lx2 = random(0,t-1) + sx + 1; ly2 = yp+2; trapdir = TRAP_HORIZ; } if ((t < 5) || (t > 12)) found = FALSE; } // Place trap xp = sx; yp = sy; for (j = 0; j <= t; ++j) { AddObject(tobjtype, xp, yp); xp += xa; yp += ya; } // Place levers AddObject(lobjtype, lx1, ly1); AddObject(lobjtype, lx2, ly2); ++trapid; // Next trap } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddLeverObj(int lx1, int ly1, int lx2, int ly2, int x1, int y1, int x2, int y2) { int xp, yp; while (1) { xp = random(141,lx2 - lx1 + 1) + lx1; yp = random(141,ly2 - ly1 + 1) + ly1; if (! RndLocOk(xp-1, yp-1)) continue; if (! RndLocOk(xp+0, yp-1)) continue; if (! RndLocOk(xp+1, yp-1)) continue; if (! RndLocOk(xp-1, yp+0)) continue; if (! RndLocOk(xp+0, yp+0)) continue; if (! RndLocOk(xp+1, yp+0)) continue; if (! RndLocOk(xp-1, yp+1)) continue; if (! RndLocOk(xp+0, yp+1)) continue; if (! RndLocOk(xp+1, yp+1)) continue; break; } AddObject(OBJ_LEVER, xp, yp); int i = dObject[xp][yp] - 1; SetObjMapRange(i, x1, y1, x2, y2, leverid); ++leverid; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddBookLever(int lx1, int ly1, int lx2, int ly2, int x1, int y1, int x2, int y2, int msg) { /* int xp, yp; while (1) { xp = random(142,lx2 - lx1 + 1) + lx1; yp = random(142,ly2 - ly1 + 1) + ly1; if (! RndLocOk(xp-1, yp-1)) continue; if (! RndLocOk(xp+0, yp-1)) continue; if (! RndLocOk(xp+1, yp-1)) continue; if (! RndLocOk(xp-1, yp+0)) continue; if (! RndLocOk(xp+0, yp+0)) continue; if (! RndLocOk(xp+1, yp+0)) continue; if (! RndLocOk(xp-1, yp+1)) continue; if (! RndLocOk(xp+0, yp+1)) continue; if (! RndLocOk(xp+1, yp+1)) continue; break; } */ int xp, yp, xx, yy, cnt; bool done; cnt = 0; done = false; while (! done) { done = true; xp = random(139,DMAXX - DIRTEDGE) + (DIRTEDGED2); yp = random(139,DMAXY - DIRTEDGE) + (DIRTEDGED2); for (yy = -2; yy <= 2; ++yy) { for (xx = -2; xx <= 2; ++xx) if (! RndLocOk(xp+xx,yp+yy)) done = FALSE; } if (!done) { ++cnt; if (cnt > 20000) return; } } if (QuestStatus(Q_BLIND)) AddObject(OBJ_BLINDBOOK, xp, yp); if (QuestStatus(Q_WARLORD)) AddObject(OBJ_STEELTOME, xp, yp); if (QuestStatus(Q_BLOOD)) { xp = (setpc_x << 1) + DIRTEDGED2 + 9; yp = (setpc_y << 1) + DIRTEDGED2 + 24; AddObject(OBJ_BLOODBOOK, xp, yp); } app_assert((DWORD)xp < MAXDUNX); app_assert((DWORD)yp < MAXDUNY); int i = dObject[xp][yp] - 1; app_assert((DWORD)i < MAXOBJECTS); SetObjMapRange(i, x1, y1, x2, y2, leverid); SetBookMsg(i, msg); ++leverid; object[i]._oVar6 = object[i]._oAnimFrame + 1; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void InitRndBarrels() { int xp, yp, o, rv, c, t; int numobjs = random(143,5) + 3; for (int i = 0; i < numobjs; ++i) { while (1) { xp = random(143,DMAXX - DIRTEDGE) + (DIRTEDGED2); yp = random(143,DMAXY - DIRTEDGE) + (DIRTEDGED2); if (! RndLocOk(xp, yp)) continue; break; } // Add normal or exploding barrel if (random(143,4)) o = OBJ_BARREL; else o = OBJ_BARRELEX; AddObject(o, xp, yp); c = 1; bool found = true; while ((random(143,c >> 1) == 0) && (found)) { t = 0; found = false; while ((!found) && (t < 3)) { rv = random(143,8); xp += bxadd[rv]; yp += byadd[rv]; found = RndLocOk(xp, yp); ++t; } if (found) { if (random(143,5)) o = OBJ_BARREL; else o = OBJ_BARRELEX; AddObject(o, xp, yp); ++c; } } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void AddL1Objs(int x1, int y1, int x2, int y2) { int i,j,pn; for (j = y1; j < y2; ++j) { for (i = x1; i < x2; ++i) { // Add Light pn = dPiece[i][j]; if (pn == 270) AddObject(OBJ_L1LIGHT, i, j); if ((pn == 44) || (pn == 51) || (pn == 214)) AddObject(OBJ_L1DOORL, i, j); if ((pn == 46) || (pn == 56)) AddObject(OBJ_L1DOORR, i, j); } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void AddL5Objs(int x1, int y1, int x2, int y2) { int i,j,pn; for (j = y1; j < y2; ++j) { for (i = x1; i < x2; ++i) { // Add Light pn = dPiece[i][j]; // if (pn == 270) AddObject(OBJ_L1LIGHT, i, j); if (pn == 77) AddObject(OBJ_L1DOORL, i, j); if (pn == 80) AddObject(OBJ_L1DOORR, i, j); } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void AddL2Objs(int x1, int y1, int x2, int y2) { int i,j,pn; for (j = y1; j < y2; ++j) { for (i = x1; i < x2; ++i) { // Add Doors pn = dPiece[i][j]; if (pn == 13 || pn == 541) AddObject(OBJ_L2DOORL, i, j); if (pn == 17 || pn == 542) AddObject(OBJ_L2DOORR, i, j); } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddL3Objs(int x1, int y1, int x2, int y2) { int i,j,pn; for (j = y1; j < y2; ++j) { for (i = x1; i < x2; ++i) { // Add Doors pn = dPiece[i][j]; if (pn == 531) AddObject(OBJ_L3DOORL, i, j); if (pn == 534) AddObject(OBJ_L3DOORR, i, j); } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static bool TorchLocOK(int xp, int yp) { if (dFlags[xp][yp] & BFLAG_SETPC) return false; return true; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddL2Torches() { int i,j,pn; for (j = 0; j < DMAXY; ++j) { for (i = 0; i < DMAXX; ++i) { // Add Torches if(TorchLocOK(i,j)) { pn = dPiece[i][j]; if ((pn == 1) && (random(145,3) == 0)) AddObject(OBJ_TORCHL2, i, j); if ((pn == 5) && (random(145,3) == 0)) AddObject(OBJ_TORCHR2, i, j); if ((pn == 37) && (random(145,10) == 0) && (dObject[i-1][j] == 0)) AddObject(OBJ_TORCHL, i-1, j); if ((pn == 41) && (random(145,10) == 0) && (dObject[i][j-1] == 0)) AddObject(OBJ_TORCHR, i, j-1); } } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static bool WallTrapLocOk(int xp, int yp) { if (dFlags[xp][yp] & BFLAG_SETPC) return false; if (!nTrapTable[dPiece[xp][yp]]) return false; return true; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddObjTraps() { int i,j; int x,y; int rndv; char oi, oi2; if (currlevel == 1) rndv = 10; if (currlevel >= 2) rndv = 15; if (currlevel >= 5) rndv = 20; if (currlevel >= 7) rndv = 25; for (j = 0; j < DMAXY; ++j) { for (i = 0; i < DMAXX; ++i) { if ((dObject[i][j] > 0) && (random(144,100) < rndv)) { oi = dObject[i][j] - 1; if (AllObjects[object[oi]._otype].oTrapFlag) { x = i; y = j; if (random(144,2) == 0) { --x; while (!nSolidTable[dPiece[x][y]]) --x; if (WallTrapLocOk(x, y) && ((i - x) > 1)) { AddObject(OBJ_TRAPL, x, y); oi2 = dObject[x][y] - 1; object[oi2]._oVar1 = i; object[oi2]._oVar2 = j; object[oi]._oTrapFlag = TRUE; } } else { --y; while (!nSolidTable[dPiece[x][y]]) --y; if (WallTrapLocOk(x, y) && ((j - y) > 1)) { AddObject(OBJ_TRAPR, x, y); oi2 = dObject[x][y] - 1; object[oi2]._oVar1 = i; object[oi2]._oVar2 = j; object[oi]._oTrapFlag = TRUE; } } } } } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddChestTraps() { int i,j; char oi; for (j = 0; j < DMAXY; ++j) { for (i = 0; i < DMAXX; ++i) { if (dObject[i][j] > 0) { oi = dObject[i][j] - 1; if ((object[oi]._otype >= OBJ_CHEST1) && (object[oi]._otype <= OBJ_CHEST3) && (!object[oi]._oTrapFlag) && (random(0, 100) < 10)) { object[oi]._otype = (object[oi]._otype - OBJ_CHEST1) + OBJ_TCHEST1; object[oi]._oTrapFlag = TRUE; if (leveltype == 2) object[oi]._oVar4 = random(0, 2); // Type of trap #if defined(HELLFIRE2) else object[oi]._oVar4 = random(0, 7); #else else object[oi]._oVar4 = random(0, 6); #endif } } } } } /*-----------------------------------------------------------------------* ** Used by diablo level only!!!!! **-----------------------------------------------------------------------*/ static void LoadMapObjects(BYTE *pMap, int startx, int starty, int x1, int y1, int w, int h, int leveridx) { int i,j,rw,rh; int ox,oy; BYTE *lm; long mapoff; int ot, oi; InitObjFlag = TRUE; lm = pMap; rw = *lm; lm += 2; rh = *lm; // Skip map + height word mapoff = ((rw * rh) << 1) + 2; // Convert to index mini tile level instead of mega rw = rw << 1; rh = rh << 1; // Skip treasure and monster map mapoff += ((rw * rh) << 2); lm += mapoff; for (j = 0; j < rh; ++j) { for (i = 0; i < rw; ++i) { if (*lm != 0) { ot = *lm; ox = i + DIRTEDGED2 + startx; oy = j + DIRTEDGED2 + starty; AddObject(ObjTypeConv[ot], ox, oy); oi = ObjIndex(ox, oy); SetObjMapRange(oi, x1, y1, x1+w, y1+h, leveridx); } lm+=2; } } InitObjFlag = FALSE; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void LoadMapObjs(BYTE *pMap, int startx, int starty) { int i,j,rw,rh; int ox,oy; BYTE *lm; long mapoff; int ot; InitObjFlag = TRUE; lm = pMap; rw = *lm; lm += 2; rh = *lm; // Skip map + height word mapoff = ((rw * rh) << 1) + 2; // Convert to index mini tile level instead of mega rw = rw << 1; rh = rh << 1; // Skip treasure and monster map mapoff += ((rw * rh) << 2); lm += mapoff; for (j = 0; j < rh; ++j) { for (i = 0; i < rw; ++i) { if (*lm != 0) { ot = *lm; ox = i + DIRTEDGED2 + startx; oy = j + DIRTEDGED2 + starty; AddObject(ObjTypeConv[ot], ox, oy); } lm+=2; } } InitObjFlag = FALSE; } /*-----------------------------------------------------------------------* ** Levers for diablo level **-----------------------------------------------------------------------*/ static void AddDiabObjs() { BYTE *pSetPiece; int xx, yy; pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab1.DUN",NULL,'STPC'); xx = (diabquad1x << 1); yy = (diabquad1y << 1); LoadMapObjects(pSetPiece, xx, yy, diabquad2x, diabquad2y, 11, 12, 1); DiabloFreePtr(pSetPiece); pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab2a.DUN",NULL,'STPC'); xx = (diabquad2x << 1); yy = (diabquad2y << 1); LoadMapObjects(pSetPiece, xx, yy, diabquad3x, diabquad3y, 11, 11, 2); DiabloFreePtr(pSetPiece); pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab3a.DUN",NULL,'STPC'); xx = (diabquad3x << 1); yy = (diabquad3y << 1); LoadMapObjects(pSetPiece, xx, yy, diabquad4x, diabquad4y, 9, 9, 3); DiabloFreePtr(pSetPiece); } static void AddSkulkenBooks(int number) // Journal entry books JKE { int xp,yp,xx,yy,cnt; bool done; cnt = 0; done = false; while (! done) { done = true; xp = random(139,DMAXX - DIRTEDGE) + (DIRTEDGED2); yp = random(139,DMAXY - DIRTEDGE) + (DIRTEDGED2); for (yy = -2; yy <= 2; ++yy) { for (xx = -3; xx <= 3; ++xx) if (! RndLocOk(xp+xx,yp+yy)) done = FALSE; } if (!done) { ++cnt; if (cnt > 20000) return; } } AddSkulkenObject(OBJ_STORYBOOK, number, xp, yp); // AddObject(OBJ_STORYBOOK, xp, yp); AddObject(OBJ_STORYCANDLE, xp-2, yp+1); AddObject(OBJ_STORYCANDLE, xp-2, yp); AddObject(OBJ_STORYCANDLE, xp-1, yp-1); AddObject(OBJ_STORYCANDLE, xp+1, yp-1); AddObject(OBJ_STORYCANDLE, xp+2, yp); AddObject(OBJ_STORYCANDLE, xp+2, yp+1); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddStoryBooks() { int xp,yp,xx,yy,cnt; bool done; cnt = 0; done = false; while (! done) { done = true; xp = random(139,DMAXX - DIRTEDGE) + (DIRTEDGED2); yp = random(139,DMAXY - DIRTEDGE) + (DIRTEDGED2); for (yy = -2; yy <= 2; ++yy) { for (xx = -3; xx <= 3; ++xx) if (! RndLocOk(xp+xx,yp+yy)) done = FALSE; } if (!done) { ++cnt; if (cnt > 20000) return; } } AddObject(OBJ_STORYBOOK, xp, yp); AddObject(OBJ_STORYCANDLE, xp-2, yp+1); AddObject(OBJ_STORYCANDLE, xp-2, yp); AddObject(OBJ_STORYCANDLE, xp-1, yp-1); AddObject(OBJ_STORYCANDLE, xp+1, yp-1); AddObject(OBJ_STORYCANDLE, xp+2, yp); AddObject(OBJ_STORYCANDLE, xp+2, yp+1); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddHookedBodies(int freq) { int i, j, ii, jj; //Add tortured bodies on hooks for (j = 0; j < MDMAXY; ++j) { for (i = 0; i < MDMAXX; ++i) { if ((dungeon[i][j] == 1 || dungeon[i][j] == 2) && ((!random(0, freq)) && (SkipThemeRoom(i, j)))) { ii = (i << 1) + DIRTEDGED2; jj = (j << 1) + DIRTEDGED2; if ((dungeon[i][j] == 1) && (dungeon[i+1][j] == 6)) { switch(random(0, 3)) { case 0: AddObject(OBJ_TORTURE1, ii+1, jj); break; case 1: AddObject(OBJ_TORTURE2, ii+1, jj); break; case 2: AddObject(OBJ_TORTURE5, ii+1, jj); break; } } else if ((dungeon[i][j] == 2) && (dungeon[i][j+1] == 6)) { switch(random(0, 2)) { case 0: AddObject(OBJ_TORTURE3, ii, jj); break; case 1: AddObject(OBJ_TORTURE4, ii, jj); break; } } } } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddL4Goodies() { AddHookedBodies(6); InitRndLocObj(2, 6, OBJ_TNUDEM1); InitRndLocObj(2, 6, OBJ_TNUDEM2); InitRndLocObj(2, 6, OBJ_TNUDEM3); InitRndLocObj(2, 6, OBJ_TNUDEM4); InitRndLocObj(2, 6, OBJ_TNUDEW1); InitRndLocObj(2, 6, OBJ_TNUDEW2); InitRndLocObj(2, 6, OBJ_TNUDEW3); InitRndLocObj(2, 6, OBJ_DECAP); InitRndLocObj(1, 3, OBJ_CAULDRON); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddLazStand() { int xp,yp,xx,yy,cnt; bool done = false; cnt = 0; while (! done) { done = true; xp = random(139,DMAXX - DIRTEDGE) + (DIRTEDGED2); yp = random(139,DMAXY - DIRTEDGE) + (DIRTEDGED2); for (yy = -3; yy <= 3; ++yy) { for (xx = -2; xx <= 3; ++xx) if (! RndLocOk(xp+xx,yp+yy)) done = FALSE; } if (!done) { ++cnt; if (cnt > 10000) { // If can't find big area put it anywhere InitRndLocObj(1, 1, OBJ_LAZSTAND); return; } } } AddObject(OBJ_LAZSTAND, xp, yp); AddObject(OBJ_TNUDEM2, xp+0, yp+2); AddObject(OBJ_STORYCANDLE, xp+1, yp+2); AddObject(OBJ_TNUDEM3, xp+2, yp+2); AddObject(OBJ_TNUDEW1, xp+0, yp-2); AddObject(OBJ_STORYCANDLE, xp+1, yp-2); AddObject(OBJ_TNUDEW2, xp+2, yp-2); AddObject(OBJ_STORYCANDLE, xp-1, yp-1); AddObject(OBJ_TNUDEW3, xp-1, yp+0); AddObject(OBJ_STORYCANDLE, xp-1, yp+1); } /*-----------------------------------------------------------------------* ** Does not get called for setlevels so no worries **-----------------------------------------------------------------------*/ void InitObjects () { int textdef; byte *setp; ClrAllObjects(); SpellProgress = 0; // No objects on DIABLO_LEVEL. Inited seperatly if (currlevel == DIABLO_LEVEL) { AddDiabObjs(); return; } InitObjFlag = TRUE; int rs = GetRndSeed(); if (currlevel == SLAIN_HERO_LEVEL && gbMaxPlayers == 1) { AddSlainHero(); } if (currlevel == quests[Q_BKMUSHRM]._qlevel && quests[Q_BKMUSHRM]._qactive == QUEST_NOTACTIVE) { AddMushPatch(); } if (currlevel == STORY_BOOK1_LEVEL) AddStoryBooks(); else if (currlevel == STORY_BOOK2_LEVEL) AddStoryBooks(); else if (currlevel == STORY_BOOK3_LEVEL) AddStoryBooks(); if (currlevel == SKULKEN_BOOK1_LEVEL) { // AddSkulkenBooks(0); AddSkulkenBooks(1); // AddStoryBooks(); // AddStoryBooks(); } else if (currlevel == SKULKEN_BOOK2_LEVEL) { AddSkulkenBooks(2); AddSkulkenBooks(3); } else if (currlevel == SKULKEN_BOOK3_LEVEL) { AddSkulkenBooks(4); AddSkulkenBooks(5); } if (currlevel == NA_KRUL_LEVEL) { AddNa_Krul_Stuff(); } if (leveltype == 1) { if (QuestStatus(Q_BUTCHER)) AddTortures(); if (QuestStatus(Q_PWATER)) AddCandles(); if (QuestStatus(Q_LTBANNER)) AddObject(OBJ_SIGNCHEST,(setpc_x << 1) + DIRTEDGED2 + 10, (setpc_y << 1) + DIRTEDGED2 + 3); InitRndLocBigObj(10, 15, OBJ_SARC); if (currlevel < CRYPTSTART) AddL1Objs(0, 0, DMAXX, DMAXY); else AddL5Objs(0,0,DMAXX,DMAXY); InitRndBarrels(); } if (leveltype == 2) { if (QuestStatus(Q_ROCK)) InitRndLocObj5x5(1, 1, OBJ_STAND); // Rock stand if (QuestStatus(Q_SCHAMB)) InitRndLocObj5x5(1, 1, OBJ_BOOK2R); // SCamb book AddL2Objs(0, 0, DMAXX, DMAXY); AddL2Torches(); if (QuestStatus(Q_BLIND)) { if (plr[myplr]._pClass == CLASS_WARRIOR) textdef = TXT_WARBLIND; else if (plr[myplr]._pClass == CLASS_ROGUE) textdef = TXT_ROGBLIND; else if (plr[myplr]._pClass == CLASS_SORCEROR) textdef = TXT_SORBLIND; else if (plr[myplr]._pClass == CLASS_MONK) textdef = TXT_MNKBLIND; else if (plr[myplr]._pClass == CLASS_BARD) textdef = TXT_BRDBLIND; else if (plr[myplr]._pClass == CLASS_BARBARIAN) textdef = TXT_BARBLIND; quests[Q_BLIND]._qmsg = textdef; AddBookLever(0, 0, DMAXX, DMAXY, setpc_x, setpc_y, setpc_x+setpc_w+1, setpc_y+setpc_h+1, textdef); setp = LoadFileInMemSig("Levels\\L2Data\\Blind2.DUN",NULL,'STPC'); LoadMapObjs(setp, (setpc_x << 1), (setpc_y << 1)); DiabloFreePtr(setp); } if (QuestStatus(Q_BLOOD)) { if (plr[myplr]._pClass == CLASS_WARRIOR) textdef = TXT_WARBLOOD; else if (plr[myplr]._pClass == CLASS_ROGUE) textdef = TXT_ROGBLOOD; else if (plr[myplr]._pClass == CLASS_SORCEROR) textdef = TXT_SORBLOOD; else if (plr[myplr]._pClass == CLASS_MONK) textdef = TXT_MNKBLOOD; else if (plr[myplr]._pClass == CLASS_BARD) textdef = TXT_BRDBLOOD; else if (plr[myplr]._pClass == CLASS_BARBARIAN) textdef = TXT_BARBLOOD; quests[Q_BLOOD]._qmsg = textdef; AddBookLever(0, 0, DMAXX, DMAXY, setpc_x, setpc_y + 3, setpc_x + 2, setpc_y + 7, textdef); AddObject(OBJ_PEDISTAL, (setpc_x << 1) + DIRTEDGED2 + 9, (setpc_y << 1) +DIRTEDGED2 + 16); } InitRndBarrels(); } if (leveltype == 3) { AddL3Objs(0, 0, DMAXX, DMAXY); InitRndBarrels(); } if (leveltype == 4) { if (QuestStatus(Q_WARLORD)) { if (plr[myplr]._pClass == CLASS_WARRIOR) textdef = TXT_WARLORD; else if (plr[myplr]._pClass == CLASS_ROGUE) textdef = TXT_ROGLORD; else if (plr[myplr]._pClass == CLASS_SORCEROR) textdef = TXT_SORLORD; else if (plr[myplr]._pClass == CLASS_MONK) textdef = TXT_MNKLORD; else if (plr[myplr]._pClass == CLASS_BARD) textdef = TXT_BRDLORD; else if (plr[myplr]._pClass == CLASS_BARBARIAN) textdef = TXT_BARLORD; quests[Q_WARLORD]._qmsg = textdef; AddBookLever(0, 0, DMAXX, DMAXY, setpc_x, setpc_y, setpc_x+setpc_w, setpc_y+setpc_h, textdef); setp = LoadFileInMemSig("Levels\\L4Data\\Warlord.DUN",NULL,'STPC'); LoadMapObjs(setp, (setpc_x << 1), (setpc_y << 1)); DiabloFreePtr(setp); } if (QuestStatus(Q_BETRAYER) && (gbMaxPlayers == 1)) { AddLazStand(); } InitRndBarrels(); AddL4Goodies(); } InitRndLocObj(5, 10, OBJ_CHEST1); InitRndLocObj(3, 6, OBJ_CHEST2); InitRndLocObj(1, 5, OBJ_CHEST3); if (leveltype != 4) AddObjTraps(); if (leveltype > 1) AddChestTraps(); InitObjFlag = FALSE; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void SetMapObjects(BYTE *pMap, int startx, int starty) { int i,j,rw,rh; int ox,oy; BYTE *lm, *h; long mapoff; int ot; bool fileload[MAXOBJFILES]; char filestr[32]; ClrAllObjects(); InitObjFlag = TRUE; for (i = 0; i < MAXOBJFILES; ++i) fileload[i] = FALSE; // Load all must obj gfx for leveltype for (i = 0; AllObjects[i].oload != -1; ++i) { if ((AllObjects[i].oload == OBJMUST) && (leveltype == AllObjects[i].olvltype)) fileload[AllObjects[i].ofindex] = true; } lm = pMap; rw = *lm; lm += 2; rh = *lm; // Skip map + height word mapoff = ((rw * rh) << 1) + 2; // Convert to index mini tile level instead of mega rw = rw << 1; rh = rh << 1; // Skip treasure and monster map mapoff += ((rw * rh) << 2); lm += mapoff; h = lm; for (j = 0; j < rh; ++j) { for (i = 0; i < rw; ++i) { if (*lm != 0) { ot = *lm; ot = ObjTypeConv[ot]; fileload[AllObjects[ot].ofindex] = TRUE; } lm+=2; } } app_assert(numobjfiles == 0); for (i = 0; i < MAXOBJFILES; ++i) { if (fileload[i]) { ObjFileList[numobjfiles] = i; sprintf(filestr, "Objects\\%s.CEL", ObjMasterFList[i]); app_assert(! pObjCels[numobjfiles]); pObjCels[numobjfiles] = LoadFileInMemSig(filestr,NULL,'OGFX'); ++numobjfiles; } } lm = h; for (j = 0; j < rh; ++j) { for (i = 0; i < rw; ++i) { if (*lm != 0) { ot = *lm; ox = i + DIRTEDGED2 + startx; oy = j + DIRTEDGED2 + starty; AddObject(ObjTypeConv[ot], ox, oy); } lm+=2; } } InitObjFlag = FALSE; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void DeleteObject(int oi, int i) { int ox,oy; app_assert((DWORD)oi < MAXOBJECTS); ox = object[oi]._ox; oy = object[oi]._oy; dObject[ox][oy] = 0; objectavail[MAXOBJECTS - numobjects] = oi; --numobjects; if ((numobjects > 0) && (i != numobjects)) { objectactive[i] = objectactive[numobjects]; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void SetupObject(int i, int x, int y, int ot) { int ai, j; app_assert((DWORD)i < MAXOBJECTS); object[i]._otype = ot; object[i]._ox = x; object[i]._oy = y; ai = AllObjects[ot].ofindex; for (j = 0; ObjFileList[j] != ai; ++j); object[i]._oAnimData = pObjCels[j]; object[i]._oAnimFlag = AllObjects[ot].oAnimFlag; if (object[i]._oAnimFlag) { object[i]._oAnimDelay = AllObjects[ot].oAnimDelay; object[i]._oAnimCnt = random(146,AllObjects[ot].oAnimDelay); object[i]._oAnimLen = AllObjects[ot].oAnimLen; object[i]._oAnimFrame = random(146,AllObjects[ot].oAnimLen-1) + 1; } else { object[i]._oAnimDelay = 1000; object[i]._oAnimCnt = 0; object[i]._oAnimLen = AllObjects[ot].oAnimLen; object[i]._oAnimFrame = AllObjects[ot].oAnimDelay; } object[i]._oAnimWidth = AllObjects[ot].oAnimWidth; object[i]._oSolidFlag = AllObjects[ot].oSolidFlag; object[i]._oMissFlag = AllObjects[ot].oMissFlag; object[i]._oLight = AllObjects[ot].oLightFlag; object[i]._oDelFlag = FALSE; object[i]._oBreak = AllObjects[ot].oBreak; object[i]._oSelFlag = AllObjects[ot].oSelFlag; object[i]._oPreFlag = FALSE; object[i]._oTrapFlag = FALSE; object[i]._oDoorFlag = FALSE; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void SetObjMapRange(int i, int x1, int y1, int x2, int y2, int v) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oVar1 = x1; object[i]._oVar2 = y1; object[i]._oVar3 = x2; object[i]._oVar4 = y2; object[i]._oVar8 = v; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void SetBookMsg(int i, int msg) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oVar7 = msg; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddL1Door(int i, int x, int y, int ot) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oDoorFlag = TRUE; if (ot == OBJ_L1DOORL) { object[i]._oVar1 = dPiece[x][y]; object[i]._oVar2 = dPiece[x][y-1]; } else { object[i]._oVar1 = dPiece[x][y]; object[i]._oVar2 = dPiece[x-1][y]; } object[i]._oVar4 = DOOR_CLOSED; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddSCambBook(int i) { app_assert((DWORD)i < MAXOBJECTS); // if (quests[Q_SCHAMB]._qactive != QUEST_NOTACTIVE) { // object[i]._oSelFlag = OSEL_NONE; // object[i]._oAnimFrame = 6; // } object[i]._oVar1 = setpc_x; object[i]._oVar2 = setpc_y; object[i]._oVar3 = setpc_x+setpc_w+1; object[i]._oVar4 = setpc_y+setpc_h+1; object[i]._oVar6 = object[i]._oAnimFrame + 1; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddChest(int i, int t) { app_assert((DWORD)i < MAXOBJECTS); if (random(147,2) == 0) object[i]._oAnimFrame += 3; // Left or right object[i]._oRndSeed = GetRndSeed(); // Set # chest items. If a setlevel then so to max items. switch(t) { case OBJ_CHEST1: case OBJ_TCHEST1: if (setlevel) object[i]._oVar1 = 1; else object[i]._oVar1 = random(147,2); break; case OBJ_CHEST2: case OBJ_TCHEST2: if (setlevel) object[i]._oVar1 = 2; else object[i]._oVar1 = random(147,3); break; case OBJ_CHEST3: case OBJ_TCHEST3: if (setlevel) object[i]._oVar1 = 3; else object[i]._oVar1 = random(147,4); break; } object[i]._oVar2 = random(147,8); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddL2Door(int i, int x, int y, int ot) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oDoorFlag = TRUE; if (ot == OBJ_L2DOORL) ObjSetMicro(x, y, 538); else ObjSetMicro(x, y, 540); object[i]._oVar4 = DOOR_CLOSED; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddL3Door(int i, int x, int y, int ot) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oDoorFlag = TRUE; if (ot == OBJ_L3DOORL) ObjSetMicro(x, y, 531); else ObjSetMicro(x, y, 534); object[i]._oVar4 = DOOR_CLOSED; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddSarc(int i) { int x,y; app_assert((DWORD)i < MAXOBJECTS); x = object[i]._ox; y = object[i]._oy - 1; dObject[x][y] = -1 - (char)i; object[i]._oVar1 = random(153,10); object[i]._oRndSeed = GetRndSeed(); if (object[i]._oVar1 >= 8) object[i]._oVar2 = PreSpawnSkeleton(); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddFlameTrap(int i) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oVar1 = trapid; // Set trap id object[i]._oVar2 = 0; // Trap active object[i]._oVar3 = trapdir; // Horizontal, Vertical, or none object[i]._oVar4 = 0; // Init to off } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddFlameLvr(int i) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oVar1 = trapid; // Set trap id object[i]._oVar2 = OBJ_FLAMEHOLE; // Trap active } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddTrap(int i, int ot) { int mt, tdiff; // Difficulty tdiff = (currlevel / 3) + 1; // Temp hack trap JKE 7/30 if (currlevel > 16) tdiff = ((currlevel-4)/3) + 1; if (currlevel > 20) tdiff = ((currlevel-8)/3) + 1; // Missile type mt = random(148,tdiff); app_assert((DWORD)i < MAXOBJECTS); if (mt == 0) object[i]._oVar3 = MIT_ARROW; if (mt == 1) object[i]._oVar3 = MIT_FIREBOLT; if (mt == 2) object[i]._oVar3 = MIT_LIGHTCTRL; object[i]._oVar4 = 0; // Trap active } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddObjLight(int i, int r) { app_assert((DWORD)i < MAXOBJECTS); if (InitObjFlag) { DoLighting(object[i]._ox, object[i]._oy, r, -1); object[i]._oVar1 = -1; } else object[i]._oVar1 = 0; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddBarrel(int i, int ot) { app_assert((DWORD)i < MAXOBJECTS); //object[i]._oVar1 = random(149,5) + 5; // Barrel hit points object[i]._oVar1 = 0; object[i]._oRndSeed = GetRndSeed(); object[i]._oVar2 = random(149,10); // What is inside object[i]._oVar3 = random(149,3); // if item, useful or not if (object[i]._oVar2 >= 8) object[i]._oVar4 = PreSpawnSkeleton(); // Get monster index if one will pop out } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddShrine(int i) { int st, j; bool slist[NUMSHRINETYPES]; app_assert((DWORD)i < MAXOBJECTS); object[i]._oPreFlag = TRUE; for (j = 0; j < NUMSHRINETYPES; ++j) { if ((currlevel >= shrineminlvl[j]) && (currlevel <= shrinemaxlvl[j])) slist[j] = true; else slist[j] = false; if ((gbMaxPlayers != 1) && (shrineavail[j] == SHRINE_SINGLE)) slist[j] = false; if ((gbMaxPlayers == 1) && (shrineavail[j] == SHRINE_MULTI)) slist[j] = false; } // Choose shrine type do { st = random(150,NUMSHRINETYPES); } while (!slist[st]); object[i]._oVar1 = st; if (random(150,2)) { object[i]._oAnimFrame = 12; object[i]._oAnimLen = 22; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddBookcase(int i) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oRndSeed = GetRndSeed(); object[i]._oPreFlag = TRUE; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddBookstand(int i) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oRndSeed = GetRndSeed(); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddBloodFtn(int i) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oRndSeed = GetRndSeed(); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddPurifyingFountain(int i) { int x, y; app_assert((DWORD)i < MAXOBJECTS); x = object[i]._ox; y = object[i]._oy; dObject[x][y-1] = -1 - (char)i; dObject[x-1][y] = -1 - (char)i; dObject[x-1][y-1] = -1 - (char)i; object[i]._oRndSeed = GetRndSeed(); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddArmorStand(int i) { app_assert((DWORD)i < MAXOBJECTS); if (!armorFlag) { //A functional armor stand has already been placed //Only place non-functional empty stands object[i]._oAnimFlag = 2; object[i]._oSelFlag = OSEL_NONE; } object[i]._oRndSeed = GetRndSeed(); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddGoatShrine(int i) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oRndSeed = GetRndSeed(); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddCauldron(int i) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oRndSeed = GetRndSeed(); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddMurkyFountain(int i) { int x, y; app_assert((DWORD)i < MAXOBJECTS); x = object[i]._ox; y = object[i]._oy; dObject[x][y-1] = -1 - (char)i; dObject[x-1][y] = -1 - (char)i; dObject[x-1][y-1] = -1 - (char)i; object[i]._oRndSeed = GetRndSeed(); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddTearFountain(int i) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oRndSeed = GetRndSeed(); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddDecap(int i) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oRndSeed = GetRndSeed(); object[i]._oAnimFrame = random(151,8) + 1; object[i]._oPreFlag = TRUE; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ const void AddVilebook(int i) { if ((setlevel) && (setlvlnum == SL_VILEBETRAYER)) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oAnimFrame = 4; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ const void AddMagicCircle(int i) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oRndSeed = GetRndSeed(); object[i]._oPreFlag = TRUE; object[i]._oVar6 = OBJNOWARP; object[i]._oVar5 = OBJWARP1; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ const void AddBrnCross(int i) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oRndSeed = GetRndSeed(); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ const void AddPedistal(int i) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oVar1 = setpc_x; object[i]._oVar2 = setpc_y; object[i]._oVar3 = setpc_x + setpc_w; object[i]._oVar4 = setpc_y + setpc_h; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ int const StoryText[3][3] = { { TXT_BOOK11, TXT_BOOK12, TXT_BOOK13 }, { TXT_BOOK21, TXT_BOOK22, TXT_BOOK23 }, { TXT_BOOK31, TXT_BOOK32, TXT_BOOK33 } }; static void AddStoryBook(int i) { // Use the last level seed to determine book types (which of 3) SetRndSeed(glSeedTbl[16]); app_assert((DWORD)i < MAXOBJECTS); object[i]._oVar1 = random(0, 3); if (currlevel == STORY_BOOK1_LEVEL) object[i]._oVar2 = StoryText[object[i]._oVar1][0]; else if (currlevel == STORY_BOOK2_LEVEL) object[i]._oVar2 = StoryText[object[i]._oVar1][1]; else if (currlevel == STORY_BOOK3_LEVEL) object[i]._oVar2 = StoryText[object[i]._oVar1][2]; object[i]._oVar3 = (object[i]._oVar1 * 3) + (currlevel >> 2) - 1; object[i]._oAnimFrame = 5 - (object[i]._oVar1 << 1); object[i]._oVar4 = object[i]._oAnimFrame + 1; } static void addskulkenbook (int i, int number) // number is the text to associate JKE { app_assert((DWORD)i < MAXOBJECTS); if (number > 5) { object[i]._oVar8 = number; switch (object[i]._oVar8) { case 6: // object[i]._oVar2 = TXT_SPELL1; if (plr[myplr]._pClass == CLASS_WARRIOR) object[i]._oVar2 = TXT_SPELL1; else if (plr[myplr]._pClass == CLASS_ROGUE) object[i]._oVar2 = TXT_R_SPELL1; else if (plr[myplr]._pClass == CLASS_SORCEROR) object[i]._oVar2 = TXT_S_SPELL1; else if (plr[myplr]._pClass == CLASS_MONK) object[i]._oVar2 = TXT_M_SPELL1; else if (plr[myplr]._pClass == CLASS_BARD) object[i]._oVar2 = TXT_B_SPELL1; else if (plr[myplr]._pClass == CLASS_BARBARIAN) object[i]._oVar2 = TXT_C_SPELL1; break; case 7: // object[i]._oVar2 = TXT_SPELL2; if (plr[myplr]._pClass == CLASS_WARRIOR) object[i]._oVar2 = TXT_SPELL2; else if (plr[myplr]._pClass == CLASS_ROGUE) object[i]._oVar2 = TXT_R_SPELL2; else if (plr[myplr]._pClass == CLASS_SORCEROR) object[i]._oVar2 = TXT_S_SPELL2; else if (plr[myplr]._pClass == CLASS_MONK) object[i]._oVar2 = TXT_M_SPELL2; else if (plr[myplr]._pClass == CLASS_BARD) object[i]._oVar2 = TXT_B_SPELL2; else if (plr[myplr]._pClass == CLASS_BARBARIAN) object[i]._oVar2 = TXT_C_SPELL2; break; case 8: // object[i]._oVar2 = TXT_SPELL3; if (plr[myplr]._pClass == CLASS_WARRIOR) object[i]._oVar2 = TXT_SPELL3; else if (plr[myplr]._pClass == CLASS_ROGUE) object[i]._oVar2 = TXT_R_SPELL3; else if (plr[myplr]._pClass == CLASS_SORCEROR) object[i]._oVar2 = TXT_S_SPELL3; else if (plr[myplr]._pClass == CLASS_MONK) object[i]._oVar2 = TXT_M_SPELL3; else if (plr[myplr]._pClass == CLASS_BARD) object[i]._oVar2 = TXT_B_SPELL3; else if (plr[myplr]._pClass == CLASS_BARBARIAN) object[i]._oVar2 = TXT_C_SPELL3; break; } object[i]._oVar1 = 1; object[i]._oVar3 = 15; object[i]._oAnimFrame = 5 - ((object[i]._oVar1) << 1); object[i]._oVar4 = object[i]._oAnimFrame + 1; } else { object[i]._oVar1 = 1; object[i]._oVar2 = TXT_SKULLJRNL1 + number; object[i]._oVar3 = 9 + number; object[i]._oAnimFrame = 5 - (object[i]._oVar1 << 1); object[i]._oVar4 = object[i]._oAnimFrame + 1; object[i]._oVar8 = 0; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddWeaponRack(int i) { app_assert((DWORD)i < MAXOBJECTS); if (!weaponFlag) { //A functional weapon rack has already been placed //Only place non-functional empty racks object[i]._oAnimFlag = 2; object[i]._oSelFlag = OSEL_NONE; } object[i]._oRndSeed = GetRndSeed(); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddTorturedBody(int i) { app_assert((DWORD)i < MAXOBJECTS); object[i]._oRndSeed = GetRndSeed(); object[i]._oAnimFrame = random(0, 4) + 1; object[i]._oPreFlag = TRUE; } /*-----------------------------------------------------------------------* * GetRndObjLoc * * Gets a x by y empty location for object placement **-----------------------------------------------------------------------*/ static void GetRndObjLoc(int randarea, int &xx, int &yy) { int i,j; bool failed; if (randarea) { int tries = 0; do { if (++tries > 1000 && randarea > 1) --randarea; xx = random(0, DMAXX); yy = random(0, DMAXY); failed = false; for (i = 0; i < randarea && !failed; ++i) for (j = 0; j < randarea && !failed; ++j) failed = !RndLocOk(xx + i, yy + j); } while (failed); } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddMushPatch() { int x,y; if (numobjects < MAXOBJECTS) { int i = objectavail[0]; GetRndObjLoc(5, x, y); dObject[x+1][y+1] = -1 - (char)i; dObject[x+2][y+1] = -1 - (char)i; dObject[x+1][y+2] = -1 - (char)i; AddObject(OBJ_MUSHPATCH, x+2, y+2); } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void AddSlainHero() { int x, y; GetRndObjLoc(5, x, y); AddObject(OBJ_SLAINHERO, x+2, y+2); } void AddSkulkenObject(int ot, int number, int ox, int oy) { int oi; // Standard setup JKE if (numobjects < MAXOBJECTS) { oi = objectavail[0]; objectavail[0] = objectavail[MAXOBJECTS - numobjects - 1]; objectactive[numobjects] = oi; dObject[ox][oy] = (char)oi + 1; // Standard init SetupObject(oi, ox, oy, ot); addskulkenbook(oi, number); app_assert((DWORD)oi < MAXOBJECTS); object[oi]._oAnimWidth2 = (object[oi]._oAnimWidth - 64) >> 1; ++numobjects; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void AddObject(int ot, int ox, int oy) { int oi; if (numobjects < MAXOBJECTS) { oi = objectavail[0]; objectavail[0] = objectavail[MAXOBJECTS - numobjects - 1]; objectactive[numobjects] = oi; dObject[ox][oy] = (char)oi + 1; // Standard init SetupObject(oi, ox, oy, ot); // Bonus inits switch (ot) { case OBJ_L1LIGHT : //AddObjLight(oi, 10); AddObjLight(oi, 5); break; case OBJ_CANDLE1 : case OBJ_CANDLE2 : case OBJ_SKFIRE : case OBJ_BOOKCANDLE: AddObjLight(oi, 5); break; case OBJ_STORYCANDLE: AddObjLight(oi, 3); break; case OBJ_TORCHL: case OBJ_TORCHR: case OBJ_TORCHL2: case OBJ_TORCHR2: AddObjLight(oi, 8); break; case OBJ_L1DOORL : case OBJ_L1DOORR : AddL1Door(oi, ox, oy, ot); break; case OBJ_L2DOORL : case OBJ_L2DOORR : AddL2Door(oi, ox, oy, ot); break; case OBJ_L3DOORL : case OBJ_L3DOORR : AddL3Door(oi, ox, oy, ot); break; case OBJ_BOOK2R: AddSCambBook(oi); break; case OBJ_CHEST1: case OBJ_CHEST2: case OBJ_CHEST3: case OBJ_TCHEST1: case OBJ_TCHEST2: case OBJ_TCHEST3: AddChest(oi, ot); break; case OBJ_SARC: AddSarc(oi); break; case OBJ_FLAMEHOLE: AddFlameTrap(oi); break; case OBJ_FLAMELVR: AddFlameLvr(oi); break; case OBJ_WATER: app_assert((DWORD)oi < MAXOBJECTS); object[oi]._oAnimFrame = 1; break; case OBJ_TRAPL: case OBJ_TRAPR: AddTrap(oi, ot); break; case OBJ_BARREL: case OBJ_BARRELEX: AddBarrel(oi, ot); break; case OBJ_SHRINEL: case OBJ_SHRINER: AddShrine(oi); break; case OBJ_BOOKCASEL: case OBJ_BOOKCASER: AddBookcase(oi); break; case OBJ_SKELBOOK: case OBJ_BOOKSTAND: AddBookstand(oi); break; case OBJ_BLOODFTN: AddBloodFtn(oi); break; case OBJ_DECAP: AddDecap(oi); break; case OBJ_PURIFYINGFTN: AddPurifyingFountain(oi); break; case OBJ_ARMORSTAND: case OBJ_WARARMOR: AddArmorStand(oi); break; case OBJ_GOATSHRINE: AddGoatShrine(oi); break; case OBJ_CAULDRON: AddCauldron(oi); break; case OBJ_MURKYFTN: AddMurkyFountain(oi); break; case OBJ_TEARFTN: AddTearFountain(oi); break; case OBJ_BOOK2L: AddVilebook(oi); break; case OBJ_MCIRCLE1: case OBJ_MCIRCLE2: AddMagicCircle(oi); break; case OBJ_STORYBOOK: AddStoryBook(oi); break; case OBJ_TBCROSS: case OBJ_BCROSS: AddBrnCross(oi); AddObjLight(oi, 5); break; case OBJ_PEDISTAL: AddPedistal(oi); break; case OBJ_WARWEAP: case OBJ_WEAPONRACK: AddWeaponRack(oi); break; case OBJ_TNUDEM2: AddTorturedBody(oi); break; } app_assert((DWORD)oi < MAXOBJECTS); object[oi]._oAnimWidth2 = (object[oi]._oAnimWidth - 64) >> 1; ++numobjects; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void Obj_Light(int i, int lr) { int ox, oy; int dx, dy, p, tr; bool turnon = false; app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oVar1 == -1) return; ox = object[i]._ox; oy = object[i]._oy; tr = lr + PLRLRAD; if (lightflag == 0) { for (p = 0; (p < MAX_PLRS) && (!turnon); ++p) { if (!plr[p].plractive) continue; if (currlevel != plr[p].plrlevel) continue; dx = abs(plr[p]._px - ox); dy = abs(plr[p]._py - oy); if ((dx < tr) && (dy < tr)) turnon = true; } } if (turnon) { if (object[i]._oVar1 == 0) object[i]._olid = AddLight (ox, oy, lr); object[i]._oVar1 = 1; } else { if (object[i]._oVar1 == 1) AddUnLight(object[i]._olid); object[i]._oVar1 = 0; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void Obj_Circle(int i) { int px, py, ox, oy; int v1, v2, v3; app_assert((DWORD)i < MAXOBJECTS); ox = object[i]._ox; oy = object[i]._oy; px = plr[myplr]._px; py = plr[myplr]._py; if ((px == ox) && (py == oy)) { if (object[i]._otype == OBJ_MCIRCLE1) object[i]._oAnimFrame = 2; if (object[i]._otype == OBJ_MCIRCLE2) object[i]._oAnimFrame = 4; if ((ox == 45) && (oy == 47)) object[i]._oVar6 = OBJWARP2; else if ((ox == 26) && (oy == 46)) object[i]._oVar6 = OBJWARP1; else object[i]._oVar6 = OBJNOWARP; if ((ox == 35) && (oy == 36) && object[i]._oVar5 == OBJWARP3) { object[i]._oVar6 = OBJDONEWARP; v1 = 35; v2 = 46; ObjChangeMapResync(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); if (quests[Q_BETRAYER]._qactive == QUEST_NOTDONE) quests[Q_BETRAYER]._qvar1 = 4; v3 = dPiece[v1][v2]; //Cast phase AddMissile(plr[myplr]._px, plr[myplr]._py, v1, v2, plr[myplr]._pdir, MIT_PHASE, MI_ENEMYMONST, myplr, 0, 0); void TrackInit(BOOL bMouseDown); TrackInit(FALSE); // drb.patch1.start.1/24/97 // static BYTE sgbMouseDown; extern BYTE sgbMouseDown; // drb.patch1.end.1/24/97 sgbMouseDown = FALSE; ReleaseCapture(); ClrPlrPath(myplr); void StartStand(int, int); StartStand(myplr, 0); } } else { if (object[i]._otype == OBJ_MCIRCLE1) object[i]._oAnimFrame = 1; if (object[i]._otype == OBJ_MCIRCLE2) object[i]._oAnimFrame = 3; object[i]._oVar6 = OBJNOWARP; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void Obj_StopAnim(int i) { app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oAnimFrame == object[i]._oAnimLen) { object[i]._oAnimCnt = 0; object[i]._oAnimDelay = 1000; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void Obj_Door(int i) { int dx, dy; bool dok; app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oVar4 == DOOR_CLOSED) { object[i]._oSelFlag = OSEL_ALL; object[i]._oMissFlag = FALSE; } else { dx = object[i]._ox; dy = object[i]._oy; dok = (dMonster[dx][dy] == 0); dok = dok && (dItem[dx][dy] == 0); dok = dok && (dDead[dx][dy] == 0); dok = dok && (dPlayer[dx][dy] == 0); object[i]._oSelFlag = OSEL_TOP; if (dok) object[i]._oVar4 = DOOR_OPEN; else object[i]._oVar4 = DOOR_BLOCKED; object[i]._oMissFlag = TRUE; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void Obj_Sarc(int i) { app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oAnimFrame == object[i]._oAnimLen) object[i]._oAnimFlag = FALSE; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void ActivateTrapLine(int ttype, int tid) { int i, oi; for (i = 0; i < numobjects; ++i) { oi = objectactive[i]; if ((object[oi]._otype == ttype) && (object[oi]._oVar1 == tid)) { object[oi]._oVar4 = 1; object[oi]._oAnimFlag = TRUE; object[oi]._oAnimDelay = 1; object[oi]._olid = AddLight (object[oi]._ox, object[oi]._oy, 1); } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void Obj_FlameTrap(int i) { int xp,yp; int j; // Is trap active? app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oVar2 != 0) { // Not active, try dying down if (object[i]._oVar4 != 0) { --object[i]._oAnimFrame; if (object[i]._oAnimFrame == 1) { object[i]._oVar4 = 0; AddUnLight(object[i]._olid); } else { if (object[i]._oAnimFrame <= 4) ChangeLightRadius(object[i]._olid, object[i]._oAnimFrame); } } } else { // Active so continue // Not on? if (object[i]._oVar4 == 0) { if (object[i]._oVar3 == TRAP_VERT) { xp = object[i]._ox-2; yp = object[i]._oy; for (j = 0; j < 5; ++j) { if ((dPlayer[xp][yp] != 0) || (dMonster[xp][yp] != 0)) object[i]._oVar4 = 1; ++xp; } } else { xp = object[i]._ox; yp = object[i]._oy-2; for (j = 0; j < 5; ++j) { if ((dPlayer[xp][yp] != 0) || (dMonster[xp][yp] != 0)) object[i]._oVar4 = 1; ++yp; } } if (object[i]._oVar4 != 0) ActivateTrapLine(object[i]._otype, object[i]._oVar1); } else { if (object[i]._oAnimFrame == object[i]._oAnimLen) object[i]._oAnimFrame = 11; if (object[i]._oAnimFrame <= 5) ChangeLightRadius(object[i]._olid, object[i]._oAnimFrame); } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void Obj_Trap(int i) { int oti; bool otrig = false; int sx, sy, dx, dy; int x, y; int ax, ay; int mdir; // Triggered? app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oVar4 == 0) { oti = dObject[object[i]._oVar1][object[i]._oVar2] - 1; switch (object[oti]._otype) { case OBJ_CHEST1: case OBJ_CHEST2: case OBJ_CHEST3: case OBJ_SWITCHSKL: case OBJ_LEVER : case OBJ_SARC: if (object[oti]._oSelFlag == OSEL_NONE) otrig = true; break; case OBJ_L1DOORL : case OBJ_L1DOORR : case OBJ_L2DOORL : case OBJ_L2DOORR : case OBJ_L3DOORL : case OBJ_L3DOORR : if (object[oti]._oVar4 != DOOR_CLOSED) otrig = true; break; } if (otrig) { object[i]._oVar4 = 1; sx = object[i]._ox; sy = object[i]._oy; dx = object[oti]._ox; dy = object[oti]._oy; ax = dx; ay = dy; for (y = ay-1; y <= ay+1; ++y) { for (x = ax-1; x <= ax+1; ++x) { if (dPlayer[x][y] != 0) { dx = x; dy = y; } } } if (!deltaload) { mdir = GetDirection(sx, sy, dx, dy); AddMissile(sx, sy, dx, dy, mdir, object[i]._oVar3, MI_ENEMYPLR, -1, 0, 0); PlaySfxLoc(IS_TRAP, object[oti]._ox, object[oti]._oy); } object[oti]._oTrapFlag = FALSE; } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void Obj_BCrossDamage(int i) { int resist; int damage[4] = { 6, 8, 10, 12 }; if (plr[myplr]._pmode != PM_DEATH) { //Check for fire resistance. If resistance, adjust damage accordingly. resist = plr[myplr]._pFireResist; if (resist > 0) damage[leveltype-1] -= (damage[leveltype-1] * resist) / 100; //Is the player in the fire? app_assert((DWORD)i < MAXOBJECTS); if ((plr[myplr]._px == object[i]._ox) && (plr[myplr]._py == object[i]._oy-1)) { //Subtract damage plr[myplr]._pHitPoints -= damage[leveltype-1]; plr[myplr]._pHPBase -= damage[leveltype-1]; //Check if player is dead if ((plr[myplr]._pHitPoints >> HP_SHIFT) <= 0) { // rjs - manashld fix? - SetPlayerHitPoints(myplr, 0); StartPlrKill(myplr, FALSE); } else { //Play pain sfx if (plr[myplr]._pClass == CLASS_WARRIOR) PlaySfxLoc(PS_WARR68, plr[myplr]._px, plr[myplr]._py); #if !IS_VERSION(SHAREWARE) else if (plr[myplr]._pClass == CLASS_ROGUE) PlaySfxLoc(PS_ROGUE68, plr[myplr]._px, plr[myplr]._py); else if (plr[myplr]._pClass == CLASS_SORCEROR) PlaySfxLoc(PS_MAGE68, plr[myplr]._px, plr[myplr]._py); else if (plr[myplr]._pClass == CLASS_MONK) PlaySfxLoc(PS_MONK68, plr[myplr]._px, plr[myplr]._py); else if (plr[myplr]._pClass == CLASS_BARD) PlaySfxLoc(PS_BARD68, plr[myplr]._px, plr[myplr]._py); else if (plr[myplr]._pClass == CLASS_BARBARIAN) PlaySfxLoc(PS_BARBARIAN68, plr[myplr]._px, plr[myplr]._py); #endif } drawhpflag = TRUE; } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void ProcessObjects () { int i, oi; for (i = 0; i < numobjects; ++i) { oi = objectactive[i]; app_assert((DWORD)oi < MAXOBJECTS); switch (object[oi]._otype) { case OBJ_L1LIGHT : Obj_Light(oi, 10); break; case OBJ_CANDLE2 : case OBJ_SKFIRE : case OBJ_BOOKCANDLE: Obj_Light(oi, 5); break; case OBJ_STORYCANDLE: Obj_Light(oi, 3); break; case OBJ_CRUX1 : case OBJ_CRUX2 : case OBJ_CRUX3 : case OBJ_BARREL: case OBJ_BARRELEX: case OBJ_SHRINEL: case OBJ_SHRINER: Obj_StopAnim(oi); break; case OBJ_L1DOORL : case OBJ_L1DOORR : case OBJ_L2DOORL : case OBJ_L2DOORR : case OBJ_L3DOORL : case OBJ_L3DOORR : Obj_Door(oi); break; case OBJ_TORCHL: case OBJ_TORCHR: case OBJ_TORCHL2: case OBJ_TORCHR2: Obj_Light(oi, 8); break; case OBJ_SARC: Obj_Sarc(oi); break; case OBJ_FLAMEHOLE: Obj_FlameTrap(oi); break; case OBJ_TRAPL: case OBJ_TRAPR: Obj_Trap(oi); break; case OBJ_MCIRCLE1: case OBJ_MCIRCLE2: Obj_Circle(oi); break; case OBJ_TBCROSS: case OBJ_BCROSS: Obj_Light(oi, 10); Obj_BCrossDamage(oi); break; } // Animate Objects if (object[oi]._oAnimFlag) { ++object[oi]._oAnimCnt; if (object[oi]._oAnimCnt >= object[oi]._oAnimDelay) { object[oi]._oAnimCnt = 0; ++object[oi]._oAnimFrame; if (object[oi]._oAnimFrame > object[oi]._oAnimLen) object[oi]._oAnimFrame = 1; } } } i = 0; while (i < numobjects) { oi = objectactive[i]; if (object[oi]._oDelFlag) { DeleteObject(oi, i); i = 0; } else ++i; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void ObjSetMicro(int dx, int dy, int pn) { WORD *mtsource; int t; WORD *mt; dPiece[dx][dy] = pn; --pn; mt = &(dMT2[CalcRot(dx,dy)].mt[0]); if (leveltype != 4) { mtsource = (WORD *)(pMiniTiles + 20*pn); for(t = 0; t < 10; ++t) // MiniTiles array uses opposite y direction // hence wierd index on next line mt[t] = mtsource[8-(t&0xe)+(t&1)]; } else { mtsource = (WORD *)(pMiniTiles + 32*pn); for(t = 0; t < 16; ++t) // MiniTiles array uses opposite y direction // hence wierd index on next line mt[t] = mtsource[14-(t&0xe)+(t&1)]; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void ObjSetMicro12(int dx, int dy) { long mt1,mt2; int pn; pn = dPiece[dx][dy] - 1; __asm { mov esi,dword ptr [pMiniTiles] xor eax,eax mov ax,word ptr [pn] mov ebx,20 mul ebx add esi,eax add esi,16 xor eax,eax lodsw mov word ptr [mt1],ax lodsw mov word ptr [mt2],ax } dMT2[CalcRot(dx,dy)].mt[0] = mt1 & 0xffff; dMT2[CalcRot(dx,dy)].mt[1] = mt2 & 0xffff; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void ObjSetMini(int x, int y, int v) { long v1,v2,v3,v4; int xx, yy; __asm { mov esi,dword ptr [pMegaTiles] xor eax,eax mov ax,word ptr [v]; dec eax shl eax,3 add esi,eax xor eax,eax lodsw inc eax mov dword ptr [v1],eax lodsw inc eax mov dword ptr [v2],eax lodsw inc eax mov dword ptr [v3],eax lodsw inc eax mov dword ptr [v4],eax } xx = (x << 1) + DIRTEDGED2; yy = (y << 1) + DIRTEDGED2; ObjSetMicro(xx, yy, v1); ObjSetMicro(xx+1, yy, v2); ObjSetMicro(xx, yy+1, v3); ObjSetMicro(xx+1, yy+1, v4); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void ObjL1Special(int x1, int y1, int x2, int y2) { int i,j; for (j = y1; j <= y2; ++j) { for (i = x1; i <= x2; ++i) { dSpecial[i][j] = 0; // Place tops of arches if (dPiece[i][j] == 12) dSpecial[i][j] = 1; if (dPiece[i][j] == 11) dSpecial[i][j] = 2; if (dPiece[i][j] == 71) dSpecial[i][j] = 1; if (dPiece[i][j] == 259) dSpecial[i][j] = 5; if (dPiece[i][j] == 249) dSpecial[i][j] = 2; if (dPiece[i][j] == 325) dSpecial[i][j] = 2; if (dPiece[i][j] == 321) dSpecial[i][j] = 1; if (dPiece[i][j] == 255) dSpecial[i][j] = 4; if (dPiece[i][j] == 211) dSpecial[i][j] = 1; if (dPiece[i][j] == 344) dSpecial[i][j] = 2; if (dPiece[i][j] == 341) dSpecial[i][j] = 1; if (dPiece[i][j] == 331) dSpecial[i][j] = 2; if (dPiece[i][j] == 418) dSpecial[i][j] = 1; if (dPiece[i][j] == 421) dSpecial[i][j] = 2; } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void ObjL2Special(int x1, int y1, int x2, int y2) { int i,j; for (j = y1; j <= y2; ++j) { for (i = x1; i <= x2; ++i) { dSpecial[i][j] = 0; if (dPiece[i][j] == 541) dSpecial[i][j] = 5; if (dPiece[i][j] == 178) dSpecial[i][j] = 5; if (dPiece[i][j] == 551) dSpecial[i][j] = 5; if (dPiece[i][j] == 542) dSpecial[i][j] = 6; if (dPiece[i][j] == 553) dSpecial[i][j] = 6; if (dPiece[i][j] == 13) dSpecial[i][j] = 5; if (dPiece[i][j] == 17) dSpecial[i][j] = 6; } } for (j = y1; j <= y2; ++j) { for (i = x1; i <= x2; ++i) { if (dPiece[i][j] == 132) { dSpecial[i][j+1] = 2; dSpecial[i][j+2] = 1; } if ((dPiece[i][j] == 135) || (dPiece[i][j] == 139)) { dSpecial[i+1][j] = 3; dSpecial[i+2][j] = 4; } } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void DoorSet(int oi, int dx, int dy) { int pn; app_assert((DWORD)oi < MAXOBJECTS); pn = dPiece[dx][dy]; if (currlevel < HIVESTART) { if (pn == 43) ObjSetMicro(dx,dy,392); if (pn == 45) ObjSetMicro(dx,dy,394); if ((pn == 50) && (object[oi]._otype == OBJ_L1DOORL)) ObjSetMicro(dx,dy,411); if ((pn == 50) && (object[oi]._otype == OBJ_L1DOORR)) ObjSetMicro(dx,dy,412); if (pn == 54) ObjSetMicro(dx,dy,397); if (pn == 55) ObjSetMicro(dx,dy,398); if (pn == 61) ObjSetMicro(dx,dy,399); if (pn == 67) ObjSetMicro(dx,dy,400); if (pn == 68) ObjSetMicro(dx,dy,401); if (pn == 69) ObjSetMicro(dx,dy,403); if (pn == 70) ObjSetMicro(dx,dy,404); if (pn == 72) ObjSetMicro(dx,dy,406); if (pn == 212) ObjSetMicro(dx,dy,407); // Blood if (pn == 354) ObjSetMicro(dx,dy,409); // Plain L if (pn == 355) ObjSetMicro(dx,dy,410); // Plain R if (pn == 411) ObjSetMicro(dx,dy,396); // Double open if (pn == 412) ObjSetMicro(dx,dy,396); // Double open } else { if (pn == 75) ObjSetMicro(dx,dy,204); if (pn == 79) ObjSetMicro(dx,dy,208); if ((pn == 86) && (object[oi]._otype == OBJ_L1DOORL)) ObjSetMicro(dx,dy,232); if ((pn == 86) && (object[oi]._otype == OBJ_L1DOORR)) ObjSetMicro(dx,dy,234); if (pn == 91) ObjSetMicro(dx,dy,215); if (pn == 93) ObjSetMicro(dx,dy,218); if (pn == 99) ObjSetMicro(dx,dy,220); if (pn == 111) ObjSetMicro(dx,dy,222); if (pn == 113) ObjSetMicro(dx,dy,224); if (pn == 115) ObjSetMicro(dx,dy,226); if (pn == 117) ObjSetMicro(dx,dy,228); if (pn == 119) ObjSetMicro(dx,dy,230); if (pn == 232) ObjSetMicro(dx,dy,212); // Double open if (pn == 234) ObjSetMicro(dx,dy,212); // Double open } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void RedoPlayerVision() { int p; for (p = 0; p < MAX_PLRS; ++p) { if (! plr[p].plractive) continue; if (currlevel != plr[p].plrlevel) continue; ChangeVisionXY(plr[p]._pvid, plr[p]._px, plr[p]._py); } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateL1RDoor(int pnum, int oi, bool sendflag) { int dx, dy; bool dok; app_assert((DWORD)oi < MAXOBJECTS); if (object[oi]._oVar4 == DOOR_BLOCKED) { if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); return; } dx = object[oi]._ox; dy = object[oi]._oy; if (object[oi]._oVar4 == DOOR_CLOSED) { if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_OPENDOOR,oi); if (currlevel < CRYPTSTART) { if (!deltaload) PlaySfxLoc(IS_DOOROPEN, object[oi]._ox, object[oi]._oy); } else { if (!deltaload) PlaySfxLoc(CR_DOOROPEN, object[oi]._ox, object[oi]._oy); } if (currlevel < CRYPTSTART) ObjSetMicro(dx,dy,395); else ObjSetMicro(dx,dy,209); if (currlevel < HIVESTART) dSpecial[dx][dy] = 8; else dSpecial[dx][dy] = 2; ObjSetMicro12(dx,dy-1); --dx; object[oi]._oAnimFrame += 2; #ifdef NO_L5_DOORS if (currlevel > HIVESTART) object[oi]._oAnimFrame = -1; #endif object[oi]._oPreFlag = TRUE; DoorSet(oi, dx, dy); object[oi]._oVar4 = DOOR_OPEN; object[oi]._oSelFlag = OSEL_TOP; RedoPlayerVision(); } else { if (currlevel < CRYPTSTART) { if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); } else { if (!deltaload) PlaySfxLoc(CR_DOORCLOS, object[oi]._ox, object[oi]._oy); } dok = (dMonster[dx][dy] == 0); dok = dok && (dItem[dx][dy] == 0); dok = dok && (dDead[dx][dy] == 0); if (dok) { if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_CLOSEDOOR,oi); object[oi]._oVar4 = DOOR_CLOSED; object[oi]._oSelFlag = OSEL_ALL; ObjSetMicro(dx,dy,object[oi]._oVar1); if (currlevel < HIVESTART) { if (object[oi]._oVar2 != 50) ObjSetMicro(dx-1,dy,object[oi]._oVar2); else { // Double door if (dPiece[dx-1][dy] == 396) ObjSetMicro(dx-1,dy,411); else ObjSetMicro(dx-1,dy,object[oi]._oVar2); } } else { if (object[oi]._oVar2 != 86) ObjSetMicro(dx-1,dy,object[oi]._oVar2); else { // Double door if (dPiece[dx-1][dy] == 210) ObjSetMicro(dx-1,dy,232); else ObjSetMicro(dx-1,dy,object[oi]._oVar2); } } object[oi]._oAnimFrame -= 2; object[oi]._oPreFlag = FALSE; RedoPlayerVision(); } else object[oi]._oVar4 = DOOR_BLOCKED; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateL1LDoor(int pnum, int oi, bool sendflag) { int dx, dy; bool dok; app_assert((DWORD)oi < MAXOBJECTS); if (object[oi]._oVar4 == DOOR_BLOCKED) { if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); return; } dx = object[oi]._ox; dy = object[oi]._oy; if (object[oi]._oVar4 == DOOR_CLOSED) { if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_OPENDOOR,oi); if (currlevel < CRYPTSTART) { if (!deltaload) PlaySfxLoc(IS_DOOROPEN, object[oi]._ox, object[oi]._oy); } else { if (!deltaload) PlaySfxLoc(CR_DOOROPEN, object[oi]._ox, object[oi]._oy); } if (currlevel < CRYPTSTART) { if (object[oi]._oVar1 == 214) ObjSetMicro(dx,dy,408); //Blood else ObjSetMicro(dx,dy,393); } else ObjSetMicro(dx,dy,206); if (currlevel < HIVESTART) dSpecial[dx][dy] = 7; else dSpecial[dx][dy] = 1; ObjSetMicro12(dx-1,dy); --dy; object[oi]._oAnimFrame += 2; #ifdef NO_L5_DOORS if (currlevel > HIVESTART) object[oi]._oAnimFrame = -1; #endif object[oi]._oPreFlag = TRUE; DoorSet(oi, dx, dy); object[oi]._oVar4 = DOOR_OPEN; object[oi]._oSelFlag = OSEL_TOP; RedoPlayerVision(); } else { if (currlevel < CRYPTSTART) { if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); } else { if (!deltaload) PlaySfxLoc(CR_DOORCLOS, object[oi]._ox, object[oi]._oy); } dok = (dMonster[dx][dy] == 0); dok = dok && (dItem[dx][dy] == 0); dok = dok && (dDead[dx][dy] == 0); if (dok) { if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_CLOSEDOOR,oi); object[oi]._oVar4 = DOOR_CLOSED; object[oi]._oSelFlag = OSEL_ALL; ObjSetMicro(dx,dy,object[oi]._oVar1); if (currlevel < HIVESTART) { if (object[oi]._oVar2 != 50) ObjSetMicro(dx,dy-1,object[oi]._oVar2); else { // Double door if (dPiece[dx][dy-1] == 396) ObjSetMicro(dx,dy-1,412); else ObjSetMicro(dx,dy-1,object[oi]._oVar2); } } else { if (object[oi]._oVar2 != 86) ObjSetMicro(dx,dy-1,object[oi]._oVar2); else { // Double door if (dPiece[dx][dy-1] == 210) ObjSetMicro(dx,dy-1,234); else ObjSetMicro(dx,dy-1,object[oi]._oVar2); } } object[oi]._oAnimFrame -= 2; object[oi]._oPreFlag = FALSE; RedoPlayerVision(); } else object[oi]._oVar4 = DOOR_BLOCKED; } } /*-----------------------------------------------------------------------*/ // this is the stupidest fix I've ever seen an' I did it! JKE /*-----------------------------------------------------------------------*/ void OpenCloseAllDoors() { int i; BOOL odeltaload = deltaload; deltaload = TRUE; for (i = 0; i < MAXOBJECTS; ++i) { if (object[i]._otype == OBJ_L1DOORL) { OperateL1LDoor(myplr, i, FALSE); OperateL1LDoor(myplr, i, FALSE); } else if (object[i]._otype == OBJ_L1DOORR) { OperateL1RDoor(myplr, i, FALSE); OperateL1RDoor(myplr, i, FALSE); } } deltaload = odeltaload; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateL2RDoor(int pnum, int oi, bool sendflag) { int dx, dy; bool dok; app_assert((DWORD)oi < MAXOBJECTS); if (object[oi]._oVar4 == DOOR_BLOCKED) { if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); return; } dx = object[oi]._ox; dy = object[oi]._oy; if (object[oi]._oVar4 == DOOR_CLOSED) { if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_OPENDOOR,oi); if (!deltaload) PlaySfxLoc(IS_DOOROPEN, object[oi]._ox, object[oi]._oy); ObjSetMicro(dx,dy,17); object[oi]._oAnimFrame += 2; object[oi]._oPreFlag = TRUE; object[oi]._oVar4 = DOOR_OPEN; object[oi]._oSelFlag = OSEL_TOP; RedoPlayerVision(); } else { if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); dok = (dMonster[dx][dy] == 0); dok = dok && (dItem[dx][dy] == 0); dok = dok && (dDead[dx][dy] == 0); if (dok) { if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_CLOSEDOOR,oi); object[oi]._oVar4 = DOOR_CLOSED; object[oi]._oSelFlag = OSEL_ALL; ObjSetMicro(dx,dy,540); object[oi]._oAnimFrame -= 2; object[oi]._oPreFlag = FALSE; RedoPlayerVision(); } else object[oi]._oVar4 = DOOR_BLOCKED; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ const void OperateL2LDoor(int pnum, int oi, BOOL sendflag) { int dx, dy; bool dok; app_assert((DWORD)oi < MAXOBJECTS); if (object[oi]._oVar4 == DOOR_BLOCKED) { if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); return; } dx = object[oi]._ox; dy = object[oi]._oy; if (object[oi]._oVar4 == DOOR_CLOSED) { if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_OPENDOOR,oi); if (!deltaload) PlaySfxLoc(IS_DOOROPEN, object[oi]._ox, object[oi]._oy); ObjSetMicro(dx,dy,13); object[oi]._oAnimFrame += 2; object[oi]._oPreFlag = TRUE; object[oi]._oVar4 = DOOR_OPEN; object[oi]._oSelFlag = OSEL_TOP; RedoPlayerVision(); } else { if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); dok = (dMonster[dx][dy] == 0); dok = dok && (dItem[dx][dy] == 0); dok = dok && (dDead[dx][dy] == 0); if (dok) { if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_CLOSEDOOR,oi); object[oi]._oVar4 = DOOR_CLOSED; object[oi]._oSelFlag = OSEL_ALL; ObjSetMicro(dx,dy,538); object[oi]._oAnimFrame -= 2; object[oi]._oPreFlag = FALSE; RedoPlayerVision(); } else object[oi]._oVar4 = DOOR_BLOCKED; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateL3RDoor(int pnum, int oi, bool sendflag) { int dx, dy; bool dok; app_assert((DWORD)oi < MAXOBJECTS); if (object[oi]._oVar4 == DOOR_BLOCKED) { if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); return; } dx = object[oi]._ox; dy = object[oi]._oy; if (object[oi]._oVar4 == DOOR_CLOSED) { if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_OPENDOOR,oi); if (!deltaload) PlaySfxLoc(IS_DOOROPEN, object[oi]._ox, object[oi]._oy); ObjSetMicro(dx,dy,541); object[oi]._oAnimFrame += 2; object[oi]._oPreFlag = TRUE; object[oi]._oVar4 = DOOR_OPEN; object[oi]._oSelFlag = OSEL_TOP; RedoPlayerVision(); } else { if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); dok = (dMonster[dx][dy] == 0); dok = dok && (dItem[dx][dy] == 0); dok = dok && (dDead[dx][dy] == 0); if (dok) { if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_CLOSEDOOR,oi); object[oi]._oVar4 = DOOR_CLOSED; object[oi]._oSelFlag = OSEL_ALL; ObjSetMicro(dx,dy,534); object[oi]._oAnimFrame -= 2; object[oi]._oPreFlag = FALSE; RedoPlayerVision(); } else object[oi]._oVar4 = DOOR_BLOCKED; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateL3LDoor(int pnum, int oi, bool sendflag) { int dx, dy; bool dok; app_assert((DWORD)oi < MAXOBJECTS); if (object[oi]._oVar4 == DOOR_BLOCKED) { if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); return; } dx = object[oi]._ox; dy = object[oi]._oy; if (object[oi]._oVar4 == DOOR_CLOSED) { if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_OPENDOOR,oi); if (!deltaload) PlaySfxLoc(IS_DOOROPEN, object[oi]._ox, object[oi]._oy); ObjSetMicro(dx,dy,538); object[oi]._oAnimFrame += 2; object[oi]._oPreFlag = TRUE; object[oi]._oVar4 = DOOR_OPEN; object[oi]._oSelFlag = OSEL_TOP; RedoPlayerVision(); } else { if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); dok = (dMonster[dx][dy] == 0); dok = dok && (dItem[dx][dy] == 0); dok = dok && (dDead[dx][dy] == 0); if (dok) { if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_CLOSEDOOR,oi); object[oi]._oVar4 = DOOR_CLOSED; object[oi]._oSelFlag = OSEL_ALL; ObjSetMicro(dx,dy,531); object[oi]._oAnimFrame -= 2; object[oi]._oPreFlag = FALSE; RedoPlayerVision(); } else object[oi]._oVar4 = DOOR_BLOCKED; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void MonstCheckDoors(int m) { int i, oi, dpx, dpy; int mx, my; mx = monster[m]._mx; my = monster[m]._my; if (!(dObject[mx-1][my-1] || dObject[mx][my-1] || dObject[mx+1][my-1] || dObject[mx-1][my] || dObject[mx+1][my] || dObject[mx-1][my+1] || dObject[mx][my+1] || dObject[mx+1][my+1])) return; for (i = 0; i < numobjects; ++i) { oi = objectactive[i]; app_assert((DWORD)oi < MAXOBJECTS); if ((object[oi]._otype == OBJ_L1DOORL) || (object[oi]._otype == OBJ_L1DOORR)) { if (object[oi]._oVar4 == DOOR_CLOSED) { dpx = abs(object[oi]._ox - mx); dpy = abs(object[oi]._oy - my); if ((dpx == 1) && (dpy <= 1) && (object[oi]._otype == OBJ_L1DOORL)) OperateL1LDoor(myplr, oi, true); if ((dpx <= 1) && (dpy == 1) && (object[oi]._otype == OBJ_L1DOORR)) OperateL1RDoor(myplr, oi, true); } } if ((object[oi]._otype == OBJ_L2DOORL) || (object[oi]._otype == OBJ_L2DOORR)) { if (object[oi]._oVar4 == DOOR_CLOSED) { dpx = abs(object[oi]._ox - mx); dpy = abs(object[oi]._oy - my); if ((dpx == 1) && (dpy <= 1) && (object[oi]._otype == OBJ_L2DOORL)) OperateL2LDoor(myplr, oi, true); if ((dpx <= 1) && (dpy == 1) && (object[oi]._otype == OBJ_L2DOORR)) OperateL2RDoor(myplr, oi, true); } } if ((object[oi]._otype == OBJ_L3DOORL) || (object[oi]._otype == OBJ_L3DOORR)) { if (object[oi]._oVar4 == DOOR_CLOSED) { dpx = abs(object[oi]._ox - mx); dpy = abs(object[oi]._oy - my); if ((dpx == 1) && (dpy <= 1) && (object[oi]._otype == OBJ_L3DOORR)) OperateL3RDoor(myplr, oi, true); if ((dpx <= 1) && (dpy == 1) && (object[oi]._otype == OBJ_L3DOORL)) OperateL3LDoor(myplr, oi, true); } } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void ObjChangeMap(int x1, int y1, int x2, int y2) { int i,j; for (j = y1; j <= y2; ++j) { for (i = x1; i <= x2; ++i) { ObjSetMini(i, j, pdungeon[i][j]); dungeon[i][j] = pdungeon[i][j]; // For automap } } if ((leveltype == 1)&&(currlevel < HIVESTART)) { // JKE ObjL1Special((x1 << 1) + DIRTEDGED2, (y1 << 1) + DIRTEDGED2, (x2 << 1) + DIRTEDGED2 + 1, (y2 << 1) + DIRTEDGED2 + 1); AddL1Objs((x1 << 1) + DIRTEDGED2, (y1 << 1) + DIRTEDGED2, (x2 << 1) + DIRTEDGED2 + 1, (y2 << 1) + DIRTEDGED2 + 1); } if (leveltype == 2) { ObjL2Special((x1 << 1) + DIRTEDGED2, (y1 << 1) + DIRTEDGED2, (x2 << 1) + DIRTEDGED2 + 1, (y2 << 1) + DIRTEDGED2 + 1); AddL2Objs((x1 << 1) + DIRTEDGED2, (y1 << 1) + DIRTEDGED2, (x2 << 1) + DIRTEDGED2 + 1, (y2 << 1) + DIRTEDGED2 + 1); } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void ObjChangeMapResync(int x1, int y1, int x2, int y2) { int i,j; for (j = y1; j <= y2; ++j) { for (i = x1; i <= x2; ++i) { ObjSetMini(i, j, pdungeon[i][j]); dungeon[i][j] = pdungeon[i][j]; // For automap } } if ((leveltype == 1)&&(currlevel < HIVESTART)) ObjL1Special((x1 << 1) + DIRTEDGED2, (y1 << 1) + DIRTEDGED2, (x2 << 1) + DIRTEDGED2 + 1, (y2 << 1) + DIRTEDGED2 + 1); if (leveltype == 2) ObjL2Special((x1 << 1) + DIRTEDGED2, (y1 << 1) + DIRTEDGED2, (x2 << 1) + DIRTEDGED2 + 1, (y2 << 1) + DIRTEDGED2 + 1); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateL1Door(int pnum, int i, bool sendflag) { int dpx, dpy; app_assert((DWORD)i < MAXOBJECTS); dpx = abs(object[i]._ox - plr[pnum]._px); dpy = abs(object[i]._oy - plr[pnum]._py); if ((dpx == 1) && (dpy <= 1) && (object[i]._otype == OBJ_L1DOORL)) OperateL1LDoor(pnum, i, sendflag); if ((dpx <= 1) && (dpy == 1) && (object[i]._otype == OBJ_L1DOORR)) OperateL1RDoor(pnum, i, sendflag); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateLever(int pnum, int i) { bool mapflag; int j, oi, ot; app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oSelFlag == OSEL_NONE) return; if (!deltaload) PlaySfxLoc(IS_LEVER, object[i]._ox, object[i]._oy); // Toggle to on object[i]._oSelFlag = OSEL_NONE; ++object[i]._oAnimFrame; mapflag = true; if (currlevel == DIABLO_LEVEL) { for (j = 0; j < numobjects; ++j) { oi = objectactive[j]; ot = object[oi]._otype; if (ot == OBJ_SWITCHSKL) { if ((object[i]._oVar8 == object[oi]._oVar8) && (object[oi]._oSelFlag != OSEL_NONE)) mapflag = FALSE; } } } if (currlevel == NA_KRUL_LEVEL) { // dPiece[Na_Krul.LeverX][Na_Krul.LeverY] = 316; OpenNaKrul(); Na_Krul.Lever_Thrown = TRUE; mapflag = FALSE; quests[Q_NA_KRUL]._qactive = QUEST_DONE; } if (mapflag) ObjChangeMap(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateBook(int pnum, int i) { int v1, v2, v3; int j, oi, ot, itm; app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oSelFlag == OSEL_NONE) return; if ((setlevel) && (setlvlnum == SL_VILEBETRAYER)) { bool found = false; bool dowarp = false; for (j = 0; j < numobjects; ++j) { oi = objectactive[j]; ot = object[oi]._otype; if ((ot == OBJ_MCIRCLE2) && (object[oi]._oVar6 == OBJWARP1)) { v1 = 27; v2 = 29; // rmw.patch1.start.1/23/97 // object[oi]._oVar6 == OBJDONEWARP; object[oi]._oVar6 = OBJDONEWARP; // rmw.patch1.end.1/23/97 dowarp = TRUE; } if ((ot == OBJ_MCIRCLE2) && (object[oi]._oVar6 == OBJWARP2)) { v1 = 43; v2 = 29; // rmw.patch1.start.1/23/97 // object[oi]._oVar6 == OBJDONEWARP; object[oi]._oVar6 = OBJDONEWARP; // rmw.patch1.end.1/23/97 dowarp = TRUE; } if (dowarp) { v3 = dPiece[v1][v2]; ++object[dObject[35][36]-1]._oVar5; AddMissile(plr[pnum]._px, plr[pnum]._py, v1, v2, plr[pnum]._pdir, MIT_PHASE, MI_ENEMYMONST, pnum, 0, 0); found = TRUE; dowarp = FALSE; } } if (!found) return; } // Toggle open object[i]._oSelFlag = OSEL_NONE; ++object[i]._oAnimFrame; if ((setlevel) && (setlvlnum == SL_BONECHAMB)) { __int64 t = 1; plr[myplr]._pMemSpells |= t << (SPL_GUARDIAN-1); if (plr[pnum]._pSplLvl[SPL_GUARDIAN] < SPELLCAP) { ++plr[myplr]._pSplLvl[SPL_GUARDIAN]; } quests[Q_SCHAMB]._qactive = QUEST_DONE; if (!deltaload) PlaySfxLoc(IS_QUESTDN, object[i]._ox, object[i]._oy); InitDiabloMsg(MSG_INBONE); AddMissile(plr[myplr]._px, plr[myplr]._py, object[i]._ox - 2, object[i]._oy - 4, plr[myplr]._pdir, MIT_GUARDIAN, MI_ENEMYMONST, myplr, 0, 0); } if ((setlevel) && (setlvlnum == SL_VILEBETRAYER)) { ObjChangeMapResync(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); for (itm = 0; itm < numobjects; ++itm) SyncObjectAnim(objectactive[itm]); } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateBookLever(int pnum, int i) { int x,y, tren; app_assert(gbMaxPlayers == 1); x = (setpc_x << 1) + DIRTEDGED2; y = (setpc_y << 1) + DIRTEDGED2; app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oSelFlag == OSEL_NONE) return; if (qtextflag) return; // Check quests if ((object[i]._otype == OBJ_BLINDBOOK) && (quests[Q_BLIND]._qvar1 == 0)) { quests[Q_BLIND]._qactive = QUEST_NOTDONE; quests[Q_BLIND]._qlog = TRUE; quests[Q_BLIND]._qvar1 = 1; } if ((object[i]._otype == OBJ_BLOODBOOK) && (quests[Q_BLOOD]._qvar1 == 0)) { quests[Q_BLOOD]._qactive = QUEST_NOTDONE; quests[Q_BLOOD]._qlog = TRUE; quests[Q_BLOOD]._qvar1 = 1; SpawnQuestItem(IDI_BLDSTONE, (setpc_x << 1) + 3 + DIRTEDGED2, (setpc_y << 1) + 10 + DIRTEDGED2, FALSE, ISEL_FLR); SpawnQuestItem(IDI_BLDSTONE, (setpc_x << 1) + 15 + DIRTEDGED2, (setpc_y << 1) + 10 + DIRTEDGED2, FALSE, ISEL_FLR); SpawnQuestItem(IDI_BLDSTONE, (setpc_x << 1) + 9 + DIRTEDGED2, (setpc_y << 1) + 17 + DIRTEDGED2, FALSE, ISEL_FLR); } if ((object[i]._otype == OBJ_STEELTOME) && (quests[Q_WARLORD]._qvar1 == 0)) { quests[Q_WARLORD]._qactive = QUEST_NOTDONE; quests[Q_WARLORD]._qlog = TRUE; quests[Q_WARLORD]._qvar1 = 1; } // Change map if (object[i]._oAnimFrame != object[i]._oVar6) { if (object[i]._otype != OBJ_BLOODBOOK) ObjChangeMap(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); if (object[i]._otype == OBJ_BLINDBOOK) { CreateItem(UID_OPTAMULET, x+5, y+5); tren = TransVal; TransVal = 9; DRLG_MRectTrans(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); TransVal = tren; } } // Toggle open // object[i]._oSelFlag = OSEL_NONE; object[i]._oAnimFrame = object[i]._oVar6; // Display msg InitQTextMsg(object[i]._oVar7); if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateSChambBk(int pnum, int i) { int textdef,j; app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oSelFlag == OSEL_NONE) return; if (qtextflag) return; // object[i]._oSelFlag = OSEL_NONE; // Change map if (object[i]._oAnimFrame != object[i]._oVar6) { ObjChangeMapResync(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); for (j = 0; j < numobjects; ++j) SyncObjectAnim(objectactive[j]); } // Toggle open object[i]._oAnimFrame = object[i]._oVar6; if (quests[Q_SCHAMB]._qactive == QUEST_NOTACTIVE) { quests[Q_SCHAMB]._qactive = QUEST_NOTDONE; quests[Q_SCHAMB]._qlog = TRUE; } if (plr[myplr]._pClass == CLASS_WARRIOR) textdef = TXT_WARBONE; else if (plr[myplr]._pClass == CLASS_ROGUE) textdef = TXT_ROGBONE; else if (plr[myplr]._pClass == CLASS_SORCEROR) textdef = TXT_SORBONE; else if (plr[myplr]._pClass == CLASS_MONK) textdef = TXT_MNKBONE; else if (plr[myplr]._pClass == CLASS_BARD) textdef = TXT_BRDBONE; else if (plr[myplr]._pClass == CLASS_BARBARIAN) textdef = TXT_BARBONE; quests[Q_SCHAMB]._qmsg = textdef; InitQTextMsg(textdef); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateChest(int pnum, int i, bool sendmsg) { int j, mdir, mtype = MIT_ARROW; app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oSelFlag == OSEL_NONE) return; if (!deltaload) PlaySfxLoc(IS_CHEST, object[i]._ox, object[i]._oy); object[i]._oSelFlag = OSEL_NONE; object[i]._oAnimFrame += 2; if (deltaload) return; SetRndSeed(object[i]._oRndSeed); if (setlevel) { //Create only good items for set levels for (j = 0; j < object[i]._oVar1; ++j) { CreateRndItem(object[i]._ox, object[i]._oy, TRUE, sendmsg, FALSE); } } else { for (j = 0; j < object[i]._oVar1; ++j) { if (object[i]._oVar2) CreateRndItem(object[i]._ox, object[i]._oy, FALSE, sendmsg, FALSE); else CreateRndUseful(pnum, object[i]._ox, object[i]._oy, sendmsg); } } if ((object[i]._oTrapFlag) && (object[i]._otype >= OBJ_TCHEST1) && (object[i]._otype <= OBJ_TCHEST3)) { mdir = GetDirection(object[i]._ox, object[i]._oy, plr[pnum]._px, plr[pnum]._py); switch(object[i]._oVar4) { case 0: mtype = MIT_ARROW; break; case 1: mtype = MIT_FARROW; break; case 2: mtype = MIT_NOVA; break; case 3: mtype = MIT_FLAMEBOX; // SpawnSkeleton(object[i]._oVar2, object[i]._ox, object[i]._oy); break; case 4: mtype = MIT_DISENCHANT; break; case 5: mtype = MIT_MANAREMOVE; break; #if defined(HELLFIRE2) // GWP Another good trap might be acid splatted all around. case 6: mtype = MIT_LIGHTBOX; // SpawnSkeleton(object[i]._oVar2, object[i]._ox, object[i]._oy); break; #endif default: mtype = MIT_ARROW; break; } AddMissile(object[i]._ox, object[i]._oy, plr[pnum]._px, plr[pnum]._py, mdir, mtype, MI_ENEMYPLR, -1, 0, 0); object[i]._oTrapFlag = FALSE; } if (pnum == myplr) NetSendCmdParam2(FALSE,CMD_PLROPOBJ,pnum,i); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateMushPatch(int pnum, int i) { int x, y; if (!(quests[Q_BKMUSHRM]._qactive == QUEST_NOTDONE && (quests[Q_BKMUSHRM]._qvar1 >= QS_TOMEGIVEN))) // FUNGALTM was given to Witch { if (!deltaload && pnum == myplr) { if (plr[myplr]._pClass == CLASS_WARRIOR) PlaySFX(PS_WARR13); #if !IS_VERSION(SHAREWARE) else if (plr[myplr]._pClass == CLASS_ROGUE) PlaySFX(PS_ROGUE13); else if (plr[myplr]._pClass == CLASS_SORCEROR) PlaySFX(PS_MAGE13); else if (plr[myplr]._pClass == CLASS_MONK) PlaySFX(PS_MONK13); else if (plr[myplr]._pClass == CLASS_BARD) PlaySFX(PS_BARD13); else if (plr[myplr]._pClass == CLASS_BARBARIAN) PlaySFX(PS_BARBARIAN13); #endif } return; } app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oSelFlag == OSEL_NONE) return; if (!deltaload) PlaySfxLoc(IS_CHEST, object[i]._ox, object[i]._oy); object[i]._oSelFlag = OSEL_NONE; object[i]._oAnimFrame += 1; if (deltaload) return; GetSuperItemLoc(object[i]._ox, object[i]._oy, x, y); SpawnQuestItem(IDI_MUSHROOM, x,y,0, ISEL_NONE); quests[Q_BKMUSHRM]._qvar1 = QS_MUSHSPAWNED; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateInnSignChest(int pnum, int i) { int x, y; if (!(quests[Q_LTBANNER]._qvar1 == 2)) { if (!deltaload && pnum == myplr) { if (plr[myplr]._pClass == CLASS_WARRIOR) PlaySFX(PS_WARR24); #if !IS_VERSION(SHAREWARE) else if (plr[myplr]._pClass == CLASS_ROGUE) PlaySFX(PS_ROGUE24); else if (plr[myplr]._pClass == CLASS_SORCEROR) PlaySFX(PS_MAGE24); else if (plr[myplr]._pClass == CLASS_MONK) PlaySFX(PS_MONK24); else if (plr[myplr]._pClass == CLASS_BARD) PlaySFX(PS_BARD24); else if (plr[myplr]._pClass == CLASS_BARBARIAN) PlaySFX(PS_BARBARIAN24); #endif } return; } if (object[i]._oSelFlag == OSEL_NONE) return; if (!deltaload) PlaySfxLoc(IS_CHEST, object[i]._ox, object[i]._oy); object[i]._oSelFlag = OSEL_NONE; object[i]._oAnimFrame += 2; if (deltaload) return; GetSuperItemLoc(object[i]._ox, object[i]._oy, x, y); SpawnQuestItem(IDI_BANNER, x,y,0, ISEL_NONE); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateSlainHero(int pnum, int i, bool sendmsg) { app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oSelFlag == OSEL_NONE) return; object[i]._oSelFlag = OSEL_NONE; if (deltaload) return; if (plr[pnum]._pClass == CLASS_WARRIOR) { //Create magic breast plate CreateMagicArmor(object[i]._ox, object[i]._oy, IT_HARMOR, ITEM_BPLATE, FALSE, TRUE); #if !IS_VERSION(SHAREWARE) PlaySfxLoc(PS_WARR9, plr[myplr]._px, plr[myplr]._py); #endif } else if (plr[pnum]._pClass == CLASS_ROGUE) { //Create magic long battle bow CreateMagicWeapon(object[i]._ox, object[i]._oy, IT_BOW, ITEM_STLLONGBOW, FALSE, TRUE); #if !IS_VERSION(SHAREWARE) PlaySfxLoc(PS_ROGUE9, plr[myplr]._px, plr[myplr]._py); #endif } else if (plr[pnum]._pClass == CLASS_SORCEROR) { //Create book of lightning CreateSpellBook(object[i]._ox, object[i]._oy, SPL_LIGHTNING, FALSE, TRUE); #if !IS_VERSION(SHAREWARE) PlaySfxLoc(PS_MAGE9, plr[myplr]._px, plr[myplr]._py); #endif } else if (plr[pnum]._pClass == CLASS_MONK) { //Create magic staff CreateMagicWeapon(object[i]._ox, object[i]._oy, IT_STAFF, ITEM_STLSTAFF, FALSE, TRUE); #if !IS_VERSION(SHAREWARE) PlaySfxLoc(PS_MONK9, plr[myplr]._px, plr[myplr]._py); #endif } else if (plr[pnum]._pClass == CLASS_BARD) { //Create special sword. CreateMagicWeapon(object[i]._ox, object[i]._oy, IT_SWORD, ITEM_BASTSRD, FALSE, TRUE); #if !IS_VERSION(SHAREWARE) PlaySfxLoc(PS_BARD9, plr[myplr]._px, plr[myplr]._py); #endif } else if (plr[pnum]._pClass == CLASS_BARBARIAN) { //Create special sword. CreateMagicWeapon(object[i]._ox, object[i]._oy, IT_AXE, ITEM_BTLAXE, FALSE, TRUE); #if !IS_VERSION(SHAREWARE) PlaySfxLoc(PS_BARBARIAN9, plr[myplr]._px, plr[myplr]._py); #endif } if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateTrapLvr(int i) { int j, oi; app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oAnimFrame == 1) { // Toggle to on ++object[i]._oAnimFrame; for (j = 0; j < numobjects; ++j) { oi = objectactive[j]; if ((object[oi]._otype == object[i]._oVar2) && (object[oi]._oVar1 == object[i]._oVar1)) { object[oi]._oVar2 = 1; object[oi]._oAnimFlag = FALSE; } } } else { // Toggle to off --object[i]._oAnimFrame; for (j = 0; j < numobjects; ++j) { oi = objectactive[j]; if ((object[oi]._otype == object[i]._oVar2) && (object[oi]._oVar1 == object[i]._oVar1)) { object[oi]._oVar2 = 0; if (object[oi]._oVar4 != 0) object[oi]._oAnimFlag = TRUE; } } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateSarc(int pnum, int i, bool sendmsg) { app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oSelFlag == OSEL_NONE) return; if (!deltaload) PlaySfxLoc(IS_SARC, object[i]._ox, object[i]._oy); object[i]._oSelFlag = OSEL_NONE; if (deltaload) { object[i]._oAnimFrame = object[i]._oAnimLen; return; } else { object[i]._oAnimFlag = TRUE; object[i]._oAnimDelay = 3; } SetRndSeed(object[i]._oRndSeed); if (object[i]._oVar1 <= 2) CreateRndItem(object[i]._ox, object[i]._oy, FALSE, sendmsg, FALSE); if (object[i]._oVar1 >= 8) SpawnSkeleton(object[i]._oVar2, object[i]._ox, object[i]._oy); #if CHEATS if (itemcheat) CreateMagicWeapon(object[i]._ox, object[i]._oy, IT_STAFF, ITEM_SHRTSTAFF, FALSE, TRUE); #endif if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateL2Door(int pnum, int i, bool sendflag) { int dpx, dpy; app_assert((DWORD)i < MAXOBJECTS); dpx = abs(object[i]._ox - plr[pnum]._px); dpy = abs(object[i]._oy - plr[pnum]._py); if ((dpx == 1) && (dpy <= 1) && (object[i]._otype == OBJ_L2DOORL)) OperateL2LDoor(pnum, i, sendflag); if ((dpx <= 1) && (dpy == 1) && (object[i]._otype == OBJ_L2DOORR)) OperateL2RDoor(pnum, i, sendflag); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateL3Door(int pnum, int i, bool sendflag) { int dpx, dpy; app_assert((DWORD)i < MAXOBJECTS); dpx = abs(object[i]._ox - plr[pnum]._px); dpy = abs(object[i]._oy - plr[pnum]._py); if ((dpx == 1) && (dpy <= 1) && (object[i]._otype == OBJ_L3DOORR)) OperateL3RDoor(pnum, i, sendflag); if ((dpx <= 1) && (dpy == 1) && (object[i]._otype == OBJ_L3DOORL)) OperateL3LDoor(pnum, i, sendflag); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperatePedistal(int pnum, int i) { int jstn; app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oVar6 != 3) { if (PlrHasItem(pnum, IDI_BLDSTONE, jstn)) { RemoveInvItem(pnum, jstn); ++object[i]._oAnimFrame; ++object[i]._oVar6; } if (object[i]._oVar6 == 1) { if (!deltaload) PlaySfxLoc(LS_PUDDLE, object[i]._ox, object[i]._oy); ObjChangeMap(setpc_x, setpc_y + 3, setpc_x + 2, setpc_y + 7); } if (object[i]._oVar6 == 2) { if (!deltaload) PlaySfxLoc(LS_PUDDLE, object[i]._ox, object[i]._oy); ObjChangeMap(setpc_x + 6, setpc_y + 3, setpc_x + setpc_w, setpc_y + 7); } if (object[i]._oVar6 == 3) { if (!deltaload) PlaySfxLoc(LS_BLODSTAR, object[i]._ox, object[i]._oy); ObjChangeMap(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); byte *setp; setp = LoadFileInMemSig("Levels\\L2Data\\Blood2.DUN", NULL, 'STPC'); LoadMapObjs(setp, (setpc_x << 1), (setpc_y << 1)); DiabloFreePtr(setp); CreateItem(UID_ARMOFVAL, (setpc_x << 1) + 9 + DIRTEDGED2, (setpc_y << 1) + 3 + DIRTEDGED2); object[i]._oSelFlag = OSEL_NONE; } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void TryDisarm(int pnum, int i) { int j, oi, oti; int trapdisper; bool checkflag; if (pnum == myplr) NewCursor(GLOVE_CURS); app_assert((DWORD)i < MAXOBJECTS); if (!object[i]._oTrapFlag) return; trapdisper = (plr[pnum]._pDexterity << 1) - (currlevel * 5); if (random(154,100) > trapdisper) return; for (j = 0; j < numobjects; ++j) { oi = objectactive[j]; checkflag = false; if (object[oi]._otype == OBJ_TRAPL) checkflag = true; if (object[oi]._otype == OBJ_TRAPR) checkflag = true; if (checkflag) { oti = dObject[object[oi]._oVar1][object[oi]._oVar2] - 1; if (oti == i) { object[oi]._oVar4 = 1; object[i]._oTrapFlag = FALSE; } } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ int ItemMiscIdIdx(int imiscid) { int i = 0; while ((AllItemsList[i].iRnd == IRND_NO) || (AllItemsList[i].iMiscId != imiscid)) ++i; return(i); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateShrine(int pnum, int i, int sType) { int r, xx, yy, idata, sc; int v1, v2, v3, v4; __int64 lv, t; bool done; //Fixes any gold cheats if (dropGoldFlag) { dropGoldFlag = FALSE; dropGoldValue = 0; } app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oSelFlag == OSEL_NONE) return; SetRndSeed(object[i]._oRndSeed); object[i]._oSelFlag = OSEL_NONE; if (! deltaload) { PlaySfxLoc(sType, object[i]._ox, object[i]._oy); object[i]._oAnimFlag = TRUE; object[i]._oAnimDelay = 1; } else { object[i]._oAnimFrame = object[i]._oAnimLen; object[i]._oAnimFlag = FALSE; } switch (object[i]._oVar1) { case 0 : // Mysterious if (deltaload) return; if (pnum != myplr) return; //Subtract 1 from all attributes ModifyPlrStr(pnum, -1); ModifyPlrMag(pnum, -1); ModifyPlrDex(pnum, -1); ModifyPlrVit(pnum, -1); //Add 6 to random attribute. We are actually adding 5 since we //subtracted 1 above. switch(random(0, 4)) { case 0: ModifyPlrStr(pnum, 6); break; case 1: ModifyPlrMag(pnum, 6); break; case 2: ModifyPlrDex(pnum, 6); break; case 3: ModifyPlrVit(pnum, 6); break; } CheckStats(pnum); InitDiabloMsg(SHRINE_1); break; case 1 : // Hidden v1 = 0; if (deltaload) return; if (pnum != myplr) return; //Find out if player has any items equipped for (r = 0; r < NUM_INVLOC; ++r) { if (plr[pnum].InvBody[r]._itype != -1) ++v1; } //Add 10 to max and current durability of all equipped items. if (v1 > 0) { for (r = 0; r < NUM_INVLOC; ++r) { if (plr[pnum].InvBody[r]._itype != -1) { //Ignore any items which are indestructible. if ((plr[pnum].InvBody[r]._iMaxDur != INFINITE_DUR) && (plr[pnum].InvBody[r]._iMaxDur != 0)) { plr[pnum].InvBody[r]._iDurability += 10; plr[pnum].InvBody[r]._iMaxDur += 10; if (plr[pnum].InvBody[r]._iDurability > plr[pnum].InvBody[r]._iMaxDur) plr[pnum].InvBody[r]._iDurability = plr[pnum].InvBody[r]._iMaxDur; } } } done = false; while (!done) { // JMM.PATCH3 int numitems = 0; for( r = 0; r < NUM_INVLOC; ++r ) { if ( plr[pnum].InvBody[r]._itype != -1 ) ++numitems; } if( !numitems ) { done = true; break; } // JMM.ENDPATCH3 r = random(0, NUM_INVLOC); if (plr[pnum].InvBody[r]._itype != -1) { //Ignore any items which are indestructible. if ((plr[pnum].InvBody[r]._iMaxDur != INFINITE_DUR) && (plr[pnum].InvBody[r]._iMaxDur != 0)) { //Subtract 20 from random equipped item. We are actually //subtracting 10 since we added 10 above. plr[pnum].InvBody[r]._iDurability -= 20; plr[pnum].InvBody[r]._iMaxDur -= 20; if (plr[pnum].InvBody[r]._iDurability <= 0) plr[pnum].InvBody[r]._iDurability = 1; if (plr[pnum].InvBody[r]._iMaxDur <= 0) plr[pnum].InvBody[r]._iMaxDur = 1; done = true; break; } } } } InitDiabloMsg(SHRINE_2); break; case 2: // Gloomy (Single Player Only) if (deltaload) return; if (pnum == myplr) { if (plr[pnum].HeadItem._itype != -1) plr[pnum].HeadItem._iAC += 2; if (plr[pnum].BodyItem._itype != -1) plr[pnum].BodyItem._iAC += 2; if (plr[pnum].Hand1Item._itype != -1) { if (plr[pnum].Hand1Item._itype == IT_SHIELD) plr[pnum].Hand1Item._iAC += 2; else { --plr[pnum].Hand1Item._iMaxDam; if (plr[pnum].Hand1Item._iMaxDam < plr[pnum].Hand1Item._iMinDam) plr[pnum].Hand1Item._iMaxDam = plr[pnum].Hand1Item._iMinDam; } } if (plr[pnum].Hand2Item._itype != -1) { if (plr[pnum].Hand2Item._itype == IT_SHIELD) plr[pnum].Hand2Item._iAC += 2; else { --plr[pnum].Hand2Item._iMaxDam; if (plr[pnum].Hand2Item._iMaxDam < plr[pnum].Hand2Item._iMinDam) plr[pnum].Hand2Item._iMaxDam = plr[pnum].Hand2Item._iMinDam; } } for (r = 0; r < plr[pnum]._pNumInv; ++r) { switch(plr[pnum].InvList[r]._itype) { case IT_SHIELD: case IT_ARMOR: case IT_MARMOR: case IT_HARMOR: case IT_HELM: plr[pnum].InvList[r]._iAC += 2; break; case IT_SWORD: case IT_AXE: case IT_BOW: case IT_MACE: case IT_STAFF: --plr[pnum].InvList[r]._iMaxDam; if (plr[pnum].InvList[r]._iMaxDam < plr[pnum].InvList[r]._iMinDam) plr[pnum].InvList[r]._iMaxDam = plr[pnum].InvList[r]._iMinDam; break; } } InitDiabloMsg(SHRINE_3); } break; case 3: // Weird (Single Player Only) if (deltaload) return; if (pnum == myplr) { if ((plr[pnum].Hand1Item._itype != -1) && (plr[pnum].Hand1Item._itype != IT_SHIELD)) ++plr[pnum].Hand1Item._iMaxDam; if ((plr[pnum].Hand2Item._itype != -1) && (plr[pnum].Hand2Item._itype != IT_SHIELD)) ++plr[pnum].Hand2Item._iMaxDam; for (r = 0; r < plr[pnum]._pNumInv; ++r) { switch(plr[pnum].InvList[r]._itype) { case IT_SWORD: case IT_AXE: case IT_BOW: case IT_MACE: case IT_STAFF: ++plr[pnum].InvList[r]._iMaxDam; break; } } InitDiabloMsg(SHRINE_4); } break; case 4: // Magical case 11: // Supernatural if (deltaload) return; //Cast mana shield AddMissile(plr[pnum]._px, plr[pnum]._py, plr[pnum]._px, plr[pnum]._py, plr[pnum]._pdir, MIT_MANASHIELD, -1, pnum, 0, (leveltype << 1)); if (pnum != myplr) return; InitDiabloMsg(SHRINE_5); break; case 5: // Stone if (deltaload) return; if (pnum == myplr) { for (r = 0; r < NUM_INVLOC; ++r) { if (plr[pnum].InvBody[r]._itype == IT_STAFF) plr[pnum].InvBody[r]._iCharges = plr[pnum].InvBody[r]._iMaxCharges; } for (r = 0; r < plr[pnum]._pNumInv; ++r) { if (plr[pnum].InvList[r]._itype == IT_STAFF) plr[pnum].InvList[r]._iCharges = plr[pnum].InvList[r]._iMaxCharges; } for (r = 0; r < MAXSPD; ++r) { if (plr[pnum].SpdList[r]._itype == IT_STAFF) plr[pnum].SpdList[r]._iCharges = plr[pnum].SpdList[r]._iMaxCharges; } InitDiabloMsg(SHRINE_6); } break; case 6: // Religious if (deltaload) return; if (pnum == myplr) { for (r = 0; r < NUM_INVLOC; ++r) { plr[pnum].InvBody[r]._iDurability = plr[pnum].InvBody[r]._iMaxDur; } for (r = 0; r < plr[pnum]._pNumInv; ++r) { plr[pnum].InvList[r]._iDurability = plr[pnum].InvList[r]._iMaxDur; } for (r = 0; r < MAXSPD; ++r) { plr[pnum].SpdList[r]._iDurability = plr[pnum].SpdList[r]._iMaxDur; } InitDiabloMsg(SHRINE_7); } break; case 7: // Enchanted (Levels 1-8 Only) if (deltaload) return; if (pnum != myplr) return; //Get memorized spell count sc = 0; lv = 1; for (r = 1; r <= MAXSPELLS; ++r) { if (plr[pnum]._pMemSpells & lv) ++sc; lv = lv << 1; } //Only add and subtract if player has more than 1 spell memorized if (sc > 1) { //Add one to all memorized spell levels lv = 1; for (r = 1; r <= MAXSPELLS; ++r) { if (plr[pnum]._pMemSpells & lv) { if (plr[pnum]._pSplLvl[r] < SPELLCAP) { ++plr[pnum]._pSplLvl[r]; v1 = r; } } lv = lv << 1; } //Subtract 2 from random memorized spell. We are actually subtracting //1 since we added 1 above. done = false; while (!done) { lv = 1; r = random(0, MAXSPELLS); lv = lv << r; if (plr[pnum]._pMemSpells & lv) { if (plr[pnum]._pSplLvl[r+1] >= 2) plr[pnum]._pSplLvl[r+1] -= 2; else plr[pnum]._pSplLvl[r+1] = 0; done = true; break; } } } InitDiabloMsg(SHRINE_8); break; case 8: // Thaumaturgic (Single Player Only) //All chests regenerate for (r = 0; r < numobjects; ++r) { v1 = objectactive[r]; app_assert((DWORD)v1 < MAXOBJECTS); if (((object[v1]._otype == OBJ_CHEST1) || (object[v1]._otype == OBJ_CHEST2) || (object[v1]._otype == OBJ_CHEST3)) && (object[v1]._oSelFlag == OSEL_NONE)) { object[v1]._oRndSeed = GetRndSeed(); object[v1]._oSelFlag = OSEL_FLR; object[v1]._oAnimFrame -= 2; } } if (deltaload) return; if (pnum == myplr) InitDiabloMsg(SHRINE_9); break; case 9: // Fascinating if (deltaload) return; if (pnum != myplr) return; //Give player fire bolt level +2 t = 1; plr[pnum]._pMemSpells |= t << (SPL_FIREBOLT-1); if (plr[pnum]._pSplLvl[SPL_FIREBOLT] < SPELLCAP) ++plr[pnum]._pSplLvl[SPL_FIREBOLT] ; if (plr[pnum]._pSplLvl[SPL_FIREBOLT] < SPELLCAP) ++plr[pnum]._pSplLvl[SPL_FIREBOLT] ; //Subtract 1/10 of mana v1 = plr[pnum]._pMaxManaBase / 10; v2 = plr[pnum]._pMana - plr[pnum]._pManaBase; v3 = plr[pnum]._pMaxMana - plr[pnum]._pMaxManaBase; plr[pnum]._pManaBase -= v1; plr[pnum]._pMana -= v1; plr[pnum]._pMaxMana -= v1; plr[pnum]._pMaxManaBase -= v1; if ((plr[pnum]._pMana >> MANA_SHIFT) <= 0) { plr[pnum]._pMana = v2; plr[pnum]._pManaBase = 0; } if ((plr[pnum]._pMaxMana >> MANA_SHIFT) <= 0) { plr[pnum]._pMaxMana = v3; plr[pnum]._pMaxManaBase = 0; } InitDiabloMsg(SHRINE_10); break; case 10: // Cryptic if (deltaload) return; //Cast nova AddMissile(plr[pnum]._px, plr[pnum]._py, plr[pnum]._px, plr[pnum]._py, plr[pnum]._pdir, MIT_NOVA, -1, pnum, 0, (leveltype << 1)); if (pnum != myplr) return; //Give full mana plr[pnum]._pMana = plr[pnum]._pMaxMana; plr[pnum]._pManaBase = plr[pnum]._pMaxManaBase; InitDiabloMsg(SHRINE_11); break; case 12: // Eldritch if (deltaload) return; if (pnum == myplr) { //All health and mana potions become full rejuv. for (r = 0; r < plr[pnum]._pNumInv; ++r) { if (plr[pnum].InvList[r]._itype == IT_MISC) { if ((plr[pnum].InvList[r]._iMiscId == IMID_PLHEAL) || (plr[pnum].InvList[r]._iMiscId == IMID_PMANA)) { idata = ItemMiscIdIdx(IMID_REJUV); SetPlrHandItem(&plr[pnum].HoldItem, idata); GetPlrHandSeed(&plr[pnum].HoldItem); plr[pnum].HoldItem._iStatFlag = TRUE; plr[pnum].InvList[r] = plr[pnum].HoldItem; } if ((plr[pnum].InvList[r]._iMiscId == IMID_PHEAL) || (plr[pnum].InvList[r]._iMiscId == IMID_PFMANA)) { idata = ItemMiscIdIdx(IMID_FREJUV); SetPlrHandItem(&plr[pnum].HoldItem, idata); GetPlrHandSeed(&plr[pnum].HoldItem); plr[pnum].HoldItem._iStatFlag = TRUE; plr[pnum].InvList[r] = plr[pnum].HoldItem; } } } for (r = 0; r < MAXSPD; ++r) { if (plr[pnum].SpdList[r]._itype == IT_MISC) { if ((plr[pnum].SpdList[r]._iMiscId == IMID_PLHEAL) || (plr[pnum].SpdList[r]._iMiscId == IMID_PMANA)) { idata = ItemMiscIdIdx(IMID_REJUV); SetPlrHandItem(&plr[pnum].HoldItem, idata); GetPlrHandSeed(&plr[pnum].HoldItem); plr[pnum].HoldItem._iStatFlag = TRUE; plr[pnum].SpdList[r] = plr[pnum].HoldItem; } if ((plr[pnum].SpdList[r]._iMiscId == IMID_PHEAL) || (plr[pnum].SpdList[r]._iMiscId == IMID_PFMANA)) { idata = ItemMiscIdIdx(IMID_FREJUV); SetPlrHandItem(&plr[pnum].HoldItem, idata); GetPlrHandSeed(&plr[pnum].HoldItem); plr[pnum].HoldItem._iStatFlag = TRUE; plr[pnum].SpdList[r] = plr[pnum].HoldItem; } } } InitDiabloMsg(SHRINE_13); } break; case 13: // Eerie if (deltaload) return; if (pnum != myplr) return; //Add 2 to magic ModifyPlrMag(pnum, 2); CheckStats(pnum); InitDiabloMsg(SHRINE_14); break; case 14: // Divine if (deltaload) return; if (pnum != myplr) return; //Put this in because full rejuvs are only available from level 7 on. if ((currlevel << 1) < 7) { //Create 1 full heal and 1 full mana CreateTypeItem(object[i]._ox, object[i]._oy, FALSE, IT_MISC, IMID_PFMANA, FALSE, TRUE); CreateTypeItem(object[i]._ox, object[i]._oy, FALSE, IT_MISC, IMID_PHEAL, FALSE, TRUE); } else { //Create 2 full rejuv CreateTypeItem(object[i]._ox, object[i]._oy, FALSE, IT_MISC, IMID_FREJUV, FALSE, TRUE); CreateTypeItem(object[i]._ox, object[i]._oy, FALSE, IT_MISC, IMID_FREJUV, FALSE, TRUE); } //Give full mana and life plr[pnum]._pMana = plr[pnum]._pMaxMana; plr[pnum]._pManaBase = plr[pnum]._pMaxManaBase; plr[pnum]._pHitPoints = plr[pnum]._pMaxHP; plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase; InitDiabloMsg(SHRINE_15); break; case 15: // Holy if (deltaload) return; v4 = 0; do { v1 = random(159,DMAXX); v2 = random(159,DMAXY); v3 = dPiece[v1][v2]; ++v4; if (v4 > (DMAXX*DMAXY)) break; } while (nSolidTable[v3] != 0 || dObject[v1][v2] != 0 || dMonster[v1][v2] != 0); //Cast phase AddMissile(plr[pnum]._px, plr[pnum]._py, v1, v2, plr[pnum]._pdir, MIT_PHASE, -1, pnum, 0, (leveltype << 1)); if (pnum != myplr) return; InitDiabloMsg(SHRINE_16); break; case 16: // Sacred if (deltaload) return; if (pnum != myplr) return; //Give player charged bolt level +2 t = 1; plr[pnum]._pMemSpells |= t << (SPL_CBOLT-1); if (plr[pnum]._pSplLvl[SPL_CBOLT] < SPELLCAP) ++plr[pnum]._pSplLvl[SPL_CBOLT] ; if (plr[pnum]._pSplLvl[SPL_CBOLT] < SPELLCAP) ++plr[pnum]._pSplLvl[SPL_CBOLT] ; //Subtract 1/10 of mana v1 = plr[pnum]._pMaxManaBase / 10; v2 = plr[pnum]._pMana - plr[pnum]._pManaBase; v3 = plr[pnum]._pMaxMana - plr[pnum]._pMaxManaBase; plr[pnum]._pManaBase -= v1; plr[pnum]._pMana -= v1; plr[pnum]._pMaxMana -= v1; plr[pnum]._pMaxManaBase -= v1; if ((plr[pnum]._pMana >> MANA_SHIFT) <= 0) { plr[pnum]._pMana = v2; plr[pnum]._pManaBase = 0; } if ((plr[pnum]._pMaxMana >> MANA_SHIFT) <= 0) { plr[pnum]._pMaxMana = v3; plr[pnum]._pMaxManaBase = 0; } InitDiabloMsg(SHRINE_17); break; case 17: // Spiritual if (deltaload) return; if (pnum != myplr) return; //Fill inventory with gold for (r = 0; r < MAXINV; ++r) { if (plr[pnum].InvGrid[r] == 0) { v2 = (leveltype * 5) + random(160,leveltype * 10); v1 = plr[pnum]._pNumInv; plr[pnum].InvList[v1] = golditem; plr[pnum].InvList[v1]._iSeed = GetRndSeed(); ++plr[pnum]._pNumInv; plr[pnum].InvGrid[r] = plr[pnum]._pNumInv; plr[pnum].InvList[v1]._ivalue = v2; plr[pnum]._pGold += v2; SetGoldCurs(pnum, v1); } } InitDiabloMsg(SHRINE_18); break; case 18: // Spooky (Multi Player Only) if (deltaload) return; if (pnum == myplr) InitDiabloMsg(SHRINE_19); else { //Full rejuv for other players InitDiabloMsg(SHRINE_19B); plr[myplr]._pHitPoints = plr[myplr]._pMaxHP; plr[myplr]._pHPBase = plr[myplr]._pMaxHPBase; plr[myplr]._pMana = plr[myplr]._pMaxMana; plr[myplr]._pManaBase = plr[myplr]._pMaxManaBase; } break; case 19: // Abandoned if (deltaload) return; if (pnum != myplr) return; //Add 2 to dexterity ModifyPlrDex(pnum, 2); CheckStats(pnum); if (pnum == myplr) InitDiabloMsg(SHRINE_20); break; case 20: // Creepy if (deltaload) return; if (pnum != myplr) return; //Add 2 to strength ModifyPlrStr(pnum, 2); CheckStats(pnum); if (pnum == myplr) InitDiabloMsg(SHRINE_21); break; case 21: // Quiet if (deltaload) return; if (pnum != myplr) return; //Add 2 to vitality ModifyPlrVit(pnum, 2); CheckStats(pnum); if (pnum == myplr) InitDiabloMsg(SHRINE_22); break; case 22: // Secluded if (deltaload) return; if (pnum == myplr) { //Complete automap for current level for (yy = 0; yy < AUTOMAPY; ++yy) { for (xx = 0; xx < AUTOMAPX; ++xx) automapview[xx][yy] = TRUE; } InitDiabloMsg(SHRINE_23); } break; case 23: // Ornate if (deltaload) return; if (pnum != myplr) return; //Give player holy bolt level +2 t = 1; plr[pnum]._pMemSpells |= t << (SPL_HBOLT-1); if (plr[pnum]._pSplLvl[SPL_HBOLT] < SPELLCAP) ++plr[pnum]._pSplLvl[SPL_HBOLT] ; if (plr[pnum]._pSplLvl[SPL_HBOLT] < SPELLCAP) ++plr[pnum]._pSplLvl[SPL_HBOLT] ; //Subtract 1/10 of mana v1 = plr[pnum]._pMaxManaBase / 10; v2 = plr[pnum]._pMana - plr[pnum]._pManaBase; v3 = plr[pnum]._pMaxMana - plr[pnum]._pMaxManaBase; plr[pnum]._pManaBase -= v1; plr[pnum]._pMana -= v1; plr[pnum]._pMaxMana -= v1; plr[pnum]._pMaxManaBase -= v1; if ((plr[pnum]._pMana >> MANA_SHIFT) <= 0) { plr[pnum]._pMana = v2; plr[pnum]._pManaBase = 0; } if ((plr[pnum]._pMaxMana >> MANA_SHIFT) <= 0) { plr[pnum]._pMaxMana = v3; plr[pnum]._pMaxManaBase = 0; } InitDiabloMsg(SHRINE_24); break; case 24: // Glimmering if (deltaload) return; if (pnum != myplr) return; //All items are identified for (r = 0; r < NUM_INVLOC; ++r) { if ((plr[pnum].InvBody[r]._iMagical != IMAGIC_NONE) && !plr[pnum].InvBody[r]._iIdentified) plr[pnum].InvBody[r]._iIdentified = TRUE; } for (r = 0; r < plr[pnum]._pNumInv; ++r) { if ((plr[pnum].InvList[r]._iMagical != IMAGIC_NONE) && !plr[pnum].InvList[r]._iIdentified) plr[pnum].InvList[r]._iIdentified = TRUE; } for (r = 0; r < MAXSPD; ++r) { if ((plr[pnum].SpdList[r]._iMagical != IMAGIC_NONE) && !plr[pnum].SpdList[r]._iIdentified) plr[pnum].SpdList[r]._iIdentified = TRUE; } InitDiabloMsg(SHRINE_25); break; case 25: // Tainted (Multi Player Only) if (deltaload) return; if (pnum == myplr) InitDiabloMsg(SHRINE_26); else { //All other players get +1 to 3 random stats and -1 to other InitDiabloMsg(SHRINE_26B); r = random(155,4); if (r == 0) v1 = 1; else v1 = -1; if (r == 1) v2 = 1; else v2 = -1; if (r == 2) v3 = 1; else v3 = -1; if (r == 3) v4 = 1; else v4 = -1; ModifyPlrStr(myplr, v1); ModifyPlrMag(myplr, v2); ModifyPlrDex(myplr, v3); ModifyPlrVit(myplr, v4); CheckStats(myplr); } break; case 26: // Oily // Increase good stats by 1. if (deltaload) return; if (pnum != myplr) return; InitDiabloMsg(SHRINE_27); switch(plr[myplr]._pClass) { case CLASS_SORCEROR: ModifyPlrMag(myplr,2); break; case CLASS_ROGUE: ModifyPlrDex(myplr,2); break; case CLASS_WARRIOR: ModifyPlrStr(myplr,2); break; case CLASS_BARBARIAN: ModifyPlrVit(myplr,2); break; case CLASS_MONK: ModifyPlrStr(myplr,1); ModifyPlrDex(myplr,1); break; case CLASS_BARD: ModifyPlrDex(myplr,1); ModifyPlrMag(myplr,1); break; } CheckStats(pnum); AddMissile(object[i]._ox, object[i]._oy, plr[myplr]._px, plr[myplr]._py, plr[myplr]._pdir, MIT_FIREWALL, MI_ENEMYPLR, 0, 2 + (2 * currlevel), 0); break; case 27: // Glowing { if (deltaload) return; if (pnum != myplr) return; InitDiabloMsg(SHRINE_28); long CurrentExp = plr[myplr]._pExperience; long ModMagic; if (CurrentExp > 5000) { ModMagic = 5; CurrentExp = (long)(CurrentExp * 0.95); } else { ModMagic = CurrentExp/1000; CurrentExp = 0; } ModifyPlrMag(myplr, ModMagic); plr[myplr]._pExperience = CurrentExp; CheckStats(pnum); } break; case 28: // Mendicant's { if (deltaload) return; if (pnum != myplr) return; InitDiabloMsg(SHRINE_29); long const HalfCurrentGold = plr[myplr]._pGold / 2; AddPlrExperience(myplr, plr[myplr]._pLevel, HalfCurrentGold); TakePlrsMoney(HalfCurrentGold); // uses global var myplr. CheckStats(pnum); } break; case 29: // Sparkling if (deltaload) return; if (pnum != myplr) return; InitDiabloMsg(SHRINE_30); AddPlrExperience(myplr, plr[myplr]._pLevel, 1000 * currlevel); AddMissile(object[i]._ox, object[i]._oy, plr[myplr]._px, plr[myplr]._py, plr[myplr]._pdir, MIT_FLASH, MI_ENEMYPLR, 0, 2 + (3 * currlevel), 0); CheckStats(pnum); break; case 30: // Town if (deltaload) return; if (pnum != myplr) return; InitDiabloMsg(SHRINE_31); AddMissile(object[i]._ox, object[i]._oy, plr[myplr]._px, plr[myplr]._py, plr[myplr]._pdir, MIT_TOWN, MI_ENEMYPLR, 0, 0, 0); break; case 31: // Shimmering if (deltaload) return; if (pnum != myplr) return; InitDiabloMsg(SHRINE_32); plr[pnum]._pMana = plr[pnum]._pMaxMana; // restore to full mana. plr[pnum]._pManaBase = plr[pnum]._pMaxManaBase; break; case 32: // Solar { if (deltaload) return; if (pnum != myplr) return; time_t time_of_day = time(0); struct tm * const tmbuf = localtime(&time_of_day); if (tmbuf->tm_hour > 20 || tmbuf->tm_hour < 4) { InitDiabloMsg(SHRINE_33D); ModifyPlrVit(myplr, 2); } else if (tmbuf->tm_hour > 18) { InitDiabloMsg(SHRINE_33C); ModifyPlrMag(myplr, 2); } else if (tmbuf->tm_hour > 12) { InitDiabloMsg(SHRINE_33B); ModifyPlrStr(myplr, 2); } else if (tmbuf->tm_hour > 4) { InitDiabloMsg(SHRINE_33A); ModifyPlrDex(myplr, 2); } CheckStats(pnum); } break; case 33: // Murphy's { if (deltaload) return; if (pnum != myplr) return; InitDiabloMsg(SHRINE_34); long i; long broken = 0; for (i = 0; i < 7; ++i) { ItemStruct * const itm = &plr[myplr].InvBody[i]; if (itm->_itype == -1) continue; if (random(0,3) == 0 && itm->_iDurability != INFINITE_DUR && itm->_iDurability != 0) // There are two values for infinite durablity !!! { // Randomly break something. itm->_iDurability /= 2; broken = 1; break; } } if (!broken) { long const ThirdCurrentGold = plr[myplr]._pGold / 3; TakePlrsMoney(ThirdCurrentGold); // uses global var myplr. } } break; } CalcPlrInv(pnum, TRUE); force_redraw = FULLDRAW; if (pnum == myplr) NetSendCmdParam2(FALSE,CMD_PLROPOBJ,pnum,i); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateSkelBook(int pnum, int i, bool sendmsg) { app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oSelFlag == OSEL_NONE) return; if (!deltaload) PlaySfxLoc(IS_ISCROL, object[i]._ox, object[i]._oy); object[i]._oSelFlag = OSEL_NONE; object[i]._oAnimFrame += 2; if (deltaload) return; SetRndSeed(object[i]._oRndSeed); if (random(161,5)) CreateTypeItem(object[i]._ox, object[i]._oy, FALSE, IT_MISC, IMID_SCROLL, sendmsg, FALSE); else CreateTypeItem(object[i]._ox, object[i]._oy, FALSE, IT_MISC, IMID_BOOK, sendmsg, FALSE); if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateBookCase(int pnum, int i, bool sendmsg) { app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oSelFlag == OSEL_NONE) return; if (!deltaload) PlaySfxLoc(IS_ISCROL, object[i]._ox, object[i]._oy); object[i]._oSelFlag = OSEL_NONE; object[i]._oAnimFrame -= 2; if (deltaload) return; SetRndSeed(object[i]._oRndSeed); CreateTypeItem(object[i]._ox, object[i]._oy, FALSE, IT_MISC, IMID_BOOK, sendmsg, FALSE); if (QuestStatus(Q_ZHAR)) { if (monster[4].mName == UniqMonst[MU_ZHAR].mName) { if ((monster[4]._msquelch == 255) && (monster[4]._mhitpoints != 0)) { monster[4].mtalkmsg = TXT_ZHAR2; M_StartStand(0, monster[4]._mdir); monster[4]._mgoal = MG_ATTACK2; monster[4]._mmode = MM_TALK; } } } if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateDecap(int pnum, int i, bool sendmsg) { app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oSelFlag == OSEL_NONE) return; object[i]._oSelFlag = OSEL_NONE; if (deltaload) return; SetRndSeed(object[i]._oRndSeed); CreateRndItem(object[i]._ox, object[i]._oy, FALSE, sendmsg, FALSE); if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateArmorStand(int pnum, int i, bool sendmsg) { int uniqueRnd; app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oSelFlag == OSEL_NONE) return; object[i]._oSelFlag = OSEL_NONE; ++object[i]._oAnimFrame; if (deltaload) return; SetRndSeed(object[i]._oRndSeed); //Randomize uniqueness uniqueRnd = random(0, 2); //Create an appropriate armor for the current level if (currlevel <= 5) { //Create unique only IT_ARMOR CreateTypeItem(object[i]._ox, object[i]._oy, TRUE, IT_ARMOR, IMID_NONE, sendmsg, FALSE); } else if (currlevel >= 6 && currlevel <= 9) { //Create random unique IT_MARMOR CreateTypeItem(object[i]._ox, object[i]._oy, uniqueRnd, IT_MARMOR, IMID_NONE, sendmsg, FALSE); } else if (currlevel >= 10 && currlevel <= 12) { //Create non-unique IT_HARMOR CreateTypeItem(object[i]._ox, object[i]._oy, FALSE, IT_HARMOR, IMID_NONE, sendmsg, FALSE); } else if (currlevel >= 13 && currlevel <= 16) { //Create unique IT_HARMOR CreateTypeItem(object[i]._ox, object[i]._oy, TRUE, IT_HARMOR, IMID_NONE, sendmsg, FALSE); } else if (currlevel >= 17) { //Use the uniques for now, but we will add our own specifics JKE 7/30 CreateTypeItem(object[i]._ox, object[i]._oy, TRUE, IT_HARMOR, IMID_NONE, sendmsg, FALSE); } if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static int FindValidShrine(int i) /*-----------------------------------------------------------------------* ** Description: Used by OperateGoatShrine and OperateCauldron to find a ** usable shrine function. ** Input: i = Object index ** Return: Shrine function index. **-----------------------------------------------------------------------*/ { int rv; bool done = false; //Search until we find a valid shrine type. Ignore Thaumaturgic shrine //because it could possibly screw up the animation. do { rv = random(0, NUMSHRINETYPES); if ((currlevel >= shrineminlvl[rv]) && (currlevel <= shrinemaxlvl[rv]) && (rv != 8)) { done = true; } if (done) { if ((gbMaxPlayers != 1) && (shrineavail[rv] == SHRINE_SINGLE)) { done = FALSE; } else if ((gbMaxPlayers == 1) && (shrineavail[rv] == SHRINE_MULTI)) { done = FALSE; } else done = TRUE; //We found a shrine type we can use. } } while (!done); return rv; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateGoatShrine(int pnum, int i, int sType) { app_assert((DWORD)i < MAXOBJECTS); SetRndSeed(object[i]._oRndSeed); object[i]._oVar1 = FindValidShrine(i); OperateShrine(pnum, i, sType); object[i]._oAnimDelay = 2; force_redraw = FULLDRAW; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateCauldron(int pnum, int i, int sType) { app_assert((DWORD)i < MAXOBJECTS); SetRndSeed(object[i]._oRndSeed); object[i]._oVar1 = FindValidShrine(i); OperateShrine(pnum, i, sType); object[i]._oAnimFrame = 3; object[i]._oAnimFlag = FALSE; force_redraw = FULLDRAW; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static bool OperateFountains(int pnum, int i) { int ii; bool rv = false; app_assert((DWORD)i < MAXOBJECTS); SetRndSeed(object[i]._oRndSeed); switch(object[i]._otype) { case OBJ_PURIFYINGFTN: if (deltaload) return rv; if (pnum != myplr) return rv; if (plr[pnum]._pMana < plr[pnum]._pMaxMana) { PlaySfxLoc(LS_FOUNTAIN, object[i]._ox, object[i]._oy); //Add 1 Mana point plr[pnum]._pMana += (1 << MANA_SHIFT); plr[pnum]._pManaBase += (1 << MANA_SHIFT); if (plr[pnum]._pMana > plr[pnum]._pMaxMana) { plr[pnum]._pMana = plr[pnum]._pMaxMana; plr[pnum]._pManaBase = plr[pnum]._pMaxManaBase; } rv = true; } else if (!deltaload) PlaySfxLoc(LS_FOUNTAIN, object[i]._ox, object[i]._oy); break; case OBJ_BLOODFTN: if (deltaload) return rv; if (pnum != myplr) return rv; if (plr[pnum]._pHitPoints < plr[pnum]._pMaxHP) { PlaySfxLoc(LS_FOUNTAIN, object[i]._ox, object[i]._oy); //Add 1 HP point plr[pnum]._pHitPoints += (1 << HP_SHIFT); plr[pnum]._pHPBase += (1 << HP_SHIFT); if (plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) { plr[pnum]._pHitPoints = plr[pnum]._pMaxHP; plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase; } rv = true; } else if (!deltaload) PlaySfxLoc(LS_FOUNTAIN, object[i]._ox, object[i]._oy); break; case OBJ_MURKYFTN: if (object[i]._oSelFlag != OSEL_NONE) { if (!deltaload) PlaySfxLoc(LS_FOUNTAIN, object[i]._ox, object[i]._oy); object[i]._oSelFlag = OSEL_NONE; if (deltaload) return rv; //Casts infravision AddMissile(plr[pnum]._px, plr[pnum]._py, plr[pnum]._px, plr[pnum]._py, plr[pnum]._pdir, MIT_INFRA, -1, pnum, 0, (leveltype << 1)); rv = true; if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); } break; case OBJ_TEARFTN: if (object[i]._oSelFlag != OSEL_NONE) { int rndVal; int statVal = -1; int saveRnd = -1; int status = FALSE; ii = 0; if (!deltaload) PlaySfxLoc(LS_FOUNTAIN, object[i]._ox, object[i]._oy); object[i]._oSelFlag = OSEL_NONE; if (deltaload) return rv; if (pnum != myplr) return rv; //-1 to random stat, +1 to another do { if ((rndVal = random(0, 4)) != saveRnd) { switch(rndVal) { case 0: ModifyPlrStr(pnum, statVal); break; case 1: ModifyPlrMag(pnum, statVal); break; case 2: ModifyPlrDex(pnum, statVal); break; case 3: ModifyPlrVit(pnum, statVal); break; } saveRnd = rndVal; statVal = 1; ++ii; } if (ii > 1) status = TRUE; } while(!status); CheckStats(pnum); rv = true; if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); } break; } force_redraw = FULLDRAW; return rv; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateWeaponRack(int pnum, int i, bool sendmsg) { int weaponType, sfxType; app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oSelFlag == OSEL_NONE) return; SetRndSeed(object[i]._oRndSeed); //Choose random weapon/sfx type switch((random(0, 4)+1)) { case 1: weaponType = IT_SWORD; sfxType = IS_FSWOR; break; case 2: weaponType = IT_AXE; sfxType = IS_FAXE; break; case 3: weaponType = IT_BOW; sfxType = IS_FBOW; break; case 4: weaponType = IT_MACE; sfxType = IS_FAXE; break; } object[i]._oSelFlag = OSEL_NONE; ++object[i]._oAnimFrame; if (deltaload) return; //Create a random weapon. Create unique weapons from level 4 down. if (leveltype > 1) CreateTypeItem(object[i]._ox, object[i]._oy, TRUE, weaponType, IMID_NONE, sendmsg, FALSE); else CreateTypeItem(object[i]._ox, object[i]._oy, FALSE, weaponType, IMID_NONE, sendmsg, FALSE); if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateStoryBook(int pnum, int i) { app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oSelFlag == OSEL_NONE) return; if (deltaload) return; if (qtextflag) return; if (pnum != myplr) return; object[i]._oAnimFrame = object[i]._oVar4; PlaySfxLoc(IS_ISCROL, object[i]._ox, object[i]._oy); if ((object[i]._oVar8 != 0) && (currlevel == NA_KRUL_LEVEL)) { if ((Na_Krul.Lever_Thrown != TRUE) && (quests[Q_NA_KRUL]._qactive != QUEST_DONE)) if(HCheckSpell(object[i]._oVar8)) { NetSendCmd(FALSE,CMD_OPEN_NAKRUL); return; } } else if (currlevel >= CRYPTSTART) { quests[Q_NA_KRUL]._qactive = QUEST_NOTDONE; quests[Q_NA_KRUL]._qlog = TRUE; quests[Q_NA_KRUL]._qmsg = object[i]._oVar2; } InitQTextMsg(object[i]._oVar2); NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void OperateLazStand(int pnum, int i) { int x, y; app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oSelFlag == OSEL_NONE) return; if (deltaload) return; if (qtextflag) return; if (pnum != myplr) return; ++object[i]._oAnimFrame; object[i]._oSelFlag = OSEL_NONE; GetSuperItemLoc(object[i]._ox, object[i]._oy, x, y); SpawnQuestItem(IDI_LAZSTAFF, x, y, 0, ISEL_NONE); //quests[Q_BKMUSHRM]._qvar1 = QS_MUSHSPAWNED; } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void OperateObject(int pnum, int i, BOOL TeleFlag) { bool senditemmsg; if (pnum == myplr) senditemmsg = true; else senditemmsg = false; app_assert((DWORD)i < MAXOBJECTS); switch (object[i]._otype) { case OBJ_L1DOORL : case OBJ_L1DOORR : if (TeleFlag) { if (object[i]._otype == OBJ_L1DOORL) OperateL1LDoor(pnum, i, true); if (object[i]._otype == OBJ_L1DOORR) OperateL1RDoor(pnum, i, true); } else { if (pnum == myplr) OperateL1Door(pnum, i, TRUE); } break; case OBJ_L2DOORL : case OBJ_L2DOORR : if (TeleFlag) { if (object[i]._otype == OBJ_L2DOORL) OperateL2LDoor(pnum, i, true); if (object[i]._otype == OBJ_L2DOORR) OperateL2RDoor(pnum, i, true); } else { if (pnum == myplr) OperateL2Door(pnum, i, TRUE); } break; case OBJ_L3DOORL : case OBJ_L3DOORR : if (TeleFlag) { if (object[i]._otype == OBJ_L3DOORL) OperateL3LDoor(pnum, i, true); if (object[i]._otype == OBJ_L3DOORR) OperateL3RDoor(pnum, i, true); } else { if (pnum == myplr) OperateL3Door(pnum, i, TRUE); } break; case OBJ_SWITCHSKL: case OBJ_LEVER : OperateLever(pnum, i); break; case OBJ_BOOK2L: OperateBook(pnum, i); break; case OBJ_BOOK2R: OperateSChambBk(pnum, i); break; case OBJ_CHEST1: case OBJ_CHEST2: case OBJ_CHEST3: case OBJ_TCHEST1: case OBJ_TCHEST2: case OBJ_TCHEST3: OperateChest(pnum, i, senditemmsg); break; case OBJ_SARC: OperateSarc(pnum, i, senditemmsg); break; case OBJ_FLAMELVR: OperateTrapLvr(i); break; // case OBJ_BOOKLVR: case OBJ_BLINDBOOK: case OBJ_BLOODBOOK: case OBJ_STEELTOME: OperateBookLever(pnum, i); break; case OBJ_SHRINEL: case OBJ_SHRINER: OperateShrine(pnum, i, IS_MAGIC); break; case OBJ_SKELBOOK: case OBJ_BOOKSTAND: OperateSkelBook(pnum, i, senditemmsg); break; case OBJ_BOOKCASEL: case OBJ_BOOKCASER: OperateBookCase(pnum, i, senditemmsg); break; case OBJ_DECAP: OperateDecap(pnum, i, senditemmsg); break; case OBJ_ARMORSTAND: case OBJ_WARARMOR: OperateArmorStand(pnum, i, senditemmsg); break; case OBJ_GOATSHRINE: OperateGoatShrine(pnum, i, LS_GSHRINE); break; case OBJ_CAULDRON: OperateCauldron(pnum, i, LS_CALDRON); break; case OBJ_MURKYFTN: case OBJ_TEARFTN: case OBJ_BLOODFTN: case OBJ_PURIFYINGFTN: OperateFountains(pnum, i); break; case OBJ_STORYBOOK: OperateStoryBook(pnum, i); break; case OBJ_PEDISTAL: OperatePedistal(pnum, i); break; case OBJ_WARWEAP: case OBJ_WEAPONRACK: OperateWeaponRack(pnum, i, senditemmsg); break; case OBJ_MUSHPATCH: OperateMushPatch(pnum, i); break; case OBJ_LAZSTAND: OperateLazStand(pnum, i); break; case OBJ_SLAINHERO: OperateSlainHero(pnum, i, senditemmsg); break; case OBJ_SIGNCHEST: OperateInnSignChest(pnum, i); break; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void SyncOpL1Door(int pnum, int cmd, int i) { if (pnum == myplr) return; bool opok = false; app_assert((DWORD)i < MAXOBJECTS); if ((cmd == CMD_OPENDOOR) && (object[i]._oVar4 == DOOR_CLOSED)) opok = TRUE; if ((cmd == CMD_CLOSEDOOR) && (object[i]._oVar4 == DOOR_OPEN)) opok = TRUE; if (opok) { if (object[i]._otype == OBJ_L1DOORL) OperateL1LDoor(-1, i, false); if (object[i]._otype == OBJ_L1DOORR) OperateL1RDoor(-1, i, false); } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void SyncOpL2Door(int pnum, int cmd, int i) { if (pnum == myplr) return; bool opok = false; app_assert((DWORD)i < MAXOBJECTS); if ((cmd == CMD_OPENDOOR) && (object[i]._oVar4 == DOOR_CLOSED)) opok = true; if ((cmd == CMD_CLOSEDOOR) && (object[i]._oVar4 == DOOR_OPEN)) opok = true; if (opok) { if (object[i]._otype == OBJ_L2DOORL) OperateL2LDoor(-1, i, false); if (object[i]._otype == OBJ_L2DOORR) OperateL2RDoor(-1, i, false); } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void SyncOpL3Door(int pnum, int cmd, int i) { if (pnum == myplr) return; bool opok = false; app_assert((DWORD)i < MAXOBJECTS); if ((cmd == CMD_OPENDOOR) && (object[i]._oVar4 == DOOR_CLOSED)) opok = true; if ((cmd == CMD_CLOSEDOOR) && (object[i]._oVar4 == DOOR_OPEN)) opok = true; if (opok) { if (object[i]._otype == OBJ_L3DOORL) OperateL3LDoor(-1, i, false); if (object[i]._otype == OBJ_L3DOORR) OperateL3RDoor(-1, i, false); } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void SyncOpObject(int pnum, int cmd, int i) { app_assert((DWORD)i < MAXOBJECTS); switch (object[i]._otype) { case OBJ_L1DOORL : case OBJ_L1DOORR : SyncOpL1Door(pnum, cmd, i); break; case OBJ_L2DOORL : case OBJ_L2DOORR : SyncOpL2Door(pnum, cmd, i); break; case OBJ_L3DOORL : case OBJ_L3DOORR : SyncOpL3Door(pnum, cmd, i); break; case OBJ_SWITCHSKL: case OBJ_LEVER : OperateLever(pnum, i); break; case OBJ_CHEST1: case OBJ_CHEST2: case OBJ_CHEST3: case OBJ_TCHEST1: case OBJ_TCHEST2: case OBJ_TCHEST3: OperateChest(pnum, i, FALSE); break; case OBJ_SARC: OperateSarc(pnum, i, FALSE); break; // case OBJ_BOOKLVR: case OBJ_BLINDBOOK: case OBJ_BLOODBOOK: case OBJ_STEELTOME: OperateBookLever(pnum, i); break; case OBJ_SHRINEL: case OBJ_SHRINER: OperateShrine(pnum, i, IS_MAGIC); break; case OBJ_SKELBOOK: case OBJ_BOOKSTAND: OperateSkelBook(pnum, i, FALSE); break; case OBJ_BOOKCASEL: case OBJ_BOOKCASER: OperateBookCase(pnum, i, FALSE); break; case OBJ_DECAP: OperateDecap(pnum, i, FALSE); break; case OBJ_ARMORSTAND: case OBJ_WARARMOR: OperateArmorStand(pnum, i, FALSE); break; case OBJ_GOATSHRINE: OperateGoatShrine(pnum, i, LS_GSHRINE); break; case OBJ_CAULDRON: OperateCauldron(pnum, i, LS_CALDRON); break; case OBJ_MURKYFTN: case OBJ_TEARFTN: OperateFountains(pnum, i); break; case OBJ_STORYBOOK: OperateStoryBook(pnum, i); break; case OBJ_PEDISTAL: OperatePedistal(pnum, i); break; case OBJ_WARWEAP: case OBJ_WEAPONRACK: OperateWeaponRack(pnum, i, FALSE); break; case OBJ_MUSHPATCH: OperateMushPatch(pnum, i); break; case OBJ_SLAINHERO: OperateSlainHero(pnum, i, FALSE); break; case OBJ_SIGNCHEST: OperateInnSignChest(pnum, i); break; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void BreakCrux(int i) { int j, ot, oi; bool mapflag; app_assert((DWORD)i < MAXOBJECTS); object[i]._oAnimFlag = TRUE; object[i]._oAnimFrame = 1; object[i]._oAnimDelay = 1; object[i]._oSolidFlag = TRUE; object[i]._oMissFlag = TRUE; object[i]._oBreak = OBJ_BROKEN; object[i]._oSelFlag = OSEL_NONE; mapflag = true; for (j = 0; j < numobjects; ++j) { oi = objectactive[j]; ot = object[oi]._otype; if ((ot == OBJ_CRUX1) || (ot == OBJ_CRUX2) || (ot == OBJ_CRUX3)) { if (object[i]._oVar8 == object[oi]._oVar8) { if (object[oi]._oBreak != OBJ_BROKEN) mapflag = false; } } } if (mapflag) { if (!deltaload) PlaySfxLoc(IS_LEVER, object[i]._ox, object[i]._oy); ObjChangeMap(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ // DKT971012: Gary has items.cpp checked out; this should go there void RndUnique(int x, int y, int level) { int uil[MAXUITEMS]; int i, numui = 0; for (i=UID_LGTFORGE+1; i < MAXUITEMS && UniqueItemList[i].UIItemId != -1; ++i) { if (level*2 >= UniqueItemList[i].UIMinLvl) uil[numui++] = i; } if (numui > 0) { int uitem = uil[random(0, numui)]; SpawnUnique(uitem, x, y); } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void BreakBarrel(int pnum, int i, int dam, BOOL forcebreak, BOOL sendmsg) { int x, y, oi; app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oSelFlag == OSEL_NONE) return; // already broken? if (forcebreak) { object[i]._oVar1 = 0; // force it to bust open } else { object[i]._oVar1 -= dam; // normal damage // if someone else is breaking the object, and it wasn't a force break // message, then it hasn't broken yet. if ((pnum != myplr) && (object[i]._oVar1 <= 0)) object[i]._oVar1 = 1; } if (object[i]._oVar1 > 0) { if (!deltaload) PlaySfxLoc(IS_IBOW, object[i]._ox, object[i]._oy); return; } object[i]._oVar1 = 0; // broken object[i]._oAnimFlag = TRUE; object[i]._oAnimFrame = 1; object[i]._oAnimDelay = 1; object[i]._oSolidFlag = FALSE; object[i]._oMissFlag = TRUE; object[i]._oBreak = OBJ_BROKEN; object[i]._oSelFlag = OSEL_NONE; object[i]._oPreFlag = TRUE; if (deltaload) { object[i]._oAnimFrame = object[i]._oAnimLen; object[i]._oAnimCnt = 0; object[i]._oAnimDelay = 1000; return; } if (object[i]._otype == OBJ_BARRELEX) { bool foo; if (currlevel >= CRYPTSTART && currlevel <= CRYPTEND) PlaySfxLoc(IS_URNFIRE, object[i]._ox, object[i]._oy); else if (currlevel >= HIVESTART && currlevel <= HIVEEND) PlaySfxLoc(IS_PODFIRE, object[i]._ox, object[i]._oy); else PlaySfxLoc(IS_BARLFIRE, object[i]._ox, object[i]._oy); for (y = object[i]._oy-1; y <= object[i]._oy+1; ++y) { for (x = object[i]._ox-1; x <= object[i]._ox+1; ++x) { if (dMonster[x][y] > 0) MonsterTrapHit(dMonster[x][y]-1, 1, 4, 0, MIMT_FIRE, 0); if (dPlayer[x][y] > 0) PlayerMHit(dPlayer[x][y]-1, -1, 0, 8, 16, MIMT_FIRE, 0, FALSE, &foo); if (dObject[x][y] > 0) { oi = dObject[x][y] - 1; if ((object[oi]._otype == OBJ_BARRELEX) && (object[oi]._oBreak != OBJ_BROKEN)) BreakBarrel(pnum, oi, dam, TRUE, sendmsg); } } } } else { if (currlevel >= CRYPTSTART && currlevel <= CRYPTEND) PlaySfxLoc(IS_URN, object[i]._ox, object[i]._oy); else if (currlevel >= HIVESTART && currlevel <= HIVEEND) PlaySfxLoc(IS_POD, object[i]._ox, object[i]._oy); else PlaySfxLoc(IS_BARREL, object[i]._ox, object[i]._oy); SetRndSeed(object[i]._oRndSeed); #if CHEATS if (uniqcheat) RndUnique(object[i]._ox, object[i]._oy, currlevel); else #endif if (object[i]._oVar2 <= 1) { if (!object[i]._oVar3) CreateRndUseful(pnum, object[i]._ox, object[i]._oy, sendmsg); else CreateRndItem(object[i]._ox, object[i]._oy, FALSE, sendmsg, FALSE); } if (object[i]._oVar2 >= 8) SpawnSkeleton(object[i]._oVar4, object[i]._ox, object[i]._oy); } if (pnum == myplr) NetSendCmdParam2(FALSE,CMD_BREAKOBJ,pnum,i); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void BreakObject(int pnum, int oi) { int objdam, mind, maxd; if (pnum != -1) { mind = plr[pnum]._pIMinDam; maxd = plr[pnum]._pIMaxDam; objdam = random(163,maxd - mind + 1) + mind; objdam += (objdam * plr[pnum]._pIBonusDam) / 100; objdam += plr[pnum]._pIBonusDamMod + plr[pnum]._pDamageMod; } else objdam = 10; app_assert((DWORD)oi < MAXOBJECTS); switch (object[oi]._otype) { case OBJ_CRUX1 : case OBJ_CRUX2 : case OBJ_CRUX3 : BreakCrux(oi); break; case OBJ_BARREL: case OBJ_BARRELEX: BreakBarrel(pnum, oi, objdam, FALSE, TRUE); break; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void SyncBreakObj(int pnum, int oi) { app_assert((DWORD)oi < MAXOBJECTS); switch (object[oi]._otype) { case OBJ_BARREL: case OBJ_BARRELEX: BreakBarrel(pnum, oi, 0, TRUE, FALSE); break; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void SyncL1Doors(int i) { int dx, dy; app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oVar4 == DOOR_CLOSED) { object[i]._oMissFlag = FALSE; return; } else object[i]._oMissFlag = TRUE; dx = object[i]._ox; dy = object[i]._oy; object[i]._oSelFlag = OSEL_TOP; if (currlevel < HIVESTART) { if (object[i]._otype == OBJ_L1DOORL) { if (object[i]._oVar1 == 214) ObjSetMicro(dx,dy,408); //Blood else ObjSetMicro(dx,dy,393); dSpecial[dx][dy] = 7; ObjSetMicro12(dx-1,dy); --dy; } else { ObjSetMicro(dx,dy,395); if (currlevel < HIVESTART) dSpecial[dx][dy] = 8; ObjSetMicro12(dx,dy-1); --dx; } } else { if (object[i]._otype == OBJ_L1DOORL) { ObjSetMicro(dx,dy,206); dSpecial[dx][dy] = 1; ObjSetMicro12(dx-1,dy); --dy; } else { ObjSetMicro(dx,dy,209); dSpecial[dx][dy] = 2; ObjSetMicro12(dx,dy-1); --dx; } } DoorSet(i, dx, dy); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void SyncCrux(int i) { int j, ot, oi; bool mapflag; mapflag = TRUE; for (j = 0; j < numobjects; ++j) { oi = objectactive[j]; app_assert((DWORD)oi < MAXOBJECTS); ot = object[oi]._otype; if ((ot == OBJ_CRUX1) || (ot == OBJ_CRUX2) || (ot == OBJ_CRUX3)) { if (object[i]._oVar8 == object[oi]._oVar8) { if (object[oi]._oBreak != OBJ_BROKEN) mapflag = FALSE; } } } if (mapflag) ObjChangeMap(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void SyncLever(int i) { app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oSelFlag == OSEL_NONE) { ObjChangeMap(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void SyncQSTLever(int i) { int tren; app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oAnimFrame == object[i]._oVar6) { ObjChangeMapResync(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); if (object[i]._otype == OBJ_BLINDBOOK) { tren = TransVal; TransVal = 9; DRLG_MRectTrans(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); TransVal = tren; } } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void SyncPedistal(int i) { byte *setp; app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oVar6 == 1) { ObjChangeMapResync(setpc_x, setpc_y + 3, setpc_x + 2, setpc_y + 7); } if (object[i]._oVar6 == 2) { ObjChangeMapResync(setpc_x, setpc_y + 3, setpc_x + 2, setpc_y + 7); ObjChangeMapResync(setpc_x + 6, setpc_y + 3, setpc_x + setpc_w, setpc_y + 7); } if (object[i]._oVar6 == 3) { ObjChangeMapResync(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); setp = LoadFileInMemSig("Levels\\L2Data\\Blood2.DUN", NULL, 'STPC'); LoadMapObjs(setp, (setpc_x << 1), (setpc_y << 1)); DiabloFreePtr(setp); } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void SyncL2Doors(int i) { int dx, dy; app_assert((DWORD)i < MAXOBJECTS); if (object[i]._oVar4 == DOOR_CLOSED) object[i]._oMissFlag = FALSE; else object[i]._oMissFlag = TRUE; dx = object[i]._ox; dy = object[i]._oy; object[i]._oSelFlag = OSEL_TOP; //Fix doors upon returning to level or loading level if ((object[i]._otype == OBJ_L2DOORL) && (object[i]._oVar4 == DOOR_CLOSED)) { ObjSetMicro(dx,dy,538); } else if ((object[i]._otype == OBJ_L2DOORL) && ((object[i]._oVar4 == DOOR_OPEN) || (object[i]._oVar4 == DOOR_BLOCKED))) { ObjSetMicro(dx,dy,13); } else if ((object[i]._otype == OBJ_L2DOORR) && (object[i]._oVar4 == DOOR_CLOSED)) { ObjSetMicro(dx,dy,540); } else if ((object[i]._otype == OBJ_L2DOORR) && ((object[i]._oVar4 == DOOR_OPEN) || (object[i]._oVar4 == DOOR_BLOCKED))) { ObjSetMicro(dx,dy,17); } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void SyncL3Doors(int i) { int dx, dy; app_assert((DWORD)i < MAXOBJECTS); object[i]._oMissFlag = TRUE; dx = object[i]._ox; dy = object[i]._oy; object[i]._oSelFlag = OSEL_TOP; //Fix doors upon returning to level or loading level if ((object[i]._otype == OBJ_L3DOORL) && (object[i]._oVar4 == DOOR_CLOSED)) { ObjSetMicro(dx,dy,531); } else if ((object[i]._otype == OBJ_L3DOORL) && ((object[i]._oVar4 == DOOR_OPEN) || (object[i]._oVar4 == DOOR_BLOCKED))) { ObjSetMicro(dx,dy,538); } else if ((object[i]._otype == OBJ_L3DOORR) && (object[i]._oVar4 == DOOR_CLOSED)) { ObjSetMicro(dx,dy,534); } else if ((object[i]._otype == OBJ_L3DOORR) && ((object[i]._oVar4 == DOOR_OPEN) || (object[i]._oVar4 == DOOR_BLOCKED))) { ObjSetMicro(dx,dy,541); } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void SyncObjectAnim(int o) { int ai, ot, j; app_assert((DWORD)o < MAXOBJECTS); ot = object[o]._otype; ai = AllObjects[ot].ofindex; for (j = 0; ObjFileList[j] != ai; ++j); object[o]._oAnimData = pObjCels[j]; switch (object[o]._otype) { case OBJ_L1DOORL : case OBJ_L1DOORR : SyncL1Doors(o); break; case OBJ_L2DOORL : case OBJ_L2DOORR : SyncL2Doors(o); break; case OBJ_L3DOORL : case OBJ_L3DOORR : SyncL3Doors(o); break; case OBJ_CRUX1 : case OBJ_CRUX2 : case OBJ_CRUX3 : SyncCrux(o); break; case OBJ_SWITCHSKL: case OBJ_LEVER : case OBJ_BOOK2L: SyncLever(o); break; case OBJ_BLINDBOOK: case OBJ_STEELTOME: case OBJ_BOOK2R: SyncQSTLever(o); break; case OBJ_PEDISTAL: SyncPedistal(o); break; } } /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ void GetObjectStr(int i) { app_assert((DWORD)i < MAXOBJECTS); switch (object[i]._otype) { case OBJ_CRUX1 : case OBJ_CRUX2 : case OBJ_CRUX3 : strcpy(infostr, "Crucified Skeleton"); break; case OBJ_LEVER : case OBJ_FLAMELVR: strcpy(infostr, "Lever"); break; case OBJ_L1DOORL : case OBJ_L1DOORR : case OBJ_L2DOORL : case OBJ_L2DOORR : case OBJ_L3DOORL : case OBJ_L3DOORR : if (object[i]._oVar4 == DOOR_OPEN) strcpy(infostr, "Open Door"); if (object[i]._oVar4 == DOOR_CLOSED) strcpy(infostr, "Closed Door"); if (object[i]._oVar4 == DOOR_BLOCKED) strcpy(infostr, "Blocked Door"); break; case OBJ_BOOK2L: if (setlevel) { if (setlvlnum == SL_BONECHAMB) strcpy(infostr, "Ancient Tome"); else if (setlvlnum == SL_VILEBETRAYER) strcpy(infostr, "Book of Vileness"); } break; case OBJ_SWITCHSKL: strcpy(infostr, "Skull Lever"); break; // case OBJ_BOOKLVR: // strcpy(infostr, "Tome"); // break; case OBJ_BOOK2R: strcpy(infostr, "Mythical Book"); break; case OBJ_CHEST1: case OBJ_TCHEST1: strcpy(infostr, "Small Chest"); break; case OBJ_CHEST2: case OBJ_TCHEST2: strcpy(infostr, "Chest"); break; case OBJ_CHEST3: case OBJ_TCHEST3: case OBJ_SIGNCHEST: strcpy(infostr, "Large Chest"); break; case OBJ_SARC: strcpy(infostr, "Sarcophagus"); break; case OBJ_BOOKSHELF: strcpy(infostr, "Bookshelf"); break; case OBJ_BOOKCASEL: case OBJ_BOOKCASER: strcpy(infostr, "Bookcase"); break; case OBJ_BARREL: case OBJ_BARRELEX: if (currlevel >= HIVESTART && currlevel <= HIVEEND) strcpy(infostr, "Pod"); else if (currlevel >= CRYPTSTART && currlevel <= CRYPTEND) strcpy(infostr, "Urn"); else strcpy(infostr, "Barrel"); break; case OBJ_SHRINEL: case OBJ_SHRINER: sprintf(tempstr, "%s Shrine", shrinestrs[object[i]._oVar1]); strcpy(infostr, tempstr); break; case OBJ_SKELBOOK: strcpy(infostr, "Skeleton Tome"); break; case OBJ_BOOKSTAND: strcpy(infostr, "Library Book"); break; case OBJ_BLOODFTN: strcpy(infostr, "Blood Fountain"); break; case OBJ_DECAP: strcpy(infostr, "Decapitated Body"); break; case OBJ_BLINDBOOK: strcpy(infostr, "Book of the Blind"); break; case OBJ_STEELTOME: strcpy(infostr, "Steel Tome"); break; case OBJ_BLOODBOOK: strcpy(infostr, "Book of Blood"); break; case OBJ_PURIFYINGFTN: strcpy(infostr, "Purifying Spring"); break; case OBJ_ARMORSTAND: case OBJ_WARARMOR: strcpy(infostr, "Armor"); break; case OBJ_WARWEAP: strcpy(infostr, "Weapon Rack"); break; case OBJ_GOATSHRINE: strcpy(infostr, "Goat Shrine"); break; case OBJ_CAULDRON: strcpy(infostr, "Cauldron"); break; case OBJ_MURKYFTN: strcpy(infostr, "Murky Pool"); break; case OBJ_TEARFTN: strcpy(infostr, "Fountain of Tears"); break; case OBJ_PEDISTAL: strcpy(infostr, "Pedestal of Blood"); break; case OBJ_STORYBOOK: strcpy(infostr, StoryBookName[object[i]._oVar3]); break; case OBJ_WEAPONRACK: strcpy(infostr, "Weapon Rack"); break; case OBJ_MUSHPATCH: strcpy(infostr, "Mushroom Patch"); break; case OBJ_LAZSTAND: strcpy(infostr, "Vile Stand"); break; case OBJ_SLAINHERO: strcpy(infostr, "Slain Hero"); break; } if ((plr[myplr]._pClass == CLASS_ROGUE) && (object[i]._oTrapFlag)) { sprintf(tempstr, "Trapped %s", infostr); strcpy(infostr, tempstr); infoclr = ICOLOR_RED; } } static void SpellBook (int number, int locx, int locy) { AddSkulkenObject(OBJ_STORYBOOK, number, locx, locy); } static void AddNa_Krul_Stuff() { int spell; AddNaKrulLeverObj(); spell = random(0, 6); switch (spell) { case 0: SpellBook(6, Na_Krul.x + 3, Na_Krul.y); SpellBook(7, Na_Krul.x + 2, Na_Krul.y - 3); SpellBook(8, Na_Krul.x + 2, Na_Krul.y + 2); break; case 1: SpellBook(6, Na_Krul.x + 3, Na_Krul.y); SpellBook(8, Na_Krul.x + 2, Na_Krul.y - 3); SpellBook(7, Na_Krul.x + 2, Na_Krul.y + 2); break; case 2: SpellBook(7, Na_Krul.x + 3, Na_Krul.y); SpellBook(6, Na_Krul.x + 2, Na_Krul.y - 3); SpellBook(8, Na_Krul.x + 2, Na_Krul.y + 2); break; case 3: SpellBook(7, Na_Krul.x + 3, Na_Krul.y); SpellBook(8, Na_Krul.x + 2, Na_Krul.y - 3); SpellBook(6, Na_Krul.x + 2, Na_Krul.y + 2); break; case 4: SpellBook(8, Na_Krul.x + 3, Na_Krul.y); SpellBook(7, Na_Krul.x + 2, Na_Krul.y - 3); SpellBook(6, Na_Krul.x + 2, Na_Krul.y + 2); break; case 5: SpellBook(8, Na_Krul.x + 3, Na_Krul.y); SpellBook(6, Na_Krul.x + 2, Na_Krul.y - 3); SpellBook(7, Na_Krul.x + 2, Na_Krul.y + 2); break; } } static bool HCheckSpell(int number) { switch (number) { case 6: SpellProgress = 1; break; case 7: if (SpellProgress == 1) SpellProgress = 2; else SpellProgress = 0; break; case 8: if (SpellProgress == 2) { // qtextflag = FALSE; // stream_stop(); return true; } else SpellProgress = 0; } return false; } void OpenNaKrul() { if (currlevel == NA_KRUL_LEVEL) { PlaySfxLoc(CR_DOOROPEN, Na_Krul.x, Na_Krul.y); dPiece[Na_Krul.x][Na_Krul.y] = 298; dPiece[Na_Krul.x][Na_Krul.y - 1] = 301; dPiece[Na_Krul.x][Na_Krul.y - 2] = 300; dPiece[Na_Krul.x][Na_Krul.y + 1] = 299; SetDungeonMicros(); } } void OpenNaKrul2() { dPiece[Na_Krul.x][Na_Krul.y] = 298; dPiece[Na_Krul.x][Na_Krul.y - 1] = 301; dPiece[Na_Krul.x][Na_Krul.y - 2] = 300; dPiece[Na_Krul.x][Na_Krul.y + 1] = 299; SetDungeonMicros(); } static void AddNaKrulLeverObj() { int xp, yp; while (1) { xp = random(141,80) + DIRTEDGED2; yp = random(141,80) + DIRTEDGED2; if (! RndLocOk(xp-1, yp-1)) continue; if (! RndLocOk(xp+0, yp-1)) continue; if (! RndLocOk(xp+1, yp-1)) continue; if (! RndLocOk(xp-1, yp+0)) continue; if (! RndLocOk(xp+0, yp+0)) continue; if (! RndLocOk(xp+1, yp+0)) continue; if (! RndLocOk(xp-1, yp+1)) continue; if (! RndLocOk(xp+0, yp+1)) continue; if (! RndLocOk(xp+1, yp+1)) continue; break; } // temp test xp = Na_Krul.x + 3; yp = Na_Krul.y - 1; Na_Krul.LeverX = xp; Na_Krul.LeverY = yp; AddObject(OBJ_LEVER, xp, yp); }