If you appreciate the work done within the wiki, please consider supporting The Cutting Room Floor on Patreon. Thanks for all your support!

Development:Diablo (Windows)

From The Cutting Room Floor
Jump to navigation Jump to search

This page details development materials of Diablo (Windows).

How about a nice leek in this trying time?
This page or section details content from the June 2019 Diablo Hellfire Leak.

On June 29th, 2019, the source code for Diablo's expansion, Hellfire, was leaked on the Internet Archive. It can be downloaded here.

Contents

Among the source code are a number of interesting files.

BUGS.TXT

*) in MonsterStruct the field mArmorClass should be a short instead of a char.
   Currently it overflows in HELL mode.
   
*) Peril and Devastation can be on Bows but do nothing. Peril should be
  removed from bows, Devastation damage should be added to the arrows.

*) Items of Jester have a 0 to 600% damage, not 0-> to 500% either
   change the text or the calculation.

*) If you drop a weapon then pick it up (For a Barbarian anyway) half your 
   life pts come back. (Inventory bug)
   
*) Doppelganger can clone a golem. (Should be prevented)

*) Rage go to town, and back and you are in a permant rage.

D523BD.ZIP, D523BF.ZIP

These files contain the original executable for Diablo, dated May 23, 1997, hence the name of the files. This approximately corresponds to version 1.04 of the game. D523BD.ZIP contains a debug build of the game, and D523BF.ZIP contains a final release build of the game.

FIXES.TXT


*) Fixed the bug where picking up gold when your inventory is full
duplicates the gold in your hand and fills your gold slot.

*) Fixed the Berserk spell to prevent crashes.

*) Fixed entering the new levels.

*) Fixed to dropping and picking back up oiled items.

*) Fixed generating spell books by Adria.

*) Fixed placing of weapons for all player classes.

*) Fixed generating rings of fire behind a wall.


Donald:

*) Fixed Gosip.

*) Fix to item changing between games.

12/29/97
*)Fix to gold cursor when full of gold in inventory.

FUTURES.TXT

This file apparently seems to describe a Priest class that never made it to the final release.

Bad Priest: 
  Low max strength:
  Medium armor cuts spell level in half.
  Full armor sets spell level to 1.
  
  Daggers and small swords are best.
  
  
  Large weapons don't do full damage. (Priest is too weak)
  
  Benefit: mana cost is really low.  Heal other in Multiplayer mode

PATCH.TXT

This file seems to document changes made by a developer with the initials "pjw"

--------------------------------------------------------------------
patch.txt
--------------------------------------------------------------------



--------------------------------------------------------------------
PATCH 1 -- 1/13/97
--------------------------------------------------------------------


diabloui.dll (connect.cpp)
--------------------------------------------------------------------
corrects crash bug when attempting to join game created with an
invalid time (year < 1970 or year > 2036)

checks for characters with (level==0) and treats that as an invalid
diablo character (no portrait, can't create or join)

mike.rc
--------------------------------------------------------------------
Added version information


storm.dll (snet.cpp)
--------------------------------------------------------------------
send relative time instead of absolute time to players joining game
(helps correct diabloui crash bug)


standard.snp (ipx.cpp)
--------------------------------------------------------------------
run-time dynamically link to wsock32.dll to prevent errors when
that file does not exist.


battle.snp (chatchnl.cpp)
--------------------------------------------------------------------
fixed deallocated pointer error which caused player to get locked out
after creating a channel

joingame.cpp
--------------------------------------------------------------------
added more descriptive messages for can't join if game is full or
game owner is not responding.

games shown in the list of public games will not disappear anymore.
The list will be refreshed only if the user closes and opens the join 
game dialog.

scrollrt.cpp
engine.cpp
--------------------------------------------------------------------
corrects the NULL cell buffer errors and other data corruption in draw code
now uses "GRACEFUL_EXIT" to prevent fatal exits on error conditions


diablo.rc
--------------------------------------------------------------------
version number changed
changed IDESCAPE to IDCANCEL for IDD_CDROM_ERR dialog
now matches code in appfat.cpp


init.cpp
--------------------------------------------------------------------
version number changed


dx.cpp -- init_backbuf()
--------------------------------------------------------------------
potential bug -- never actually seen
commented out ddraw_assert on failure to unlock video surface.
In NT it is possible to lose a video surface while it is locked.


dx.cpp:170 -- init_directx() fail on SetDisplayMode
--------------------------------------------------------------------
reported bug -- occurs on some notebook systems
if direct draw doesn't support switching screen resolutions, try
switching color depth and keep same screen resolution


wave.cpp -- patSFileReadFile()
--------------------------------------------------------------------
reported bug -- can't recover from read failure
if read failure occurs, restart read from beginning,
not from where read error occurred


wave.cpp/appfat.cpp -- InsertCDDlg()
--------------------------------------------------------------------
reported bug -- both OK and Exit buttons did the same thing (oops)


sound.cpp -- snd_restore_snd()
--------------------------------------------------------------------
potential bug -- never actually seen
if sound buffer cannot be locked, no error occurs, sound skipped


sound.cpp:384 -- snd_set_format()
--------------------------------------------------------------------
reported bug -- sound cards don't support SetFormat()
commented out assertion


diablo.cpp -- CommandLine()
--------------------------------------------------------------------
fixed silly problem with special direct draw command line options so
they can now appear anywhere on the command line instead of at the end


init.cpp -- MainWndProc()
--------------------------------------------------------------------
correct palette problems when other applications realize their 
palettes in the background.


pfile.cpp
--------------------------------------------------------------------
removed "retribution" code which deletes player inventory when
cheating dectected.


mpqapi.cpp
--------------------------------------------------------------------
removed time-stamp save code which appears to damage registry on
some systems.  Code was related to "retribution" code

The "retribution" code mentioned here appears to an aggressive anti-cheating system that would damage the user's computer if cheating was detected.

UNIQUES.TXT

This appears to be an email from Donald Tsang, the lead programmer for Synergistic Software at the time, detailing how the unique item generation system works.

------------Donald------------

Re: Mr. Tsang Could you Please... from Donald Tsang (donaldtsang), Wed Jan 28 15:47:19 US/Pacific 1998 In-reply-to To Mister Tsang.

(please call me Donald; "Mr. Tsang" makes me feel old. :)

Okay, so the random item generator has determined that you may deserve a random unique of a certain type (say, rings).

Now it goes through the list of uniques, and sees if there are any that you're allowed to have on that dungeon level (plus a few if you're getting this from a unique critter) that you haven't already found this session.

It then takes the last one of those it finds (which is, presumably, the highest-level-and-therefore-best), and gives it to you.

Me, I would've made that last step just a random pick from the list (perhaps weighted toward the highest-level one), but what do I know? 

Tsang's analysis is mostly correct, but it misses a few critical caveats regarding it.

Windebug

At first glance, this folder appears to include a debug build of the game. However, it actually has a lot of hidden secrets within it.

GENDATA/HELLFIRE.SAV

This is a higher quality version of the HELLFIRE.SMK video that plays at the start of the game.

SFX/HELLFIRE

This folder has a number of sound effects that are referenced by the code, but aren't present in hfvoice.mpq.

File Name Speaker Audio Transcript Notes
CRNRSTON.WAV Unknown
And in the year of Golden Light, it was so decreed that a great cathedral should be raised, for the glory of Heaven. And for the cornerstone was brought from the Holy Land a block of translucent stone. And the stone was of this world, and of all worlds, as the spirit of Light is both within and beyond us, in all things.

The stone brought all it touched to all the worlds, uniting them in Light. In the Year of the Drawing Shadows, the ground shook, and the cathedral tumbled and shattered. And in the time that followed, of the building of catacombs and castles against the ravages of the Sin War, the ruins were taken for their stones. And so it was that the Cornerstone vanished from the eyes of man, lost, perhaps forever.

The source code has two sets of text for a subtitle for this - one that is commented out, and one that is not. They both vary, but the one that is commented out matches this source file.
DEFILER1.WAV The Defiler
Ahh, mammal, welcome. Such a... tasty planet you have. My Nest shall spread across this land, and you and your species shall serve as food for our colony. I'm sure our meeting will be quite... delicious. Has matching subtitles in the source code. Has a completely different voice actor.
DEFILER2.WAV
Have you been enjoying yourself, little mammal? How pathetic. Your little world will be no challenge at all.
DEFILER3.WAV
Come closer, morsel...come find me, the Defiler. I have waited thousands of years...do not try my patience any further.
DEFILER4.WAV
Ah, I can smell you...you are close! Close! Ssss...the scent of blood and fear...how enticing...
DEFILER5.WAV
Ah, there you are! We meet at last...and you will be meat...at last... Has a completely different voice actor.
FARMER10.WAV Lester the Farmer
Gillian is the girl that works for Ogden at the Rising Sun Inn. Between you and me, she's not too bright. But she is sweet enough to rot your teeth. Heh heh. This appears to be gossip for Lester. Unfortunately though, Lester doesn't have any code to do gossping.
FARMER11.WAV
I supply Ogden with all sorts of fresh produce and dairy products. He's a bit squirrelly at times, but he's a good fellow. You should drop by and see him sometime.
FARMER12.WAV
If Farnham would listen to my advice and stick to cold milk as opposed to warm ale, he'd be a productive member of society by now.
FARMER13.WAV
Griswold is as big as a tree, and strong as an ox. He's also very well schooled in the art of crafting weapons and armor. So if you need anything like that...well, that's where I'd go.
FARMER14.WAV
Oh, Cain is a might strange if you ask me. And, since you have, I'll let you in on a little secret. He can divine the secrets of anything, but his powers require the mystic powers that reside within gold. Or at least, that's what I heard him tell Griswold.
FARMER15.WAV
Adria lives in that run-down old shack right across the river. Strange things happen there at night. But, she's nice enough and never bothers my cows. So, she's alright by me.
FARMER16.WAV
If you're ever hurt, or just want to tell someone your problems, Pepin is the person to see. Rumor has it that he even has the power to raise people from the dead. But, I don't believe it.
FARMER17.WAV
That Wirt! What a little hellion! Oh...I guess that's not such a nice thing to say, what with things being the way they are and all...
SKLJRN1.WAV Skulken the Necromancer
Cloudy and cooler today. Casting the nets of necromancy across the void landed two new subspecies of flying horror; a good day's work. Must remember to order some more bat guano and black candles from Adria; I'm running a bit low. Appears to be used from a "skull journal", the journal of a necromancer?
SKLJRN2.WAV
I have tried spells, threats, abjuration and bargaining with the new creature. My means which have enslaved many lesser demons have no effect on this fearsome beast; it only leers at me in a most unpleasant fashion. This line, and the lines that follow it, aren't correctly subtitled in the code, but aren't used at all either. Rather, the correct subtitles for these lines are listed in comments above the code for them.
SKLJRN3.WAV
The trapped creature's howls of fury keep me from sleep-- it rages and curses the name of the one who sent it to the void, and against myself, for trapping it here. Its words fill my heart with terror, yet I cannot block out its voice.
SKLJRN4.WAV
My home is coming alive, corrupted by the darkness of my unwanted prisoner... The crypts are full of shadows... I see things at the corners of my vision, hear the sounds of claws, and of searching. Searching, I think, for me. For this journal. They must not learn the secret! The creature must not be released!
SKLJRN5.WAV
In its ranting, the creature has let slip its name. It calls itself Na-Krul. The name is familiar to me... I wish I could research it, but the smaller horrors have destroyed my library in their endless searching. Still, the syllables fill me with a cold dread... I prefer to think of it as only the creature rather than ponder its true name.
SKLJRN6.WAV
Time is running out. With my last entry I must reveal the way to defeat the demon, then conceal that text, lest the demon-creatures find some way to use my knowledge to free their lord. I have kept my athame, at least; when all is lost I would rather meet my death at the end of a dagger, than at the claws of a demon.
SKLJRN7.WAV
Whoever finds this, you must stop this demon creature. It is too late for me now; its hellish minions are clawing at this last door behind which I cower. I have hobbled the creature by powerful spells and encased it behind thick walls, yet it will not be enough. You will need the power of the spells in my three grimoires, cast only in their proper sequence. The levers at the entry will remove the barriers and free the demon; touch them not! Use only the spells! The spells in the correct sequence will open the magical doorways, and allow you to face the demon and, I hope, defeat it.

May the Heavens have mercy on us all.

TRDSNG1.WAV Wandering Trader
♬ A wandering rhyming trader I,

Doomed to never sell nor buy,

But only switch, exchange and swap,

Losing money with every stop,

Wait a moment, stay a while,

I've got a deal to make you smile,

A deal that you'll be glad you made,

If you and I can work a trade. ♬

Sung in a sing-song fashion. These lines don't appear anywhere in the code, comments or otherwise.

Voiced by Donald Tsang, the lead programmer of Hellfire.

TRDSNG2A.WAV
♬ Here's a bauble shining bright,

For man or maiden's fair delight. ♬

TRDSNG2B.WAV
♬ Here's a weapon, sure and true,

A trade and it belongs to you. ♬

TRDSNG2C.WAV
♬ Here is armor strong and tough,

Yours if the trade is good enough. ♬

TRDSNG2D.WAV
♬ Here's a book, a text, a tome,

Trade with me and take it home. ♬

TRDSNG3A.WAV
♬ If this prize is worth some strife,

Then bring to me a magic knife. ♬

TRDSNG3B.WAV
♬ I only trade, I do not joke,

In trade I'll take a magic cloak. ♬

TRDSNG3C.WAV
♬ To get it all you need to bring is a simple, magic, ring. ♬
TRDSNG3D.WAV
♬ I'll swap you this,

and in its place,

I'll take a simple, normal mace. ♬

TRDSNG3E.WAV
♬ Wander far and search a field,

Return to me and bring a shield. ♬

TRDSNG4.WAV
♬ Alas my friend, what you have brought,

Is not in fact, that which I sought.

We can do business still I feel,

Let me propose another deal. ♬

TRDSNG5.WAV
♬ You have it, that's perfect.

Then it's a deal.

A bargain, a bonus, it's almost a steal.

Take this with my blessings,

Fellow trader most wise.

Now I bid you good deals,

And I bid you good buys. ♬ (Byes?)

TRDSPK1.WAV
A wandering rhyming trader I, doomed to never sell nor buy, but only switch, exchange and swap, losing money with every stop. Wait a moment, stay a while, I've got a deal to make you smile, a deal that you'll be glad you made, if you and I can work a trade. Spoken-tone version of the above. These don't appear anywhere in the code.

Voiced by Donald Tsang, the lead programmer of Hellfire.

TRDSPK2A.WAV
Here's a bauble shining bright, for man or maiden's fair delight.
TRDSPK2B.WAV
Here's a weapon, sure and true. A trade and it belongs to you.
TRDSPK2C.WAV
Here is armor strong and tough. Yours if the trade is good enough.
TRDSPK2D.WAV
Here's a book, a text, a tome. Trade with me and take it home.
TRDSPK3A.WAV
If this prize is worth some strife, then bring to me a magic knife.
TRDSPK3B.WAV
I only trade, I do not joke. In trade I'll take a magic cloak.
TRDSPK3C.WAV
To get it all you need to bring is a simple, magic, ring.
TRDSPK3D.WAV
I'll swap you this, and in its place, I'll take a simple, normal mace.
TRDSPK3E.WAV
Wander far and search a field, return to me and bring a shield.
TRDSPK4.WAV
Alas my friend, what you have brought, is not in fact, that which I sought. We can do business still I feel. Let me propose another deal.
TRDSPK5.WAV
You have it, that's perfect. Then it's a deal. A bargain, a bonus, it's almost a steal. Take this with my blessings, fellow trader most wise. Now I bid you good deals, and I bid you good buys. (Byes?)

SFX/MONKOLD

Within this folder is a completely different voiceover for the Monk character. Unlike the one that is used by the retail game, this one actually has a complete set of dialogue. That is, the Monk character in the final game (and indeed, the files within SFX/MONK) doesn't have all of the missing lines that are present in the vanilla/non-expansion game, but this different set of dialogue does.

Perhaps this one wasn't chosen because it has a pretty stereotypically Asian accent, or maybe because the sound quality wasn't as good. The true reason is unfortunately unknown.

MONKOLD (Not used) MONK (Used)

Backlash Files

In a rather bizarre twist, the source code dump also features some files belonging to the Hellfire Multiplayer Patch, which might suggest that the original developers of Hellfire had some part to play in developing it.

BACKLASH.NFO


     ß                                       ß                       ß   Ý
     Û  Ü               Ü          ÜÛÜ  Ý ÛÜ  ßÜÛÜ                  ÜÛÜß ÛÝ
   ° ÛÛÜ  ßÜÜ ÜÛÜß   ÜÛÛ  Üß   ß ßßßß   Û ßßß   ßßßß ß  ß ßÜÛßß ß ßßß ßß ÛÛ ßÜ
   ± ÛßÛÛÜ  ßÛÛß ÜÜÛÛßß  Ûß ÜÜÛÛÛÛÛÛÛß ÞÛÝÛÛÛÛÛÛß ÜÜÛÛÛ²±°  ÜÜÛÛÛÛÛÛ²±°  ÛÛÛ Û
   ° ÛÛÛÛÛÛÜ  ß ÛÛÛß °°°  ÜÛÛß ÜÜ  ÜÜ  ÛÛ        ÛÛÛß ÜÜÜ  ÛÛÛß Ü  ÜÜÜ Þ ÛÛÛ Û
     ÛÛÛ ßÛÛÛÜ ßÛÛ Ü ±±± ÞÛÛ  ÛÛÛ Ûß ÜÛÛß °°° ß ÛÛÛ Ü ÛÛÛ ÛÛÛ  ßßÜ ÛÛÛ ² ÛÛÛ Û°
   ° ÛÛÛ Ü ßÛÛÛ ÛÛ ß ²²² ÛÛÝÞ ÛÛÛ  ÜÛÛß  ±±±± Þ ÛÛÛ   ÛÛÛ ßÛÛÛÜÜÜ  ÛÛÛ ß ÛÛÛ Û±
   ± ²²² ß ÜÛÛÛ ÛÛ ÛÛÛÛÛ ÛÛ ²Ý²²²ÛÛÛß Ü² ²²²² Û ²²² ÛÛÛÛÛ Ü    ßÛÛÜ ßÛ ÛÛÛÛÛ ²°
  °² ±±± ßÛÛÛß ÜÛÛ   ÛÛÛ ÛÛ Þ ±±± ßÛÛÜ ß ÛÛÛÛ ² ±±± Ü ÛÛÛ °ÛÛÛÜ  ÛÛÛ Û Ü ÛÛÛ ±
  ±Û °°° Ü ßÛÛÜ ßÛ Ý ÛÛÛ ÛÛÝ  °°° Ü ßÛÛÜ ßÛÛÛ Ý °°° ² ÛÛÛ   ß²ßß ÛÛÛ Û ² ÛÛÛ °
  °Û     ßß  ÛÛÛ Û Û ÛÛÛ ÞÛÛÜ     ßß  ÛÛÛ ÛÛÛÜ        ÛÛÛ  ß   ÜÛÛÛß Û Ü ÛÛÛ
   ßÛÛÛÛÛÛÛÛÛÛÛß Û Ü ÛÛÛ  ßÛÛÛÛÛÛÛ²±° ÛÛÛ  ßÛÛÛ²±° °± ÛÛß ²ÛÛÛÛÛÛß ÜÛßÞÜ ÛÛÛ °
            Ü    Ý   ÛÛÛ ßÜ   ÜÜÜ  Ü  ßÛÛ ÛÜÜ Ü       Û            Þ   ßÝÞÛÝ ±
     ß ßß ßßßÛÛÜÜ ÜÝ Ûß  ßÛß   ÛÝ ßÛÛÜ Û ÜßÛÜÛßßßß ß  Ý ß ASCII<ROY/SAC>  Û  °
      ß ßßÛß Ý  ß      Þ  ß  ß Ý   Ûß ß proudly presents                  Ý


  ÚÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄ¿
 ÚÁÄùú                                                                    úùÄÁ¿
 ³³ þ                 DiABLO HELLFiRE MULTiPLAYER PATCH                    þ ³³
 ÀÂÄÄÄÄùú                                                              úùÄÄÄÄÂÙ
 ÚÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅ¿
 ³³   SUPPLiER......:n/a                ÆÅ REQUiRED CPU.......:P90           ³³
 À³Ä  CRACKER.......:LTD.               ³³ REQUiRED RAM.......:16MB         ijÙ
 Ú³ÄÄ STRiPPER......:n/a                ³³ REQUiRED HD SPACE..:-           Äij¿
 ³³   PACKAGER......:LTD                ŵ REQUiRED OS........:WIN95              ³³
 ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ³
 À³¿  RELEASE.DATE..:11/30/97           ÆÅ DiRECTX............: 5.0         Ú³Ù
  ³ú  PROTECTiON....:n/a                ³³ SVGA...............: YES         ú³
  ³ú  RELEASE.SiZE..:2kb                ³³ SOUNDBLASTER.......: YES         ú³
 Ú³Ù  GAME TYPE.....:RPG                ŵ GENERAL-MiDi.......: NOPE        À³¿
 ³ÀÄÄÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÍÄÄÙ³
 ÀÂÄùú  ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ  úùÄÂÙ
  ÀÄÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄÄÙ


  ÚÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄ¿
 ÚÁÄùú                                                                    úùÄÁ¿
 ³³ þ                            RELEASE NOTES:                            þ ³³
 ÀÂÄÄÄùú      As we all was and are big fans of this fantastic                ³
  ³           RPG we missed the Multiplayer Options which made                ³
  ³           Diablo one of the best games in `97.                            ³
  ³           And when i saw that Multiplayer Routines are included           ³
  ³           in the Release of Hellfire i looked through the code            ³
  ³           and found the routine.                                          ³
  ³           Seems that just some Beta testers was allowed to play           ³
  ³           Hellfire in Multiplayer Mode.                                   ³
  ³           I take no responsibility for any damage to your character       ³
  ³           crashed or whatever while using this patch.                     ³
  ³           Battle.Net isnt supported, guess why! :p                        ³
  ³                                                                     úùÄÄÄÂÙ
  ³                                                                          ³
  ³                                                                          ³
  ³                                                                          ³
 ÚÁÄùú                                                                    úùÄÁ¿
 ³³ þ                            iNSTALL NOTES:                            þ ³³
 ÀÂÄùú                                                                    úùÄÂÙ
  ³           Run the patch from your Hellfire Directory!                    ³
  ³           Thats all!                                                     ³
  ³                                                                          ³
  ³                                                                          ³
  ³                                                                          ³
  ³                                                                          ³
 ÚÁÄÄÄùú                                                                úùÄÄÄÁ¿
 ³³ þ                                                                      þ ³³
 ÀÂÄùú                                                                    úùÄÂÙ
  ³                                                                          ³
  ³                                                                          ³
  ÀÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄÙ


  ÚÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄ¿
 ÚÁÄùú                                                                    úùÄÁ¿
 ³³ þ                           GROUP GREETiNGS                            þ ³³
 ÀÂÄÄÄùú                                                                úùÄÄÄÂÙ
 Ú³Ù                                                                        À³¿
 þ³        CAMPAiGN - CLASS - PARADOX - RAZOR - SAC - SCANDAL - TRSi         ³þ
 À³¿                                                                        Ú³Ù
 ÚÁÄÄÄùú                                                                úùÄÄÄÁ¿
 ³³ þ            WE ARE BACK iN FULL ARMOR, SO TAKE CARE BOYS!!            þ ³³
 ÀÂÄùú                                                                    úùÄÂÙ
  ÀÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄÙ


  ÚÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄ¿
 ÚÁÄùú                                                                    úùÄÁ¿
 ³³ þ                                                                      þ ³³
 ÀÂÄÄÄùú Ú¿                                                          Ú¿ úùÄÄÄÂÙ
 Ú³ÄÄÄÄÄÄÁ³¿                      LTD..ASMADi                       Ú³ÁÄÄÄÄÄij¿
 À³¿     Ú³Ù                                                        À³¿     Ú³Ù
  ³³     ³³   APOLLO..CAULDRON..COCKROACH..CONTROL..CYRAXX..FiBRE    ³³     ³³
  ³³     ³³      FLi7E..iNFiNiTY..JAYDEE..KHADGAR..LGB..MAYHEM       ³³     ³³
  ³³     ³³    OVERHEAD..OLiVER STONED..PALLADiN..QUAD..SEKTOiD      ³³     ³³
  ³³     ³³     SiLVER..STUPiT..TANKARD..YODLER..ZoLDAN..ZZ187       ³³     ³³
 Ú³Ù     À³¿                                                        Ú³Ù     À³¿
 ÀÅ¿     ÚÅÙ                                                        ÀÅ¿     ÚÅÙ
  À³ÄÄÄÄij٠                                                         À³ÄÄÄÄijÙ
  ÚÙ     ³                    BLH-HELPLiNE@USA.NET                    ³     À¿
  ³³ þ  ÚÙ                                                            À¿  þ ³³
  ÀÂÄùú ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ úùÄÂÙ
   ÀÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄÙ


  ÚÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄ¿
 ÚÁÄùú                                                                    úùÄÁ¿
 ³³ þ                         DiSTRiBUTiON SYSTEMS                         þ ³³
 ÀÂÄÂÄÄÄùú                                                            úùÄÄÄÂÄÂÙ
  ³ÚÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅ¿³
 Ú³Ù³ T.. N...........     ĵ  4 NODES  Å  BBS  GERMAN HQ ÆÄ    10 GiGZ    ³À³¿
 óÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅij´
 ³³ ³ F....... O. S....... ĵ  34 MBiT  Å  FTP   WORLD HQ ÆÄ    13 GiGZ    ³ ³³
 óÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅij´
 ³³ ³ T.. R..... M.....    ĵ 100 MBiT  Å  FTP    EURO HQ ÆÄ    26 GiGZ    ³ ³³
 óÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅij´
 ³³ ³ C......              ĵ  10 MBiT  Å  FTP  GERMAN HQ ÆÄ    19 GiGZ    ³ ³³
 óÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅij´
 À³¿³ T.. W..... H....     ĵ  34 MBiT  Å  FTP   DUTCH HQ ÆÄ     7 GiGZ    ³Ú³Ù
  ÃÙÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙÀ´
 ÚÁÄÄÄÄÄùú                                                            úùÄÄÄÄÄÁ¿
 ³³ þ                                                                      þ ³³
 ÀÂÄùú                                                                    úùÄÂÙ
  ÀÄÄÄÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄÄÄÄÙ

 
  ÚÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄ¿
 ÚÁÄùú                                                                    úùÄÁ¿
 ³³ þ          A SOFTWARE WORTH CODiNG í iS A SOFTWARE WORTH USiNG         þ ³³
 ÀÂÄÄÄùú                                                                úùÄÄÄÂÙ
  ÀÅÄÄÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄÄÄÅÙ
   ÀÄÄÄÄÄÂÄÄÄÄÄ[ NFO HEADER BY ROY <SAC> - NFO DESiGN BY YOdLER ]ÄÄÄÄÄÂÄÄÄÄÄÙ
         ÀÄÄÄÄÄÄÄÄÄÄÄÄ[ LAST UPDATE: 11-18-97 BY MAYHEM ]ÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

                   - - -- ---> FEEL THE BACKLASH <--- -- - - 

FILE_ID.DIZ

   DiABLO HELLFiRE MULTiPLAYER PATCH [1/1]  
ßßßßÛÜßßßßÛÜßßßßÛÛ ²Û ÛÛ ²Û ßßßÛÜ ÜÛßÛÛßßß ÜÛ
:²ÛÜÛß ²Û ÛÛ ²Û ß  ÛÛÜÛß ÛÛ ²Û ÛÛ ßÛÜÜ  ²ÛÜÛÛ
|ÛÛ Û² ÛÛßÛÛ ÛÛ Ü  ÛÛ ÛÛ ÛÛ ÛÛßÛÛ ÜÜ ÛÛ ÛÛ ÛÛ
³ÛÛÜÛß ÛÛ Û² ßÛÜÛÛ ÛÛ Û² ßÛÜÜÜ Û² ²ÛÜÛß ÛÛ Û²
ÀÄÄÄÄ[ RELEASE DATE: 11/30/1997 ]ÄÄÄÄÄroyÄÄÄÄ

HELLFIRE.LDB

It's not known what this file was used for precisely, but it seems to list a user named GARYP within it:

GARYP                           Admin                           

The Code Itself

All files

All of the files developed by Blizzard North have a header that follows this convention:

/*-----------------------------------------------------------------------**
** 								Diablo
**
**							   <file purpose>
**
** 				(C)1995 Condor, Inc. All rights reserved.
**
**-----------------------------------------------------------------------**
**	$Header: /Diablo/DIABLO.CPP 16    <date> <name> $
**-----------------------------------------------------------------------*/

There's two interesting things: first that the headers all still mention the game developers as Condor, Inc, instead of Blizzard North, and that these date back to 1995.

For example, this is CURSOR.CPP, which was last edited by David Brevik on February 12, 1997:

/*-----------------------------------------------------------------------**
** 								Diablo
**
**							  Cursor file
**
** 				(C)1995 Condor, Inc. All rights reserved.
**
**-----------------------------------------------------------------------**
**	$Header: /Diablo/CURSOR.CPP 4     2/12/97 10:48a Dbrevik2 $
**-----------------------------------------------------------------------**
**
** 							 File Routines
**-----------------------------------------------------------------------*/

Any other files from Blizzard Entertainment have a header like this:

//***********************************************************************
//   Assertion System
//
//   Copyright (c) 1996 by Blizzard Entertainment.
//   All rights reserved.
//***********************************************************************

The Hellfire developers don't seem to have edited any of these headers.

HELLFIRE2

There's an unused preprocessor definition: HELLFIRE2. Any of the code contained within is content that wasn't implemented in Hellfire, perhaps due to lack of time or resources, and was probably intended to be in a second expansion pack for Diablo. Unfortunately, that didn't materialize.

The following sections have been found:

#if defined (HELLFIRE2)
		SI_RINGOFFIRE,		// SPL_RINGOFLIGHT
		SI_REDSKULL,		// SPL_AURA
		SI_ETHERALIZE,		// SPL_SPIRALFIREBALL
#endif

The above maps some unused spell icons to three spells that aren't fully defined: "Ring of Light", "Aura", and "Spiral Firebolt."

#if defined (HELLFIRE2)
	{ SPL_RINGOFLIGHT,	  					// #defines name of spell for ease of use
	28,										// base cost in mana
	ST_LIGHT,								// spell type (fire, light, misc)
	"Ring of Light",						// text name of spell
	NULL,									// text name of spell if it can be a skill
	6,										// lvl book can be found
	6,										// lvl staff can be found
	TRUE,									// Targeted spell?
	FALSE,									// Avail in town?
	23,										// min intelligence to use
	IS_CAST2,								// sfx to use
	{ MIT_LIGHTBOX, NULL, NULL },			// missiles to launch per casting
	2,										// mana adj per spell lvl
	16,										// min mana for use
	8,										// min number of staff charges
	16,										// max number of staff charges
	6000,									// book cost
	400 },									// scroll cost
	
	{ SPL_AURA,								// #defines name of spell for ease of use
	30,										// base cost in mana
	ST_LIGHT,								// spell type (fire, light, misc)
	"Aura",									// text name of spell
	NULL,									// text name of spell if it can be a skill
	1,										// lvl book can be found
	1,										// lvl staff can be found
	FALSE,									// Targeted spell?
	FALSE,									// Avail in town?
	33,										// min intelligence to use
	IS_CAST4,								// sfx to use
	{ MIT_AURA, MIT_AURA2, NULL },			// missiles to launch per casting
	2,										// mana adj per spell lvl
	16,										// min mana for use
	20,										// min number of staff charges
	40,										// max number of staff charges
	7500,									// book cost
	500 },									// scroll cost

	{ SPL_SPIRALFIREBALL,					// #defines name of spell for ease of use
	6,										// base cost in mana
	ST_FIRE,								// spell type (fire, light, misc)
	"Spiral Firebolt",						// text name of spell
	NULL,									// text name of spell if it can be a skill
	1,										// lvl book can be found
	1,										// lvl staff can be found
	FALSE,									// Targeted spell?
	FALSE,									// Avail in town?
	15,										// min intelligence to use
	IS_CAST2,								// sfx to use
	{ MIT_SPIRALFIREBALL, NULL, NULL },			// missiles to launch per casting
	1,										// mana adj per spell lvl
	3,										// min mana for use
	40,										// min number of staff charges
	80,										// max number of staff charges
	1000,									// book cost
	50 },									// scroll cost
#endif	// HELLFIRE2

The above defines the main data for the spells.

void AddAura(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
{
#if (PRE_BETA && PRE_FLASH) || !PRE_BETA

#if defined(HELLFIRE2)
	app_assert(mi < MAXMISSILES && mi >= 0);
	if (mienemy == MI_ENEMYMONST) {
		if (id != -1) {
			missile[mi]._midam = 0;
			missile[mi]._mirange = 245 + (10 * missile[mi]._mispllvl) + (2 * (id > 0) ? plr[id]._pLevel : 1);
			plr[id]._pBaseToBlk += 50;
			UseMana(id, SPL_AURA);
		} 
	}
#endif
	//PutMissile(mi);
#else
	missile[mi]._miDelFlag = TRUE;
#endif
}

The above is some code for the Aura spell.

// The first entry will be filled during init with the player types skill
int SpellPages[6][7] = {
	{ 0, SPL_FIREBOLT, SPL_CBOLT, SPL_HBOLT, SPL_HEAL, SPL_HEALOTHER, SPL_FLAME },
	{ SPL_RESURRECT, SPL_WALL, SPL_TELEKINESIS, SPL_LIGHTNING, SPL_TOWN, SPL_FLASH, SPL_STONE },
	{ SPL_PHASE, SPL_MANASHLD, SPL_ELEMENT, SPL_FIREBALL, SPL_WAVE, SPL_CHAIN, SPL_GUARDIAN},
	{ SPL_NOVA, SPL_GOLEM, SPL_TELE, SPL_APOCA, SPL_BONESPIRIT, SPL_BSTAR, SPL_ETHER },
	{ SPL_LTWALL, SPL_IMMOLATION, SPL_TELESTAIRS, SPL_REFLECT, SPL_BERSERK, SPL_RINGOFFIRE, SPL_SHOWMAGITEMS },
#if defined (HELLFIRE2)
	{ SPL_RINGOFLIGHT, SPL_AURA, SPL_SPIRALFIREBALL, -1, -1, -1, -1 }
#else
	{ -1, -1, -1, -1, -1, -1, -1 }
#endif
};

HELLFIRE2 would've had a sixth spell page with Ring of Light, Aura, and Spiral Firebolt in it. The rest of the entries are undefined for the page.

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
				}
			}
		}
	}
}
#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

HELLFIRE2 has an additional trap type that creates a small lightning wall. The comment in this code lists another cool trap idea.

Cheats

If the game is compiled with the CHEATS preprocessor definition, it opens up quite a few codepaths that aren't active in the retail version of the game.

Adding any of these commandline arguments to the game will trigger special behavior:

Commandline Argument Notes
b Writes item drops to C:/droplog.txt.
i Inactive players in multiplayer aren't booted out of the game.
$ From the code: "this cheat flag is for testing without having your character die every two seconds -- doesn't have all the nasty side effects of the cheat flag"

It has the following effects:

  • Your attacks never miss.
  • Your attacks always kill monsters in one hit.
  • Monsters never hit the player.
  • You don't take damage from Blood Star or Bone Spirit.
  • New character saves always have Level 1 Teleport.
^ From the code: "this cheat flag is the do-everything cheat for programmers -- it has all sorts of nasty side effects which may hide bugs"

It has the following effects:

  • Pressing 'A' will activate the monster under your cursor.
  • Pressing 'a' will increase the current spell on your speedbar by 1 level. It'll also allow Teleport to be used while in town.
  • Pressing '0' or ')' will cycle between your character firing fire arrows, lightning arrows, and normal arrows (if you are using a bow)
  • Pressing 'l' or 'L' will toggle your light radius.
  • Pressing 't' or 'T' will display the player's current position on the screen, and if a monster is hovered, it will show its position on the screen as well.
  • Monsters always drop items.
  • Your attacks never miss.
  • Your attacks always kill monsters in one hit.
  • Monsters never hit the player.
  • You don't take damage from Blood Star or Bone Spirit.
  • Spells don't cost mana and can be cast in all situations.
  • The player is spawned initially near the mausoleum.
  • New character saves have all spells memorized at the start of the game.
d The "dave debug" mode. It allows all unique monsters to spawn on any level. Additionally, items that drop are always unique and you can talk to NPCs from any distance away.
w The "dave cheat" (possibly programmed in by David Brevik). This has a number of effects, including:
  • When the game is compiled in cheat mode, normally premium items sold by Griswold have an uncapped level. This caps them to their retail release level of 20.
  • You start the game with 200000 gold instead of 100 gold.
  • Pressing ? turns on Quest Message debug.
  • Pressing Escape while the Quest Message debug is active will pop up a quest dialogue. Pressing + and - will cycle between them.
  • Pressing + speeds up fullscreen dialogue from NPCs while in Quest Message debug. Pressing - slows it down. This only works on NPCs in town, not in the dungeon.
  • Pressing | fills the inventory full of gold.
  • Pressing ~ restocks Adria and Griswold's premium items.
  • Pressing [ removes all gold in the inventory.
  • Pressing ] sets all spells to learned and level 10.
  • Pressing : sets spells to specific values (see table below)
  • Pressing . prints some debug text about the dungeon to the screen.
l (level type) (level number) You'll start the game in this level.
m (monster type) Allows you to manually add monster types to the list of monsters that spawn in a level.
q (quest number) Marks a quest as being active, but not completed.
r (seed) Sets the random seed.
s Allows you to scroll the map using the mouse cursor. This might've been a leftover from when the game was a turn-based dungeon crawler, but left in as a cheat.
t (level type) (level number) This is identical to "l". The difference is that this will mark the player as being in a special quest area as opposed to a normal level.
j (level number) This changes the trigger of the Catacombs to another level. This only appears to work in a fully-packed (4 players) multiplayer game.
v Draws boxes around tiles to indicate vision of the player and monsters.
f Turns on a frame counter.
7 The "item cheat." Gold never drops. In addition, sarcophagi always drop magical short staffs and items always spawn at the maximum dungeon level (15), regardless of where they are found.
8 The "unique cheat." When barrels are broken, they'll always drop a unique item.

Pressing ':' while the "dave cheat" is active will set the player's spells to the following levels and memorize them so that they can be cast:

Spell Spell Level
Fire Bolt 8
Charged Bolt 11
Holy Bolt 10
Healing 7
Heal Other 5
Lightning 9
Fire Wall 5
Telekinesis 3
Town Portal 3
Flash 3
Phase 2
Mana Shield 2
Flame Wave 4
Fire Ball 3
Stone Curse 1
Chain Lightning 1
Guardian 4
Elemental 3
Nova 1
Golem 2
Blood Star 1
Bone Spirit 1

Additionally, pressing these hotkeys during gameplay has these effects:

Hotkey Description
F2 Prints various debug information to the screen.
F3 Prints information about the item under the mouse cursor.
F4 Prints quest debug information.

CONTROL.cpp

SPICONTYPE, the enum that relates to spell icons, has a few items of interest in it:

typedef enum {
	SI_INVALID,
	SI_FIREBOLT,
	SI_HEAL,
	SI_LIGHTNING,
	SI_FLASH,
	SI_IDENTIFY,
	SI_FIREWALL,
	SI_TOWNPORTAL,
	SI_STONECURSE,
	SI_INFRAVISION,
	SI_HEALOTHER,
	SI_NOVA,
	SI_FIREBALL,
	SI_MANASHIELD,
	SI_FLAMEWAVE,
	SI_INFERNO,
	SI_CHAINLIGHTNING,
	SI_JABBERWOCK,		// with eyes of flame...
	SI_GUARDIAN,
	SI_BLOODRITUAL,		// unused, looks like Krull
	SI_INVISIBILITY,
	SI_GOLEM,
	SI_ETHEREALIZE,
	//SI_BLOODBOIL,		// unused
	SI_RAGE,			// Replaced bloodboil.
	SI_TELEPORT,
	SI_APOCALYPSE,
	SI_REPAIR,
	SI_EMPTY,
	SI_PHASE,
	SI_RECHARGE,
	SI_BONESPIRIT,
	SI_REDSKULL,		// unused
	SI_PENTAGRAM,		// unused
	SI_FIRECLOUD,		// unused
	SI_LONGHORN,		// unused
	SI_PENTASTAR,		// unused
	SI_BLOODSTAR,
	SI_DISARM,
	SI_ELEMENTAL,
	SI_CHARGEDBOLT,
	SI_TELEKINESIS,
	SI_RESURRECT,
	SI_HOLYBOLT,
	
#if 1	
	// new icons
	SI_WARP,
	SI_SEARCH,
	SI_REFLECT,
	SI_LIGHTNINGWALL,
	SI_IMMOLATION,
	SI_BERSERK,
	SI_RINGOFFIRE,
	SI_JESTER,
	SI_MANA,
	
	SI_LAST

#else
	// faked icons
	SI_WARP = SI_PHASE,
	SI_SEARCH = SI_INFRAVISION,
	SI_REFLECT = SI_MANASHIELD,
	SI_LIGHTNINGWALL = SI_FIREWALL,
	SI_IMMOLATION = SI_NOVA,
	SI_BERSERK = SI_REDSKULL,
	SI_RINGOFFIRE = SI_PENTAGRAM,
	SI_MANA = SI_BLOODRITUAL,
	SI_JESTER = SI_ETHEREALIZE,
	
	SI_LAST = SI_HOLYBOLT+1
#endif	
} SPICONTYPE;

Of note:

Without bugs or exploits, spells can't go to level zero, so a description marking it as unusable...well...goes unused.

if (v == 0) sprintf(tempstr, "Spell Level 0 - Unusable");

As seen in pre-release versions of the game, the main panel will say "Welcome to Diablo - Press F1 for help" when you first start up the game. This code is still present, just commented out:

	//AddPanelString("Welcome to Diablo", TEXT_CENTER);	// This was ok (pre Demo) now its not
	//AddPanelString("Press F1 for help", TEXT_CENTER);

DEBUG.CPP

This entire file is pretty much unused, as all of the functions that are called from it are only used in a debug build:

/*-----------------------------------------------------------------------**
** 								Diablo
**
**							Debugging file
**
** 				(C)1995 Condor, Inc. All rights reserved.
**
**-----------------------------------------------------------------------**
**	$Header: /Diablo/DEBUG.CPP 1     1/22/97 2:06p Dgartner $
**-----------------------------------------------------------------------*/

#include	"diablo.h"
#pragma hdrstop
#include	"debug.h"
#include	"engine.h"
#include	"error.h"

#include	"items.h"
#include	"gendung.h"
#include	"player.h"


/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
BYTE *pSquareCel;


/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
void InitDebugGFX() {
	app_assert(! pSquareCel);
	if (visiondebug)
		pSquareCel = LoadFileInMemSig("Data\\Square.CEL",NULL,'DBGS');
}


/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
void FreeDebugGFX() {
	DiabloFreePtr(pSquareCel);
}

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
#define DEBUGSEEDS	4096

int debugseeds[DEBUGSEEDS];
//int seedcnt, seedidx[17];
int seedcnt, seedidx[NUMLEVELS+1];	// JKE to add crypt
BOOL seedflag = FALSE;

void InitDebugSeeds()
{
	for (int i = 0; i < DEBUGSEEDS; i++) debugseeds[i] = -1;
	seedcnt = 0;
	for (i = 0; i < 17; i++) seedidx[i] = 0;
}

void StartDebugSeeds()
{
	if (currlevel == 0) return;
	seedcnt = seedidx[currlevel];
	seedflag = TRUE;
}

void EndDebugSeeds()
{
	if (currlevel == 0) return;
	seedidx[currlevel+1] = seedcnt;
	seedflag = FALSE;
}

void SaveDebugSeed(int s)
{
	if (!seedflag) return;
	if (seedcnt == DEBUGSEEDS) return;
	if (currlevel == 0) return;
	if (debugseeds[seedcnt] == -1) {
		debugseeds[seedcnt] = s;
	} else {
		if (debugseeds[seedcnt] != s) app_fatal("Seeds desynced");
	}
	seedcnt++;
}


/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/

#if 0
char davehold1[5][MAXDUNX][MAXDUNY];
char davehold2[5][MAXDUNX][MAXDUNY];
BOOL daveinited[5] = { FALSE, FALSE, FALSE, FALSE, FALSE };

#define LEVELCHECK		1

void DaveCheck()
{
	int xp, yp;

	//if (currlevel != LEVELCHECK) return;
	if (currlevel == 0) return;
	if (currlevel >= 5) return;
	for (yp = 0; yp < MAXDUNY; yp++) {
		for (xp = 0; xp < MAXDUNX; xp++) {
			if (dMonster[xp][yp] != 0) app_fatal("Monsters not cleared");
			if (dPlayer[xp][yp] != 0) app_fatal("Players not cleared");
			if (daveinited[currlevel]) {
				if (davehold1[currlevel][xp][yp] != (dFlags[xp][yp] & BFLAG_MONSTACTIVE))
					app_fatal("MonstActive not same");
				if (davehold2[currlevel][xp][yp] != (dFlags[xp][yp] & BFLAG_SETPC))
					app_fatal("Set Piece not same");
			} else {
				davehold1[currlevel][xp][yp] = dFlags[xp][yp] & BFLAG_MONSTACTIVE;
				davehold2[currlevel][xp][yp] = dFlags[xp][yp] & BFLAG_SETPC;
			}
		}
	}
	daveinited[currlevel] = TRUE;
}
#endif

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/

#if 1
#include "msg.h"
int blipplr = 0;

void BlipDebug(BOOL next)
{
	if (next) blipplr = (blipplr + 1) & 0x3;

	int i = blipplr;
	char tempstr[128];

	sprintf(tempstr, "Plr %i : Active = %i", i, plr[i].plractive);
	NetSendString((1 << myplr), tempstr);
	if (plr[i].plractive) {
		sprintf(tempstr, "  Plr %i is %s", i, plr[i]._pName);
		NetSendString((1 << myplr), tempstr);
		sprintf(tempstr, "  Lvl = %i : Change = %i", plr[i].plrlevel, plr[i]._pLvlChanging);
		NetSendString((1 << myplr), tempstr);
		sprintf(tempstr, "  x = %i, y = %i : tx = %i, ty = %i : fx = %i, fy = %i",
			plr[i]._px, plr[i]._py, plr[i]._ptargx, plr[i]._ptargy, plr[i]._pfutx, plr[i]._pfuty);
		NetSendString((1 << myplr), tempstr);
		sprintf(tempstr, "  mode = %i : daction = %i : walk[0] = %i", plr[i]._pmode, plr[i].destAction, plr[i].walkpath[0]);
		NetSendString((1 << myplr), tempstr);
		sprintf(tempstr, "  inv = %i : hp = %i", plr[i]._pInvincible, plr[i]._pHitPoints);
		NetSendString((1 << myplr), tempstr);
	}
}
#endif

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/

#if 1
#include "quests.h"
int currqdebug = 0;

void PrintQuestDebug()
{
	char tempstr[128];

	sprintf(tempstr, "Quest %i :  Active = %i, Var1 = %i", currqdebug, quests[currqdebug]._qactive, quests[currqdebug]._qvar1);
	NetSendString((1 << myplr),tempstr);
	currqdebug++;
	if (currqdebug == MAXQUESTS) currqdebug = 0;
}
#endif

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/

#if 1
#include	"monstint.h"
#include	"themes.h"
#include	"drlg_l4.h"
extern byte dung[L4DUNX][L4DUNY];
extern byte L4dungeon[L4DX][L4DY];

char mphold1[NUMLEVELS+1][MAXDUNX][MAXDUNY];
char mphold2[NUMLEVELS+1][MAXDUNX][MAXDUNY];

void DaveCheck2()
{
	int xp, yp;

	for (yp = 0; yp < MAXDUNY; yp++) {
		for (xp = 0; xp < MAXDUNX; xp++) {
			if (dMonster[xp][yp] != 0) app_fatal("Monsters not cleared");
			if (dPlayer[xp][yp] != 0) app_fatal("Players not cleared");
			mphold1[currlevel][xp][yp] = dFlags[xp][yp] & BFLAG_MONSTACTIVE;
			mphold2[currlevel][xp][yp] = dFlags[xp][yp] & BFLAG_SETPC;
		}
	}
}

/*-----------------------------------------------------------------------*/

void PrintDaveCheck2()
{
	int i, j, xp, yp, sum1, sum2, sum3;
	long fv;
	char tempstr[128];

	sum1 = 0;
	sum2 = 0;
	for (yp = 0; yp < MAXDUNY; yp++) {
		for (xp = 0; xp < MAXDUNX; xp++) {
			sum1 += mphold1[currlevel][xp][yp];
			sum2 += mphold2[currlevel][xp][yp];
		}
	}
	sprintf(tempstr, "Level %i : Monst Active Sum = %i : dFlag sum = %i", currlevel, sum1, sum2);
	NetSendString((1 << myplr),tempstr);

	sum1 = 0;
	sum2 = 0;
	for (i = 1; i <= MAXTILES; i++) {
		if (nSolidTable[i]) {
			sum1 += i;
			sum2++;
		}
	}
	
	// Calc a volume of monsters
	fv = 0;
	for (i = DIRTEDGED2; i < (DMAXY - (DIRTEDGED2)); i++) {
		for (j = DIRTEDGED2; j < (DMAXX - (DIRTEDGED2)); j++) {
			if (!SolidLoc(i,j)) fv++;
		}
	}

	sum3 = 0;
	for (j = 0; j < MDMAXY; j++) {
		for (i = 0; i < MDMAXX; i++) sum3 += dungeon[i][j];
	}

	sprintf(tempstr, "Solid Sum = %i:%i : Monst Vol = %i : Dungeon Sum = %i", sum1, sum2, fv, sum3);
	NetSendString((1 << myplr),tempstr);

	sum1 = 0;
	for (j = 0; j < MAXDUNY; j++) {
		for (i = 0; i < MAXDUNX; i++) {
			sum1 += dTransVal[i][j];
		}
	}

	sum2 = 0;
	for (j = 0; j < DMAXY; j++) {
		for (i = 0; i < DMAXX; i++) {
			sum2 += dPiece[i][j];
		}
	}

	sprintf(tempstr, "Num themes = %i/%i : Trans Sum = %i : dPiece Sum = %i", numthemes, themeCount, sum1, sum2);
	NetSendString((1 << myplr),tempstr);

	if (leveltype == 4) {
		sum1 = 0;
		for (j = 0; j < L4DUNY; j++) {
			for (i = 0; i < L4DUNX; i++) sum1 += dung[i][j];
		}
		sum2 = 0;
		for (j = 0; j < L4DY; j++) {
			for (i = 0; i < L4DX; i++) sum2 += L4dungeon[i][j];
		}
		sprintf(tempstr, "dung sum = %i : L4Dungeon sum = %i", sum1, sum2);
	}
}

/*-----------------------------------------------------------------------*/

int dungdebugy = 0;

void DaveDungDebug()
{
	int sum, i;
	char tempstr[128];

	sum = 0;
	for (i = 0; i < MDMAXX; i++) sum += dungeon[i][dungdebugy];

	sprintf(tempstr, "dungeon Y=%i sum = %i", dungdebugy, sum);
	NetSendString((1 << myplr), tempstr);

	dungdebugy++;
	if (dungdebugy == MDMAXY) dungdebugy = 0;
}
#endif

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/

#if 1
#include	"sound.h"
#include	"monster.h"
#include	"monstdat.h"
#include	"cursor.h"

int debugmonst = 0;

void PrintDaveMonst(int m)
{
	char tempstr[128];
	int inlist, i;

	sprintf(tempstr, "Monster %i = %s", m, monster[m].mName);
	NetSendString((1 << myplr), tempstr);
	sprintf(tempstr, "X = %i, Y = %i", monster[m]._mx, monster[m]._my);
	NetSendString((1 << myplr), tempstr);
	sprintf(tempstr, "Enemy = %i, HP = %i", monster[m]._menemy, monster[m]._mhitpoints);
	NetSendString((1 << myplr), tempstr);
	sprintf(tempstr, "Mode = %i, Var1 = %i", monster[m]._mmode, monster[m]._mVar1);
	NetSendString((1 << myplr), tempstr);
	inlist = 0;
	for (i = 0; i < nummonsters; i++) {
		if (monstactive[i] == m) inlist = 1;
	}
	sprintf(tempstr, "Active List = %i, Squelch = %i", inlist, monster[m]._msquelch);
	NetSendString((1 << myplr), tempstr);
}

void DaveDebugMonst()
{
	int cm;

	if (cursmonst == -1) {
		if (dMonster[cursmx][cursmy] == 0) cm = debugmonst;
		else {
			if (dMonster[cursmx][cursmy] > 0) cm = dMonster[cursmx][cursmy] - 1;
			else cm = -(dMonster[cursmx][cursmy] + 1);
		}
	} else cm = cursmonst;

	PrintDaveMonst(cm);
}

void DaveDebugMonst2()
{
	char tempstr[128];
	debugmonst++;
	if (debugmonst == MAXMONSTERS) debugmonst = 0;
	sprintf(tempstr, "Current debug monster = %i", debugmonst);
	NetSendString((1 << myplr), tempstr);
}

#endif

DIABLO.CPP

// Temp vars (delete all uses before final compile)
long gv1;
long gv2;
long gv3;
long gv4;
long gv5;

Spoiler alert...they weren't deleted.

/* pjw.patch2.start
static const char sgszErrFile[] = "c:\\helfire_.err";
static void write_exception(struct _EXCEPTION_POINTERS *pep) {
	FILE * f = fopen(sgszErrFile,"wb");
	if (! f) return;

	PEXCEPTION_RECORD per = pep->ExceptionRecord;
	while (per) {
		fprintf(
			f,
			"exception: 0x%08x\r\ncode address: 0x%08x\r\n",
			per->ExceptionCode,
			per->ExceptionAddress
		);

		if (per->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
			if (per->ExceptionInformation[0])
				fprintf(f,"write access violation at 0x%08x\r\n",per->ExceptionInformation[1]);
			else
				fprintf(f,"read access violation at 0x%08x\r\n",per->ExceptionInformation[1]);
		}

		per = per->ExceptionRecord;
	}

	fclose(f);
}
pjw.patch2.end */

This code appears to be for a crash dumper. Why it was removed is a mystery, although writing to "C:\\helfire_.err" probably wouldn't have been ideal.

//******************************************************************
//******************************************************************
BOOL grab_event() {
	// NOTE: this event never gets cleaned up by our code
	// we rely upon windows to clean up this event so that it
	// occurs as late as possible in the program exit.  This is
	// a really nasty hack to make sure that SMACKER doesn't
	// initialize improperly
	SetLastError(0);
	HANDLE hExtraEvent = CreateEvent(NULL,FALSE,FALSE,"DiabloEvent");
	HANDLE hEvent = CreateEvent(NULL,FALSE,FALSE,"HellfireEvent");
	return ERROR_ALREADY_EXISTS != GetLastError();
}

The comment in this function makes light of something that was previously unknown for years: the game will create blank, unused Windows events for seemingly no reason, and aren't cleaned up.

	// play magazine quotes
	/*
	#if IS_VERSION(SHAREWARE)
		#ifndef NDEBUG
		if (cineflag) play_quotes();
		#else
		play_quotes();
		#endif
	#endif
	*/

This occurs at the start of the game. The play_quotes() function goes completely unused because this code is commented out. It is responsible for displaying quotes.cel onscreen, which otherwise goes unused in the retail game.

	// play beta warning
	#if IS_VERSION(BETA)
		#ifndef NDEBUG
		if (cineflag) {
		#endif
			UiBetaDisclaimer(5);
			BlackPalette();
		#ifndef NDEBUG
		}
		#endif
	#endif

This occurs right before the main menu is shown. It displays a dialog box onscreen that uses ui_art/disclaim.pcx. Since this code is only compiled in beta versions of the game, that file also goes unused.

	// play "buy me" screens
	/*
	#if IS_VERSION(SHAREWARE)
		#ifndef NDEBUG
		if (cineflag) play_quit();
		#else
		play_quit();
		#endif
	#endif
	*/

This occurs at the end of the game. In older and shareware versions of the game, it would show some screenshots and other media. play_quit() isn't defined in the code, though.

/*
		// testing diablo death
		case 'k':
#define MT_DIABLO 110
			for (int i = 0; i < nummonsters; i++) {
				int mi = monstactive[i];
				if (monster[mi].MType->mtype == MT_DIABLO)
					M_StartKill(mi, myplr);
			}
			return;
*/			

Pressing 'k' at one point during development would've killed Diablo. If only it were that easy...

//******************************************************************
//******************************************************************
// pjw.patch1.start
static void CRASH() {
#if 0	// !!! @@@ !!! fix in final
	static BYTE sgbCheating = FALSE;
	if (! sgbCheating) {
		sgbCheating = TRUE;
		app_warning("Cheating detected");
		void myDebugBreak();
		myDebugBreak();
	}
#else
	LPDWORD pFrame = (LPDWORD) plr[myplr]._pAnimData;
	pFrame[plr[myplr]._pAnimFrame + 1] ^= 0x3fffffff;
#endif
	FullBlit(TRUE);
}
// pjw.patch1.end

This code isn't called. The function that it's supposed to be called from (plr_encrypt) is #ifdef'd out. Ostensibly, it's supposed to be used for an anticheat measure that involved encrypting the player's data before certain critical code paths, and then decrypting it and performing a checksum on the difference. If the checksum doesn't match, then the game would crash.

This was probably removed because it would've adversely affected the game's performance. The encryption is done every second.

doom.cpp

Most of the code here goes unused. It's all related to the Map of the Stars ("Map of Doom", internally, and "Strange Map" according to some prerelease screenshots) quest - specifically, the display of the map.

/*-----------------------------------------------------------------------**
** 								Diablo
**
**							Map of Doom file
**
** 				(C)1995 Condor, Inc. All rights reserved.
**
**-----------------------------------------------------------------------**
**	$Header: /Diablo/DOOM.CPP 1     1/22/97 2:06p Dgartner $
**-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/

#include	"diablo.h"
#pragma hdrstop
#include	"doom.h"
#include	"engine.h"
#include	"control.h"
#include	"gendung.h"

/*-----------------------------------------------------------------------*
** Global Variables
**-----------------------------------------------------------------------*/

#define DOOM_NUMFRAMES	30
#define DOOM_ENDFRAME	31
#define DOOM_TICK		1200	// Every 20*60 (1 min) frames is next doom map cycle
#define DOOM_TOTAL		(DOOM_NUMFRAMES*DOOM_TICK)+1
#define DOOM_ANIMSPD	5

bool drawmapofdoom = false;
static BYTE *pDoomCel = 0;
int doomtime = 0;
static int currdoom = 0;
static int animdoomdelay = 0;

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/

void InitMapOfDoomTime()
{
	if (doomtime > 0) return;
	doomtime = 0;
}

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/

void DoMapOfDoomTime()
{
	if (doomtime < DOOM_TOTAL) {
		doomtime++;
		if (doomtime == DOOM_TOTAL) {
			#if !IS_VERSION(SHAREWARE)
			PlayInGameMovie("gendata\\doom.smk");
			#endif
			doomtime++;
		}
	}
}

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/

int CheckMapOfDoomTime()
{
	if (doomtime == DOOM_TOTAL) return(DOOM_ENDFRAME);
	return(doomtime / DOOM_TICK);
}

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/

void FreeDoomMem()
{
	if (pDoomCel != NULL)
	{
		DiabloFreePtr(pDoomCel);
		pDoomCel = NULL;
	}
}

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/

static bool GetDoomMem()
{
	FreeDoomMem();
	pDoomCel = DiabloAllocPtrSig((227 + 1) * 1024,'DOOM');
	return (pDoomCel != 0);
}

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/

static bool LoadDoomFrame()
{
	bool result = false;
	
//	if (currlevel < HIVESTART)
//	{
//		if (currdoom == DOOM_ENDFRAME) {
//			strcpy(tempstr, "Items\\Map\\MapZDoom.CEL");
//		}
//		else if (currdoom < 10) {
//			sprintf (tempstr, "Items\\Map\\MapZ000%i.CEL", currdoom);
//		}
//		else sprintf (tempstr, "Items\\Map\\MapZ00%i.CEL", currdoom);
//		LoadFileWithMem(tempstr, pDoomCel);
//	}
//	else
	{
		strcpy(tempstr, "Items\\Map\\MapZtown.CEL");
		if (LoadFileWithMem(tempstr, pDoomCel)) {
			result = true;
		}
	}
	return result;
}

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/

void InitMapOfDoomView()
{
	if (GetDoomMem()) {
		if (CheckMapOfDoomTime() == DOOM_ENDFRAME) currdoom = DOOM_ENDFRAME;
		else currdoom = 0;
		if (LoadDoomFrame())
			drawmapofdoom = true;
		else
			EndMapOfDoomView();
	}
}

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/

void EndMapOfDoomView()
{
	//if (!drawmapofdoom) return;
	drawmapofdoom = false;
	FreeDoomMem();
}

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/

void DrawMapOfDoom()
{
	if (!drawmapofdoom) return;

//	if (currdoom != DOOM_ENDFRAME) {
//		animdoomdelay++;
//		if (animdoomdelay >= DOOM_ANIMSPD) {
//			animdoomdelay = 0;
//			currdoom++;
//			if (currdoom > CheckMapOfDoomTime()) currdoom = 0;
//			LoadDoomFrame();
//		}
//	}
	DrawCel(64, 511, pDoomCel, 1, 640);
}

Note that a lot of it was reappropriated in Hellfire for a different purpose.

ERROR.CPP

"No multiplayer functions in demo",
"Direct Sound Creation Failed",
"Not enough space to save",
"No Pause in town",
"Copying to a hard disk is recommended",
"Multiplayer sync problem",
"No pause in multiplayer",
"Loading...",
"Saving...",
"You must be at least level 8 to use this.",		//40
"You must be at least level 13 to use this.",		//41
"You must be at least level 17 to use this.",		//42

These error messages aren't used. The last three are meant to be used when accessing the Catacombs, Caves, or Hell, but that restriction does not exist in the final game.

"Not available in shareware version",

This is used in the shareware version, but not in the retail version of the game.

help.cpp

Interestingly, there is commented out text for help for a Microsoft demo. The retail game's help information is significantly more terse than this is.

There is also text for the shareware and Battle.net beta that differs from the retail game, but for the sake of brevity, and because they are only very slightly different from this text, they have been excluded.

/*-----------------------------------------------------------------------*
** Microsoft demo text
/*-----------------------------------------------------------------------*

static const char helpdata[] = {
"Welcome mortals! Hellfire is real-time action in a dark, gothic role-playing game. "
"Prepare to be taken into the very depths of hell on your quest to destroy the Lord "
"of all Evil - Diablo.|"
"|"
"This Help section is designed to make your playing experience as easy as possible. "
"Let's get started...|"
"|"
"$Keyboard Shortcuts:|"
"Hellfire can be played exclusively by using the mouse controls.  There are times, however, "
"when you may want to use shortcuts to some commands by using the keyboard.  These "
"shortcuts are listed below:|"
"|"
"F1: Open the Help Screen|"
"Esc: Displays the main menu|"
"Tab: Displays the Auto-map|"
"Space: Removes all screens and map from the play area|"
"S: Opens Spell selection pop-up menu|"
"I: Opens the Inventory screen|"
"C: Opens the Character screen|"
"Z: Zooms the game screen in and out|"
"F: Reduces the brightness of the screen|"
"G: Increases the brightness of the screen|"
"Shift + Left Click: Fire any Bow without moving|"
"1,2,3: While the Spell selection pop-up menu is active, these keys will "
"set that number as a hot-key selection (pressing the number will "
"automatically ready that spell).|"
"|"
"$Movement:|"
"Movement is controlled by the mouse.  The gauntlet on the screen is your cursor. "
"Use this to indicate the destination of your character and then left-click to move "
"to that area.|"
"|"
"$Selecting Items:|"
"What you can interact with within the game is easily identifiable.  Simply move the "
"cursor over any object or creature.  If the object can be picked up, attacked, activated "
"or used in any way, it will be immediately outlined and highlighted with a description of "
"the object appearing in the text area on the control panel.|"
"|"
"Example: If you select a door and then left-click the character will walk to the door and "
"open it.  A second click closes the door.  If you left-click on a selected weapon, the "
"character will walk over to it and put it in his inventory. If you left-click on a selected "
"creature....|"
"|"
"$Combat:|"
"Combat is initiated by left-clicking on a creature that has been selected.  Left-clicking "
"on a creature that you are next to will cause your character to attack it immediately. "
"Left-clicking on a distant creature will cause the character to walk to the creature and "
"then attack. This will work if your character has a melee weapon (sword, mace, club, etc.), "
"just a shield or is unarmed.|"
"|"
"If your character is equipped with a bow, left-clicking will fire an arrow at a selected "
"creature. Holding down the shift key and then left-clicking allows the character to fire "
"the bow without accidentally moving.|"
"|"
"$Picking up Objects:|"
"If you left-click an item - such as a weapon, armor, scroll or book - your character will "
"move to that item and add it to his inventory automatically.  If you do not have enough "
"room in your inventory for the item, it will fall from your grasp and you will receive a "
"message that more room is needed.  Open your inventory screen and try re-arranging or "
"removing items to carry what you really want or need.|"
"|"
"$Inventory:|"
"You can toggle the Inventory screen on and off by clicking the INV> button on the control "
"panel.  Items may be moved around in your inventory by selecting them and then left-clicking "
"to pick them up.  When you pick up an item while in the inventory screen, your cursor "
"changes into the item. You can then place this item into empty spaces in your inventory, "
"swap them with other items in your inventory or equip them.|"
"|"
"If you have an item that you no longer wish to carry, simply grab the item from your "
"inventory and then left-click in the play area to drop it.|"
"|"
"$Equipping Items:|"
"Equipping items is done by picking up an item from your inventory and placing it in the "
"appropriate boxes on the figure in the Inventory screen. Weapons and shields go into the "
"large spaces to the  right or left of the figure. Two-handed weapons such as bows and "
"axes preclude the use of a shield and will take up both of these large spaces.|"
"|"
"Cloaks, robes, capes and all other armor must go in the central torso slot of the figure.|"
"|"
"Helmets and caps  go in the head box and rings go into the small boxes at the hands of "
"the figure.|"
"|"
"To change items that your character has equipped, pick up a new item and place it on top "
"of the item you wish to remove.  Your character will automatically swap the items and the "
"cursor will now change into the item that was in that box.|"
"|"
"$Usable Items:|"
"Potions, elixirs, oils and books are classified as usable items.  These items can be used "
"by right-clicking on them in the inventory screen.  Any one item can also be 'readied' in "
"the same way as spells. To ready an item, left-click the 'select current item' button to "
"the left of the red health ball on the control panel. "
"A pop-up menu will activate that you can scroll through to choose an item to be readied. "
"Left-click when the desired item is selected and you will see that item displayed on the "
"button.  To use a readied item, simply right-click on the 'select current item' button or "
"press the Enter key on your keyboard.|"
"|"
"$Item Information:|"
"All items in Hellfire share certain common attributes.  These are damage, durability, charges "
"and minimum requirements.|"
"|"
"Damage: This is represented by a range that shows the minimum and maximum damage that item "
"can inflict. An sword that has a (2-6) after its name does a minimum of two damage and a "
"maximum of six when it hits. Damage can be modified by the quality of the weapon, the "
"characters strength and magic.|"
"|"
"Durability: This is how long an item can last before it is rendered useless. This is "
"represented by a ratio of current durability to maximum durability. A shield that has a "
"durability of 15/20 would have 15 points of damage it could take from use before it was "
"rendered useless. Maximum durability can be affected by the quality of the item, magic or "
"repairs upon the item. Minimum durability can be raised by repairing an item.|"
"When the durability of an item you are wearing or wielding drops to 5 points or below, "
"an icon of the image appears in the lower left corner above the control panel. These icons "
"warn the player that the item is about to break and needs to be repaired soon.|"
"|"
"Charges: Some items have charges associated with. These represent how many times that item "
"can be used to cast the spell or affect indicated in its description.  Charges are "
"represented by a ratio of charges left to maximum charges. A staff that has charges of "
"2/5 could be used to cast 2 more spells before it was rendered powerless (it could still "
"be used to attack with physically). Maximum charges can be affected by the magic or "
"recharges cast upon the item. Minimum charges can be raised by recharging the item.|"
"|"
"Minimum Requirements: These are the minimum requirements that a character must meet to "
"wield the item. The more powerful an item is, the higher the minimum requirements will be. "
"If a character does not meet these requirements, he will be unable to equip the item and "
"its name and information will be displayed in red.  The item artwork will also have a red "
"tint to it in the Inventory screen.|"
"|"
"There are also three classes of items in Hellfire.  These are mundane, magic and Unique:|"
"|"
"Mundane items have no special attributes and their information is displayed in white text.|"
"|"
"Magic Items are represented by blue text descriptions. Use the Identify spell to determine "
"their exact properties and attributes.|"
"|"
"Unique items are fully identified when you obtain them. Information on these items is "
"displayed in gold.|"
"|"
"$Skills:|"
"Important Note - Skills do not work in the town in this pre-release demo. Left-clicking "
"on the 'select current spell' button will open a pop-up menu that will allow you to ready "
"a skill or spell for use.  To use a readied skill or spell, simply right-click in the main "
"play area.|"
"|"
"Skills are the innate abilities of your character. These skills are different depending on "
"what class you choose and they require no mana to use.|"
"|"
"The Warrior starts the game with the Repair skill.  The Repair Skill icon appears as the "
"'select current spell' button found next to the blue Mana sphere on the control panel. "
"When the skill is useable, the button will be gold in color.  The game starts with the "
"button grayed out as you cannot repair or cast spells in the town.|"
"|"
"The Repair skill allows the Warrior to fix an item that has been worn by use or is damaged "
"in combat.  To repair an item, have the Repair Skill selected (your character starts the "
"game this way) and right-click the mouse as if you were casting a spell.  Your cursor will "
"change into a hammer shaped cursor that you will use to select the item to be repaired. "
"Repairing an item will decrease the maximum durability of that item, but can be done while "
"in the labyrinth.|"
"|"
"The Blacksmith can repair items, but it will cost you gold. When the Blacksmith repairs "
"an item, it does not decrease the maximum durability of the item.|"
"|"
"$Spells:|"
"Important Note - Spells do not work in the town in this pre-release demo.|"
"|"
"Spells are magical effects that can be cast from a scroll, a staff or memorized from a "
"book.  Spells may or may not require mana to use and are available to all classes.|"
"|"
"Spells cast from an item (a scroll or staff) cost no mana to use, but are limited by "
"the number of charges available on the item.  Scrolls always have one charge while staves "
"may have multiple charges. To use spells from a staff, you must equip the staff to cast "
"the spell. Spells that are cast from staves are represented by an orange icon button in "
"the 'select current spell' button area.  Scrolls are represented by a red button.|"
"|"
"Memorized spells cost mana to cast, but they can be used as long as the character has "
"mana to power them.  The Warrior starts the game with no memorized spells.  If the "
"character finds a book in the labyrinth, he can memorize the spell written in that "
"book by opening the Inventory screen and right-clicking on the book.  This will make "
"the spell always available to the character for casting.  Memorized spells are denoted "
"by a blue button.|"
"|"
"While some spells affect the caster, some spells require a target. These targeted spells "
"are cast in the direction that you indicate with your cursor on the play area.  If you "
"highlight a creature, you will cast that spell at that creature.  Not all items within "
"the labyrinth can be targeted.|"
"|"
"Example: A fireball spell will travel at the creature or to the location you right-click "
"on.  A Healing spell will simply add health to your character while diminishing his "
"available mana and requires no targeting.|"
"|"
"You can also set a spell or scroll as a Hot Key position for instant selection.  Start "
"by opening the pop-up menu as described in the skill section above.  Assign Hot Keys by "
"hitting the 1, 2 or 3 keys on your keyboard after scrolling through the available spells "
"and skills and stopping on the one you wish to assign.|"
"|"
"$Health and Mana:|"
"The two spheres in the control panel display your health and mana.  Your health is a "
"measure of how much life force your character has.  The red sphere of fluid on the left "
"side of the control panel represents the health of your character.  When the fluid is "
"gone - your character is dead.|"
"|"
"The blue fluid on the right side of the control panel represents your character's "
"available mana. Mana is the magical force used by your character to cast spells.  When "
"the liquid in the sphere is low or depleted, you may be unable to cast some (or all) of "
"your spells.|"
"|"
"$Control Panel:|"
"The control panel is how you receive detailed information in Hellfire and interact with "
"much of your surroundings.  Here is a quick run-down of the control panel areas and their "
"use:|"
"|"
"INV:  This button is used to access your Inventory screen|"
"CHAR: This button is used to access your Character Statistics screen|"
"Current Item: This is the item that has been readied for immediate use|"
"Current Spell: This is the spell that has been readied for immediate casting|"
"Health Sphere: This is the amount of health your character currently has|"
"Mana Sphere: This is the amount of mana your character currently has|"
"Automap: This button activates the mapping overlay|"
"Main Menu: This activates the main menu screen|"
"Multiplayer Message: Unavailable in the pre-release demo|"
"Message Filter: Unavailable in the pre-release demo|"
"Description Area: This is where any important information about creatures or items "
"you can interact with is displayed.|"
"|"
"Character Info:|"
"Toggle the Character Statistics Screen on and off by clicking the <CHAR button on the "
"control panel.  This screen shows the 'nuts and bolts' of your character.  There are "
"four major statistics that dictate how your character progresses in the game.|"
"|"
"STRENGTH: This is how physically powerful your character is. This statistic plays a "
"large part in  determining how much damage you can do when attacking creatures.|"
"|"
"MAGIC: This is how attuned your character is with the arcane powers of the world. "
"This statistic plays a large part in  determining how much mana you have available "
"for casting spells.|"
"|"
"DEXTERITY: This is how quick of foot and hand your character is. This statistic plays "
"a large part in  determining the chance you have to hit creatures in combat.|"
"|"
"VITALITY: This is how physically fit your character is. This statistic plays a large "
"part in  determining how much health your character has when he is undamaged.|"
"|"
"$Main Menu:|"
"To activate the Game Menu, click the button with the pentagram symbol on the left "
"of the control panel.  You have three options in this menu.|"
"|"
"Save: This saves the game you are currently playing. Please note that this pre-release "
"demo will only save one game at a time.  Saving overwrites any previously saved game.|"
"|"
"Load: This loads the last game that you have saved.|"
"|"
"Quit: This exits the program. Please note that this does not automatically save your "
"game. If you wish to save the game you are currently playing, select save game before "
"quitting.|"
"|"
"Auto-map: Hellfire will automatically map where you have been in the labyrinth. To access "
"the auto-map, click the button with the compass symbol on the left of the control panel. "
"You can also hit the TAB key on your keyboard to activate the auto-map.  You can zoom in "
"and out of the map with the + and - keys.  Scrolling the map is done with the arrow keys.|"
"|"
"$Tech support:|"
"This is a pre-release version of Hellfire.  We have tried to make this as bug free as possible. "
"There will be no patches or updates of this pre-release demo available. The version will "
"not be supported by our tech support lines.|"
"|"
"$For maximum performance:|"
"We recommend copying the Hellfire folder onto your hard drive.|"
"&" };

/*-----------------------------------------------------------------------*/

itemdat.cpp

There are a few commented-out items here:

/* removed 11/23 by dave
	{ IRND_NORMAL, IC_ITEM, IL_INV, ITEM_BLKBTL, IT_MISC, ITEMID_NONE, "Potion of Experience", NULL,
	20, 0,
	0, 0, 0, 0,
	0, 0, 0,
	0, IMID_PEXP, 0, TRUE, 0, 0 },
*/

	// Oils removed 11/21 by dave
	// Oils back in for hellfire 7/30 by donald

/*	{ IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Firebolt", NULL,
	1, 0,
	0, 0, 0, 0,
	0, 0, 0,
	0, IMID_TSCROLL, SPL_FIREBOLT, TRUE, 50, 50 },
	{ IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Charged Bolt", NULL,
	1, 0,
	0, 0, 0, 0,
	0, 0, 0,
	0, IMID_TSCROLL, SPL_CBOLT, TRUE, 50, 50 },
	{ IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Holy Bolt", NULL,
	1, 0,
	0, 0, 0, 0,
	0, 0, 0,
	0, IMID_TSCROLL, SPL_HBOLT, TRUE, 50, 50 },
*/

/*	{ IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Telekinesis", NULL,
	1, 0,
	0, 0, 0, 0,
	0, 21, 0,
	0, IMID_TSCROLL, SPL_TELEKINESIS, TRUE, 50, 50 },
*/

/*	{ IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Bone Spirit", NULL,
	14, 0,
	0, 0, 0, 0,
	0, 35, 0,
	0, IMID_TSCROLL, SPL_, TRUE, 2000, 2000 },
	{ IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Blood Star", NULL,
	20, 0,
	0, 0, 0, 0,
	0, 35, 0,
	0, IMID_TSCROLL, SPL_, TRUE, 2000, 2000 },
*/

"dave" refers to David Brevik. "donald" is Donald Tsang, the lead programmer of Hellfire. Notably, the Potion of Experience uses the same icon as the Oils from Hellfire.

This item isn't commented out, but it does mention Blood Boil, which was cut late in development:

// used to be scroll of blood boil - no longer in game - rjs
	{ IRND_NO, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of None", NULL,
	99, 0,
	0, 0, 0, 0,
	0, 61, 0,
	0, IMID_TSCROLL, SPL_NONE, TRUE, 1000, 1000 },

Lightforge is not present in Hellfire. It was acquirable in Diablo, but is #ifdef'd out in Hellfire. Notably, it was a proposed quest reward from Tremain, who is not in the game.

#if 0	
	{ "Lightforge", ITEMID_MACE, 1, 6, 26675, 
	PL_LIGHT, 4, 4,
	PL_TODAM, 150, 150,
	PL_TOHIT, 25, 25,
	PL_FHIT, 10, 20,
	PL_IND, 0, 0,
	PL_STATS, 8, 8
	},
#endif	

The following unique items are commented out:

	/*	
	{ "Azurewrath", ITEMID_BASTSWORD, 1, 5, 66500, 
	PL_DAMDEMON, 200, 200,
	PL_TOHIT, 40, 40,
	PL_LHIT, 10, 20,
	PL_STR, 15, 15,
	PL_RMAG, 100, 100,
	0, 0, 0
	},
	{ "Blackest Blade", ITEMID_SCIMITAR, 1, 5, 23667, 
	PL_MANA, 50, 50,
	PL_RALL, 25, 25,
	PL_TOHIT, 20, 20,
	PL_TODAM, 100, 100,
	PL_CONST, 0, 0,
	0, 0, 0   
	},
	{ "Codex of Enlightenment", ITEMID_BOOK, 1, 4, 5000, 
	PL_X, 0, 0,
	PL_X, 0, 0,
	PL_X, 0, 0,
	PL_GFX, ITEM_BOOK3, 0,
	0, 0, 0,
	0, 0, 0
	},
*/

  // Book
/*	{ "Zhar the Mad's Memoirs", ITEMID_NONE, 6, 4, 4000, 
	PL_NMANA, 10, 10,
	PL_NMAG, 10, 10,
	PL_SLVL, 1, 1,
	PL_GFX, ITEM_BOOK1, 0,
	0, 0, 0,
	0, 0, 0
	},
	{ "T'farc Evol's Tomb", ITEMID_NONE, 8, 4, 5000, 
	PL_MAG, 15, 15,
	PL_NMANA, 25, 25,
	PL_SLVL, 1, 1,
	PL_GFX, ITEM_BOOK2, 0,
	0, 0, 0,
	0, 0, 0
	},
	// Amulet
	{ "Yulm's Mystic Amulet", ITEMID_AMULET, 1, 4, 1200, 
	PL_MAG, 10, 10,
	PL_RALL, 10, 10,
	PL_NSTATS, 5, 5,
	PL_GFX, ITEM_AMULET2, 0,
	0, 0, 0,
	0, 0, 0
	},
	{ "Torka's Amulet of Power", ITEMID_AMULET, 2, 4, 19700, 
	PL_SLVL, 1, 1,
	PL_MAG, 5, 5,
	PL_LEECH, 5, 5,
	PL_GFX, ITEM_AMULET2, 0,
	0, 0, 0,
	0, 0, 0
	},
	{ "Amulet of the Dead", ITEMID_AMULET, 12, 4, 5000, 
	PL_NMANA, 20, 20,
	PL_X, 0, 0,//(NW)
	PL_X, 0, 0,//(NW)
	PL_GFX, ITEM_AMULET4, 0,
	0, 0, 0,
	0, 0, 0
	},
	{ "Scarab Amulet", ITEMID_AMULET, 18, 3, 5000, 
	PL_STATS, 5, 5,
	PL_X, 0, 0,//(NW)
	PL_GFX, ITEM_AMULET3, 0,
	0, 0, 0,
	0, 0, 0,
	0, 0, 0
	},
*/

Azurewrath is indicated as the reward from the cut Izual quest. There aren't any unique books in the game, so it isn't clear where the Codex of Enlightenment, T'farc Evol's Tomb, or Zhar the Mad's Memoirs would fit in. Lastly, both Amulet of the Dead and Scarab Amulet have stats that don't work correctly (and are labeled by the comment as "(NW)")

itemdat.h

The following item powers are defined, but are either unused or commented out:

//#define PL_SCOST	12		// Spell cost (-) (removed by drb for multiplayer pickup flag)
//#define PL_SDUR		13		// Spell duration (removed by drb for unique crash)
#define PL_CHAOS	18		//not in game
#define PL_INVIS	40		//not in game  Player invisible from radius
#define PL_NOHEAL	47		// User can't heal
#define PL_FEAR		48		// When monster is struck, runs in fear (50%-ML)
#define PL_RABID	49		//not in game
#define PL_SEEINVIS	51		//not in game See invisible
#define PL_MNOHEAL	54		// Monster no longer heals
#define PL_HYPER	71		// Hyperspace spell (param1 charges)
#define PL_X		94		// Unknown???? TEMP--------

The following item IDs are defined, but are unused:

#define IMID_PSHEAL			4	// Potion of Serious heal
#define IMID_PDHEAL			5	// Potion of Deadly heal
#define IMID_PEXP			8	// Potion of Experience
#define IMID_PNEXP			9	// Potion of Negative Experience
#define IMID_ENSTR			14	// Elixir of Negative Strength
#define IMID_ENMAG			15	// Elixir of Negative Magic
#define IMID_ENDEX			16	// Elixir of Negative Dexerity
#define IMID_ENVIT			17	// Elixir of Negative Vitaltiy
#define IMID_MEAT			28	// Slab of meat
#define IMID_MAPOFDOOM		42	// The end quest map of doom item

Misc comment:

#define ITEMID_ARMRCOW		69// dude!

items.cpp

Oils were apparently supposed to be sellable to Griswold, but this was deemed too powerful, and thus, was commented out:

BOOL SmithItemOk(int i)
{
	BOOL rv;

	rv = TRUE;
	// Selling oil is too powerful for the money received.
//	if (AllItemsList[i].iMiscId > IMID_FIRSTOIL &&
//		AllItemsList[i].iMiscId < IMID_LASTOIL) rv = TRUE;
//	else
		if (AllItemsList[i].itype == IT_MISC) rv = FALSE;
	
	if (AllItemsList[i].itype == IT_GOLD) rv = FALSE;
	if (AllItemsList[i].itype == IT_FOOD) rv = FALSE;
	if (AllItemsList[i].itype == IT_STAFF
		&& AllItemsList[i].iSpell != 0) rv = FALSE;
	if (AllItemsList[i].itype == IT_RING) rv = FALSE;
	if (AllItemsList[i].itype == IT_AMULET) rv = FALSE;
	return(rv);
}

These item effects go completely unused:

		case PL_NOHEAL:
			strcpy(tempstr, "you can't heal");
			break;
		case PL_MNOHEAL:
			strcpy(tempstr, "hit monster doesn't heal");
			break;
		case PL_FALCON:
			strcpy(tempstr, "Faster attack swing");
			// not used
			break;
		case PL_INFRA:
			strcpy(tempstr, "see with infravision");
			break;
		case PL_HARQUN3:
			if (x->_iPLFR <= 0) sprintf(tempstr, " ");
			else if (x->_iPLFR >= 1) sprintf(tempstr, "Resist Fire : %+i%%", x->_iPLFR);
			break;
		default:
			strcpy(tempstr, "Another ability (NW)");
			break;

It isn't super clear how PL_HARQUN3 would be used, seeing as how it's identical to the normal Fire Resistance items.

"Another ability (NW)" is the default case when a item effect description does not exist, but all of the cases are covered in the retail game. However, various prototypes can have the "Another ability (NW)" on a few items.

mainmenu.cpp

In the final game, there is a dedicated music track for the main menu. Apparently this wasn't always the case though, since we have a bit of pointless code at the bottom of menu_music() to pick music:

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
void menu_music() {
	static int snMusic = MUSIC_INTRO;
	music_start(snMusic);

#if !IS_VERSION(SHAREWARE)
	// look for a music track which is not the town, cause it's
	// too wimpy for initial theme music, and is not l1, cause the
	// players will hear waaaay too much of l1 music
	do {
		snMusic++; // next track
		if (snMusic == NUM_MUSIC) snMusic = 0; // handle wrap
	} while (snMusic == MUSIC_TOWN || snMusic == MUSIC_L1);
#endif
}

And get a load of this, apparently they planned an attract mode for the main menu!

			case MAINMENU_ATTRACT_MODE:
				// it crashes after 20 minutes, so stop doing this.

			break;

MISSILES.CPP

/*-----------------------------------------------------------------------*
**-----------------------------------------------------------------------*/
/*void AddDoom(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
{
	int i, j, k, l;
	int mid;

	// search in a 5 radius around tile clicked for monster 
	for (k = 0; k < 6; ++k) {
		l = CrawlNum[k];
		j = l + 1;
		for (i = CrawlTable[l]; i > 0; --i) {
			mid = dMonster[(dx + CrawlTable[j])][(dy + CrawlTable[(j + 1)])];
			if (mid != 0) {
				if (mid > 0) --mid;
				else mid = -(mid + 1);
				if ((monster[mid]._mhitpoints >> HP_SHIFT) > 0) {
					missile[mi]._miVar1 = dx + CrawlTable[j];
					missile[mi]._miVar2 = dy + CrawlTable[j + 1];
					missile[mi]._miVar3 = mid;
					i = -99;
					k = 6;
					break;
				}
			}
			j += 2;
		}
	}

	// if no monsters found in search
	if (i != -99) {
		missile[mi]._miDelFlag = TRUE;
		return;
	}

	GetMissileVel(mi, sx, sy, missile[mi]._miVar1, missile[mi]._miVar2, 16);
	SetMissDir(mi, GetDirection(sx, sy, missile[mi]._miVar1, missile[mi]._miVar2));

	missile[mi]._mix = sx;
	missile[mi]._miy = sy;
	missile[mi]._misx = sx;
	missile[mi]._misy = sy;
	missile[mi]._misource = id;
	missile[mi]._midam = 26;

	missile[mi]._mirange = ((plr[id]._pLevel << 4) >> 2) + (plr[id]._pLevel << 4) ;
	for (i = GetSpellLevel(id, SPL_DOOM); i > 0; --i) missile[mi]._mirange += ((missile[mi]._mirange << 4) >> 3);
	missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7);

	UseMana(id, SPL_DOOM);
	PutMissile(mi);
}*/

/*-----------------------------------------------------------------------*
**-----------------------------------------------------------------------*/
/*void MI_Doom(int i)
{
	int k, l, m, n;
	int mid;

	--missile[i]._mirange;

	// check if monster moved
	mid = dMonster[(missile[i]._miVar1)][(missile[i]._miVar2)];
	if (mid != 0) {
		if (mid > 0) --mid;
		else mid = -(mid + 1);
	}

	// if he did search again
	if (mid != missile[i]._miVar3) {
		for (m = 0; m < 6; ++m) {
			n = CrawlNum[m];
			l = n + 1;
			for (k = CrawlTable[n]; k > 0; --k) {
				mid = dMonster[((missile[i]._miVar1) + CrawlTable[l])][((missile[i]._miVar2) + CrawlTable[(l + 1)])];
				if (mid != 0) {
					if (mid > 0) --mid;
					else mid = -(mid + 1);
					if (mid == missile[i]._miVar3) {
						missile[i]._miVar1 += CrawlTable[l];
						missile[i]._miVar2 += CrawlTable[l + 1];
						k = -99;
						m = 6;
						break;
					}
				}
				l += 2;
			}
		}

		// if monster killed before doom kills it
		if (k != -99) {
			missile[i]._miDelFlag = TRUE;
			PutMissile(i);
			return;
		}

		// get new velocity and directions
		GetMissileVel(i, missile[i]._mix, missile[i]._miy, missile[i]._miVar1, missile[i]._miVar2, 16);
		SetMissDir(i, GetDirection(missile[i]._mix, missile[i]._miy, missile[i]._miVar1, missile[i]._miVar2));
	}

	
	// move missile
	if (missile[i]._mimfnum != 9) {
		missile[i]._mitxoff += missile[i]._mixvel;
		missile[i]._mityoff += missile[i]._miyvel;
		GetMissilePos(i);
	}

	// get mid for current missile pos - for checking if target monster killed
	mid = dMonster[(missile[i]._mix)][(missile[i]._miy)];
	if (mid != 0) {
		if (mid > 0) --mid;
		else mid = -(mid + 1);
	}

	// check for collision if not followed monster dont end missile
	k = missile[i]._mirange;
	if ((missile[i]._mix != plr[myplr]._px) || (missile[i]._miy != plr[myplr]._py)) CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 0);
	if ((missile[i]._mirange == 0) && (mid != missile[i]._miVar3) && (missile[i]._miHitFlag == TRUE)) missile[i]._mirange = k;
	
	// if target monster not dead halt missile in place
	if ((missile[i]._mirange == 0) && (mid == missile[i]._miVar3)) {
		missile[i]._mirange = k;
		if ((monster[mid]._mhitpoints >> HP_SHIFT) > 0) {
			if (missile[i]._mimfnum != 9) {
				SetMissDir(i, 9);
			}
		} else {
			// target is killed so re-search
			for (m = 1; m < 6; ++m) {
				n = CrawlNum[m];
				l = n + 1;
				for (k = CrawlTable[n]; k > 0; --k) {
					mid = dMonster[((missile[i]._miVar1) + CrawlTable[l])][((missile[i]._miVar2) + CrawlTable[(l + 1)])];
					if (mid != 0) {
						if (mid > 0) --mid;
						else mid = -(mid + 1);
						if ((monster[mid]._mhitpoints >> HP_SHIFT) > 0) {
							missile[i]._miVar1 += CrawlTable[l];
							missile[i]._miVar2 += CrawlTable[l + 1];
							missile[i]._miVar3 = mid;
							k = -99;
							m = 6;
							break;
						}
					}
					l += 2;
				}
			}

			// get new velocity and directions
			if (k == 0) missile[i]._mirange = 0;
			else {
				GetMissileVel(i, missile[i]._mix, missile[i]._miy, missile[i]._miVar1, missile[i]._miVar2, 16);
				SetMissDir(i, GetDirection(missile[i]._mix, missile[i]._miy, missile[i]._miVar1, missile[i]._miVar2));
			}
		}
	}

	// delete or place missile
	if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
	PutMissile(i);
}*/

This code is responsible for the Doom Serpents missiles, which don't appear, and this code is commented out.

/*-----------------------------------------------------------------------*
**-----------------------------------------------------------------------*/
/*void AddInvis(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
{
	int i;

	missile[mi]._mirange = plr[id]._pLevel << 4;
	for (i = GetSpellLevel(id, SPL_INVIS); i > 0; --i) missile[mi]._mirange += ((missile[mi]._mirange << 4) >> 3);
	missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7);
	UseMana(id, SPL_INVIS);
	missile[mi]._miDelFlag = TRUE;
}*/

Likewise, this is for handling the Invisibility spell.

/*-----------------------------------------------------------------------*
**-----------------------------------------------------------------------*/
void AddBoil(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam)
{
	// not in game
	missile[mi]._miDelFlag = TRUE;
	return;
/*
#if (PRE_BETA && PRE_BLOODB) || !PRE_BETA
	missile[mi]._miVar1 = dx;
	missile[mi]._miVar2 = dy;
	missile[mi]._mirange = 1;
#else
	missile[mi]._miDelFlag = TRUE;
#endif*/
}

/*-----------------------------------------------------------------------*
**-----------------------------------------------------------------------*/
void MI_Boil(int i)
{
	app_assert(i < MAXMISSILES && i >= 0);
	missile[i]._miDelFlag = TRUE;
	return;
	
/*#if (PRE_BETA && PRE_BLOODB) || !PRE_BETA
	int j, mid, id, dx, dy, pct;
	long dm;

	BOOL M_Talker (int);

	id = missile[i]._misource;
	dx = missile[i]._miVar1;
	dy = missile[i]._miVar2;
	mid = dMonster[dx][dy];

	if (mid > 0) --mid;
	else mid = -(mid + 1);
	if (mid > 0) {
		if ((M_Talker(mid) && monster[mid].mtalkmsg != 0) || ((plr[id]._pLevel - 6 + missile[i]._mispllvl) <= monster[mid].mLevel)) {
			missile[i]._miDelFlag = TRUE;
			return;
		}

		if (monster[mid].mMagicRes & M_IM) return;

		dm = monster[mid]._mhitpoints;
		monster[mid]._mhitpoints = 0;
		M_StartKill(mid, id);
		AddPlrExperience(id, monster[mid].mLevel, monster[mid].mExp);
		dMonster[monster[mid]._mx][monster[mid]._my] = 0;
		monster[mid]._mDelFlag = TRUE;
		AddMissile(monster[mid]._mx, monster[mid]._my, monster[mid]._mx, monster[mid]._my, plr[id]._pdir, MIT_SPURT, MI_ENEMYMONST, id, (random(87, 2) + 1), 0);
		AddDead(monster[mid]._mx, monster[mid]._my, spurtndx, monster[mid]._mdir);

		pct = 0;
		for (j = 0; j < missile[i]._mispllvl && j < 5; ++j) pct += 10;
		//dm = (monster[mid]._mmaxhp >> 1);
		if (pct > 0) dm -= (dm / pct);
		plr[id]._pHitPoints -= dm;
		plr[id]._pHPBase -= dm;

		if (plr[id]._pHitPoints > plr[id]._pMaxHP) {
			plr[id]._pHitPoints = plr[id]._pMaxHP;
			plr[id]._pHPBase = plr[id]._pMaxHPBase;
		}
		if (plr[id]._pHitPoints <= 0) {
			// rjs - manashld fix? - plr[id]._pHitPoints = 0;
			StartPlrKill(id, FALSE);
		} else StartPlrHit(id, dm);

		PlaySfxLoc(LS_BLODBOIL, monster[mid]._mx, monster[mid]._my);
		UseMana(id, SPL_BLOODB);
	}
	--missile[i]._mirange;
	if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE;
#endif*/
}

This code isn't called. It's very stripped down, and handled for Blood Boil.

MONSTDAT.CPP

MonstConvTbl contains a few interesting entries:

		0, //BlackWound
		0, //SinWar
		0,
		0, //Lazarus
		0, //Warlord
		0, //FleshDoom
		0, //Snotspil
		0, //Temptress
		0,  //Lachdanan

These dummied-out lines mention BlackWound and SinWar (?), but also Fleshdoom and Temptress, who are almost certainly related to some cut quests.

objdat.h

A whole pile of object IDs are defined, but are dummied out:

// These are not used yet, so their numbers are not relevent
#define OBJ_BLADEL		0
#define OBJ_BLADER		0
#define OBJ_BLOCK		0
#define OBJ_BOOK1L		0
#define OBJ_BOOK1R		0
#define OBJ_CANBRA		0
#define OBJ_CHAINEL		0
#define OBJ_CHAINER		0
#define OBJ_CHAING1L	0
#define OBJ_CHAING1R	0
#define OBJ_CHAING2L	0
#define OBJ_CHAING2R	0
#define OBJ_CHAINLL		0
#define OBJ_CHAINLR		0
#define OBJ_FTNROUND	0
#define OBJ_FTNL		0
#define OBJ_FTNR		0
#define OBJ_GATEL		0
#define OBJ_GATER		0
#define OBJ_SPKTRAP		0
#define OBJ_STEAMTRAP	0
#define OBJ_SWITCHML	0
#define OBJ_SWITCHMR	0
#define OBJ_SWITCHRL	0
#define OBJ_SWITCHRR	0
#define OBJ_SWITCHSKR	0
#define OBJ_WATERJUG	0
#define OBJ_TORTURE6R	0
#define OBJ_NUDEW1L		0
#define OBJ_NUDEW1R		0
#define OBJ_NUDEW2L		0
#define OBJ_NUDEW8		0
#define OBJ_NUDEMAN1L	0
#define OBJ_NUDEMAN1R	0
#define OBJ_NUDEMAN3	0
#define OBJ_VAPOR		0
#define	OBJ_DEADSKL		0
#define OBJ_INVPLATE	0
#define OBJ_WOODPLATE	0
#define OBJ_MTLPLATE	0
#define OBJ_STNPLATE	0
#define	OBJ_ANVIL		0
#define	OBJ_FORGE		0
#define OBJ_BIGROCK		0
#define	OBJ_ROCK1		0
#define OBJ_ROCK2		0
#define	OBJ_ROCK3		0
#define	OBJ_ROCK4		0
#define	OBJ_STALAG1		0
#define	OBJ_STALAG2		0
#define	OBJ_STALAG3		0
#define	OBJ_STALAG4		0
#define	OBJ_STALAG5		0
#define	OBJ_ALTGIRL		0
#define	OBJ_TORCH		0
#define OBJ_VILEPORT	0

OBJECTS.cpp

In the final game, there is no minimum level that shrines can appear at. All shrines can appear on the first level of the dungeon. However, the source code has a table that allows the programmers to set the minimum level for the shrines, it's just all set to 1s:

// 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
};

"Journal: The Ensorcellment" goes unused here. Notably, it's the only time that the summoner in the crypts is given a name:

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"
};

There's other references to this Skulken character too, such as the functions "AddSkulkenBooks" and "AddSkulkenObject". As mentioned above, the first book ("Journal: The Ensorcellment") goes unused because its code is commented out, perhaps by mistake:

	if (currlevel == SKULKEN_BOOK1_LEVEL) 
	{
//		AddSkulkenBooks(0);
		AddSkulkenBooks(1);

//		AddStoryBooks();
//		AddStoryBooks();
	}

Tainted shrines are multiplayer-only shrines that do nothing for the activator, but subtract three attributes by 1 and add 1 to another random attribute. According to a comment in the code though, this might not be the intended effect. Instead, the opposite is the case: it's meant to add 1 to 3 random stats and subtract 1 from another stat. The logic seems to be ill-formed, and therefore, bugged:

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;

A non-existent item, "Tome", seems to be commented out:

//		case OBJ_BOOKLVR:
//			strcpy(infostr, "Tome");
//			break;

pfile.cpp

Once again, there is code regarding "retribution" here. In this case, it is used for checking save files. Save files are actually just MPQ archives. The anti-cheating code checks various properties of the MPQ, such as the timestamp of it against the file creation time. If something doesn't match, the save file in question gets wiped - no gold, items, stats or spells will exist on the player character. This only executes in multiplayer. In Hellfire at least, it seems that this retribution code is #ifdef'd out:

// pjw.patch1.start -- remove retribution code
#define PREVENT_CHEATING	0	// 0 in final
#ifdef NDEBUG
#undef PREVENT_CHEATING
#define PREVENT_CHEATING 0
#endif
// pjw.patch1.end

//******************************************************************
//******************************************************************
#if PREVENT_CHEATING
static BOOL FixCheaters(BOOL * pbMsgBox,DWORD dwChar) {
	app_assert(dwChar < MAX_CHARACTERS);

	// only perform cheat detection/correction for multiplayer chars
	if (gbMaxPlayers == 1) return TRUE;

	// compare current state of archive time stamps to expected values
	char szSaveArchive[MAX_PATH];
	archive_name(szSaveArchive,MAX_PATH,dwChar, ARCHIVE_HELLFIRE);
	if (MPQCompareTimeStamps(szSaveArchive,dwChar))
		return TRUE;

	HSARCHIVE hsArchive = NULL;
	if (! SFileOpenArchive(szSaveArchive,ARCHIVE_PRIORITY,0,&hsArchive))
		return TRUE;

	// load character
	PkPlayerStruct pack;
	if (! LoadCharacter(hsArchive,&pack))
		pack.pName[0] = 0;
	else
		PackClearCheater(&pack);
	SFileCloseArchive(hsArchive);
	hsArchive = NULL;

	// write all characters
	if (pack.pName[0]) {
		if (! MPQOpenArchive(szSaveArchive,TRUE,dwChar)) return FALSE;
		SaveCharacter(&pack);
		MPQCloseArchive(szSaveArchive,TRUE,dwChar);
		MPQUpdateCreationTimeStamp(szSaveArchive,dwChar);
	}
	else {
		BOOL MPQSetAttributes(const char * pszArchive,BOOL bHide);
		MPQSetAttributes(szSaveArchive,FALSE);
		DeleteFile(szSaveArchive);
	}

	if (pbMsgBox && *pbMsgBox) {
		*pbMsgBox = FALSE;
		UiMessageBoxCallback(
			ghMainWnd,
			"A problem with your saved game file has been detected."
			"The file has been fixed, but changes to it may have occurred.",
			"Diablo",
			MB_OK
		);
	}

	return TRUE;
}
#endif

The save files are encoded with the computer name in multiplayer, so you can't easily transfer them across computers. The memory that is filled in with the user's computer name is defined to a rather interesting constant:

//******************************************************************
// private
//******************************************************************
// signature name for machines with no network name
#ifndef ENCRYPTNAME
#define ENCRYPTNAME "xrgyrkj1"
#endif

It isn't clear where "xrgyrkj1" comes from, or what it's supposed to mean.

#if !ENCRYPT_WITH_NAME
#define ENCRYPTNAME "BROPER"	// replace name to debug specific file
#endif

If the code is compiled in such a fashion that this sharing is disabled, the default computer name is "BROPER" - short for Bill Roper, an employee at Blizzard North and none other than the voice of Diablo himself (at least in Diablo II).

PLAYER.CPP

In the retail game, all character classes move at the same speed. However, at one point it seems like the Warrior and Rogue were meant to move faster than the Sorceror, because there is a table for this, and there's some commented out code with what the speeds were going to be:

// Different walk velocities for different classes
int PlrWalkTbl[NUM_CLASSES][3] = {
	{ 2048, 1024, 512 },		// Warrior (8 frames)
	//{ 2730, 1365, 682 },		// Warrior (6 frames)
	{ 2048, 1024, 512 },		// Rogue (8 frames)
	//{ 2340, 1170, 585 },		// Rogue (7 frames)
	{ 2048, 1024, 512 }, 		// Sorceror (8 frames)
	{ 2048, 1024, 512 }, 		// Monk (8 frames)
	{ 2048, 1024, 512 },		// Bard (8 frames)
	{ 2048, 1024, 512 } };		// Barbarian (8 frames)

// Different walk lengths for different classes
//int PlrWalkLenTbl[3] = { 6, 7, 8 };
int PlrWalkLenTbl[NUM_CLASSES] = { 8, 8, 8, 8, 8, 8 };

At one point, there used to be a maximum level cap of 13, much lower than what we got in the retail game (50):

long ExpLvlsTbl[MAX_EXPLVLS+1] = {
/*	0,				// 0		Changed 11/5 Dave
	1000,			// 1
	2400,			// 2
	4353,			// 3
	7070,			// 4
	10837,			// 5
	16044,			// 6
	23217,			// 7
	33065,			// 8
	46542,			// 9
	64925,			// 10
	89917,			// 11
	123782,			// 12
	169516,			// 13*/

	0,				// 0
	2000,			// 1
	4620,			// 2
	8040,			// 3
	12489,			// 4
	18258,			// 5
	25712,			// 6
	35309,			// 7
	47622,			// 8
	63364,			// 9
	83419,			// 10
	108879,			// 11
	141086,			// 12
	181683,			// 13
	231075,			// 14
	313656,			// 15
	424067,			// 16
	571190,			// 17
	766569,			// 18
	1025154,		// 19
	1366227,		// 10
	1814568,		// 21
	2401895,		// 22
	3168651,		// 23
	4166200,		// 24
	5459523,		// 25
	7130496,		// 26
	9281874,		// 27
	12042092,		// 28
	15571031,		// 29
	20066900,		// 30
	25774405,		// 31
	32994399,		// 32
	42095202,		// 33
	53525811,		// 34
	67831218,		// 35
	85670061,		// 36
	107834823,		// 37
	135274799,		// 38
	169122009,		// 39
	210720231,		// 40
	261657253,		// 41
	323800420,		// 42
	399335440,		// 43
	490808349,		// 44
	601170414,		// 45
	733825617,		// 46
	892680222,		// 47
	1082908612,		// 48
	1310707109,		// 49
	1583495809 };	// 50

Unfortunately for us all, the art never arrived:

	//
	//
	// Fix this when the art arrives.
	//
	//
	else if (pc == CLASS_BARD)
	{
		if (gn == PGFX_FGUY) {			// Axe
			plr[pnum]._pAFrames = 22;
			plr[pnum]._pAFNum = 13;
		}
		else if (gn == PGFX_BGUY) {		// Bow
			plr[pnum]._pAFrames = 12;
			plr[pnum]._pAFNum = 11;
		}
		else if (gn == PGFX_TGUY) {		// Staff
			plr[pnum]._pAFrames = 16;
			plr[pnum]._pAFNum = 11;
		}
		else if (gn == PGFX_GUY) {		// Sword and shield
			plr[pnum]._pAFNum = 10;
		}
		else if (gn == PGFX_XGUY) {		// Sword
			plr[pnum]._pAFNum = 10;
		}
	}
	else if (pc == CLASS_BARBARIAN)
	{
		if (gn == PGFX_FGUY) {			// Axe
			plr[pnum]._pAFrames = 20;
			plr[pnum]._pAFNum = 8;
		}
		else if (gn == PGFX_BGUY) {		// Bow
			if (leveltype != 0) plr[pnum]._pNFrames = 8;
			plr[pnum]._pAWidth = 96;
			plr[pnum]._pAFNum = 11;
		}
		else if (gn == PGFX_TGUY) {		// Staff
			plr[pnum]._pAFrames = 16;
			plr[pnum]._pAFNum = 11;
		}
		else if (gn == PGFX_ZGUY) {		// Mace
			plr[pnum]._pAFNum = 8;
		}
		else if (gn == PGFX_CGUY) {		// Mace with Shield
			plr[pnum]._pAFNum = 8;
		}
	}

Unfortunately, despite the comment to the contrary, this is still bugged, and suffers from a Year 2038 problem:

// dig.patch1.start.2/4/97
	// time() returns -1 if clock is set far ahead, e.g., the year 2097.
	// Many customers have broken clock, resulting in all games being the same.

//	SetRndSeed((int) time(NULL));
	SetRndSeed((int) GetTickCount());
// dig.patch1.end.2/4/97

This code is #ifdef'd out in Hellfire, but is not in Diablo. Because of this, footstep sounds don't play:

#if 0
	// changed _pAnimFrame == 2 to == 3 to prevent "extra" footstep == pat
	if ((plr[pnum]._pAnimFrame == 3)
		|| (plr[pnum]._pWFrames == 8 && plr[pnum]._pAnimFrame == 7)
		|| (plr[pnum]._pWFrames != 8 && plr[pnum]._pAnimFrame == 4))
		PlaySfxLoc(PS_WALK1, plr[pnum]._px, plr[pnum]._py);
	//TempWalkFix(pnum);
#endif

Various bits and pieces of Hellfire-related level-entry code is commented out:

else if ((currlevel == HIVESTART) && (!plr[myplr]._pLvlVisited[HIVESTART]) && (gbMaxPlayers == 1) && (!(plr[myplr].pHellfireMsgs & DUNGMSG_1))) 
	{
		// play Defiler 1 JKE
		sfxdelay = 10;
		sfxdnum = HSFX_DEFILER1;
		quests[Q_DEFILER]._qactive = QUEST_NOTDONE;
		quests[Q_DEFILER]._qlog = TRUE;
		quests[Q_DEFILER]._qmsg = TXT_DEFILER1;
		plr[myplr].pHellfireMsgs |= DUNGMSG_1;
	} 
/*	else if ((currlevel == (HIVESTART+1)) && (!plr[myplr]._pLvlVisited[(HIVESTART+1)]) && (gbMaxPlayers == 1) && (!(plr[myplr].pHellfireMsgs & DUNGMSG_2))) {
		// play Defiler 2 JKE
		sfxdelay = 10;
			sfxdnum = HSFX_DEFILER2;
		plr[myplr].pHellfireMsgs |= DUNGMSG_2;
	} */
	else if ((currlevel == (HIVESTART+2)) && (!plr[myplr]._pLvlVisited[(HIVESTART+2)]) && (gbMaxPlayers == 1) && (!(plr[myplr].pHellfireMsgs & DUNGMSG_3))) {
		// play Defiler 3 JKE
		sfxdelay = 10;
			sfxdnum = HSFX_DEFILER3;
		plr[myplr].pHellfireMsgs |= DUNGMSG_3;
	} 
/*	else if ((currlevel == (HIVESTART+3)) && (!plr[myplr]._pLvlVisited[(HIVESTART+3)]) && (gbMaxPlayers == 1) && (!(plr[myplr].pHellfireMsgs & DUNGMSG_4))) {
		// play Defiler 4 JKE
		sfxdelay = 10;
			sfxdnum = HSFX_DEFILER4;
		plr[myplr].pHellfireMsgs |= DUNGMSG_4;
	} */
	else if ((currlevel == CRYPTSTART) && (!plr[myplr]._pLvlVisited[CRYPTSTART]) && (gbMaxPlayers == 1) && (!(plr[myplr].pDungMsgs & DUNGMSG_6))) {
		// play "great power " JKE
		sfxdelay = 30;

//		sfxdnum = HSFX_CORNERSTONE1;
/*		quests[Q_CORNERSTONE]._qactive = QUEST_NOTDONE;
		quests[Q_CORNERSTONE]._qlog = TRUE;
		quests[Q_CORNERSTONE]._qmsg = TXT_CORNERSTONE1;
		InitQTextMsg(TXT_CORNERSTONE1); */
		
		#if !IS_VERSION(SHAREWARE)
		if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR92;
		else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE92;
		else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE92;
		else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK92;
		else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD92;
		else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN92;
		#else
		if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR92;
		#endif 

		plr[myplr].pDungMsgs |= DUNGMSG_6;
	} 

portal.cpp

There's a note about a bug that occurred at one point:

	// Give it a lightsource
//DL - 11/9/97
// This is a serious bug.  Under certain situations, missile[i] will be
// uninitialized, causing coordinate (0, 0) to be passed to AddLight().
// When the light is processed later, and the radius is subtracted from
// the (0, 0) coordinate, the light table will be written to with negative
// indicies, causing an array underwrite.  This was causing a crash on the
// Mac because it was overwriting the memory block header, trashing the
// application's heap.  I don't know what is getting overwritten on the PC
// version. An example of when this will happen is if player 1 creates a
// new game, and player 2 joins it.  Both players go to level 1.  Player 2
// casts town portal (with cheats on). On player 1's machine,
// AddWarpMissile( will be called with i = 1 (player 2's player index).
// Since there are no missles yet, AddMissile() will use missle index 0, so
// mi wil be 0. But since i is 1, AddLight() will be passed the coordinates
// of missle[1], which doesn't exist, so its coordinates are undefined.  In
// this case, they are uninitialized, so they are zero.

//	if (currlevel != 0) missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, 15);
	if (currlevel != 0) missile[mi]._mlid = AddLight(missile[mi]._mix, missile[mi]._miy, 15);

Quests.cpp

There is a whole unused quest here that isn't fully defined: "Wandering Trader." Presumably this would've involved giving items to the Wandering Trader (see above), but it didn't make it to the final release:

	// New quests for Hellfire JKEQUEST
	{ 17, 17, 255, Q_CRYPTMAP,  100, 0, QFLAG_MULTI,    TXT_CRYPTMAP7,	"Grave Matters" },		// 16
	{  9,  9, 255, Q_FARMER,	100, 0, QFLAG_MULTI,	TXT_FARMER1,	"Farmer's Orchard" },		// 17
	{ 17, -1, 255, Q_THEO,		100, 0, 0,				TXT_THEO2,		"Little Girl" },			// 18
	{ 19, -1, 255, Q_TRADER,	100, 0, 0,				TXT_TRADER1,	"Wandering Trader" },		// 19
	{ 17, 17, 255, Q_DEFILER,	100, 0, QFLAG_MULTI,	TXT_DEFILER1,	"The Defiler" },			// 20
	{ 21, 21, 255, Q_NA_KRUL,	100, 0, QFLAG_MULTI,	TXT_NA_KRUL1,	"Na-Krul" },				// 21
	{ 21, -1, 255, Q_CORNERSTONE, 100, 0, 0,		  TXT_CORNERSTONE1,	"Cornerstone of the World"}, // 22
	{  9,  9, 255, Q_COWSUIT,		100, 0, QFLAG_MULTI,	TXT_COWSUIT4,		"The Jersey's Jersey" }		// 23

"Maze" does not appear, and is mentioned elsewhere in the code:

char *questtrigstr[] = {
	"King Leoric's Tomb",
	"The Chamber of Bone",
	"Maze",
	"A Dark Passage",
	"Unholy Altar"
};

Lastly, there's a bit of a funny comment regarding Snotspill:

// additional inits for the quests (not to be messed with)
	if (quests[Q_SKELKING]._qactive == QUEST_NOTAVAIL) quests[Q_SKELKING]._qvar2 = 2;
	if (quests[Q_ROCK]._qactive == QUEST_NOTAVAIL) quests[Q_ROCK]._qvar2 = 2;
	quests[Q_LTBANNER]._qvar1 = 1;  // so the door is open to snotspil for the lame gamers (LAME!!!)
	if (gbMaxPlayers != 1) quests[Q_BETRAYER]._qvar1 = 2;	// so that betrayer is on level 15

SetMaps.cpp

The Maze level doesn't appear, so code regarding it goes unused:

char *SetLevelName[] = {
	"",
	"Skeleton King's Lair",
	"Bone Chamber",
	"Maze",
	"Poisoned Water Supply",
	"Archbishop Lazarus' Lair",
};

		case SL_MAZE:
			LoadPreL1Dungeon("Levels\\L1Data\\Lv1MazeA.DUN", 20, 50);
			LoadL1Dungeon("Levels\\L1Data\\Lv1MazeB.DUN", 20, 50);
			LoadPalette ("Levels\\L1Data\\L1_5.pal");
			AddL1Objs(0, 0, DMAXX, DMAXY);
			DRLG_SetMapTrans("Levels\\L1Data\\Lv1MazeA.DUN");
			break;

Spelldat.cpp

Data for the cut spells Doom Serpents, Blood Ritual, Invisibility, Blood Boil, and Etherealize are present here:

	{ SPL_DOOM,								// #defines name of spell for ease of use
	0,										// base cost in mana
	ST_LIGHT,								// spell type (fire, light, misc)
	"Doom Serpents",						// text name of spell
	NULL,									// text name of spell if it can be a skill
	-1,										// lvl book can be found
	-1,										// lvl staff can be found
	FALSE,									// Targeted spell?
	FALSE,									// Avail in town?
	0,										// min intelligence to use
	IS_CAST2,								// sfx to use
	{ NULL, NULL, NULL },					// missiles to launch per casting
	0,										// mana adj per spell lvl
	0,										// min mana for use
	40,										// min number of staff charges
	80,										// max number of staff charges
	0,										// book cost
	0 },									// scroll cost

	{ SPL_BLOODR,							// #defines name of spell for ease of use
	0,										// base cost in mana
	ST_MISC,								// spell type (fire, light, misc)
	"Blood Ritual",							// text name of spell
	NULL,									// text name of spell if it can be a skill
	-1,										// lvl book can be found
	-1,										// lvl staff can be found
	FALSE,									// Targeted spell?
	FALSE,									// Avail in town?
	0,										// min intelligence to use
	IS_CAST2,								// sfx to use
	{ NULL, NULL, NULL },					// missiles to launch per casting
	0,										// mana adj per spell lvl
	0,										// min mana for use
	40,										// min number of staff charges
	80,										// max number of staff charges
	0,										// book cost
	0 },									// scroll cost

	{ SPL_INVIS,							// #defines name of spell for ease of use
	0,										// base cost in mana
	ST_MISC,								// spell type (fire, light, misc)
	"Invisibility",							// text name of spell
	NULL,									// text name of spell if it can be a skill
	-1,										// lvl book can be found
	-1,										// lvl staff can be found
	FALSE,									// Targeted spell?
	FALSE,									// Avail in town?
	0,										// min intelligence to use
	IS_CAST2,								// sfx to use
	{ NULL, NULL, NULL },					// missiles to launch per casting
	0,										// mana adj per spell lvl
	0,										// min mana for use
	40,										// min number of staff charges
	80,										// max number of staff charges
	0,										// book cost
	0 },									// scroll cost

	#if 0
	{ SPL_BLOODB,							// #defines name of spell for ease of use
	0,										// base cost in mana
	ST_LIGHT,								// spell type (fire, light, misc)
	"Blood Boil",							// text name of spell
	NULL,									// text name of spell if it can be a skill
	-1,										// lvl book can be found
	-1,										// lvl staff can be found
	TRUE,									// Targeted spell?
	FALSE,									// Avail in town?
	0,										// min intelligence to use
	IS_CAST8,								// sfx to use
	{ NULL, NULL, NULL },					// missiles to launch per casting
	0,										// mana adj per spell lvl
	0,										// min mana for use
	0,										// min number of staff charges
	0,										// max number of staff charges
	0,										// book cost
	0 },									// scroll cost
	#else
	{ SPL_RAGE,								// #defines name of spell for ease of use
	15,										// base cost in mana
	ST_MISC,								// spell type (fire, light, misc)
	"Rage",									// text name of spell
	"Rage",									// text name of spell if it can be a skill
	-1,										// lvl book can be found
	-1,										// lvl staff can be found
	FALSE,									// Targeted spell?
	FALSE,									// Avail in town?
	0,										// min intelligence to use
	IS_CAST8,								// sfx to use
	{ MIT_RAGE, NULL, NULL },				// missiles to launch per casting
	1,										// mana adj per spell lvl
	1,										// min mana for use
	0,										// min number of staff charges
	0,										// max number of staff charges
	0,										// book cost
	0 },									// scroll cost
	#endif

	{ SPL_ETHER,							// #defines name of spell for ease of use
	100,									// base cost in mana
	ST_MISC,								// spell type (fire, light, misc)
	"Etherealize",							// text name of spell
	NULL,									// text name of spell if it can be a skill
#if IS_VERSION(RETAIL)
	-1,										// lvl book can be found
	-1,										// lvl staff can be found
#else
	-1,-1,
#endif
	FALSE,									// Targeted spell?
	FALSE,									// Avail in town?
	93,										// min intelligence to use
	IS_CAST2,								// sfx to use
	{ MIT_ETHER, NULL, NULL },				// missiles to launch per casting
	0,										// mana adj per spell lvl
	100,									// min mana for use
	2,										// min number of staff charges
	6,										// max number of staff charges
	26000,										// book cost
	1600 },									// scroll cost

Textdat.cpp

Evidently, the Map of Stars (Map of Doom, Strange Map...whatever the quest is meant to be called) was cut so late in development that it's the only quest whose subtitles are still within the code. Synergistic Software didn't delete any of the subtitles.

/*-----------------------------------------------------------------------**
** Map of Doom Quest
**-----------------------------------------------------------------------*/
#if !IS_VERSION(SHAREWARE)
static char Doom1[] = "So, the legend of the Map is real.  Even I never "
"truly believed any of it!  I suppose it is time that I told you the "
"truth about who I am, my friend.  You see, I am not all that I seem...\n \n"
"My true name is Deckard Cain the Elder, and I am the last descendant "
"of an ancient Brotherhood that was dedicated to keeping and safeguarding "
"the secrets of a timeless evil.  An evil that quite obviously has now "
"been released...\n \n"
"The evil that you move against is the dark Lord of Terror - known to "
"mortal men as Diablo.  It was he who was imprisoned within the Labyrinth "
"many centuries ago.  The Map that you hold now was created ages ago to "
"mark the time when Diablo would rise again from his imprisonment.  When "
"the two stars on that map align, Diablo will be at the height of his "
"power.  He will be all but invincible...\n \n"
"You are now in a race against time, my friend!  Find Diablo and destroy "
"him before the stars align, for we may never have a chance to rid the "
"world of his evil again! |";

//If the hero returns before the stars align and Diablo is Alive
static char Doom2[] = "Our time is running short!  I sense his dark power "
"building and only you can stop him from attaining his full might. |";

//If the hero returns after the stars align and Diablo is Alive
static char Doom3[] = "I am sure that you tried your best, but I fear that "
"even your strength and will may not be enough.  Diablo is now at the "
"height of his earthly power, and you will need all your courage and "
"strength to defeat him.  May the Light protect and guide you, my friend.  "
"I will help in any way that I am able. |";

static char Doom4[] = "If the witch can't help you and suggests you see Cain, "
"what makes you think that I would know anything?  It sounds like this is a "
"very serious matter.  You should hurry along and see the storyteller as "
"Adria suggests. |";

static char Doom5[] = "I can't make much of the writing on this map, but "
"perhaps Adria or Cain could help you decipher what this refers to. \n \n"
"I can see that it is a map of the stars in our sky, but any more than "
"that is beyond my talents. |";

static char Doom6[] = "The best person to ask about that sort of thing "
"would be our storyteller. \n \n"
"Cain is very knowledgeable about ancient "
"writings, and that is easily the oldest looking piece of paper that "
"I have ever seen. |";

static char Doom7[] = "I have never seen a map of this sort before.  Where'd you get it?  "
"Although I have no idea how to read this, Cain or Adria may be able "
"to provide the answers that you seek. |";

static char Doom8[] = "Listen here, come close.  I don't know if you know "
"what I know, but you have really got somethin' here.  That's a map. |";

static char Doom9[] = "Oh, I'm afraid this does not bode well at all.  This map "
"of the stars portends great disaster, but its secrets are not mine to "
"tell.  The time has come for you to have a very serious conversation "
"with the Storyteller... |";

static char Doom10[] = "I've been looking for a map, but that certainly "
"isn't it.  You should show that to Adria - she can probably tell you "
"what it is.  I'll say one thing; it looks old, and old usually means "
"valuable. |";
#endif

This bit of text goes unused. It's likely it was meant for some kind of book. Note that the commented-out text is apparently the matching subtitle for CRNRSTON.WAV, as described above.

static char Cornerstone1[] = "And in the year of the Golden Light, it was so decreed "
"that a great Cathedral be raised.  The cornerstone of this holy place was to be "
"carved from the translucent stone Antyrael, named for the Angel who shared his power "
"with the Horadrim.  \n \nIn the Year of Drawing Shadows, the ground shook and the Cathedral "
"shattered and fell.  As the building of catacombs and castles began and man stood "
"against the ravages of the Sin War, the ruins were scavenged for their stones.  And "
"so it was that the cornerstone vanished from the eyes of man. \n \nThe stone was of this "
"world -- and of all worlds -- as the Light is both within all things and beyond all "
"things. Light and unity are the products of this holy foundation, a unity of purpose "
"and a unity of possession.|";

/*"And in the year of Golden Light, it was so "
"decreed that a great cathedral should be raised, for the glory of Heaven.  "
"And for the cornerstone was brought from the Holy Land a block of "
"translucent stone.  And the stone was of this world, and of all worlds, as "
"the spirit of Light is both within and beyond us, in all things.  "
"The stone brought all it touched to all the worlds, uniting them in Light.  "
"In the Year of the Drawing Shadows, the ground shook, and the cathedral "
"tumbled and shattered.  And in the time that followed, of the building of "
"catacombs and castles against the ravages of the Sin War, the ruins were "
"taken for their stones.  And so it was that the Cornerstone vanished from "
"the eyes of man, lost, perhaps forever.|";*/

There are some alternate lines for Lester that are commented out.

/*"Here, you're that hero everyone's talking about!  "
"You're just the type to help a poor farmer out of a terrible fix!  You "
"see, right at the border of my orchard, just south of here, there's a "
"horrible thing swelling out of the ground!  I daren't go near me own "
"land!  So I got an alchemist to make a magic doo-hickey that'll "
"blast that thing.  All you gotta do is take it over and drop it in.  "
"I'd do it myself, but my leg's acting up, my lumbago, old war wounds, "
"you know. |";*/

/*"You ain't done that measly little thing for me "
"yet?  You're young!  Never a thought for a poor common peasant... "
"it's a sad world.|";*/

/*"Please, can you get that snarkfarbin' thing outta "
"myfield?  It's blockin' the path to me privy!|";*/

/*"You don't have that doo-hickey no more, but I "
"didn't hear any kaboom!  Don't tell me you lost it!  Those things don't "
"come cheap!  You gotta find it, and blast that slimy-lookin' thing outta "
"there!|";*/

/*"You blasted the sucker, eh?  Many thanks to you, you're so kind, "
"many thanks.  I don't know, things comin' out of the ground, monsters taking over the church, "
"these are hard times... I'm a poor man, I ain't got much, but... take this, take this with my"
"  great thanks.|";*/

/*"Oh, such a trouble I have... maybe... Nah, you're just a kid, "
"still wet behind the ears!  I can't ask you to do this.  If only you were a little better "
"prepared.|";*/

/*"Off with you!  What I need done would take a real hero... maybe "
"someday you'll qualify.|";*/

/*"I need something done, but how do I know you won't just skip town "
"on me?  Make a name for yourself, kid, and then come find me.|";*/

/*"Talk of the town is that you show real promise!  Maybe if you live "
"up to the rumors... someday, I might have a little job for you.|";*/

/*"Busy fighting evil, huh?  Well, if you live long enough to know "
"what you're doing, look me up, I got a little job you might be interested in.|";*/

All of this code goes unused.

static char Skulljrnl1[] = "Cloudy and cooler today.  Casting the nets of necromancy across "
"the void landed two new subspecies of flying horror; a good day's work.  Must remember to "
"order some more bat guano and black candles from Adria; I'm running a bit low.|";

static char Skulljrnl2[] = "I have tried spells, threats, abjuration and bargaining with "
"this foul creature -- to no avail.  My methods of enslaving lesser demons seem to have no "
"effect on this fearsome beast.|"; 

/*"I have tried spells, threats, abjuration and bargaining with "
"the new creature.  My means which have enslaved many lesser demons have no effect on this "
"fearsome beast; it only leers at me in a most unpleasant fashion. |";*/

static char Skulljrnl3[] = "My home is slowly becoming corrupted by the vileness of this "
"unwanted prisoner.  The crypts are	full of shadows that move just beyond the corners of "
"my vision.  The faint scrabble of claws dances at the edges of my hearing. They are "
"searching, I think, for this journal.|";

/*"The trapped creature's howls of fury keep me from sleep-- it "
"rages and curses the name of the one who sent it to the void, and against myself, for "
"trapping it here.  Its words fill my heart with terror, yet I cannot block out its voice.|";*/

static char Skulljrnl4[] = "In its ranting, the creature has let slip its name -- "
"Na-Krul.  I have attempted to research the name, but the smaller demons have somehow "
"destroyed my library.  Na-Krul... The name fills me with a cold dread.  I prefer to "
"think of it only as The Creature rather than ponder its true name.|";

/*"My home is coming alive, corrupted by the darkness of my "
"unwanted prisoner... The crypts are full of shadows... I see things at the corners of my "
"vision, hear the sounds of claws, and of searching.  Searching, I think, for me.  For "
"this journal.  They must not learn the secret!  The creature must not be released!|";*/

static char Skulljrnl5[] = "The entrapped creature's howls of fury keep me from gaining "
"much needed sleep.  It rages against the one who sent it to the Void, and it "
"calls foul curses upon me for trapping it here.  Its words fill my heart with terror, "
"and yet I cannot block out its voice.|";

/*"In its ranting, the creature has let slip its name.  It calls "
"itself Na-Krul.  The name is familiar to me... I wish I could research it, but the smaller "
"horrors have destroyed my library in their endless searching.  Still, the syllables fill "
"me with a cold dread... I prefer to think of it only as the creature rather than ponder "
"its true name.|";*/

static char Skulljrnl6[] = "My time is quickly running out.  I must record the ways to "
"weaken the demon, and then conceal that text, lest his minions find some way to use "
"my knowledge to free their lord.  I hope that whoever finds this journal will seek the "
"knowledge.|";
 
/*"Time is running out.  With my last entry I must reveal the way "
"to defeat the demon, then conceal that text, lest the demon-creatures find some way to "
"use my knowledge to free their lord.  I have kept my athame, at least; when all is lost "
"I would rather meet my death at the end of a dagger, than at the claws of a demon.|";*/

static char Skulljrnl7[] = "Whoever finds this scroll is charged with stopping the demonic "
"creature that lies within these walls.  My time is over. Even now, its hellish minions "
"claw at the frail door behind which I hide.  \n \nI have hobbled the demon with arcane "
"magic and encased it within great walls, but I fear that will not be enough. "  
"\n \nThe spells found in my three grimoires will provide you protected entrance to his "
"domain, but only if cast in their proper sequence.  The levers at the entryway "
"will remove the barriers and free the demon; touch them not!  Use only these spells to "
"gain entry or his power may be too great for you to defeat.|";

/*"Whoever finds this, you must stop this demon creature.  It is "
"too late for me now; its hellish minions are clawing at this last door behind which I "
"cower.  I have hobbled the creature by powerful spells and encased it behind thick walls, "
"yet it will not be enough.  You will need the power of the spells in my three grimoires, "
"cast only in their proper sequence.  The levers at the entry will remove the barriers and "
"free the demon; touch them not!  Use only the spells!  The spells in the correct sequence "
"will open the magical doorways, and allow you to face the demon and, I hope, defeat it.  "
"May the Heavens have mercy on us all.|";*/

static char Defiler1[] = "Ahh, mammal, welcome.  Such a... tasty planet you have.  My Nest shall spread "
"across this land, and you and your species shall serve as food for our colony.  I'm sure "
"our meeting will be quite... delicious. |";

static char Defiler2[] = "Have you been enjoying yourself, little mammal?  How pathetic. "
"Your little world will be no challenge at all.|";

static char Defiler3[] = "Come closer, morsel...come find me, the Defiler. I have waited "
"thousands of years...do not try my patience any further. |";

static char Defiler4[] = "Ah, I can smell you...you are close! Close! Ssss...the scent "
"of blood and fear...how enticing...|";

textdat.h

The top of this file has a handy guide for reading the #defines...including placeholder data for Tremain! He has a definition at the top, and various "P"s where his dialogue was supposed to be, but isn't.

/*-----------------------------------------------------------------------**
** Defines
**-----------------------------------------------------------------------*/
//	STORYTELLER				ST
//	TAVERN OWNER			TO
//	PRIEST					P
//	HEALER					H
//	BARMAID					BM
//	BLACKSMITH				BS
//	TOWN DRUNK				TD
//	WITCH					W
//	PEG-LEGGED BOY			PB
/*-----------------------------------------------------------------------**
//	QUESTS
**-----------------------------------------------------------------------*/
// Skeleton King Quest
#define TXT_KINGST1		0	//	ST
#define TXT_KINGTO1		1	//	TO quest init
#define TXT_KINGTO2		2	//	TO return before end
#define TXT_KINGTO3		3	//	TO return upon completion
//	P
#define TXT_KINGH1		4	//	H
#define TXT_KINGBM1		5	//	BM
#define TXT_KINGBS1		6	//	BS
#define TXT_KINGTD1		7	//	TD	
#define TXT_KINGW1		8	//	W
#define TXT_KINGPB1		9	//	PB 

#define TXT_KING1		10	//	Skeleton King

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
//	Banner of Light Quest
#define TXT_BOLST1		11	//	ST
#define TXT_BOLTO1		12	//	TO quest init
#define TXT_BOLTO2		13	//	TO return sign
//	P
#define TXT_BOLH1		14	//	H
#define TXT_BOLBM1		15	//	BM
#define TXT_BOLBS1		16	//	BS
#define TXT_BOLTD1		17	//	TD	
#define TXT_BOLW1		18	//	W
#define TXT_BOLPB1		19	//	PB 

#define TXT_BOL1		20	//	Snotspil first time
#define TXT_BOL2		21	//	Snotspil empty handed
#define TXT_BOL3		22	//	Snotspil with sign

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
//	Vile Betrayer Quest
#define TXT_VBST1		23	//	ST quest not done
#define TXT_VBST2		24	//	ST quest init
#define TXT_VBST3		25	//	ST quest done
#define TXT_VBTO1		26	//	TO
#define TXT_VBP3		27	//	not in  
#define TXT_VBP4		28	//	not in
#define TXT_VBH1		29	//	H
#define TXT_VBBM1		30	//	BM
#define TXT_VBBS1		31	//	BS
#define TXT_VBTD1		32	//	TD	
#define TXT_VBW1		33	//	W
#define TXT_VBPB1		34	//	PB

#define TXT_VB1			35	//	Lazurus before sacrafice
#define TXT_VB2			36	//	Lazurus	after sacrafice

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
//	Poisoned Water Quest
#define TXT_PWST1		37	//	ST
#define TXT_PWTO1		38	//	TO
//	P
#define TXT_PWH1		39	//	H quest init
#define TXT_PWH2		40	//	H return before done
#define TXT_PWH3		41	//	H quest done
#define TXT_PWBM1		42	//	BM
#define TXT_PWBS1		43	//	BS
#define TXT_PWTD1		44	//	TD	
#define TXT_PWW1		45	//	W
#define TXT_PWPB1		46	//	PB 

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
//	The Chamber of Bone Quest
#define TXT_BONEST1		47	//	ST
#define TXT_BONETO1		48	//	TO
//	P
#define TXT_BONEH1		49	//	H
#define TXT_BONEBM1		50	//	BM
#define TXT_BONEBS1		51	//	BS
#define TXT_BONETD1		52	//	TD	
#define TXT_BONEW1		53	//	W
#define TXT_BONEPB1		54	//	PB 

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
//	The Butcher Quest
#define TXT_BUTCHST1	55	//	ST
#define TXT_BUTCHTO1	56	//	TO
//	P
#define TXT_BUTCHH1		57	//	H
#define TXT_BUTCHBM1	58	//	BM
#define TXT_BUTCHBS1	59	//	BS
#define TXT_BUTCHTD1	60	//	TD	
#define TXT_BUTCHW1		61	//	W
#define TXT_BUTCHPB1	62	//	PB 

#define TXT_BUTCH1		63	//	Wounded Townsman
#define TXT_BUTCH2		64	//	Butcher

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
//	Halls of the Blind Quest
#define TXT_BLINDST1	65		//	ST
#define TXT_BLINDTO1	66		//	TO
//	P
#define TXT_BLINDH1		67	//	H
#define TXT_BLINDBM1	68		//	BM
#define TXT_BLINDBS1	69		//	BS
#define TXT_BLINDTD1	70		//	TD	
#define TXT_BLINDW1		71	//	W
#define TXT_BLINDPB1	72		//	PB 

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
//	Veil of Steel Quest
#define TXT_VEILST1		73	//	ST
#define TXT_VEILTO1		74	//	TO
//	P
#define TXT_VEILH1		75	//	H
#define TXT_VEILBM1		76	//	BM
#define TXT_VEILBS1		77	//	BS
#define TXT_VEILTD1		78	//	TD	
#define TXT_VEILW1		79	//	W
#define TXT_VEILPB1		80	//	PB 

#define TXT_VEIL1		81	//	Lachdanan first time
#define TXT_VEIL2		82	//	Lachdanan without elixir
#define TXT_VEIL3		83	//	Lachdanan with elixir

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
//	The Anvil of Fury Quest
#define TXT_ANVILST1	84	//	ST
#define TXT_ANVILTO1	85		//	TO
//	P
#define TXT_ANVILH1		86	//	H
#define TXT_ANVILBM1	87		//	BM
#define TXT_ANVILBS1	88		//	BS
#define TXT_ANVILBS2	89		//	BS
#define TXT_ANVILBS3	90		//	BS
#define TXT_ANVILTD1	91		//	TD	
#define TXT_ANVILW1		92	//	W
#define TXT_ANVILPB1	93		//	PB 

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
//	Stones of Blood Quest
#define TXT_BLOODST1	94		//	ST
#define TXT_BLOODTO1	95		//	TO
//	P
#define TXT_BLOODH1		96	//	H
#define TXT_BLOODBM1	97		//	BM
#define TXT_BLOODBS1	98		//	BS
#define TXT_BLOODTD1	99		//	TD	
#define TXT_BLOODW1		100	//	W
#define TXT_BLOODPB1	101		//	PB 

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
//	Warlord of Blood Quest
#define TXT_WARLRDST1	102	//	ST
#define TXT_WARLRDTO1	103	//	TO
//	P
#define TXT_WARLRDH1	104	//	H
#define TXT_WARLRDBM1	105	//	BM
#define TXT_WARLRDBS1	106	//	BS
#define TXT_WARLRDTD1	107	//	TD	
#define TXT_WARLRDW1	108		//	W
#define TXT_WARLRDPB1	109	//	PB 

#define TXT_WARLRD1		110	//	Warlord of the Blood

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
//	Ring of Infravision Quest
#define TXT_INFRAST1	111		//	ST
#define TXT_INFRATO1	112		//	TO
//	P
#define TXT_INFRAH1		113	//	H
#define TXT_INFRABM1	114		//	BM
#define TXT_INFRABS1	115		//	BS
#define TXT_INFRABS2	116		//	BS
#define TXT_INFRABS3	117		//	BS
#define TXT_INFRATD1	118		//	TD	
#define TXT_INFRAW1		119	//	W
#define TXT_INFRAPB1	120		//	PB 

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
//	Black Mushroom Quest
#define TXT_BLKMST1		121	//	ST
#define TXT_BLKMTO1		122	//	TO
//	P
#define TXT_BLKMH1		123	//	H no brain
#define TXT_BLKMH2		124	//	H with brain
#define TXT_BLKMBM1		125	//	BM
#define TXT_BLKMBS1		126	//	BS
#define TXT_BLKMTD1		127	//	TD	
#define TXT_BLKMW1		128	//	W
#define TXT_BLKMW2		129	//	W
#define TXT_BLKMW3		130	//	W
#define TXT_BLKMW4		131	//	W
#define TXT_BLKMW5		132	//	W
#define TXT_BLKMPB1		133	//	PB 

/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
//	Map of Doom Quest
#define TXT_MODST1		134	//	ST quest init
#define TXT_MODST2		135	//	ST return before stars align and Diablo alive
#define TXT_MODST3		136	//	ST return after stars align and Diablo alive
#define TXT_MODTO1		137	//	TO
//	P
#define TXT_MODH1		138	//	H
#define TXT_MODBM1		139	//	BM
#define TXT_MODBS1		140	//	BS
#define TXT_MODTD1		141	//	TD	
#define TXT_MODW1		142	//	W
#define TXT_MODPB1		143	//	PB