mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2024-11-25 16:34:00 +00:00
method header lines
This commit is contained in:
parent
846c975be6
commit
ebeea4706d
@ -1,11 +1,15 @@
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
|
||||
public abstract class AbstractImage extends AbstractFile
|
||||
{
|
||||
public AbstractImage (String name, byte[] buffer)
|
||||
{
|
||||
super (name, buffer);
|
||||
}
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
abstract class AbstractImage extends AbstractFile
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
// ---------------------------------------------------------------------------------//
|
||||
AbstractImage (String name, byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
}
|
||||
}
|
@ -1,325 +1,367 @@
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
class Character extends AbstractFile
|
||||
{
|
||||
private final Attributes attributes;
|
||||
private final Statistics stats;
|
||||
int scenario;
|
||||
|
||||
private final Collection<Spell> spellBook = new ArrayList<> ();
|
||||
private final Collection<Baggage> baggageList = new ArrayList<> ();
|
||||
|
||||
static String[] races = { "No race", "Human", "Elf", "Dwarf", "Gnome", "Hobbit" };
|
||||
static String[] alignments = { "Unalign", "Good", "Neutral", "Evil" };
|
||||
static String[] types =
|
||||
{ "Fighter", "Mage", "Priest", "Thief", "Bishop", "Samurai", "Lord", "Ninja" };
|
||||
static String[] statuses =
|
||||
{ "OK", "Afraid", "Asleep", "Paralyze", "Stoned", "Dead", "Ashes", "Lost" };
|
||||
|
||||
public Character (String name, byte[] buffer, int scenario)
|
||||
{
|
||||
super (name, buffer);
|
||||
this.scenario = scenario;
|
||||
|
||||
attributes = new Attributes ();
|
||||
stats = new Statistics ();
|
||||
|
||||
stats.race = races[buffer[34] & 0xFF];
|
||||
stats.typeInt = buffer[36] & 0xFF;
|
||||
stats.type = types[stats.typeInt];
|
||||
stats.ageInWeeks = HexFormatter.intValue (buffer[38], buffer[39]);
|
||||
stats.statusValue = buffer[40];
|
||||
stats.status = statuses[stats.statusValue];
|
||||
stats.alignment = alignments[buffer[42] & 0xFF];
|
||||
|
||||
stats.gold = HexFormatter.intValue (buffer[52], buffer[53])
|
||||
+ HexFormatter.intValue (buffer[54], buffer[55]) * 10000;
|
||||
stats.experience = HexFormatter.intValue (buffer[124], buffer[125])
|
||||
+ HexFormatter.intValue (buffer[126], buffer[127]) * 10000;
|
||||
stats.level = HexFormatter.intValue (buffer[132], buffer[133]);
|
||||
|
||||
stats.hitsLeft = HexFormatter.intValue (buffer[134], buffer[135]);
|
||||
stats.hitsMax = HexFormatter.intValue (buffer[136], buffer[137]);
|
||||
stats.armourClass = buffer[176];
|
||||
|
||||
attributes.strength = (buffer[44] & 0xFF) % 16;
|
||||
if (attributes.strength < 3)
|
||||
attributes.strength += 16;
|
||||
attributes.array[0] = attributes.strength;
|
||||
|
||||
int i1 = (buffer[44] & 0xFF) / 16;
|
||||
int i2 = (buffer[45] & 0xFF) % 4;
|
||||
attributes.intelligence = i1 / 2 + i2 * 8;
|
||||
attributes.array[1] = attributes.intelligence;
|
||||
|
||||
attributes.piety = (buffer[45] & 0xFF) / 4;
|
||||
attributes.array[2] = attributes.piety;
|
||||
|
||||
attributes.vitality = (buffer[46] & 0xFF) % 16;
|
||||
if (attributes.vitality < 3)
|
||||
attributes.vitality += 16;
|
||||
attributes.array[3] = attributes.vitality;
|
||||
|
||||
int a1 = (buffer[46] & 0xFF) / 16;
|
||||
int a2 = (buffer[47] & 0xFF) % 4;
|
||||
attributes.agility = a1 / 2 + a2 * 8;
|
||||
attributes.array[4] = attributes.agility;
|
||||
|
||||
attributes.luck = (buffer[47] & 0xFF) / 4;
|
||||
attributes.array[5] = attributes.luck;
|
||||
}
|
||||
|
||||
public void linkItems (List<Item> itemList)
|
||||
{
|
||||
boolean equipped;
|
||||
boolean identified;
|
||||
int totItems = buffer[58];
|
||||
stats.assetValue = 0;
|
||||
|
||||
for (int ptr = 60; totItems > 0; ptr += 8, totItems--)
|
||||
{
|
||||
int itemID = buffer[ptr + 6] & 0xFF;
|
||||
if (scenario == 3)
|
||||
itemID = (itemID + 24) % 256;
|
||||
if (itemID >= 0 && itemID < itemList.size ())
|
||||
{
|
||||
Item item = itemList.get (itemID);
|
||||
equipped = (buffer[ptr] == 1);
|
||||
identified = (buffer[ptr + 4] == 1);
|
||||
baggageList.add (new Baggage (item, equipped, identified));
|
||||
stats.assetValue += item.getCost ();
|
||||
item.partyOwns++;
|
||||
}
|
||||
else
|
||||
System.out.println (name + " ItemID : " + itemID + " is outside range 0:"
|
||||
+ (itemList.size () - 1));
|
||||
}
|
||||
}
|
||||
|
||||
public void linkSpells (List<Spell> spellList)
|
||||
{
|
||||
for (int i = 138; i < 145; i++)
|
||||
for (int bit = 0; bit < 8; bit++)
|
||||
if (((buffer[i] >>> bit) & 1) == 1)
|
||||
{
|
||||
int index = (i - 138) * 8 + bit;
|
||||
if (index > 0 && index <= spellList.size ())
|
||||
spellBook.add (spellList.get (index - 1));
|
||||
else
|
||||
System.out.println ("LinkSpell: " + name + " SpellID : " + index
|
||||
+ " is outside range 1:" + spellList.size ());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText ()
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
text.append ("Character name ..... " + name);
|
||||
text.append ("\n\nRace ............... " + stats.race);
|
||||
text.append ("\nType ............... " + stats.type);
|
||||
text.append ("\nAlignment .......... " + stats.alignment);
|
||||
text.append ("\nStatus ............. " + stats.status);
|
||||
// text.append ("\nType ............... " + stats.typeInt);
|
||||
// text.append ("\nStatus ............. " + stats.statusValue);
|
||||
text.append ("\nGold ............... " + String.format ("%,d", stats.gold));
|
||||
text.append ("\nExperience ......... " + String.format ("%,d", stats.experience));
|
||||
text.append ("\nNext level ......... " + String.format ("%,d", stats.nextLevel));
|
||||
text.append ("\nLevel .............. " + stats.level);
|
||||
text.append ("\nAge in weeks ....... "
|
||||
+ String.format ("%,d (%d)", stats.ageInWeeks, (stats.ageInWeeks / 52)));
|
||||
text.append ("\nHit points left .... " + stats.hitsLeft);
|
||||
text.append ("\nMaximum hits ....... " + stats.hitsMax);
|
||||
text.append ("\nArmour class ....... " + stats.armourClass);
|
||||
text.append ("\nAsset value ........ " + String.format ("%,d", stats.assetValue));
|
||||
text.append ("\nAwards ............. " + isWinner ());
|
||||
text.append ("\nOut ................ " + isOut ());
|
||||
text.append ("\n\nStrength ........... " + attributes.strength);
|
||||
text.append ("\nIntelligence ....... " + attributes.intelligence);
|
||||
text.append ("\nPiety .............. " + attributes.piety);
|
||||
text.append ("\nVitality ........... " + attributes.vitality);
|
||||
text.append ("\nAgility ............ " + attributes.agility);
|
||||
text.append ("\nLuck ............... " + attributes.luck);
|
||||
|
||||
int[] spellPoints = getMageSpellPoints ();
|
||||
text.append ("\n\nMage spell points ..");
|
||||
for (int i = 0; i < spellPoints.length; i++)
|
||||
text.append (" " + spellPoints[i]);
|
||||
|
||||
spellPoints = getPriestSpellPoints ();
|
||||
text.append ("\nPriest spell points ");
|
||||
for (int i = 0; i < spellPoints.length; i++)
|
||||
text.append (" " + spellPoints[i]);
|
||||
|
||||
text.append ("\n\nSpells :");
|
||||
for (Spell s : spellBook)
|
||||
text.append ("\n" + s);
|
||||
|
||||
text.append ("\n\nItems :");
|
||||
for (Baggage b : baggageList)
|
||||
text.append ("\n" + b);
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
public void linkExperience (ExperienceLevel exp)
|
||||
{
|
||||
stats.nextLevel = exp.getExperiencePoints (stats.level);
|
||||
}
|
||||
|
||||
public int[] getMageSpellPoints ()
|
||||
{
|
||||
int[] spells = new int[7];
|
||||
|
||||
for (int i = 0; i < 7; i++)
|
||||
spells[i] = buffer[146 + i * 2];
|
||||
|
||||
return spells;
|
||||
}
|
||||
|
||||
public int[] getPriestSpellPoints ()
|
||||
{
|
||||
int[] spells = new int[7];
|
||||
|
||||
for (int i = 0; i < 7; i++)
|
||||
spells[i] = buffer[160 + i * 2];
|
||||
|
||||
return spells;
|
||||
}
|
||||
|
||||
public Long getNextLevel ()
|
||||
{
|
||||
return stats.nextLevel;
|
||||
}
|
||||
|
||||
// this is temporary until I have more data
|
||||
public String isWinner ()
|
||||
{
|
||||
int v1 = buffer[206];
|
||||
int v2 = buffer[207];
|
||||
if (v1 == 0x01)
|
||||
return ">";
|
||||
if (v1 == 0x00 && v2 == 0x00)
|
||||
return "";
|
||||
if (v1 == 0x00 && v2 == 0x20)
|
||||
return "D";
|
||||
if (v1 == 0x20 && v2 == 0x20)
|
||||
return "*D";
|
||||
if (v1 == 0x21 && v2 == 0x60)
|
||||
return ">*DG";
|
||||
if (v1 == 0x21 && v2 == 0x28)
|
||||
return ">*KD";
|
||||
return "Unknown : " + v1 + " " + v2;
|
||||
}
|
||||
|
||||
public boolean isOut ()
|
||||
{
|
||||
return (buffer[32] == 1);
|
||||
}
|
||||
|
||||
public String getType ()
|
||||
{
|
||||
return stats.type;
|
||||
}
|
||||
|
||||
public String getRace ()
|
||||
{
|
||||
return stats.race;
|
||||
}
|
||||
|
||||
public String getAlignment ()
|
||||
{
|
||||
return stats.alignment;
|
||||
}
|
||||
|
||||
public Attributes getAttributes ()
|
||||
{
|
||||
return attributes;
|
||||
}
|
||||
|
||||
public Statistics getStatistics ()
|
||||
{
|
||||
return stats;
|
||||
}
|
||||
|
||||
public Iterator<Baggage> getBaggage ()
|
||||
{
|
||||
return baggageList.iterator ();
|
||||
}
|
||||
|
||||
public Iterator<Spell> getSpells ()
|
||||
{
|
||||
return spellBook.iterator ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString ()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public class Baggage
|
||||
{
|
||||
public Item item;
|
||||
public boolean equipped;
|
||||
public boolean identified;
|
||||
|
||||
public Baggage (Item item, boolean equipped, boolean identified)
|
||||
{
|
||||
this.item = item;
|
||||
this.equipped = equipped;
|
||||
this.identified = identified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString ()
|
||||
{
|
||||
return String.format ("%s%-15s (%d)", equipped ? "*" : " ", item.getName (),
|
||||
item.getCost ());
|
||||
}
|
||||
}
|
||||
|
||||
public class Statistics implements Cloneable
|
||||
{
|
||||
public String race;
|
||||
public String type;
|
||||
public String alignment;
|
||||
public String status;
|
||||
public int typeInt;
|
||||
public int statusValue;
|
||||
public int gold;
|
||||
public int experience;
|
||||
public long nextLevel;
|
||||
public int level;
|
||||
public int ageInWeeks;
|
||||
public int hitsLeft;
|
||||
public int hitsMax;
|
||||
public int armourClass;
|
||||
public int assetValue;
|
||||
}
|
||||
|
||||
public class Attributes
|
||||
{
|
||||
public int strength;
|
||||
public int intelligence;
|
||||
public int piety;
|
||||
public int vitality;
|
||||
public int agility;
|
||||
public int luck;
|
||||
public int[] array;
|
||||
|
||||
public Attributes ()
|
||||
{
|
||||
array = new int[6];
|
||||
}
|
||||
}
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class Character extends AbstractFile
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private final Attributes attributes;
|
||||
private final Statistics stats;
|
||||
int scenario;
|
||||
|
||||
private final Collection<Spell> spellBook = new ArrayList<> ();
|
||||
private final Collection<Baggage> baggageList = new ArrayList<> ();
|
||||
|
||||
static String[] races = { "No race", "Human", "Elf", "Dwarf", "Gnome", "Hobbit" };
|
||||
static String[] alignments = { "Unalign", "Good", "Neutral", "Evil" };
|
||||
static String[] types =
|
||||
{ "Fighter", "Mage", "Priest", "Thief", "Bishop", "Samurai", "Lord", "Ninja" };
|
||||
static String[] statuses =
|
||||
{ "OK", "Afraid", "Asleep", "Paralyze", "Stoned", "Dead", "Ashes", "Lost" };
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
Character (String name, byte[] buffer, int scenario)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
this.scenario = scenario;
|
||||
|
||||
attributes = new Attributes ();
|
||||
stats = new Statistics ();
|
||||
|
||||
stats.race = races[buffer[34] & 0xFF];
|
||||
stats.typeInt = buffer[36] & 0xFF;
|
||||
stats.type = types[stats.typeInt];
|
||||
stats.ageInWeeks = HexFormatter.intValue (buffer[38], buffer[39]);
|
||||
stats.statusValue = buffer[40];
|
||||
stats.status = statuses[stats.statusValue];
|
||||
stats.alignment = alignments[buffer[42] & 0xFF];
|
||||
|
||||
stats.gold = HexFormatter.intValue (buffer[52], buffer[53])
|
||||
+ HexFormatter.intValue (buffer[54], buffer[55]) * 10000;
|
||||
stats.experience = HexFormatter.intValue (buffer[124], buffer[125])
|
||||
+ HexFormatter.intValue (buffer[126], buffer[127]) * 10000;
|
||||
stats.level = HexFormatter.intValue (buffer[132], buffer[133]);
|
||||
|
||||
stats.hitsLeft = HexFormatter.intValue (buffer[134], buffer[135]);
|
||||
stats.hitsMax = HexFormatter.intValue (buffer[136], buffer[137]);
|
||||
stats.armourClass = buffer[176];
|
||||
|
||||
attributes.strength = (buffer[44] & 0xFF) % 16;
|
||||
if (attributes.strength < 3)
|
||||
attributes.strength += 16;
|
||||
attributes.array[0] = attributes.strength;
|
||||
|
||||
int i1 = (buffer[44] & 0xFF) / 16;
|
||||
int i2 = (buffer[45] & 0xFF) % 4;
|
||||
attributes.intelligence = i1 / 2 + i2 * 8;
|
||||
attributes.array[1] = attributes.intelligence;
|
||||
|
||||
attributes.piety = (buffer[45] & 0xFF) / 4;
|
||||
attributes.array[2] = attributes.piety;
|
||||
|
||||
attributes.vitality = (buffer[46] & 0xFF) % 16;
|
||||
if (attributes.vitality < 3)
|
||||
attributes.vitality += 16;
|
||||
attributes.array[3] = attributes.vitality;
|
||||
|
||||
int a1 = (buffer[46] & 0xFF) / 16;
|
||||
int a2 = (buffer[47] & 0xFF) % 4;
|
||||
attributes.agility = a1 / 2 + a2 * 8;
|
||||
attributes.array[4] = attributes.agility;
|
||||
|
||||
attributes.luck = (buffer[47] & 0xFF) / 4;
|
||||
attributes.array[5] = attributes.luck;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void linkItems (List<Item> itemList)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
boolean equipped;
|
||||
boolean identified;
|
||||
int totItems = buffer[58];
|
||||
stats.assetValue = 0;
|
||||
|
||||
for (int ptr = 60; totItems > 0; ptr += 8, totItems--)
|
||||
{
|
||||
int itemID = buffer[ptr + 6] & 0xFF;
|
||||
if (scenario == 3)
|
||||
itemID = (itemID + 24) % 256;
|
||||
if (itemID >= 0 && itemID < itemList.size ())
|
||||
{
|
||||
Item item = itemList.get (itemID);
|
||||
equipped = (buffer[ptr] == 1);
|
||||
identified = (buffer[ptr + 4] == 1);
|
||||
baggageList.add (new Baggage (item, equipped, identified));
|
||||
stats.assetValue += item.getCost ();
|
||||
item.partyOwns++;
|
||||
}
|
||||
else
|
||||
System.out.println (name + " ItemID : " + itemID + " is outside range 0:"
|
||||
+ (itemList.size () - 1));
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void linkSpells (List<Spell> spellList)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
for (int i = 138; i < 145; i++)
|
||||
for (int bit = 0; bit < 8; bit++)
|
||||
if (((buffer[i] >>> bit) & 1) == 1)
|
||||
{
|
||||
int index = (i - 138) * 8 + bit;
|
||||
if (index > 0 && index <= spellList.size ())
|
||||
spellBook.add (spellList.get (index - 1));
|
||||
else
|
||||
System.out.println ("LinkSpell: " + name + " SpellID : " + index
|
||||
+ " is outside range 1:" + spellList.size ());
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
text.append ("Character name ..... " + name);
|
||||
text.append ("\n\nRace ............... " + stats.race);
|
||||
text.append ("\nType ............... " + stats.type);
|
||||
text.append ("\nAlignment .......... " + stats.alignment);
|
||||
text.append ("\nStatus ............. " + stats.status);
|
||||
// text.append ("\nType ............... " + stats.typeInt);
|
||||
// text.append ("\nStatus ............. " + stats.statusValue);
|
||||
text.append ("\nGold ............... " + String.format ("%,d", stats.gold));
|
||||
text.append ("\nExperience ......... " + String.format ("%,d", stats.experience));
|
||||
text.append ("\nNext level ......... " + String.format ("%,d", stats.nextLevel));
|
||||
text.append ("\nLevel .............. " + stats.level);
|
||||
text.append ("\nAge in weeks ....... "
|
||||
+ String.format ("%,d (%d)", stats.ageInWeeks, (stats.ageInWeeks / 52)));
|
||||
text.append ("\nHit points left .... " + stats.hitsLeft);
|
||||
text.append ("\nMaximum hits ....... " + stats.hitsMax);
|
||||
text.append ("\nArmour class ....... " + stats.armourClass);
|
||||
text.append ("\nAsset value ........ " + String.format ("%,d", stats.assetValue));
|
||||
text.append ("\nAwards ............. " + isWinner ());
|
||||
text.append ("\nOut ................ " + isOut ());
|
||||
text.append ("\n\nStrength ........... " + attributes.strength);
|
||||
text.append ("\nIntelligence ....... " + attributes.intelligence);
|
||||
text.append ("\nPiety .............. " + attributes.piety);
|
||||
text.append ("\nVitality ........... " + attributes.vitality);
|
||||
text.append ("\nAgility ............ " + attributes.agility);
|
||||
text.append ("\nLuck ............... " + attributes.luck);
|
||||
|
||||
int[] spellPoints = getMageSpellPoints ();
|
||||
text.append ("\n\nMage spell points ..");
|
||||
for (int i = 0; i < spellPoints.length; i++)
|
||||
text.append (" " + spellPoints[i]);
|
||||
|
||||
spellPoints = getPriestSpellPoints ();
|
||||
text.append ("\nPriest spell points ");
|
||||
for (int i = 0; i < spellPoints.length; i++)
|
||||
text.append (" " + spellPoints[i]);
|
||||
|
||||
text.append ("\n\nSpells :");
|
||||
for (Spell s : spellBook)
|
||||
text.append ("\n" + s);
|
||||
|
||||
text.append ("\n\nItems :");
|
||||
for (Baggage b : baggageList)
|
||||
text.append ("\n" + b);
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void linkExperience (ExperienceLevel exp)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
stats.nextLevel = exp.getExperiencePoints (stats.level);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public int[] getMageSpellPoints ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int[] spells = new int[7];
|
||||
|
||||
for (int i = 0; i < 7; i++)
|
||||
spells[i] = buffer[146 + i * 2];
|
||||
|
||||
return spells;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public int[] getPriestSpellPoints ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int[] spells = new int[7];
|
||||
|
||||
for (int i = 0; i < 7; i++)
|
||||
spells[i] = buffer[160 + i * 2];
|
||||
|
||||
return spells;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public Long getNextLevel ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return stats.nextLevel;
|
||||
}
|
||||
|
||||
// this is temporary until I have more data
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public String isWinner ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int v1 = buffer[206];
|
||||
int v2 = buffer[207];
|
||||
if (v1 == 0x01)
|
||||
return ">";
|
||||
if (v1 == 0x00 && v2 == 0x00)
|
||||
return "";
|
||||
if (v1 == 0x00 && v2 == 0x20)
|
||||
return "D";
|
||||
if (v1 == 0x20 && v2 == 0x20)
|
||||
return "*D";
|
||||
if (v1 == 0x21 && v2 == 0x60)
|
||||
return ">*DG";
|
||||
if (v1 == 0x21 && v2 == 0x28)
|
||||
return ">*KD";
|
||||
return "Unknown : " + v1 + " " + v2;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public boolean isOut ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return (buffer[32] == 1);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public String getType ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return stats.type;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public String getRace ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return stats.race;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public String getAlignment ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return stats.alignment;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public Attributes getAttributes ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return attributes;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public Statistics getStatistics ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return stats;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public Iterator<Baggage> getBaggage ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return baggageList.iterator ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public Iterator<Spell> getSpells ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return spellBook.iterator ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String toString ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public class Baggage
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
public Item item;
|
||||
public boolean equipped;
|
||||
public boolean identified;
|
||||
|
||||
public Baggage (Item item, boolean equipped, boolean identified)
|
||||
{
|
||||
this.item = item;
|
||||
this.equipped = equipped;
|
||||
this.identified = identified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString ()
|
||||
{
|
||||
return String.format ("%s%-15s (%d)", equipped ? "*" : " ", item.getName (),
|
||||
item.getCost ());
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public class Statistics implements Cloneable
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
public String race;
|
||||
public String type;
|
||||
public String alignment;
|
||||
public String status;
|
||||
public int typeInt;
|
||||
public int statusValue;
|
||||
public int gold;
|
||||
public int experience;
|
||||
public long nextLevel;
|
||||
public int level;
|
||||
public int ageInWeeks;
|
||||
public int hitsLeft;
|
||||
public int hitsMax;
|
||||
public int armourClass;
|
||||
public int assetValue;
|
||||
}
|
||||
|
||||
public class Attributes
|
||||
{
|
||||
public int strength;
|
||||
public int intelligence;
|
||||
public int piety;
|
||||
public int vitality;
|
||||
public int agility;
|
||||
public int luck;
|
||||
public int[] array;
|
||||
|
||||
public Attributes ()
|
||||
{
|
||||
array = new int[6];
|
||||
}
|
||||
}
|
||||
}
|
@ -1,27 +1,33 @@
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
class CodedMessage extends Message
|
||||
{
|
||||
public static int codeOffset = 185;
|
||||
|
||||
public CodedMessage (byte[] buffer)
|
||||
{
|
||||
super (buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLine (int offset)
|
||||
{
|
||||
int length = buffer[offset] & 0xFF;
|
||||
byte[] translation = new byte[length];
|
||||
codeOffset--;
|
||||
for (int j = 0; j < length; j++)
|
||||
{
|
||||
translation[j] = buffer[offset + 1 + j];
|
||||
translation[j] -= codeOffset - j * 3;
|
||||
}
|
||||
return HexFormatter.getString (translation, 0, length);
|
||||
}
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class CodedMessage extends Message
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
public static int codeOffset = 185;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
CodedMessage (byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (buffer);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
protected String getLine (int offset)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int length = buffer[offset] & 0xFF;
|
||||
byte[] translation = new byte[length];
|
||||
codeOffset--;
|
||||
for (int j = 0; j < length; j++)
|
||||
{
|
||||
translation[j] = buffer[offset + 1 + j];
|
||||
translation[j] -= codeOffset - j * 3;
|
||||
}
|
||||
return HexFormatter.getString (translation, 0, length);
|
||||
}
|
||||
}
|
@ -1,27 +1,33 @@
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
class Dice
|
||||
{
|
||||
int qty;
|
||||
int sides;
|
||||
int bonus;
|
||||
|
||||
public Dice (byte[] buffer, int offset)
|
||||
{
|
||||
qty = buffer[offset];
|
||||
sides = buffer[offset + 2];
|
||||
bonus = buffer[offset + 4];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString ()
|
||||
{
|
||||
if (qty == 0)
|
||||
return "";
|
||||
StringBuilder text = new StringBuilder ();
|
||||
text.append (String.format ("%dd%d", qty, sides));
|
||||
if (bonus > 0)
|
||||
text.append ("+" + bonus);
|
||||
return text.toString ();
|
||||
}
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class Dice
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
int qty;
|
||||
int sides;
|
||||
int bonus;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
Dice (byte[] buffer, int offset)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
qty = buffer[offset];
|
||||
sides = buffer[offset + 2];
|
||||
bonus = buffer[offset + 4];
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String toString ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (qty == 0)
|
||||
return "";
|
||||
StringBuilder text = new StringBuilder ();
|
||||
text.append (String.format ("%dd%d", qty, sides));
|
||||
if (bonus > 0)
|
||||
text.append ("+" + bonus);
|
||||
return text.toString ();
|
||||
}
|
||||
}
|
@ -2,15 +2,21 @@ package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
|
||||
public class DragonData extends AbstractFile
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class DragonData extends AbstractFile
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
public DragonData (String name, byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
DragonData (String name, byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return "DragonData";
|
||||
}
|
||||
|
@ -1,44 +1,51 @@
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
class ExperienceLevel extends AbstractFile
|
||||
{
|
||||
private final long[] expLevels = new long[13];
|
||||
|
||||
public ExperienceLevel (String name, byte[] buffer)
|
||||
{
|
||||
super (name, buffer);
|
||||
|
||||
int seq = 0;
|
||||
|
||||
for (int ptr = 0; ptr < buffer.length; ptr += 6)
|
||||
{
|
||||
if (buffer[ptr] == 0)
|
||||
break;
|
||||
|
||||
long points =
|
||||
HexFormatter.intValue (buffer[ptr], buffer[ptr + 1])
|
||||
+ HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 3]) * 10000
|
||||
+ HexFormatter.intValue (buffer[ptr + 4], buffer[ptr + 5]) * 100000000L;
|
||||
expLevels[seq++] = points;
|
||||
}
|
||||
}
|
||||
|
||||
public long getExperiencePoints (int level)
|
||||
{
|
||||
if (level < 13)
|
||||
return expLevels[level];
|
||||
return (level - 12) * expLevels[0] + expLevels[12];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText ()
|
||||
{
|
||||
StringBuilder line = new StringBuilder ();
|
||||
for (long exp : expLevels)
|
||||
line.append (exp + "\n");
|
||||
return line.toString ();
|
||||
}
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class ExperienceLevel extends AbstractFile
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private final long[] expLevels = new long[13];
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
ExperienceLevel (String name, byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
|
||||
int seq = 0;
|
||||
|
||||
for (int ptr = 0; ptr < buffer.length; ptr += 6)
|
||||
{
|
||||
if (buffer[ptr] == 0)
|
||||
break;
|
||||
|
||||
long points = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1])
|
||||
+ HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 3]) * 10000
|
||||
+ HexFormatter.intValue (buffer[ptr + 4], buffer[ptr + 5]) * 100000000L;
|
||||
expLevels[seq++] = points;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
long getExperiencePoints (int level)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (level < 13)
|
||||
return expLevels[level];
|
||||
return (level - 12) * expLevels[0] + expLevels[12];
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder line = new StringBuilder ();
|
||||
for (long exp : expLevels)
|
||||
line.append (exp + "\n");
|
||||
return line.toString ();
|
||||
}
|
||||
}
|
@ -1,239 +1,253 @@
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AppleFileSource;
|
||||
import com.bytezone.diskbrowser.applefile.DefaultAppleFile;
|
||||
import com.bytezone.diskbrowser.disk.DefaultAppleFileSource;
|
||||
import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
class Header
|
||||
{
|
||||
static String[] typeText = { "header", "maze", "monsters", "rewards", "items",
|
||||
"characters", "images", "char levels" };
|
||||
static String[] scenarioNames =
|
||||
{ "PROVING GROUNDS OF THE MAD OVERLORD!", "THE KNIGHT OF DIAMONDS",
|
||||
"THE LEGACY OF LLYLGAMYN", "THE RETURN OF WERDNA" };
|
||||
|
||||
static final int MAZE_AREA = 1;
|
||||
static final int MONSTER_AREA = 2;
|
||||
static final int TREASURE_TABLE_AREA = 3;
|
||||
static final int ITEM_AREA = 4;
|
||||
static final int CHARACTER_AREA = 5;
|
||||
static final int IMAGE_AREA = 6;
|
||||
static final int EXPERIENCE_AREA = 7;
|
||||
|
||||
String scenarioTitle;
|
||||
public int scenarioID;
|
||||
List<ScenarioData> data = new ArrayList<> (8);
|
||||
FormattedDisk owner;
|
||||
|
||||
public Header (DefaultMutableTreeNode dataNode, FormattedDisk owner)
|
||||
{
|
||||
this.owner = owner;
|
||||
|
||||
AppleFileSource afs = (AppleFileSource) dataNode.getUserObject ();
|
||||
List<DiskAddress> sectors = afs.getSectors ();
|
||||
DefaultAppleFile daf = (DefaultAppleFile) afs.getDataSource ();
|
||||
scenarioTitle = HexFormatter.getPascalString (daf.buffer, 0);
|
||||
|
||||
while (scenarioID < scenarioNames.length)
|
||||
if (scenarioNames[scenarioID++].equals (scenarioTitle))
|
||||
break;
|
||||
|
||||
if (scenarioID > scenarioNames.length)
|
||||
System.out.println ("Invalid scenario ID : " + scenarioID + " " + scenarioTitle);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
data.add (new ScenarioData (daf.buffer, i, sectors));
|
||||
|
||||
StringBuilder text = new StringBuilder ("Data type Offset Size Units ???\n"
|
||||
+ "------------ ------ ----- ----- -----\n");
|
||||
|
||||
for (ScenarioData sd : data)
|
||||
text.append (sd + "\n");
|
||||
|
||||
daf.setText (text.toString ());
|
||||
|
||||
text = new StringBuilder (scenarioTitle + "\n\n");
|
||||
|
||||
int ptr = 106;
|
||||
while (daf.buffer[ptr] != -1)
|
||||
{
|
||||
text.append (HexFormatter.getPascalString (daf.buffer, ptr) + "\n");
|
||||
ptr += 10;
|
||||
}
|
||||
|
||||
DefaultAppleFileSource dafs =
|
||||
new DefaultAppleFileSource ("Header", text.toString (), owner);
|
||||
dafs.setSectors (data.get (0).sectors);
|
||||
DefaultMutableTreeNode headerNode = new DefaultMutableTreeNode (dafs);
|
||||
dataNode.add (headerNode);
|
||||
|
||||
if (scenarioID > 3)
|
||||
return;
|
||||
|
||||
int totalBlocks = data.get (0).sectors.size ();
|
||||
linkText ("Text", data.get (0).sectors.get (0), headerNode);
|
||||
|
||||
if (scenarioID < 3)
|
||||
{
|
||||
linkPictures ("Alphabet", data.get (0).sectors.get (1), headerNode);
|
||||
linkPictures ("Graphics", data.get (0).sectors.get (2), headerNode);
|
||||
linkPictures ("Unknown", data.get (0).sectors.get (3), headerNode);
|
||||
}
|
||||
|
||||
linkSpells ("Mage spells", data.get (0).sectors.get (totalBlocks - 2), headerNode);
|
||||
linkSpells ("Priest spells", data.get (0).sectors.get (totalBlocks - 1), headerNode);
|
||||
|
||||
if (false && scenarioID <= 2)
|
||||
{
|
||||
System.out.println (printChars (daf.buffer, 1));
|
||||
System.out.println (printChars (daf.buffer, 2));
|
||||
}
|
||||
}
|
||||
|
||||
private void linkText (String title, DiskAddress da, DefaultMutableTreeNode headerNode)
|
||||
{
|
||||
List<DiskAddress> blocks = new ArrayList<> ();
|
||||
blocks.add (da);
|
||||
|
||||
StringBuilder text = new StringBuilder (scenarioTitle + "\n\n");
|
||||
|
||||
int ptr = 106;
|
||||
byte[] buffer = owner.getDisk ().readSector (da);
|
||||
while (buffer[ptr] != -1)
|
||||
{
|
||||
text.append (HexFormatter.getPascalString (buffer, ptr) + "\n");
|
||||
ptr += 10;
|
||||
}
|
||||
ptr += 2;
|
||||
text.append ("\n");
|
||||
while (ptr < 512)
|
||||
{
|
||||
int value = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]);
|
||||
text.append (String.format ("%04X %,6d%n", value, value));
|
||||
ptr += 2;
|
||||
}
|
||||
|
||||
DefaultAppleFileSource dafs =
|
||||
new DefaultAppleFileSource (title, text.toString (), owner);
|
||||
dafs.setSectors (blocks);
|
||||
DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs);
|
||||
node.setAllowsChildren (false);
|
||||
headerNode.add (node);
|
||||
}
|
||||
|
||||
private void linkPictures (String title, DiskAddress da,
|
||||
DefaultMutableTreeNode headerNode)
|
||||
{
|
||||
List<DiskAddress> blocks = new ArrayList<> ();
|
||||
blocks.add (da);
|
||||
|
||||
byte[] buffer = owner.getDisk ().readSector (da);
|
||||
String text = printChars (buffer, 0);
|
||||
|
||||
DefaultAppleFileSource dafs = new DefaultAppleFileSource (title, text, owner);
|
||||
dafs.setSectors (blocks);
|
||||
DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs);
|
||||
node.setAllowsChildren (false);
|
||||
headerNode.add (node);
|
||||
}
|
||||
|
||||
private void linkSpells (String title, DiskAddress da,
|
||||
DefaultMutableTreeNode headerNode)
|
||||
{
|
||||
List<DiskAddress> blocks = new ArrayList<> ();
|
||||
blocks.add (da);
|
||||
int level = 1;
|
||||
|
||||
StringBuilder list = new StringBuilder ("Level " + level + ":\n");
|
||||
byte[] buffer = owner.getDisk ().readSector (da);
|
||||
String text = HexFormatter.getString (buffer, 0, 512);
|
||||
String[] spells = text.split ("\n");
|
||||
for (String s : spells)
|
||||
{
|
||||
if (s.length () == 0)
|
||||
break;
|
||||
if (s.startsWith ("*"))
|
||||
{
|
||||
s = s.substring (1);
|
||||
level++;
|
||||
list.append ("\nLevel " + level + ":\n");
|
||||
}
|
||||
list.append (" " + s + "\n");
|
||||
}
|
||||
|
||||
DefaultAppleFileSource dafs =
|
||||
new DefaultAppleFileSource (title, list.toString (), owner);
|
||||
dafs.setSectors (blocks);
|
||||
DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs);
|
||||
node.setAllowsChildren (false);
|
||||
headerNode.add (node);
|
||||
}
|
||||
|
||||
private String printChars (byte[] buffer, int block)
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
for (int i = block * 512; i < (block + 1) * 512; i += 64)
|
||||
{
|
||||
for (int line = 0; line < 8; line++)
|
||||
{
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
int value = buffer[i + line + j * 8] & 0xFF;
|
||||
for (int bit = 0; bit < 7; bit++)
|
||||
{
|
||||
if ((value & 0x01) == 1)
|
||||
text.append ("O");
|
||||
else
|
||||
text.append (".");
|
||||
value >>= 1;
|
||||
}
|
||||
text.append (" ");
|
||||
}
|
||||
text.append ("\n");
|
||||
}
|
||||
text.append ("\n");
|
||||
}
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
// this could be the base factory class for all Wizardry types
|
||||
class ScenarioData
|
||||
{
|
||||
int dunno;
|
||||
int total;
|
||||
int totalBlocks;
|
||||
int dataOffset;
|
||||
int type;
|
||||
List<DiskAddress> sectors;
|
||||
|
||||
public ScenarioData (byte[] buffer, int seq, List<DiskAddress> sectors)
|
||||
{
|
||||
int offset = 42 + seq * 2;
|
||||
dunno = buffer[offset] & 0xFF;
|
||||
total = buffer[offset + 16] & 0xFF;
|
||||
totalBlocks = buffer[offset + 32] & 0xFF;
|
||||
dataOffset = buffer[offset + 48] & 0xFF;
|
||||
type = seq;
|
||||
|
||||
this.sectors = new ArrayList<> (totalBlocks);
|
||||
for (int i = dataOffset, max = dataOffset + totalBlocks; i < max; i++)
|
||||
if (i < sectors.size ())
|
||||
this.sectors.add (sectors.get (i));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString ()
|
||||
{
|
||||
return String.format ("%-15s %3d %3d %3d %3d", typeText[type], dataOffset,
|
||||
totalBlocks, total, dunno);
|
||||
}
|
||||
}
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AppleFileSource;
|
||||
import com.bytezone.diskbrowser.applefile.DefaultAppleFile;
|
||||
import com.bytezone.diskbrowser.disk.DefaultAppleFileSource;
|
||||
import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class Header
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
static String[] typeText = { "header", "maze", "monsters", "rewards", "items",
|
||||
"characters", "images", "char levels" };
|
||||
static String[] scenarioNames =
|
||||
{ "PROVING GROUNDS OF THE MAD OVERLORD!", "THE KNIGHT OF DIAMONDS",
|
||||
"THE LEGACY OF LLYLGAMYN", "THE RETURN OF WERDNA" };
|
||||
|
||||
static final int MAZE_AREA = 1;
|
||||
static final int MONSTER_AREA = 2;
|
||||
static final int TREASURE_TABLE_AREA = 3;
|
||||
static final int ITEM_AREA = 4;
|
||||
static final int CHARACTER_AREA = 5;
|
||||
static final int IMAGE_AREA = 6;
|
||||
static final int EXPERIENCE_AREA = 7;
|
||||
|
||||
String scenarioTitle;
|
||||
public int scenarioID;
|
||||
List<ScenarioData> data = new ArrayList<> (8);
|
||||
FormattedDisk owner;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
Header (DefaultMutableTreeNode dataNode, FormattedDisk owner)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.owner = owner;
|
||||
|
||||
AppleFileSource afs = (AppleFileSource) dataNode.getUserObject ();
|
||||
List<DiskAddress> sectors = afs.getSectors ();
|
||||
DefaultAppleFile daf = (DefaultAppleFile) afs.getDataSource ();
|
||||
scenarioTitle = HexFormatter.getPascalString (daf.buffer, 0);
|
||||
|
||||
while (scenarioID < scenarioNames.length)
|
||||
if (scenarioNames[scenarioID++].equals (scenarioTitle))
|
||||
break;
|
||||
|
||||
if (scenarioID > scenarioNames.length)
|
||||
System.out.println ("Invalid scenario ID : " + scenarioID + " " + scenarioTitle);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
data.add (new ScenarioData (daf.buffer, i, sectors));
|
||||
|
||||
StringBuilder text = new StringBuilder ("Data type Offset Size Units ???\n"
|
||||
+ "------------ ------ ----- ----- -----\n");
|
||||
|
||||
for (ScenarioData sd : data)
|
||||
text.append (sd + "\n");
|
||||
|
||||
daf.setText (text.toString ());
|
||||
|
||||
text = new StringBuilder (scenarioTitle + "\n\n");
|
||||
|
||||
int ptr = 106;
|
||||
while (daf.buffer[ptr] != -1)
|
||||
{
|
||||
text.append (HexFormatter.getPascalString (daf.buffer, ptr) + "\n");
|
||||
ptr += 10;
|
||||
}
|
||||
|
||||
DefaultAppleFileSource dafs =
|
||||
new DefaultAppleFileSource ("Header", text.toString (), owner);
|
||||
dafs.setSectors (data.get (0).sectors);
|
||||
DefaultMutableTreeNode headerNode = new DefaultMutableTreeNode (dafs);
|
||||
dataNode.add (headerNode);
|
||||
|
||||
if (scenarioID > 3)
|
||||
return;
|
||||
|
||||
int totalBlocks = data.get (0).sectors.size ();
|
||||
linkText ("Text", data.get (0).sectors.get (0), headerNode);
|
||||
|
||||
if (scenarioID < 3)
|
||||
{
|
||||
linkPictures ("Alphabet", data.get (0).sectors.get (1), headerNode);
|
||||
linkPictures ("Graphics", data.get (0).sectors.get (2), headerNode);
|
||||
linkPictures ("Unknown", data.get (0).sectors.get (3), headerNode);
|
||||
}
|
||||
|
||||
linkSpells ("Mage spells", data.get (0).sectors.get (totalBlocks - 2), headerNode);
|
||||
linkSpells ("Priest spells", data.get (0).sectors.get (totalBlocks - 1), headerNode);
|
||||
|
||||
if (false && scenarioID <= 2)
|
||||
{
|
||||
System.out.println (printChars (daf.buffer, 1));
|
||||
System.out.println (printChars (daf.buffer, 2));
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void linkText (String title, DiskAddress da, DefaultMutableTreeNode headerNode)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
List<DiskAddress> blocks = new ArrayList<> ();
|
||||
blocks.add (da);
|
||||
|
||||
StringBuilder text = new StringBuilder (scenarioTitle + "\n\n");
|
||||
|
||||
int ptr = 106;
|
||||
byte[] buffer = owner.getDisk ().readSector (da);
|
||||
while (buffer[ptr] != -1)
|
||||
{
|
||||
text.append (HexFormatter.getPascalString (buffer, ptr) + "\n");
|
||||
ptr += 10;
|
||||
}
|
||||
ptr += 2;
|
||||
text.append ("\n");
|
||||
while (ptr < 512)
|
||||
{
|
||||
int value = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]);
|
||||
text.append (String.format ("%04X %,6d%n", value, value));
|
||||
ptr += 2;
|
||||
}
|
||||
|
||||
DefaultAppleFileSource dafs =
|
||||
new DefaultAppleFileSource (title, text.toString (), owner);
|
||||
dafs.setSectors (blocks);
|
||||
DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs);
|
||||
node.setAllowsChildren (false);
|
||||
headerNode.add (node);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void linkPictures (String title, DiskAddress da,
|
||||
DefaultMutableTreeNode headerNode)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
List<DiskAddress> blocks = new ArrayList<> ();
|
||||
blocks.add (da);
|
||||
|
||||
byte[] buffer = owner.getDisk ().readSector (da);
|
||||
String text = printChars (buffer, 0);
|
||||
|
||||
DefaultAppleFileSource dafs = new DefaultAppleFileSource (title, text, owner);
|
||||
dafs.setSectors (blocks);
|
||||
DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs);
|
||||
node.setAllowsChildren (false);
|
||||
headerNode.add (node);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void linkSpells (String title, DiskAddress da,
|
||||
DefaultMutableTreeNode headerNode)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
List<DiskAddress> blocks = new ArrayList<> ();
|
||||
blocks.add (da);
|
||||
int level = 1;
|
||||
|
||||
StringBuilder list = new StringBuilder ("Level " + level + ":\n");
|
||||
byte[] buffer = owner.getDisk ().readSector (da);
|
||||
String text = HexFormatter.getString (buffer, 0, 512);
|
||||
String[] spells = text.split ("\n");
|
||||
for (String s : spells)
|
||||
{
|
||||
if (s.length () == 0)
|
||||
break;
|
||||
if (s.startsWith ("*"))
|
||||
{
|
||||
s = s.substring (1);
|
||||
level++;
|
||||
list.append ("\nLevel " + level + ":\n");
|
||||
}
|
||||
list.append (" " + s + "\n");
|
||||
}
|
||||
|
||||
DefaultAppleFileSource dafs =
|
||||
new DefaultAppleFileSource (title, list.toString (), owner);
|
||||
dafs.setSectors (blocks);
|
||||
DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs);
|
||||
node.setAllowsChildren (false);
|
||||
headerNode.add (node);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private String printChars (byte[] buffer, int block)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
for (int i = block * 512; i < (block + 1) * 512; i += 64)
|
||||
{
|
||||
for (int line = 0; line < 8; line++)
|
||||
{
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
int value = buffer[i + line + j * 8] & 0xFF;
|
||||
for (int bit = 0; bit < 7; bit++)
|
||||
{
|
||||
if ((value & 0x01) == 1)
|
||||
text.append ("O");
|
||||
else
|
||||
text.append (".");
|
||||
value >>= 1;
|
||||
}
|
||||
text.append (" ");
|
||||
}
|
||||
text.append ("\n");
|
||||
}
|
||||
text.append ("\n");
|
||||
}
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
// this could be the base factory class for all Wizardry types
|
||||
// ---------------------------------------------------------------------------------//
|
||||
class ScenarioData
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int dunno;
|
||||
int total;
|
||||
int totalBlocks;
|
||||
int dataOffset;
|
||||
int type;
|
||||
List<DiskAddress> sectors;
|
||||
|
||||
public ScenarioData (byte[] buffer, int seq, List<DiskAddress> sectors)
|
||||
{
|
||||
int offset = 42 + seq * 2;
|
||||
dunno = buffer[offset] & 0xFF;
|
||||
total = buffer[offset + 16] & 0xFF;
|
||||
totalBlocks = buffer[offset + 32] & 0xFF;
|
||||
dataOffset = buffer[offset + 48] & 0xFF;
|
||||
type = seq;
|
||||
|
||||
this.sectors = new ArrayList<> (totalBlocks);
|
||||
for (int i = dataOffset, max = dataOffset + totalBlocks; i < max; i++)
|
||||
if (i < sectors.size ())
|
||||
this.sectors.add (sectors.get (i));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString ()
|
||||
{
|
||||
return String.format ("%-15s %3d %3d %3d %3d", typeText[type], dataOffset,
|
||||
totalBlocks, total, dunno);
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,9 @@ import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
// link for possible display algorithm:
|
||||
// http://stackoverflow.com/questions/14184655/set-position-for-drawing-binary-tree
|
||||
|
||||
public class Huffman extends AbstractFile
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class Huffman extends AbstractFile
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private static final byte[] mask = { 2, 1 }; // bits: 10 or 01
|
||||
private static final int[] offset = { 512, 256 }; // offset to left/right nodes
|
||||
@ -19,12 +21,16 @@ public class Huffman extends AbstractFile
|
||||
|
||||
private String bufferContents;
|
||||
|
||||
public Huffman (String name, byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
Huffman (String name, byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
}
|
||||
|
||||
public String decodeMessage (byte[] message)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
String decodeMessage (byte[] message)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.message = message;
|
||||
depth = 0;
|
||||
@ -39,7 +45,9 @@ public class Huffman extends AbstractFile
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private byte getChar ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int treePtr = 0; // start at the root
|
||||
|
||||
@ -63,8 +71,10 @@ public class Huffman extends AbstractFile
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (bufferContents == null)
|
||||
{
|
||||
@ -75,7 +85,9 @@ public class Huffman extends AbstractFile
|
||||
return bufferContents;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void walk (int treePtr, String path, StringBuilder text)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
for (int currentBit = 1; currentBit >= 0; --currentBit)
|
||||
if ((buffer[treePtr] & mask[currentBit]) == 0)
|
||||
|
@ -1,59 +1,65 @@
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBuffer;
|
||||
|
||||
class Image extends AbstractImage
|
||||
{
|
||||
public Image (String name, byte[] buffer)
|
||||
{
|
||||
super (name, buffer);
|
||||
|
||||
if (buffer[0] == -61 && buffer[1] == -115)
|
||||
fixSlime (buffer);
|
||||
|
||||
image = new BufferedImage (70, 50, BufferedImage.TYPE_BYTE_GRAY); // width/height
|
||||
DataBuffer db = image.getRaster ().getDataBuffer ();
|
||||
int element = 0;
|
||||
|
||||
for (int j = 0; j < 500; j++)
|
||||
{
|
||||
int bits = buffer[j] & 0xFF;
|
||||
for (int m = 0; m < 7; m++)
|
||||
{
|
||||
if (bits == 0)
|
||||
{
|
||||
element += 7 - m;
|
||||
break;
|
||||
}
|
||||
if ((bits & 1) == 1)
|
||||
db.setElem (element, 255);
|
||||
bits >>= 1;
|
||||
element++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fixSlime (byte[] buffer)
|
||||
{
|
||||
for (int i = 0; i < 208; i++)
|
||||
buffer[i] = 0;
|
||||
buffer[124] = -108;
|
||||
buffer[134] = -43;
|
||||
buffer[135] = -128;
|
||||
buffer[144] = -44;
|
||||
buffer[145] = -126;
|
||||
buffer[154] = -48;
|
||||
buffer[155] = -118;
|
||||
buffer[164] = -64;
|
||||
buffer[165] = -86;
|
||||
buffer[174] = -64;
|
||||
buffer[175] = -86;
|
||||
buffer[184] = -63;
|
||||
buffer[185] = -86;
|
||||
buffer[194] = -44;
|
||||
buffer[195] = -86;
|
||||
buffer[204] = -44;
|
||||
buffer[205] = -126;
|
||||
}
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBuffer;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class Image extends AbstractImage
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
// ---------------------------------------------------------------------------------//
|
||||
Image (String name, byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
|
||||
if (buffer[0] == -61 && buffer[1] == -115)
|
||||
fixSlime (buffer);
|
||||
|
||||
image = new BufferedImage (70, 50, BufferedImage.TYPE_BYTE_GRAY); // width/height
|
||||
DataBuffer db = image.getRaster ().getDataBuffer ();
|
||||
int element = 0;
|
||||
|
||||
for (int j = 0; j < 500; j++)
|
||||
{
|
||||
int bits = buffer[j] & 0xFF;
|
||||
for (int m = 0; m < 7; m++)
|
||||
{
|
||||
if (bits == 0)
|
||||
{
|
||||
element += 7 - m;
|
||||
break;
|
||||
}
|
||||
if ((bits & 1) == 1)
|
||||
db.setElem (element, 255);
|
||||
bits >>= 1;
|
||||
element++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void fixSlime (byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
for (int i = 0; i < 208; i++)
|
||||
buffer[i] = 0;
|
||||
buffer[124] = -108;
|
||||
buffer[134] = -43;
|
||||
buffer[135] = -128;
|
||||
buffer[144] = -44;
|
||||
buffer[145] = -126;
|
||||
buffer[154] = -48;
|
||||
buffer[155] = -118;
|
||||
buffer[164] = -64;
|
||||
buffer[165] = -86;
|
||||
buffer[174] = -64;
|
||||
buffer[175] = -86;
|
||||
buffer[184] = -63;
|
||||
buffer[185] = -86;
|
||||
buffer[194] = -44;
|
||||
buffer[195] = -86;
|
||||
buffer[204] = -44;
|
||||
buffer[205] = -126;
|
||||
}
|
||||
}
|
@ -1,32 +1,36 @@
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBuffer;
|
||||
|
||||
class ImageV2 extends AbstractImage
|
||||
{
|
||||
public ImageV2 (String name, byte[] buffer)
|
||||
{
|
||||
super (name, buffer);
|
||||
|
||||
image = new BufferedImage (70, 48, BufferedImage.TYPE_BYTE_GRAY); // width/height
|
||||
DataBuffer db = image.getRaster ().getDataBuffer ();
|
||||
int offset = 0;
|
||||
int size = 7;
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
for (int j = 0; j < 10; j++)
|
||||
for (int k = 7; k >= 0; k--)
|
||||
{
|
||||
int element = i * 560 + j * 7 + k * 70;
|
||||
int bits = buffer[offset++] & 0xFF;
|
||||
for (int m = size - 1; m >= 0; m--)
|
||||
{
|
||||
if ((bits & 1) == 1)
|
||||
db.setElem (element, 255);
|
||||
bits >>= 1;
|
||||
element++;
|
||||
}
|
||||
}
|
||||
}
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBuffer;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class ImageV2 extends AbstractImage
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
// ---------------------------------------------------------------------------------//
|
||||
ImageV2 (String name, byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
|
||||
image = new BufferedImage (70, 48, BufferedImage.TYPE_BYTE_GRAY); // width/height
|
||||
DataBuffer db = image.getRaster ().getDataBuffer ();
|
||||
int offset = 0;
|
||||
int size = 7;
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
for (int j = 0; j < 10; j++)
|
||||
for (int k = 7; k >= 0; k--)
|
||||
{
|
||||
int element = i * 560 + j * 7 + k * 70;
|
||||
int bits = buffer[offset++] & 0xFF;
|
||||
for (int m = size - 1; m >= 0; m--)
|
||||
{
|
||||
if ((bits & 1) == 1)
|
||||
db.setElem (element, 255);
|
||||
bits >>= 1;
|
||||
element++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,141 +1,163 @@
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
class Item extends AbstractFile implements Comparable<Item>
|
||||
{
|
||||
public final int itemID;
|
||||
private final int type;
|
||||
private final long cost;
|
||||
public int partyOwns;
|
||||
String genericName;
|
||||
static int counter = 0;
|
||||
public final Dice damage;
|
||||
public final int armourClass;
|
||||
public final int speed;
|
||||
|
||||
public Item (String name, byte[] buffer)
|
||||
{
|
||||
super (name, buffer);
|
||||
itemID = counter++;
|
||||
type = buffer[32];
|
||||
cost = HexFormatter.intValue (buffer[44], buffer[45])
|
||||
+ HexFormatter.intValue (buffer[46], buffer[47]) * 10000
|
||||
+ HexFormatter.intValue (buffer[48], buffer[49]) * 100000000L;
|
||||
genericName = HexFormatter.getPascalString (buffer, 16);
|
||||
damage = new Dice (buffer, 66);
|
||||
armourClass = buffer[62];
|
||||
speed = buffer[72];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText ()
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
text.append ("Name ......... : " + name);
|
||||
// int length = HexFormatter.intValue (buffer[16]);
|
||||
text.append ("\nGeneric name . : " + genericName);
|
||||
text.append ("\nType ......... : " + type);
|
||||
text.append ("\nCost ......... : " + cost);
|
||||
text.append ("\nArmour class . : " + armourClass);
|
||||
text.append ("\nDamage ....... : " + damage);
|
||||
text.append ("\nSpeed ........ : " + speed);
|
||||
text.append ("\nCursed? ...... : " + isCursed ());
|
||||
int stock = getStockOnHand ();
|
||||
text.append ("\nStock on hand : " + stock);
|
||||
if (stock < 0)
|
||||
text.append (" (always in stock)");
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
public int getType ()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
// public int getArmourClass ()
|
||||
// {
|
||||
// return buffer[62];
|
||||
// }
|
||||
|
||||
// public int getSpeed ()
|
||||
// {
|
||||
// return HexFormatter.intValue (buffer[72]);
|
||||
// }
|
||||
|
||||
public long getCost ()
|
||||
{
|
||||
return cost;
|
||||
}
|
||||
|
||||
public boolean isCursed ()
|
||||
{
|
||||
return buffer[36] != 0;
|
||||
}
|
||||
|
||||
public int getStockOnHand ()
|
||||
{
|
||||
if (buffer[50] == -1 && buffer[51] == -1)
|
||||
return -1;
|
||||
|
||||
return HexFormatter.intValue (buffer[50], buffer[51]);
|
||||
}
|
||||
|
||||
public boolean canUse (int type2)
|
||||
{
|
||||
int users = buffer[54] & 0xFF;
|
||||
return ((users >>> type2) & 1) == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString ()
|
||||
{
|
||||
StringBuilder line = new StringBuilder ();
|
||||
line.append (String.format ("%-16s", name));
|
||||
if (buffer[36] == -1)
|
||||
line.append ("(c) ");
|
||||
else
|
||||
line.append (" ");
|
||||
line.append (String.format ("%02X ", buffer[62]));
|
||||
line.append (String.format ("%02X ", buffer[34]));
|
||||
line.append (String.format ("%02X %02X", buffer[50], buffer[51]));
|
||||
|
||||
// if (buffer[50] == -1 && buffer[51] == -1)
|
||||
// line.append ("* ");
|
||||
// else
|
||||
// line.append (HexFormatter.intValue (buffer[50], buffer[51]) + " ");
|
||||
|
||||
for (int i = 38; i < 44; i++)
|
||||
line.append (HexFormatter.format2 (buffer[i]) + " ");
|
||||
for (int i = 48; i < 50; i++)
|
||||
line.append (HexFormatter.format2 (buffer[i]) + " ");
|
||||
for (int i = 52; i < 62; i++)
|
||||
line.append (HexFormatter.format2 (buffer[i]) + " ");
|
||||
// for (int i = 64; i < 78; i++)
|
||||
// line.append (HexFormatter.format2 (buffer[i]) + " ");
|
||||
|
||||
return line.toString ();
|
||||
}
|
||||
|
||||
public String getDump (int block)
|
||||
{
|
||||
StringBuilder line = new StringBuilder (String.format ("%3d %-16s", itemID, name));
|
||||
int lo = block == 0 ? 32 : block == 1 ? 46 : 70;
|
||||
int hi = lo + 24;
|
||||
if (hi > buffer.length)
|
||||
hi = buffer.length;
|
||||
for (int i = lo; i < hi; i++)
|
||||
line.append (String.format ("%02X ", buffer[i]));
|
||||
return line.toString ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo (Item otherItem)
|
||||
{
|
||||
Item item = otherItem;
|
||||
return this.type - item.type;
|
||||
}
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class Item extends AbstractFile implements Comparable<Item>
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
public final int itemID;
|
||||
private final int type;
|
||||
private final long cost;
|
||||
public int partyOwns;
|
||||
String genericName;
|
||||
static int counter = 0;
|
||||
public final Dice damage;
|
||||
public final int armourClass;
|
||||
public final int speed;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
Item (String name, byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
itemID = counter++;
|
||||
type = buffer[32];
|
||||
cost = HexFormatter.intValue (buffer[44], buffer[45])
|
||||
+ HexFormatter.intValue (buffer[46], buffer[47]) * 10000
|
||||
+ HexFormatter.intValue (buffer[48], buffer[49]) * 100000000L;
|
||||
genericName = HexFormatter.getPascalString (buffer, 16);
|
||||
damage = new Dice (buffer, 66);
|
||||
armourClass = buffer[62];
|
||||
speed = buffer[72];
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
text.append ("Name ......... : " + name);
|
||||
// int length = HexFormatter.intValue (buffer[16]);
|
||||
text.append ("\nGeneric name . : " + genericName);
|
||||
text.append ("\nType ......... : " + type);
|
||||
text.append ("\nCost ......... : " + cost);
|
||||
text.append ("\nArmour class . : " + armourClass);
|
||||
text.append ("\nDamage ....... : " + damage);
|
||||
text.append ("\nSpeed ........ : " + speed);
|
||||
text.append ("\nCursed? ...... : " + isCursed ());
|
||||
int stock = getStockOnHand ();
|
||||
text.append ("\nStock on hand : " + stock);
|
||||
if (stock < 0)
|
||||
text.append (" (always in stock)");
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public int getType ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
// public int getArmourClass ()
|
||||
// {
|
||||
// return buffer[62];
|
||||
// }
|
||||
|
||||
// public int getSpeed ()
|
||||
// {
|
||||
// return HexFormatter.intValue (buffer[72]);
|
||||
// }
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public long getCost ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return cost;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public boolean isCursed ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return buffer[36] != 0;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public int getStockOnHand ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (buffer[50] == -1 && buffer[51] == -1)
|
||||
return -1;
|
||||
|
||||
return HexFormatter.intValue (buffer[50], buffer[51]);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public boolean canUse (int type2)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int users = buffer[54] & 0xFF;
|
||||
return ((users >>> type2) & 1) == 1;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String toString ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder line = new StringBuilder ();
|
||||
line.append (String.format ("%-16s", name));
|
||||
if (buffer[36] == -1)
|
||||
line.append ("(c) ");
|
||||
else
|
||||
line.append (" ");
|
||||
line.append (String.format ("%02X ", buffer[62]));
|
||||
line.append (String.format ("%02X ", buffer[34]));
|
||||
line.append (String.format ("%02X %02X", buffer[50], buffer[51]));
|
||||
|
||||
// if (buffer[50] == -1 && buffer[51] == -1)
|
||||
// line.append ("* ");
|
||||
// else
|
||||
// line.append (HexFormatter.intValue (buffer[50], buffer[51]) + " ");
|
||||
|
||||
for (int i = 38; i < 44; i++)
|
||||
line.append (HexFormatter.format2 (buffer[i]) + " ");
|
||||
for (int i = 48; i < 50; i++)
|
||||
line.append (HexFormatter.format2 (buffer[i]) + " ");
|
||||
for (int i = 52; i < 62; i++)
|
||||
line.append (HexFormatter.format2 (buffer[i]) + " ");
|
||||
// for (int i = 64; i < 78; i++)
|
||||
// line.append (HexFormatter.format2 (buffer[i]) + " ");
|
||||
|
||||
return line.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public String getDump (int block)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder line = new StringBuilder (String.format ("%3d %-16s", itemID, name));
|
||||
int lo = block == 0 ? 32 : block == 1 ? 46 : 70;
|
||||
int hi = lo + 24;
|
||||
if (hi > buffer.length)
|
||||
hi = buffer.length;
|
||||
for (int i = lo; i < hi; i++)
|
||||
line.append (String.format ("%02X ", buffer[i]));
|
||||
return line.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public int compareTo (Item otherItem)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
Item item = otherItem;
|
||||
return this.type - item.type;
|
||||
}
|
||||
}
|
@ -1,21 +1,27 @@
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
class MazeAddress
|
||||
{
|
||||
public final int level;
|
||||
public final int row;
|
||||
public final int column;
|
||||
|
||||
public MazeAddress (int level, int row, int column)
|
||||
{
|
||||
this.level = level;
|
||||
this.row = row;
|
||||
this.column = column;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString ()
|
||||
{
|
||||
return level + "/" + row + "/" + column;
|
||||
}
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class MazeAddress
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
public final int level;
|
||||
public final int row;
|
||||
public final int column;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
MazeAddress (int level, int row, int column)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.level = level;
|
||||
this.row = row;
|
||||
this.column = column;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String toString ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return level + "/" + row + "/" + column;
|
||||
}
|
||||
}
|
@ -1,328 +1,370 @@
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.util.List;
|
||||
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
class MazeCell
|
||||
{
|
||||
static Dimension cellSize = new Dimension (22, 22); // size in pixels
|
||||
|
||||
boolean northWall;
|
||||
boolean southWall;
|
||||
boolean eastWall;
|
||||
boolean westWall;
|
||||
|
||||
boolean northDoor;
|
||||
boolean southDoor;
|
||||
boolean eastDoor;
|
||||
boolean westDoor;
|
||||
|
||||
boolean darkness;
|
||||
|
||||
boolean stairs;
|
||||
boolean pit;
|
||||
boolean spinner;
|
||||
boolean chute;
|
||||
boolean elevator;
|
||||
boolean monsterLair;
|
||||
boolean rock;
|
||||
boolean teleport;
|
||||
boolean spellsBlocked;
|
||||
|
||||
int elevatorFrom;
|
||||
int elevatorTo;
|
||||
|
||||
int messageType;
|
||||
int monsterID = -1;
|
||||
int itemID;
|
||||
|
||||
int unknown;
|
||||
|
||||
MazeAddress address;
|
||||
MazeAddress addressTo; // if teleport/stairs/chute
|
||||
|
||||
public Message message;
|
||||
public List<Monster> monsters;
|
||||
public Item itemRequired;
|
||||
public Item itemObtained;
|
||||
|
||||
public MazeCell (MazeAddress address)
|
||||
{
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public void draw (Graphics2D g, int x, int y)
|
||||
{
|
||||
g.setColor (Color.BLACK);
|
||||
g.fillRect (x, y, 22, 22);
|
||||
|
||||
g.setColor (Color.WHITE);
|
||||
|
||||
if (westWall)
|
||||
drawWest (g, x, y);
|
||||
if (eastWall)
|
||||
drawEast (g, x, y);
|
||||
if (northWall)
|
||||
drawNorth (g, x, y);
|
||||
if (southWall)
|
||||
drawSouth (g, x, y);
|
||||
|
||||
g.setColor (Color.RED);
|
||||
|
||||
if (westDoor)
|
||||
drawWest (g, x, y);
|
||||
if (eastDoor)
|
||||
drawEast (g, x, y);
|
||||
if (northDoor)
|
||||
drawNorth (g, x, y);
|
||||
if (southDoor)
|
||||
drawSouth (g, x, y);
|
||||
|
||||
g.setColor (Color.GREEN);
|
||||
|
||||
if (westDoor && westWall)
|
||||
drawWest (g, x, y);
|
||||
if (eastDoor && eastWall)
|
||||
drawEast (g, x, y);
|
||||
if (northDoor && northWall)
|
||||
drawNorth (g, x, y);
|
||||
if (southDoor && southWall)
|
||||
drawSouth (g, x, y);
|
||||
|
||||
g.setColor (Color.WHITE);
|
||||
|
||||
if (monsterLair)
|
||||
drawMonsterLair (g, x, y);
|
||||
|
||||
if (stairs)
|
||||
if (address.level < addressTo.level)
|
||||
drawStairsDown (g, x, y);
|
||||
else
|
||||
drawStairsUp (g, x, y);
|
||||
else if (message != null)
|
||||
drawChar (g, x, y, "M", Color.RED);
|
||||
else if (pit)
|
||||
drawPit (g, x, y);
|
||||
else if (chute)
|
||||
drawChute (g, x, y);
|
||||
else if (spinner)
|
||||
g.drawString ("S", x + 8, y + 16);
|
||||
else if (teleport)
|
||||
drawTeleport (g, x, y);
|
||||
else if (darkness)
|
||||
drawDarkness (g, x, y);
|
||||
else if (rock)
|
||||
drawRock (g, x, y);
|
||||
else if (elevator)
|
||||
drawElevator (g, x, y, (elevatorTo - elevatorFrom + 1) / 2);
|
||||
else if (monsterID >= 0)
|
||||
drawMonster (g, x, y);
|
||||
else if (spellsBlocked)
|
||||
drawSpellsBlocked (g, x, y);
|
||||
else if (unknown != 0)
|
||||
drawChar (g, x, y, HexFormatter.format1 (unknown), Color.GRAY);
|
||||
}
|
||||
|
||||
public void drawWest (Graphics2D g, int x, int y)
|
||||
{
|
||||
g.drawLine (x + 1, y + 1, x + 1, y + cellSize.height - 1);
|
||||
}
|
||||
|
||||
private void drawEast (Graphics2D g, int x, int y)
|
||||
{
|
||||
g.drawLine (x + cellSize.width - 1, y + 1, x + cellSize.width - 1,
|
||||
y + cellSize.height - 1);
|
||||
}
|
||||
|
||||
private void drawNorth (Graphics2D g, int x, int y)
|
||||
{
|
||||
g.drawLine (x + 1, y + 1, x + cellSize.width - 1, y + 1);
|
||||
}
|
||||
|
||||
private void drawSouth (Graphics2D g, int x, int y)
|
||||
{
|
||||
g.drawLine (x + 1, y + cellSize.height - 1, x + cellSize.width - 1,
|
||||
y + cellSize.height - 1);
|
||||
}
|
||||
|
||||
public void drawStairsUp (Graphics2D g, int x, int y)
|
||||
{
|
||||
g.drawLine (x + 6, y + 18, x + 6, y + 14);
|
||||
g.drawLine (x + 6, y + 14, x + 10, y + 14);
|
||||
g.drawLine (x + 10, y + 14, x + 10, y + 10);
|
||||
g.drawLine (x + 10, y + 10, x + 14, y + 10);
|
||||
g.drawLine (x + 14, y + 10, x + 14, y + 6);
|
||||
g.drawLine (x + 14, y + 6, x + 18, y + 6);
|
||||
}
|
||||
|
||||
public void drawStairsDown (Graphics2D g, int x, int y)
|
||||
{
|
||||
g.drawLine (x + 4, y + 7, x + 8, y + 7);
|
||||
g.drawLine (x + 8, y + 7, x + 8, y + 11);
|
||||
g.drawLine (x + 8, y + 11, x + 12, y + 11);
|
||||
g.drawLine (x + 12, y + 11, x + 12, y + 15);
|
||||
g.drawLine (x + 12, y + 15, x + 16, y + 15);
|
||||
g.drawLine (x + 16, y + 15, x + 16, y + 19);
|
||||
}
|
||||
|
||||
public void drawPit (Graphics2D g, int x, int y)
|
||||
{
|
||||
g.drawLine (x + 5, y + 14, x + 5, y + 19);
|
||||
g.drawLine (x + 5, y + 19, x + 17, y + 19);
|
||||
g.drawLine (x + 17, y + 14, x + 17, y + 19);
|
||||
}
|
||||
|
||||
public void drawChute (Graphics2D g, int x, int y)
|
||||
{
|
||||
g.drawLine (x + 6, y + 6, x + 10, y + 6);
|
||||
g.drawLine (x + 10, y + 6, x + 18, y + 18);
|
||||
}
|
||||
|
||||
public void drawElevator (Graphics2D g, int x, int y, int rows)
|
||||
{
|
||||
for (int i = 0; i < rows; i++)
|
||||
{
|
||||
g.drawOval (x + 7, y + i * 5 + 5, 2, 2);
|
||||
g.drawOval (x + 14, y + i * 5 + 5, 2, 2);
|
||||
}
|
||||
}
|
||||
|
||||
public void drawMonsterLair (Graphics2D g, int x, int y)
|
||||
{
|
||||
g.setColor (Color.YELLOW);
|
||||
g.fillOval (x + 4, y + 4, 2, 2);
|
||||
g.setColor (Color.WHITE);
|
||||
}
|
||||
|
||||
public void drawTeleport (Graphics2D g, int x, int y)
|
||||
{
|
||||
g.setColor (Color.GREEN);
|
||||
g.fillOval (x + 8, y + 8, 8, 8);
|
||||
g.setColor (Color.WHITE);
|
||||
}
|
||||
|
||||
public void drawSpellsBlocked (Graphics2D g, int x, int y)
|
||||
{
|
||||
g.setColor (Color.YELLOW);
|
||||
g.fillOval (x + 8, y + 8, 8, 8);
|
||||
g.setColor (Color.WHITE);
|
||||
}
|
||||
|
||||
public void drawMonster (Graphics2D g, int x, int y)
|
||||
{
|
||||
g.setColor (Color.RED);
|
||||
g.fillOval (x + 8, y + 8, 8, 8);
|
||||
g.setColor (Color.WHITE);
|
||||
}
|
||||
|
||||
public void drawDarkness (Graphics2D g, int x, int y)
|
||||
{
|
||||
g.setColor (Color.gray);
|
||||
for (int h = 0; h < 15; h += 7)
|
||||
for (int offset = 0; offset < 15; offset += 7)
|
||||
g.drawOval (x + offset + 4, y + h + 4, 1, 1);
|
||||
g.setColor (Color.white);
|
||||
}
|
||||
|
||||
public void drawRock (Graphics2D g, int x, int y)
|
||||
{
|
||||
for (int h = 0; h < 15; h += 7)
|
||||
for (int offset = 0; offset < 15; offset += 7)
|
||||
g.drawOval (x + offset + 4, y + h + 4, 1, 1);
|
||||
}
|
||||
|
||||
public void drawChar (Graphics2D g, int x, int y, String c, Color colour)
|
||||
{
|
||||
g.setColor (colour);
|
||||
g.fillRect (x + 7, y + 6, 11, 11);
|
||||
g.setColor (Color.WHITE);
|
||||
g.drawString (c, x + 8, y + 16);
|
||||
}
|
||||
|
||||
public void drawHotDogStand (Graphics2D g, int x, int y)
|
||||
{
|
||||
g.drawRect (x + 5, y + 11, 12, 6);
|
||||
g.drawOval (x + 6, y + 18, 3, 3);
|
||||
g.drawOval (x + 13, y + 18, 3, 3);
|
||||
g.drawLine (x + 8, y + 6, x + 8, y + 10);
|
||||
g.drawLine (x + 14, y + 6, x + 14, y + 10);
|
||||
g.drawLine (x + 5, y + 5, x + 17, y + 5);
|
||||
}
|
||||
|
||||
public String getTooltipText ()
|
||||
{
|
||||
StringBuilder sign = new StringBuilder ("<html><pre>");
|
||||
sign.append (" <b>");
|
||||
sign.append (address.row + "N ");
|
||||
sign.append (address.column + "E</b> <br>");
|
||||
|
||||
if (message != null)
|
||||
sign.append (message.toHTMLString ());
|
||||
|
||||
if (elevator)
|
||||
sign.append (" Elevator: L" + elevatorFrom + "-L" + elevatorTo + " ");
|
||||
if (stairs)
|
||||
{
|
||||
sign.append (" Stairs to ");
|
||||
if (addressTo.level == 0)
|
||||
sign.append ("castle ");
|
||||
else
|
||||
{
|
||||
sign.append ("level " + addressTo.level + " ");
|
||||
}
|
||||
}
|
||||
if (teleport)
|
||||
{
|
||||
sign.append (" Teleport to ");
|
||||
if (addressTo.level == 0)
|
||||
sign.append ("castle ");
|
||||
else
|
||||
{
|
||||
sign.append ("L" + addressTo.level + " " + addressTo.row + "N " + addressTo.column
|
||||
+ "E ");
|
||||
}
|
||||
}
|
||||
if (pit)
|
||||
sign.append (" Pit");
|
||||
if (spinner)
|
||||
sign.append (" Spinner ");
|
||||
if (chute)
|
||||
sign.append (" Chute");
|
||||
if (darkness)
|
||||
sign.append (" Darkness ");
|
||||
if (rock)
|
||||
sign.append (" Rock ");
|
||||
if (spellsBlocked)
|
||||
sign.append (" Spells fizzle out ");
|
||||
if (monsterID >= 0)
|
||||
if (monsters == null || monsterID >= monsters.size ())
|
||||
sign.append (" Monster ");
|
||||
else
|
||||
{
|
||||
Monster monster = monsters.get (monsterID);
|
||||
sign.append (" <b>" + monster.getRealName () + " </b>");
|
||||
while (monster.partnerOdds == 100)
|
||||
{
|
||||
monster = monsters.get (monster.partnerID);
|
||||
sign.append ("<br> <b>" + monster.getRealName () + " </b>");
|
||||
}
|
||||
}
|
||||
if (itemRequired != null)
|
||||
{
|
||||
sign.append (" <b>Requires: ");
|
||||
sign.append (itemRequired.getName () + " </b>");
|
||||
}
|
||||
|
||||
if (itemObtained != null)
|
||||
{
|
||||
sign.append (" <b>Obtain: ");
|
||||
sign.append (itemObtained.getName () + " </b>");
|
||||
}
|
||||
sign.append ("</pre></html>");
|
||||
return sign.toString ();
|
||||
}
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.util.List;
|
||||
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class MazeCell
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
static Dimension cellSize = new Dimension (22, 22); // size in pixels
|
||||
|
||||
boolean northWall;
|
||||
boolean southWall;
|
||||
boolean eastWall;
|
||||
boolean westWall;
|
||||
|
||||
boolean northDoor;
|
||||
boolean southDoor;
|
||||
boolean eastDoor;
|
||||
boolean westDoor;
|
||||
|
||||
boolean darkness;
|
||||
|
||||
boolean stairs;
|
||||
boolean pit;
|
||||
boolean spinner;
|
||||
boolean chute;
|
||||
boolean elevator;
|
||||
boolean monsterLair;
|
||||
boolean rock;
|
||||
boolean teleport;
|
||||
boolean spellsBlocked;
|
||||
|
||||
int elevatorFrom;
|
||||
int elevatorTo;
|
||||
|
||||
int messageType;
|
||||
int monsterID = -1;
|
||||
int itemID;
|
||||
|
||||
int unknown;
|
||||
|
||||
MazeAddress address;
|
||||
MazeAddress addressTo; // if teleport/stairs/chute
|
||||
|
||||
public Message message;
|
||||
public List<Monster> monsters;
|
||||
public Item itemRequired;
|
||||
public Item itemObtained;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
MazeCell (MazeAddress address)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void draw (Graphics2D g, int x, int y)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
g.setColor (Color.BLACK);
|
||||
g.fillRect (x, y, 22, 22);
|
||||
|
||||
g.setColor (Color.WHITE);
|
||||
|
||||
if (westWall)
|
||||
drawWest (g, x, y);
|
||||
if (eastWall)
|
||||
drawEast (g, x, y);
|
||||
if (northWall)
|
||||
drawNorth (g, x, y);
|
||||
if (southWall)
|
||||
drawSouth (g, x, y);
|
||||
|
||||
g.setColor (Color.RED);
|
||||
|
||||
if (westDoor)
|
||||
drawWest (g, x, y);
|
||||
if (eastDoor)
|
||||
drawEast (g, x, y);
|
||||
if (northDoor)
|
||||
drawNorth (g, x, y);
|
||||
if (southDoor)
|
||||
drawSouth (g, x, y);
|
||||
|
||||
g.setColor (Color.GREEN);
|
||||
|
||||
if (westDoor && westWall)
|
||||
drawWest (g, x, y);
|
||||
if (eastDoor && eastWall)
|
||||
drawEast (g, x, y);
|
||||
if (northDoor && northWall)
|
||||
drawNorth (g, x, y);
|
||||
if (southDoor && southWall)
|
||||
drawSouth (g, x, y);
|
||||
|
||||
g.setColor (Color.WHITE);
|
||||
|
||||
if (monsterLair)
|
||||
drawMonsterLair (g, x, y);
|
||||
|
||||
if (stairs)
|
||||
if (address.level < addressTo.level)
|
||||
drawStairsDown (g, x, y);
|
||||
else
|
||||
drawStairsUp (g, x, y);
|
||||
else if (message != null)
|
||||
drawChar (g, x, y, "M", Color.RED);
|
||||
else if (pit)
|
||||
drawPit (g, x, y);
|
||||
else if (chute)
|
||||
drawChute (g, x, y);
|
||||
else if (spinner)
|
||||
g.drawString ("S", x + 8, y + 16);
|
||||
else if (teleport)
|
||||
drawTeleport (g, x, y);
|
||||
else if (darkness)
|
||||
drawDarkness (g, x, y);
|
||||
else if (rock)
|
||||
drawRock (g, x, y);
|
||||
else if (elevator)
|
||||
drawElevator (g, x, y, (elevatorTo - elevatorFrom + 1) / 2);
|
||||
else if (monsterID >= 0)
|
||||
drawMonster (g, x, y);
|
||||
else if (spellsBlocked)
|
||||
drawSpellsBlocked (g, x, y);
|
||||
else if (unknown != 0)
|
||||
drawChar (g, x, y, HexFormatter.format1 (unknown), Color.GRAY);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void drawWest (Graphics2D g, int x, int y)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
g.drawLine (x + 1, y + 1, x + 1, y + cellSize.height - 1);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void drawEast (Graphics2D g, int x, int y)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
g.drawLine (x + cellSize.width - 1, y + 1, x + cellSize.width - 1,
|
||||
y + cellSize.height - 1);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void drawNorth (Graphics2D g, int x, int y)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
g.drawLine (x + 1, y + 1, x + cellSize.width - 1, y + 1);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void drawSouth (Graphics2D g, int x, int y)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
g.drawLine (x + 1, y + cellSize.height - 1, x + cellSize.width - 1,
|
||||
y + cellSize.height - 1);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void drawStairsUp (Graphics2D g, int x, int y)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
g.drawLine (x + 6, y + 18, x + 6, y + 14);
|
||||
g.drawLine (x + 6, y + 14, x + 10, y + 14);
|
||||
g.drawLine (x + 10, y + 14, x + 10, y + 10);
|
||||
g.drawLine (x + 10, y + 10, x + 14, y + 10);
|
||||
g.drawLine (x + 14, y + 10, x + 14, y + 6);
|
||||
g.drawLine (x + 14, y + 6, x + 18, y + 6);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void drawStairsDown (Graphics2D g, int x, int y)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
g.drawLine (x + 4, y + 7, x + 8, y + 7);
|
||||
g.drawLine (x + 8, y + 7, x + 8, y + 11);
|
||||
g.drawLine (x + 8, y + 11, x + 12, y + 11);
|
||||
g.drawLine (x + 12, y + 11, x + 12, y + 15);
|
||||
g.drawLine (x + 12, y + 15, x + 16, y + 15);
|
||||
g.drawLine (x + 16, y + 15, x + 16, y + 19);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void drawPit (Graphics2D g, int x, int y)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
g.drawLine (x + 5, y + 14, x + 5, y + 19);
|
||||
g.drawLine (x + 5, y + 19, x + 17, y + 19);
|
||||
g.drawLine (x + 17, y + 14, x + 17, y + 19);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void drawChute (Graphics2D g, int x, int y)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
g.drawLine (x + 6, y + 6, x + 10, y + 6);
|
||||
g.drawLine (x + 10, y + 6, x + 18, y + 18);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void drawElevator (Graphics2D g, int x, int y, int rows)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
for (int i = 0; i < rows; i++)
|
||||
{
|
||||
g.drawOval (x + 7, y + i * 5 + 5, 2, 2);
|
||||
g.drawOval (x + 14, y + i * 5 + 5, 2, 2);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void drawMonsterLair (Graphics2D g, int x, int y)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
g.setColor (Color.YELLOW);
|
||||
g.fillOval (x + 4, y + 4, 2, 2);
|
||||
g.setColor (Color.WHITE);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void drawTeleport (Graphics2D g, int x, int y)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
g.setColor (Color.GREEN);
|
||||
g.fillOval (x + 8, y + 8, 8, 8);
|
||||
g.setColor (Color.WHITE);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void drawSpellsBlocked (Graphics2D g, int x, int y)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
g.setColor (Color.YELLOW);
|
||||
g.fillOval (x + 8, y + 8, 8, 8);
|
||||
g.setColor (Color.WHITE);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void drawMonster (Graphics2D g, int x, int y)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
g.setColor (Color.RED);
|
||||
g.fillOval (x + 8, y + 8, 8, 8);
|
||||
g.setColor (Color.WHITE);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void drawDarkness (Graphics2D g, int x, int y)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
g.setColor (Color.gray);
|
||||
for (int h = 0; h < 15; h += 7)
|
||||
for (int offset = 0; offset < 15; offset += 7)
|
||||
g.drawOval (x + offset + 4, y + h + 4, 1, 1);
|
||||
g.setColor (Color.white);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void drawRock (Graphics2D g, int x, int y)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
for (int h = 0; h < 15; h += 7)
|
||||
for (int offset = 0; offset < 15; offset += 7)
|
||||
g.drawOval (x + offset + 4, y + h + 4, 1, 1);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void drawChar (Graphics2D g, int x, int y, String c, Color colour)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
g.setColor (colour);
|
||||
g.fillRect (x + 7, y + 6, 11, 11);
|
||||
g.setColor (Color.WHITE);
|
||||
g.drawString (c, x + 8, y + 16);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void drawHotDogStand (Graphics2D g, int x, int y)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
g.drawRect (x + 5, y + 11, 12, 6);
|
||||
g.drawOval (x + 6, y + 18, 3, 3);
|
||||
g.drawOval (x + 13, y + 18, 3, 3);
|
||||
g.drawLine (x + 8, y + 6, x + 8, y + 10);
|
||||
g.drawLine (x + 14, y + 6, x + 14, y + 10);
|
||||
g.drawLine (x + 5, y + 5, x + 17, y + 5);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
String getTooltipText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder sign = new StringBuilder ("<html><pre>");
|
||||
sign.append (" <b>");
|
||||
sign.append (address.row + "N ");
|
||||
sign.append (address.column + "E</b> <br>");
|
||||
|
||||
if (message != null)
|
||||
sign.append (message.toHTMLString ());
|
||||
|
||||
if (elevator)
|
||||
sign.append (" Elevator: L" + elevatorFrom + "-L" + elevatorTo + " ");
|
||||
if (stairs)
|
||||
{
|
||||
sign.append (" Stairs to ");
|
||||
if (addressTo.level == 0)
|
||||
sign.append ("castle ");
|
||||
else
|
||||
{
|
||||
sign.append ("level " + addressTo.level + " ");
|
||||
}
|
||||
}
|
||||
if (teleport)
|
||||
{
|
||||
sign.append (" Teleport to ");
|
||||
if (addressTo.level == 0)
|
||||
sign.append ("castle ");
|
||||
else
|
||||
{
|
||||
sign.append ("L" + addressTo.level + " " + addressTo.row + "N " + addressTo.column
|
||||
+ "E ");
|
||||
}
|
||||
}
|
||||
if (pit)
|
||||
sign.append (" Pit");
|
||||
if (spinner)
|
||||
sign.append (" Spinner ");
|
||||
if (chute)
|
||||
sign.append (" Chute");
|
||||
if (darkness)
|
||||
sign.append (" Darkness ");
|
||||
if (rock)
|
||||
sign.append (" Rock ");
|
||||
if (spellsBlocked)
|
||||
sign.append (" Spells fizzle out ");
|
||||
if (monsterID >= 0)
|
||||
if (monsters == null || monsterID >= monsters.size ())
|
||||
sign.append (" Monster ");
|
||||
else
|
||||
{
|
||||
Monster monster = monsters.get (monsterID);
|
||||
sign.append (" <b>" + monster.getRealName () + " </b>");
|
||||
while (monster.partnerOdds == 100)
|
||||
{
|
||||
monster = monsters.get (monster.partnerID);
|
||||
sign.append ("<br> <b>" + monster.getRealName () + " </b>");
|
||||
}
|
||||
}
|
||||
if (itemRequired != null)
|
||||
{
|
||||
sign.append (" <b>Requires: ");
|
||||
sign.append (itemRequired.getName () + " </b>");
|
||||
}
|
||||
|
||||
if (itemObtained != null)
|
||||
{
|
||||
sign.append (" <b>Obtain: ");
|
||||
sign.append (itemObtained.getName () + " </b>");
|
||||
}
|
||||
sign.append ("</pre></html>");
|
||||
return sign.toString ();
|
||||
}
|
||||
}
|
@ -12,7 +12,9 @@ import com.bytezone.common.Utility;
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
public class MazeGridV5 extends AbstractFile
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class MazeGridV5 extends AbstractFile
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private final MessageBlock messageBlock;
|
||||
List<MazeGrid> grids = new ArrayList<> ();
|
||||
@ -21,7 +23,9 @@ public class MazeGridV5 extends AbstractFile
|
||||
int maxX = 0;
|
||||
int maxY = 0;
|
||||
|
||||
public MazeGridV5 (String name, byte[] buffer, MessageBlock messageBlock)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
MazeGridV5 (String name, byte[] buffer, MessageBlock messageBlock)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
|
||||
@ -45,8 +49,10 @@ public class MazeGridV5 extends AbstractFile
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public BufferedImage getImage ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
Dimension cellSize = new Dimension (22, 22);
|
||||
int fudge = 30;
|
||||
@ -80,7 +86,9 @@ public class MazeGridV5 extends AbstractFile
|
||||
return image;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private MazeCell getLayout (int gridNo, int row, int column)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
MazeAddress address = new MazeAddress (0, row, column);
|
||||
MazeCell cell = new MazeCell (address);
|
||||
@ -103,8 +111,10 @@ public class MazeGridV5 extends AbstractFile
|
||||
return cell;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getHexDump ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder (super.getHexDump ());
|
||||
|
||||
@ -187,7 +197,9 @@ public class MazeGridV5 extends AbstractFile
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private class MazeGrid
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
MazeCell[][] grid;
|
||||
int xOffset;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,71 +1,85 @@
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
|
||||
abstract class Message extends AbstractFile
|
||||
{
|
||||
private static int nextId = 0;
|
||||
protected String message;
|
||||
private final int id;
|
||||
private int totalLines;
|
||||
List<String> lines = new ArrayList<> ();
|
||||
|
||||
public Message (byte[] buffer)
|
||||
{
|
||||
super ("Message " + nextId, buffer);
|
||||
this.id = nextId;
|
||||
|
||||
int recordLength = 42;
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
for (int ptr = 0; ptr < buffer.length; ptr += recordLength)
|
||||
{
|
||||
nextId++;
|
||||
totalLines++;
|
||||
String line = getLine (ptr);
|
||||
text.append (line + "\n");
|
||||
lines.add (line);
|
||||
}
|
||||
text.deleteCharAt (text.length () - 1);
|
||||
message = text.toString ();
|
||||
}
|
||||
|
||||
protected abstract String getLine (int offset);
|
||||
|
||||
public boolean match (int messageNum)
|
||||
{
|
||||
if (id == messageNum)
|
||||
return true;
|
||||
|
||||
// this code is to allow for a bug in scenario #1
|
||||
if (messageNum > id && messageNum < (id + totalLines))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText ()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
public String toHTMLString ()
|
||||
{
|
||||
StringBuilder message = new StringBuilder ();
|
||||
for (String line : lines)
|
||||
message.append (" " + line + " <br>");
|
||||
if (message.length () > 0)
|
||||
for (int i = 0; i < 4; i++)
|
||||
message.deleteCharAt (message.length () - 1); // remove <br> tag
|
||||
return message.toString ();
|
||||
}
|
||||
|
||||
public static void resetMessageId ()
|
||||
{
|
||||
nextId = 0;
|
||||
}
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
abstract class Message extends AbstractFile
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private static int nextId = 0;
|
||||
protected String message;
|
||||
private final int id;
|
||||
private int totalLines;
|
||||
List<String> lines = new ArrayList<> ();
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
Message (byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super ("Message " + nextId, buffer);
|
||||
this.id = nextId;
|
||||
|
||||
int recordLength = 42;
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
for (int ptr = 0; ptr < buffer.length; ptr += recordLength)
|
||||
{
|
||||
nextId++;
|
||||
totalLines++;
|
||||
String line = getLine (ptr);
|
||||
text.append (line + "\n");
|
||||
lines.add (line);
|
||||
}
|
||||
text.deleteCharAt (text.length () - 1);
|
||||
message = text.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
protected abstract String getLine (int offset);
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public boolean match (int messageNum)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (id == messageNum)
|
||||
return true;
|
||||
|
||||
// this code is to allow for a bug in scenario #1
|
||||
if (messageNum > id && messageNum < (id + totalLines))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public String toHTMLString ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder message = new StringBuilder ();
|
||||
for (String line : lines)
|
||||
message.append (" " + line + " <br>");
|
||||
if (message.length () > 0)
|
||||
for (int i = 0; i < 4; i++)
|
||||
message.deleteCharAt (message.length () - 1); // remove <br> tag
|
||||
return message.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public static void resetMessageId ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
nextId = 0;
|
||||
}
|
||||
}
|
@ -7,7 +7,9 @@ import java.util.List;
|
||||
import com.bytezone.common.Utility;
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
|
||||
public class MessageBlock extends AbstractFile implements Iterable<MessageDataBlock>
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class MessageBlock extends AbstractFile implements Iterable<MessageDataBlock>
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private final int indexOffset;
|
||||
private final int indexLength;
|
||||
@ -15,7 +17,9 @@ public class MessageBlock extends AbstractFile implements Iterable<MessageDataBl
|
||||
|
||||
private final List<MessageDataBlock> messageDataBlocks = new ArrayList<> ();
|
||||
|
||||
public MessageBlock (byte[] buffer, Huffman huffman)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
MessageBlock (byte[] buffer, Huffman huffman)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super ("bollocks", buffer);
|
||||
|
||||
@ -35,7 +39,9 @@ public class MessageBlock extends AbstractFile implements Iterable<MessageDataBl
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public String getMessageText (int messageNo)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
for (int i = 0; i < messageDataBlocks.size (); i++)
|
||||
{
|
||||
@ -46,7 +52,9 @@ public class MessageBlock extends AbstractFile implements Iterable<MessageDataBl
|
||||
return null;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public List<String> getMessageLines (int messageNo)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
List<String> lines = new ArrayList<> ();
|
||||
|
||||
@ -72,7 +80,9 @@ public class MessageBlock extends AbstractFile implements Iterable<MessageDataBl
|
||||
return lines;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public byte[] getMessage (int messageNo)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
for (int i = 0; i < messageDataBlocks.size (); i++)
|
||||
{
|
||||
@ -83,8 +93,10 @@ public class MessageBlock extends AbstractFile implements Iterable<MessageDataBl
|
||||
return null;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (text != null)
|
||||
return text;
|
||||
@ -102,8 +114,10 @@ public class MessageBlock extends AbstractFile implements Iterable<MessageDataBl
|
||||
return this.text;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public Iterator<MessageDataBlock> iterator ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return messageDataBlocks.iterator ();
|
||||
}
|
||||
|
@ -6,7 +6,9 @@ import java.util.List;
|
||||
import com.bytezone.common.Utility;
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
|
||||
public class MessageDataBlock extends AbstractFile
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class MessageDataBlock extends AbstractFile
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
final int firstMessageNo;
|
||||
final int lastMessageNo;
|
||||
@ -16,8 +18,9 @@ public class MessageDataBlock extends AbstractFile
|
||||
|
||||
private final Huffman huffman;
|
||||
|
||||
public MessageDataBlock (String name, byte[] buffer, int firstMessageNo,
|
||||
Huffman huffman)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
MessageDataBlock (String name, byte[] buffer, int firstMessageNo, Huffman huffman)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
|
||||
@ -75,7 +78,9 @@ public class MessageDataBlock extends AbstractFile
|
||||
this.name += " - " + lastMessageNo;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
byte[] getMessage (int messageNo)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
for (Message message : messages)
|
||||
if (message.msgNo == messageNo)
|
||||
@ -87,7 +92,9 @@ public class MessageDataBlock extends AbstractFile
|
||||
return null;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
String getText (int messageNo)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
for (Message message : messages)
|
||||
if (message.msgNo == messageNo)
|
||||
@ -99,8 +106,10 @@ public class MessageDataBlock extends AbstractFile
|
||||
return null;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (messages.size () == 0)
|
||||
return "No Messages";
|
||||
@ -128,8 +137,10 @@ public class MessageDataBlock extends AbstractFile
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String toString ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
@ -145,7 +156,9 @@ public class MessageDataBlock extends AbstractFile
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
class Message
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
final int msgNo;
|
||||
final int offset;
|
||||
|
@ -1,284 +1,309 @@
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
class Monster extends AbstractFile implements Comparable<Monster>
|
||||
{
|
||||
public final String genericName;
|
||||
public final String realName;
|
||||
public final int monsterID;
|
||||
List<Monster> monsters;
|
||||
Reward goldReward;
|
||||
Reward chestReward;
|
||||
|
||||
public final int type;
|
||||
public final int imageID;
|
||||
int rewardTable1;
|
||||
int rewardTable2;
|
||||
public final int partnerID;
|
||||
public final int partnerOdds;
|
||||
public final int armourClass;
|
||||
public final int speed;
|
||||
public final int mageSpellLevel;
|
||||
public final int priestSpellLevel;
|
||||
int levelDrain;
|
||||
int bonus1;
|
||||
int bonus2;
|
||||
int bonus3;
|
||||
int resistance;
|
||||
int abilities;
|
||||
public final Dice groupSize, hitPoints;
|
||||
List<Dice> damage = new ArrayList<> ();
|
||||
|
||||
static int counter = 0;
|
||||
static boolean debug = true;
|
||||
static int[] pwr = { 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 0, 0, 0, 0, 0 };
|
||||
static int[] weight1 = { 0, 1, 2, 4, 8, 16, 32, 64, 253, 506, 0 };
|
||||
static int[] weight2 = { 0, 60, 120, 180, 300, 540, 1020, 0 };
|
||||
|
||||
public static String[] monsterClass =
|
||||
{ "Fighter", "Mage", "Priest", "Thief", "Midget", "Giant", "Mythical", "Dragon",
|
||||
"Animal", "Were", "Undead", "Demon", "Insect", "Enchanted" };
|
||||
|
||||
private static int[] experience = { 55, 235, 415, 230, 380, 620, 840, 520, 550, 350, // 00-09
|
||||
475, 515, 920, 600, 735, 520, 795, 780, 990, 795, // 10-19
|
||||
1360, 1320, 1275, 680, 960, 600, 755, 1120, 2075,
|
||||
870, // 20-29
|
||||
960, 1120, 1120, 2435, 1080, 2280, 975, 875, 1135,
|
||||
1200, // 30-39
|
||||
620, 740, 1460, 1245, 960, 1405, 1040, 1220, 1520,
|
||||
1000, // 40-49
|
||||
960, 2340, 2160, 2395, 790, 1140, 1235, 1790, 1720,
|
||||
2240, // 50-59
|
||||
1475, 1540, 1720, 1900, 1240, 1220, 1020, 20435,
|
||||
5100, 3515, // 60-69
|
||||
2115, 2920, 2060, 2140, 1400, 1640, 1280, 4450,
|
||||
42840, 3300, // 70-79
|
||||
40875, 5000, 3300, 2395, 1935, 1600, 3330, 44090,
|
||||
40840, 5200, // 80-89
|
||||
4155, 3000, 9200, 3160, 7460, 7320, 15880, 1600,
|
||||
2200, 1000, 1900 // 90-100
|
||||
};
|
||||
|
||||
public Monster (String name, byte[] buffer, List<Reward> rewards,
|
||||
List<Monster> monsters)
|
||||
{
|
||||
super (name, buffer);
|
||||
|
||||
realName = name;
|
||||
genericName = HexFormatter.getPascalString (buffer, 0);
|
||||
this.monsterID = counter++;
|
||||
this.monsters = monsters;
|
||||
goldReward = rewards.get (buffer[136]);
|
||||
chestReward = rewards.get (buffer[138]);
|
||||
goldReward.addMonster (this, 0);
|
||||
chestReward.addMonster (this, 1);
|
||||
|
||||
imageID = buffer[64];
|
||||
type = buffer[78];
|
||||
armourClass = buffer[80];
|
||||
speed = buffer[82];
|
||||
levelDrain = buffer[132];
|
||||
bonus1 = buffer[134];
|
||||
rewardTable1 = buffer[136];
|
||||
rewardTable2 = buffer[138];
|
||||
partnerID = buffer[140];
|
||||
partnerOdds = buffer[142];
|
||||
mageSpellLevel = buffer[144];
|
||||
priestSpellLevel = buffer[146];
|
||||
bonus2 = buffer[150];
|
||||
bonus3 = buffer[152];
|
||||
resistance = buffer[154];
|
||||
abilities = buffer[156];
|
||||
groupSize = new Dice (buffer, 66);
|
||||
hitPoints = new Dice (buffer, 72);
|
||||
|
||||
for (int i = 0, ptr = 84; i < 8; i++, ptr += 6)
|
||||
{
|
||||
if (buffer[ptr] == 0)
|
||||
break;
|
||||
damage.add (new Dice (buffer, ptr));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText ()
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
// these values definitely affect the damage a monster does (when breathing?)
|
||||
int exp2 = ((buffer[72] & 0xFF) * (buffer[74] & 0xFF) - 1) * 20;
|
||||
int exp3 = weight2[speed]; // 1-6
|
||||
int exp4 = (10 - armourClass) * 40;
|
||||
int exp5 = getBonus (35, mageSpellLevel);
|
||||
int exp6 = getBonus (35, priestSpellLevel);
|
||||
int exp10 = getBonus (200, levelDrain);
|
||||
int exp8 = getBonus (90, bonus1);
|
||||
int exp7 = weight1[bonus3 / 10] * 80;
|
||||
int exp11 = bonus2 > 0 ? exp2 + 20 : 0;
|
||||
int exp12 = getBonus (35, Integer.bitCount (resistance & 0x7E));
|
||||
int exp9 = getBonus (40, Integer.bitCount (abilities & 0x7F));
|
||||
|
||||
text.append ("ID .............. " + monsterID);
|
||||
text.append ("\nMonster name .... " + realName);
|
||||
text.append ("\nGeneric name .... " + genericName);
|
||||
|
||||
text.append ("\n\nImage ID ........ " + imageID);
|
||||
text.append ("\nGroup size ...... " + groupSize);
|
||||
text.append ("\nHit points ...... " + hitPoints);
|
||||
if (debug)
|
||||
text.append (" " + exp2);
|
||||
|
||||
text.append ("\n\nMonster class ... " + type + " " + monsterClass[type]);
|
||||
text.append ("\nArmour class .... " + armourClass);
|
||||
if (debug)
|
||||
text.append (" " + exp4);
|
||||
text.append ("\nSpeed ........... " + speed);
|
||||
if (debug)
|
||||
text.append (" " + exp3);
|
||||
|
||||
text.append ("\n\nDamage .......... " + getDamage ());
|
||||
|
||||
text.append ("\n\nLevel drain ..... " + levelDrain);
|
||||
if (debug)
|
||||
text.append (" " + exp10);
|
||||
text.append ("\nExtra hit pts? .. " + bonus1);
|
||||
if (debug)
|
||||
text.append (" " + exp8);
|
||||
|
||||
text.append ("\n\nPartner ID ...... " + partnerID);
|
||||
if (partnerOdds > 0)
|
||||
text.append (" " + monsters.get (partnerID).name);
|
||||
text.append ("\nPartner odds .... " + partnerOdds + "%");
|
||||
|
||||
text.append ("\n\nMage level ...... " + mageSpellLevel);
|
||||
if (debug)
|
||||
text.append (" " + exp5);
|
||||
text.append ("\nPriest level .... " + priestSpellLevel);
|
||||
if (debug)
|
||||
text.append (" " + exp6);
|
||||
|
||||
text.append ("\n\nExperience bonus " + bonus2);
|
||||
if (debug)
|
||||
text.append (" " + exp11);
|
||||
text.append ("\nExperience bonus " + bonus3);
|
||||
if (debug)
|
||||
text.append (" " + exp7);
|
||||
|
||||
text.append ("\n\nResistance ...... " + String.format ("%02X", resistance));
|
||||
if (debug)
|
||||
text.append (" " + exp12);
|
||||
text.append ("\nAbilities ....... " + String.format ("%02X", abilities));
|
||||
if (debug)
|
||||
text.append (" " + exp9);
|
||||
|
||||
text.append ("\n\nExperience ...... " + (exp2 + exp3 + exp4 + exp5 + exp6 + exp7
|
||||
+ exp8 + exp9 + exp10 + exp11 + exp12));
|
||||
|
||||
text.append ("\n\n===== Gold reward ======");
|
||||
// text.append ("\nTable ........... " + rewardTable1);
|
||||
text.append ("\n" + goldReward.getText (false));
|
||||
text.append ("===== Chest reward =====");
|
||||
// text.append ("\nTable ........... " + rewardTable2);
|
||||
text.append ("\n" + chestReward.getText (false));
|
||||
|
||||
while (text.charAt (text.length () - 1) == 10)
|
||||
text.deleteCharAt (text.length () - 1);
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
public int getExperience ()
|
||||
{
|
||||
// these values definitely affect the damage a monster does (when breathing?)
|
||||
int exp2 = ((buffer[72] & 0xFF) * (buffer[74] & 0xFF) - 1) * 20;
|
||||
int exp3 = weight2[speed];
|
||||
int exp4 = (10 - armourClass) * 40;
|
||||
int exp5 = getBonus (35, mageSpellLevel);
|
||||
int exp6 = getBonus (35, priestSpellLevel);
|
||||
int exp10 = getBonus (200, levelDrain);
|
||||
int exp8 = getBonus (90, bonus1);
|
||||
int exp7 = weight1[bonus3 / 10] * 80;
|
||||
int exp11 = bonus2 > 0 ? exp2 + 20 : 0;
|
||||
int exp12 = getBonus (35, Integer.bitCount (resistance & 0x7E));
|
||||
int exp9 = getBonus (40, Integer.bitCount (abilities & 0x7F));
|
||||
return exp2 + exp3 + exp4 + exp5 + exp6 + exp7 + exp8 + exp9 + exp10 + exp11 + exp12;
|
||||
}
|
||||
|
||||
private int getBonus (int base, int value)
|
||||
{
|
||||
return base * pwr[value];
|
||||
}
|
||||
|
||||
public void setImage (BufferedImage image)
|
||||
{
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName ()
|
||||
{
|
||||
return realName;
|
||||
}
|
||||
|
||||
public String getRealName ()
|
||||
{
|
||||
return realName;
|
||||
}
|
||||
|
||||
public String getDamage ()
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
for (Dice d : damage)
|
||||
text.append (d + ", ");
|
||||
text.deleteCharAt (text.length () - 1);
|
||||
text.deleteCharAt (text.length () - 1);
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
public String getDump (int block)
|
||||
{
|
||||
StringBuilder line =
|
||||
new StringBuilder (String.format ("%3d %-16s", monsterID, realName));
|
||||
int lo = block == 0 ? 64 : block == 1 ? 88 : block == 2 ? 112 : 136;
|
||||
int hi = lo + 24;
|
||||
if (hi > buffer.length)
|
||||
hi = buffer.length;
|
||||
for (int i = lo; i < hi; i++)
|
||||
line.append (String.format ("%02X ", buffer[i]));
|
||||
if (block == 3)
|
||||
{
|
||||
int exp = getExperience ();
|
||||
line.append (String.format (" %,6d", exp));
|
||||
if (exp != experience[monsterID])
|
||||
line.append (String.format (" %,6d", experience[monsterID]));
|
||||
}
|
||||
return line.toString ();
|
||||
}
|
||||
|
||||
public boolean match (int monsterID)
|
||||
{
|
||||
return this.monsterID == monsterID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo (Monster other) // where is this used?
|
||||
{
|
||||
if (this.type == other.type)
|
||||
return 0;
|
||||
if (this.type < other.type)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString ()
|
||||
{
|
||||
return realName;
|
||||
}
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class Monster extends AbstractFile implements Comparable<Monster>
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
public final String genericName;
|
||||
public final String realName;
|
||||
public final int monsterID;
|
||||
List<Monster> monsters;
|
||||
Reward goldReward;
|
||||
Reward chestReward;
|
||||
|
||||
public final int type;
|
||||
public final int imageID;
|
||||
int rewardTable1;
|
||||
int rewardTable2;
|
||||
public final int partnerID;
|
||||
public final int partnerOdds;
|
||||
public final int armourClass;
|
||||
public final int speed;
|
||||
public final int mageSpellLevel;
|
||||
public final int priestSpellLevel;
|
||||
int levelDrain;
|
||||
int bonus1;
|
||||
int bonus2;
|
||||
int bonus3;
|
||||
int resistance;
|
||||
int abilities;
|
||||
public final Dice groupSize, hitPoints;
|
||||
List<Dice> damage = new ArrayList<> ();
|
||||
|
||||
static int counter = 0;
|
||||
static boolean debug = true;
|
||||
static int[] pwr = { 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 0, 0, 0, 0, 0 };
|
||||
static int[] weight1 = { 0, 1, 2, 4, 8, 16, 32, 64, 253, 506, 0 };
|
||||
static int[] weight2 = { 0, 60, 120, 180, 300, 540, 1020, 0 };
|
||||
|
||||
public static String[] monsterClass =
|
||||
{ "Fighter", "Mage", "Priest", "Thief", "Midget", "Giant", "Mythical", "Dragon",
|
||||
"Animal", "Were", "Undead", "Demon", "Insect", "Enchanted" };
|
||||
|
||||
private static int[] experience = { 55, 235, 415, 230, 380, 620, 840, 520, 550, 350, // 00-09
|
||||
475, 515, 920, 600, 735, 520, 795, 780, 990, 795, // 10-19
|
||||
1360, 1320, 1275, 680, 960, 600, 755, 1120, 2075,
|
||||
870, // 20-29
|
||||
960, 1120, 1120, 2435, 1080, 2280, 975, 875, 1135,
|
||||
1200, // 30-39
|
||||
620, 740, 1460, 1245, 960, 1405, 1040, 1220, 1520,
|
||||
1000, // 40-49
|
||||
960, 2340, 2160, 2395, 790, 1140, 1235, 1790, 1720,
|
||||
2240, // 50-59
|
||||
1475, 1540, 1720, 1900, 1240, 1220, 1020, 20435,
|
||||
5100, 3515, // 60-69
|
||||
2115, 2920, 2060, 2140, 1400, 1640, 1280, 4450,
|
||||
42840, 3300, // 70-79
|
||||
40875, 5000, 3300, 2395, 1935, 1600, 3330, 44090,
|
||||
40840, 5200, // 80-89
|
||||
4155, 3000, 9200, 3160, 7460, 7320, 15880, 1600,
|
||||
2200, 1000, 1900 // 90-100
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
Monster (String name, byte[] buffer, List<Reward> rewards, List<Monster> monsters)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
|
||||
realName = name;
|
||||
genericName = HexFormatter.getPascalString (buffer, 0);
|
||||
this.monsterID = counter++;
|
||||
this.monsters = monsters;
|
||||
goldReward = rewards.get (buffer[136]);
|
||||
chestReward = rewards.get (buffer[138]);
|
||||
goldReward.addMonster (this, 0);
|
||||
chestReward.addMonster (this, 1);
|
||||
|
||||
imageID = buffer[64];
|
||||
type = buffer[78];
|
||||
armourClass = buffer[80];
|
||||
speed = buffer[82];
|
||||
levelDrain = buffer[132];
|
||||
bonus1 = buffer[134];
|
||||
rewardTable1 = buffer[136];
|
||||
rewardTable2 = buffer[138];
|
||||
partnerID = buffer[140];
|
||||
partnerOdds = buffer[142];
|
||||
mageSpellLevel = buffer[144];
|
||||
priestSpellLevel = buffer[146];
|
||||
bonus2 = buffer[150];
|
||||
bonus3 = buffer[152];
|
||||
resistance = buffer[154];
|
||||
abilities = buffer[156];
|
||||
groupSize = new Dice (buffer, 66);
|
||||
hitPoints = new Dice (buffer, 72);
|
||||
|
||||
for (int i = 0, ptr = 84; i < 8; i++, ptr += 6)
|
||||
{
|
||||
if (buffer[ptr] == 0)
|
||||
break;
|
||||
damage.add (new Dice (buffer, ptr));
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
// these values definitely affect the damage a monster does (when breathing?)
|
||||
int exp2 = ((buffer[72] & 0xFF) * (buffer[74] & 0xFF) - 1) * 20;
|
||||
int exp3 = weight2[speed]; // 1-6
|
||||
int exp4 = (10 - armourClass) * 40;
|
||||
int exp5 = getBonus (35, mageSpellLevel);
|
||||
int exp6 = getBonus (35, priestSpellLevel);
|
||||
int exp10 = getBonus (200, levelDrain);
|
||||
int exp8 = getBonus (90, bonus1);
|
||||
int exp7 = weight1[bonus3 / 10] * 80;
|
||||
int exp11 = bonus2 > 0 ? exp2 + 20 : 0;
|
||||
int exp12 = getBonus (35, Integer.bitCount (resistance & 0x7E));
|
||||
int exp9 = getBonus (40, Integer.bitCount (abilities & 0x7F));
|
||||
|
||||
text.append ("ID .............. " + monsterID);
|
||||
text.append ("\nMonster name .... " + realName);
|
||||
text.append ("\nGeneric name .... " + genericName);
|
||||
|
||||
text.append ("\n\nImage ID ........ " + imageID);
|
||||
text.append ("\nGroup size ...... " + groupSize);
|
||||
text.append ("\nHit points ...... " + hitPoints);
|
||||
if (debug)
|
||||
text.append (" " + exp2);
|
||||
|
||||
text.append ("\n\nMonster class ... " + type + " " + monsterClass[type]);
|
||||
text.append ("\nArmour class .... " + armourClass);
|
||||
if (debug)
|
||||
text.append (" " + exp4);
|
||||
text.append ("\nSpeed ........... " + speed);
|
||||
if (debug)
|
||||
text.append (" " + exp3);
|
||||
|
||||
text.append ("\n\nDamage .......... " + getDamage ());
|
||||
|
||||
text.append ("\n\nLevel drain ..... " + levelDrain);
|
||||
if (debug)
|
||||
text.append (" " + exp10);
|
||||
text.append ("\nExtra hit pts? .. " + bonus1);
|
||||
if (debug)
|
||||
text.append (" " + exp8);
|
||||
|
||||
text.append ("\n\nPartner ID ...... " + partnerID);
|
||||
if (partnerOdds > 0)
|
||||
text.append (" " + monsters.get (partnerID).name);
|
||||
text.append ("\nPartner odds .... " + partnerOdds + "%");
|
||||
|
||||
text.append ("\n\nMage level ...... " + mageSpellLevel);
|
||||
if (debug)
|
||||
text.append (" " + exp5);
|
||||
text.append ("\nPriest level .... " + priestSpellLevel);
|
||||
if (debug)
|
||||
text.append (" " + exp6);
|
||||
|
||||
text.append ("\n\nExperience bonus " + bonus2);
|
||||
if (debug)
|
||||
text.append (" " + exp11);
|
||||
text.append ("\nExperience bonus " + bonus3);
|
||||
if (debug)
|
||||
text.append (" " + exp7);
|
||||
|
||||
text.append ("\n\nResistance ...... " + String.format ("%02X", resistance));
|
||||
if (debug)
|
||||
text.append (" " + exp12);
|
||||
text.append ("\nAbilities ....... " + String.format ("%02X", abilities));
|
||||
if (debug)
|
||||
text.append (" " + exp9);
|
||||
|
||||
text.append ("\n\nExperience ...... " + (exp2 + exp3 + exp4 + exp5 + exp6 + exp7
|
||||
+ exp8 + exp9 + exp10 + exp11 + exp12));
|
||||
|
||||
text.append ("\n\n===== Gold reward ======");
|
||||
// text.append ("\nTable ........... " + rewardTable1);
|
||||
text.append ("\n" + goldReward.getText (false));
|
||||
text.append ("===== Chest reward =====");
|
||||
// text.append ("\nTable ........... " + rewardTable2);
|
||||
text.append ("\n" + chestReward.getText (false));
|
||||
|
||||
while (text.charAt (text.length () - 1) == 10)
|
||||
text.deleteCharAt (text.length () - 1);
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public int getExperience ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
// these values definitely affect the damage a monster does (when breathing?)
|
||||
int exp2 = ((buffer[72] & 0xFF) * (buffer[74] & 0xFF) - 1) * 20;
|
||||
int exp3 = weight2[speed];
|
||||
int exp4 = (10 - armourClass) * 40;
|
||||
int exp5 = getBonus (35, mageSpellLevel);
|
||||
int exp6 = getBonus (35, priestSpellLevel);
|
||||
int exp10 = getBonus (200, levelDrain);
|
||||
int exp8 = getBonus (90, bonus1);
|
||||
int exp7 = weight1[bonus3 / 10] * 80;
|
||||
int exp11 = bonus2 > 0 ? exp2 + 20 : 0;
|
||||
int exp12 = getBonus (35, Integer.bitCount (resistance & 0x7E));
|
||||
int exp9 = getBonus (40, Integer.bitCount (abilities & 0x7F));
|
||||
return exp2 + exp3 + exp4 + exp5 + exp6 + exp7 + exp8 + exp9 + exp10 + exp11 + exp12;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private int getBonus (int base, int value)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return base * pwr[value];
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void setImage (BufferedImage image)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getName ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return realName;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public String getRealName ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return realName;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public String getDamage ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
for (Dice d : damage)
|
||||
text.append (d + ", ");
|
||||
text.deleteCharAt (text.length () - 1);
|
||||
text.deleteCharAt (text.length () - 1);
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public String getDump (int block)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder line =
|
||||
new StringBuilder (String.format ("%3d %-16s", monsterID, realName));
|
||||
int lo = block == 0 ? 64 : block == 1 ? 88 : block == 2 ? 112 : 136;
|
||||
int hi = lo + 24;
|
||||
if (hi > buffer.length)
|
||||
hi = buffer.length;
|
||||
for (int i = lo; i < hi; i++)
|
||||
line.append (String.format ("%02X ", buffer[i]));
|
||||
if (block == 3)
|
||||
{
|
||||
int exp = getExperience ();
|
||||
line.append (String.format (" %,6d", exp));
|
||||
if (exp != experience[monsterID])
|
||||
line.append (String.format (" %,6d", experience[monsterID]));
|
||||
}
|
||||
return line.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public boolean match (int monsterID)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return this.monsterID == monsterID;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public int compareTo (Monster other) // where is this used?
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (this.type == other.type)
|
||||
return 0;
|
||||
if (this.type < other.type)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String toString ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return realName;
|
||||
}
|
||||
}
|
@ -1,18 +1,24 @@
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
class PlainMessage extends Message
|
||||
{
|
||||
public PlainMessage (byte[] buffer)
|
||||
{
|
||||
super (buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLine (int offset)
|
||||
{
|
||||
int length = buffer[offset] & 0xFF;
|
||||
return HexFormatter.getString (buffer, offset + 1, length);
|
||||
}
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class PlainMessage extends Message
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
// ---------------------------------------------------------------------------------//
|
||||
PlainMessage (byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (buffer);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
protected String getLine (int offset)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int length = buffer[offset] & 0xFF;
|
||||
return HexFormatter.getString (buffer, offset + 1, length);
|
||||
}
|
||||
}
|
@ -9,7 +9,9 @@ import com.bytezone.diskbrowser.disk.Disk;
|
||||
import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class Relocator extends AbstractFile
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private final int checkByte;
|
||||
private final List<DiskRecord> diskRecords = new ArrayList<> ();
|
||||
@ -17,7 +19,9 @@ public class Relocator extends AbstractFile
|
||||
private final int[] diskBlocks = new int[0x800];
|
||||
private final int[] diskOffsets = new int[0x800];
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public Relocator (String name, byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
|
||||
@ -37,7 +41,9 @@ public class Relocator extends AbstractFile
|
||||
addLogicalBlock ((byte) diskRecord.diskNumber, diskSegment);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void addLogicalBlock (byte disk, DiskSegment diskSegment)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int lo = diskSegment.logicalBlock;
|
||||
int hi = diskSegment.logicalBlock + diskSegment.segmentLength;
|
||||
@ -50,7 +56,9 @@ public class Relocator extends AbstractFile
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void createNewBuffer (Disk[] dataDisks)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
AppleDisk master = (AppleDisk) dataDisks[0];
|
||||
// byte[] key1 = { 0x55, 0x55, 0x15, 0x55 };
|
||||
@ -78,8 +86,10 @@ public class Relocator extends AbstractFile
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
@ -149,7 +159,9 @@ public class Relocator extends AbstractFile
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private class DiskRecord
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int diskNumber;
|
||||
int totDiskSegments;
|
||||
@ -202,7 +214,9 @@ public class Relocator extends AbstractFile
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private class DiskSegment
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int logicalBlock;
|
||||
int physicalBlock;
|
||||
|
@ -1,141 +1,155 @@
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
|
||||
class Reward extends AbstractFile
|
||||
{
|
||||
static String[] types = { "gold", "item" };
|
||||
static final int SEGMENT_LENGTH = 18;
|
||||
int id;
|
||||
int totalElements;
|
||||
List<RewardElement> elements;
|
||||
List<Item> items;
|
||||
List<Monster> goldMonsters = new ArrayList<> ();
|
||||
List<Monster> chestMonsters = new ArrayList<> ();
|
||||
|
||||
public Reward (String name, byte[] buffer, int id, List<Item> items)
|
||||
{
|
||||
super (name, buffer);
|
||||
this.id = id;
|
||||
this.items = items;
|
||||
totalElements = buffer[4];
|
||||
elements = new ArrayList<> (totalElements);
|
||||
|
||||
for (int i = 0; i < totalElements; i++)
|
||||
{
|
||||
byte[] buffer2 = new byte[SEGMENT_LENGTH];
|
||||
System.arraycopy (buffer, i * SEGMENT_LENGTH, buffer2, 0, SEGMENT_LENGTH);
|
||||
elements.add (new RewardElement (buffer2));
|
||||
}
|
||||
}
|
||||
|
||||
public void addMonster (Monster monster, int location)
|
||||
{
|
||||
if (location == 0)
|
||||
goldMonsters.add (monster);
|
||||
else
|
||||
chestMonsters.add (monster);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText ()
|
||||
{
|
||||
return getText (true);
|
||||
}
|
||||
|
||||
public String getText (boolean showLinks)
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
for (RewardElement re : elements)
|
||||
text.append (re.getDetail () + "\n");
|
||||
|
||||
if (showLinks)
|
||||
{
|
||||
if (goldMonsters.size () > 0)
|
||||
{
|
||||
text.append ("Without chest:\n\n");
|
||||
for (Monster m : goldMonsters)
|
||||
text.append (" " + m + "\n");
|
||||
text.append ("\n");
|
||||
}
|
||||
if (chestMonsters.size () > 0)
|
||||
{
|
||||
text.append ("With chest:\n\n");
|
||||
for (Monster m : chestMonsters)
|
||||
text.append (" " + m + "\n");
|
||||
}
|
||||
}
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
public String getDump ()
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
int seq = 0;
|
||||
for (RewardElement re : elements)
|
||||
{
|
||||
text.append (seq++ == 0 ? String.format ("%02X : ", id) : " ");
|
||||
text.append (re + "\n");
|
||||
}
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
private class RewardElement
|
||||
{
|
||||
int type;
|
||||
int odds;
|
||||
byte[] buffer;
|
||||
|
||||
public RewardElement (byte[] buffer)
|
||||
{
|
||||
this.buffer = buffer;
|
||||
type = buffer[8];
|
||||
odds = buffer[6];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString ()
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
for (int i = 0; i < SEGMENT_LENGTH; i += 2)
|
||||
text.append (String.format ("%3d ", buffer[i] & 0xFF));
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
public String getDetail ()
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
text.append ("Odds ............ " + odds + "%\n");
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 0:
|
||||
text.append ("Gold ............ " + buffer[10] + "d" + buffer[12] + "\n");
|
||||
break;
|
||||
case 1:
|
||||
int lo = buffer[10] & 0xFF;
|
||||
int qty = buffer[16] & 0xFF;
|
||||
boolean title = true;
|
||||
String[] lineItem = new String[4];
|
||||
for (int i = lo, max = lo + qty; i <= max; i += lineItem.length)
|
||||
{
|
||||
String lineTitle = title ? "Items ..........." : "";
|
||||
title = false;
|
||||
for (int j = 0; j < lineItem.length; j++)
|
||||
lineItem[j] = i + j <= max ? items.get (i + j).getName () : "";
|
||||
text.append (String.format ("%-17s %-16s %-16s %-16s %-16s%n", lineTitle,
|
||||
lineItem[0], lineItem[1], lineItem[2], lineItem[3]));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
System.out.println ("Unknown reward type " + type);
|
||||
}
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
}
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class Reward extends AbstractFile
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
static String[] types = { "gold", "item" };
|
||||
static final int SEGMENT_LENGTH = 18;
|
||||
int id;
|
||||
int totalElements;
|
||||
List<RewardElement> elements;
|
||||
List<Item> items;
|
||||
List<Monster> goldMonsters = new ArrayList<> ();
|
||||
List<Monster> chestMonsters = new ArrayList<> ();
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
Reward (String name, byte[] buffer, int id, List<Item> items)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
this.id = id;
|
||||
this.items = items;
|
||||
totalElements = buffer[4];
|
||||
elements = new ArrayList<> (totalElements);
|
||||
|
||||
for (int i = 0; i < totalElements; i++)
|
||||
{
|
||||
byte[] buffer2 = new byte[SEGMENT_LENGTH];
|
||||
System.arraycopy (buffer, i * SEGMENT_LENGTH, buffer2, 0, SEGMENT_LENGTH);
|
||||
elements.add (new RewardElement (buffer2));
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void addMonster (Monster monster, int location)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (location == 0)
|
||||
goldMonsters.add (monster);
|
||||
else
|
||||
chestMonsters.add (monster);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return getText (true);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public String getText (boolean showLinks)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
for (RewardElement re : elements)
|
||||
text.append (re.getDetail () + "\n");
|
||||
|
||||
if (showLinks)
|
||||
{
|
||||
if (goldMonsters.size () > 0)
|
||||
{
|
||||
text.append ("Without chest:\n\n");
|
||||
for (Monster m : goldMonsters)
|
||||
text.append (" " + m + "\n");
|
||||
text.append ("\n");
|
||||
}
|
||||
if (chestMonsters.size () > 0)
|
||||
{
|
||||
text.append ("With chest:\n\n");
|
||||
for (Monster m : chestMonsters)
|
||||
text.append (" " + m + "\n");
|
||||
}
|
||||
}
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public String getDump ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
int seq = 0;
|
||||
for (RewardElement re : elements)
|
||||
{
|
||||
text.append (seq++ == 0 ? String.format ("%02X : ", id) : " ");
|
||||
text.append (re + "\n");
|
||||
}
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private class RewardElement
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int type;
|
||||
int odds;
|
||||
byte[] buffer;
|
||||
|
||||
public RewardElement (byte[] buffer)
|
||||
{
|
||||
this.buffer = buffer;
|
||||
type = buffer[8];
|
||||
odds = buffer[6];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString ()
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
for (int i = 0; i < SEGMENT_LENGTH; i += 2)
|
||||
text.append (String.format ("%3d ", buffer[i] & 0xFF));
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
public String getDetail ()
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
text.append ("Odds ............ " + odds + "%\n");
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 0:
|
||||
text.append ("Gold ............ " + buffer[10] + "d" + buffer[12] + "\n");
|
||||
break;
|
||||
case 1:
|
||||
int lo = buffer[10] & 0xFF;
|
||||
int qty = buffer[16] & 0xFF;
|
||||
boolean title = true;
|
||||
String[] lineItem = new String[4];
|
||||
for (int i = lo, max = lo + qty; i <= max; i += lineItem.length)
|
||||
{
|
||||
String lineTitle = title ? "Items ..........." : "";
|
||||
title = false;
|
||||
for (int j = 0; j < lineItem.length; j++)
|
||||
lineItem[j] = i + j <= max ? items.get (i + j).getName () : "";
|
||||
text.append (String.format ("%-17s %-16s %-16s %-16s %-16s%n", lineTitle,
|
||||
lineItem[0], lineItem[1], lineItem[2], lineItem[3]));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
System.out.println ("Unknown reward type " + type);
|
||||
}
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,369 +1,408 @@
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
|
||||
class Spell extends AbstractFile
|
||||
{
|
||||
private final SpellType spellType;
|
||||
private SpellThrown whenCast;
|
||||
private final int level;
|
||||
private String translation;
|
||||
private SpellTarget target;
|
||||
private String description;
|
||||
|
||||
public enum SpellType {
|
||||
MAGE, PRIEST
|
||||
};
|
||||
|
||||
public enum SpellTarget {
|
||||
PERSON, PARTY, MONSTER, MONSTER_GROUP, ALL_MONSTERS, VARIABLE, NONE, CASTER
|
||||
};
|
||||
|
||||
public enum SpellThrown {
|
||||
COMBAT, ANY_TIME, LOOTING, CAMP, COMBAT_OR_CAMP
|
||||
};
|
||||
|
||||
private static int lastSpellFound = -1;
|
||||
|
||||
private Spell (String spellName, SpellType type, int level, byte[] buffer)
|
||||
{
|
||||
super (spellName, buffer);
|
||||
this.spellType = type;
|
||||
this.level = level;
|
||||
|
||||
if (lastSpellFound + 1 < spellNames.length && spellName.equals (spellNames[lastSpellFound + 1]))
|
||||
setSpell (++lastSpellFound);
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < spellNames.length; i++)
|
||||
if (spellName.equals (spellNames[i]))
|
||||
{
|
||||
setSpell (i);
|
||||
lastSpellFound = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setSpell (int spellNo)
|
||||
{
|
||||
this.translation = translations[spellNo];
|
||||
this.description = descriptions[spellNo];
|
||||
this.whenCast = when[spellNo];
|
||||
this.target = affects[spellNo];
|
||||
}
|
||||
|
||||
public static Spell getSpell (String spellName, SpellType type, int level, byte[] buffer)
|
||||
{
|
||||
return new Spell (spellName, type, level, buffer);
|
||||
}
|
||||
|
||||
public String getName ()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public SpellType getType ()
|
||||
{
|
||||
return spellType;
|
||||
}
|
||||
|
||||
public int getLevel ()
|
||||
{
|
||||
return level;
|
||||
}
|
||||
|
||||
public String getTranslation ()
|
||||
{
|
||||
return translation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText ()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getWhenCast ()
|
||||
{
|
||||
switch (whenCast)
|
||||
{
|
||||
case COMBAT:
|
||||
return "Combat";
|
||||
case LOOTING:
|
||||
return "Looting";
|
||||
case ANY_TIME:
|
||||
return "Any time";
|
||||
case CAMP:
|
||||
return "Camp";
|
||||
case COMBAT_OR_CAMP:
|
||||
return "Combat or camp";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String getArea ()
|
||||
{
|
||||
switch (target)
|
||||
{
|
||||
case PERSON:
|
||||
return "1 Person";
|
||||
case PARTY:
|
||||
return "Entire party";
|
||||
case MONSTER:
|
||||
return "1 Monster";
|
||||
case MONSTER_GROUP:
|
||||
return "1 Monster group";
|
||||
case ALL_MONSTERS:
|
||||
return "All monsters";
|
||||
case VARIABLE:
|
||||
return "Variable";
|
||||
case NONE:
|
||||
return "None";
|
||||
case CASTER:
|
||||
return "Caster";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String toHTMLTable ()
|
||||
{
|
||||
StringBuilder text = new StringBuilder ("<table border=\"1\"");
|
||||
text.append (" width=\"100%\">\n");
|
||||
|
||||
text.append (" <tr>\n <td width=\"110\">Spell name</td>\n");
|
||||
text.append (" <td>" + name + "</td>\n </tr>\n");
|
||||
|
||||
text.append (" <tr>\n <td>Translation</td>\n");
|
||||
text.append (" <td>" + translation + "</td>\n </tr>\n");
|
||||
|
||||
text.append (" <tr>\n <td>Spell level</td>\n");
|
||||
text.append (" <td>" + level + "</td>\n </tr>\n");
|
||||
|
||||
text.append (" <tr>\n <td>Spell type</td>\n");
|
||||
text.append (" <td>" + getWhenCast () + "</td>\n </tr>\n");
|
||||
|
||||
text.append (" <tr>\n <td>Area of effect</td>\n");
|
||||
text.append (" <td>" + getArea () + "</td>\n </tr>\n");
|
||||
|
||||
text.append (" <tr>\n <td>Description</td>\n");
|
||||
text.append (" <td>" + getText () + "</td>\n </tr>\n");
|
||||
|
||||
text.append ("</table>");
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString ()
|
||||
{
|
||||
StringBuilder text = new StringBuilder (name);
|
||||
while (text.length () < 14)
|
||||
text.append (" ");
|
||||
if (spellType == SpellType.PRIEST)
|
||||
text.append ("P");
|
||||
else
|
||||
text.append ("M");
|
||||
text.append (level);
|
||||
while (text.length () < 20)
|
||||
text.append (" ");
|
||||
text.append (translation);
|
||||
while (text.length () < 40)
|
||||
text.append (" ");
|
||||
text.append (getArea ());
|
||||
while (text.length () < 60)
|
||||
text.append (" ");
|
||||
text.append (getWhenCast ());
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
private static String[] spellNames =
|
||||
{ "KALKI", "DIOS", "BADIOS", "MILWA", "PORFIC", "MATU", "CALFO", "MANIFO", "MONTINO",
|
||||
"LOMILWA", "DIALKO", "LATUMAPIC", "BAMATU", "DIAL", "BADIAL", "LATUMOFIS", "MAPORFIC",
|
||||
"DIALMA", "BADIALMA", "LITOKAN", "KANDI", "DI", "BADI", "LORTO", "MADI", "MABADI",
|
||||
"LOKTOFEIT", "MALIKTO", "KADORTO",
|
||||
|
||||
"HALITO", "MOGREF", "KATINO", "DUMAPIC", "DILTO", "SOPIC", "MAHALITO", "MOLITO",
|
||||
"MORLIS", "DALTO", "LAHALITO", "MAMORLIS", "MAKANITO", "MADALTO", "LAKANITO", "ZILWAN",
|
||||
"MASOPIC", "HAMAN", "MALOR", "MAHAMAN", "TILTOWAIT" };
|
||||
|
||||
private static String[] translations =
|
||||
{ "Blessings", "Heal", "Harm", "Light", "Shield", "Blessing & zeal", "X-ray vision",
|
||||
"Statue", "Still air", "More light", "Softness/supple", "Identification", "Prayer",
|
||||
"Heal (more)", "Hurt (more)", "Cure poison", "Shield (big)", "Heal (greatly)",
|
||||
"Hurt (greatly)", "Flame tower", "Location", "Life", "Death", "Blades", "Healing",
|
||||
"Harm (incredibly)", "Recall", "The Word of Death", "Resurrection",
|
||||
|
||||
"Little Fire", "Body Iron", "Bad Air", "Clarity", "Darkness", "Glass", "Big fire",
|
||||
"Spark storm", "Fear", "Blizzard blast", "Flame storm", "Terror", "Deadly air", "Frost",
|
||||
"Suffocation", "Dispell", "Big glass", "Change", "Apport", "Great change",
|
||||
"(untranslatable)" };
|
||||
|
||||
private static SpellThrown[] when =
|
||||
{ SpellThrown.COMBAT, SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.ANY_TIME,
|
||||
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.LOOTING, SpellThrown.COMBAT,
|
||||
SpellThrown.COMBAT, SpellThrown.ANY_TIME, SpellThrown.ANY_TIME, SpellThrown.COMBAT,
|
||||
SpellThrown.COMBAT, SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.ANY_TIME,
|
||||
SpellThrown.ANY_TIME, SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.COMBAT,
|
||||
SpellThrown.CAMP, SpellThrown.CAMP, SpellThrown.COMBAT, SpellThrown.COMBAT,
|
||||
SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT,
|
||||
SpellThrown.ANY_TIME,
|
||||
|
||||
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.CAMP,
|
||||
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT,
|
||||
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT,
|
||||
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT,
|
||||
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT_OR_CAMP, SpellThrown.COMBAT,
|
||||
SpellThrown.COMBAT, };
|
||||
|
||||
private static SpellTarget[] affects =
|
||||
{ SpellTarget.PARTY, SpellTarget.PERSON, SpellTarget.MONSTER, SpellTarget.PARTY,
|
||||
SpellTarget.CASTER, SpellTarget.PARTY, SpellTarget.CASTER, SpellTarget.MONSTER_GROUP,
|
||||
SpellTarget.MONSTER_GROUP, SpellTarget.PARTY, SpellTarget.PERSON, SpellTarget.PARTY,
|
||||
SpellTarget.PARTY, SpellTarget.PERSON, SpellTarget.MONSTER, SpellTarget.PERSON,
|
||||
SpellTarget.PARTY, SpellTarget.PERSON, SpellTarget.MONSTER, SpellTarget.PARTY,
|
||||
SpellTarget.PERSON, SpellTarget.PERSON, SpellTarget.MONSTER, SpellTarget.MONSTER_GROUP,
|
||||
SpellTarget.PERSON, SpellTarget.MONSTER, SpellTarget.PARTY, SpellTarget.MONSTER_GROUP,
|
||||
SpellTarget.PERSON,
|
||||
|
||||
SpellTarget.MONSTER, SpellTarget.CASTER, SpellTarget.MONSTER_GROUP, SpellTarget.NONE,
|
||||
SpellTarget.MONSTER_GROUP, SpellTarget.CASTER, SpellTarget.MONSTER_GROUP,
|
||||
SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP,
|
||||
SpellTarget.MONSTER_GROUP, SpellTarget.ALL_MONSTERS, SpellTarget.ALL_MONSTERS,
|
||||
SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER,
|
||||
SpellTarget.PARTY, SpellTarget.VARIABLE, SpellTarget.PARTY, SpellTarget.PARTY,
|
||||
SpellTarget.ALL_MONSTERS };
|
||||
|
||||
private static String[] descriptions =
|
||||
{
|
||||
"KALKI reduces the AC of all party members by one, and thus makes"
|
||||
+ " them harder to hit.",
|
||||
"DIOS restores from one to eight hit points of damage from a party"
|
||||
+ "member. It will not bring dead back to life.",
|
||||
"BADIOS causes one to eight hit points of damage to a monster, and"
|
||||
+ " may kill it. It is the reverse of dios. Note the BA prefix which"
|
||||
+ " means 'not'.",
|
||||
"MILWA causes a softly glowing light to follow the party, allowing"
|
||||
+ " them to see further into the maze, and also revealing all secret"
|
||||
+ " doors. See also LOMILWA. This spell lasts only a short while.",
|
||||
"PORFIC lowers the AC of the caster considerably. The effects last"
|
||||
+ " for the duration of combat.",
|
||||
"MATU has the same effects as KALKI, but at double the strength.",
|
||||
"CALFO allows the caster to determine the exact nature of a trap"
|
||||
+ " on a chest 95% of the time.",
|
||||
"MANIFO causes some of the monsters in a group to become stiff as"
|
||||
+ " statues for one or more melee rounds. The chance of success,"
|
||||
+ " and the duration of the effects, depend on the power of the"
|
||||
+ " target monsters.",
|
||||
"MONTINO causes the air around a group of monsters to stop"
|
||||
+ " transmitting sound. Like MANIFO, only some of the monsters will"
|
||||
+ " be affected, and for varying lengths of time. Monsters and"
|
||||
+ " Party members under the influence of this spell cannot cast"
|
||||
+ " spells, as they cannot utter the spell words!",
|
||||
"LOMILWA is a MILWA spell with a much longer life span. Note that"
|
||||
+ " when this spell, or MILWA are active, the Q option while"
|
||||
+ " moving through the maze is active. If Q)UICK PLOTTING is on,"
|
||||
+ " only the square you are in, and the next two squares, will"
|
||||
+ " plot. Normally you might see five or six squares ahead with"
|
||||
+ " LOMILWA on. Quick Plotting lets you move fast through known"
|
||||
+ " areas. Note that it will be turned off when you enter camp or"
|
||||
+ " combat mode.",
|
||||
"DIALKO cures paralysis, and removes the effects of MANIFO and"
|
||||
+ " KATINO from one member of the party.",
|
||||
"LATUMAPIC makes it readily apparent exactly what the opposing" + " monsters really are.",
|
||||
"BAMATU has the effects of MATU at twice the effectiveness.",
|
||||
"DIAL restores two to 16 hit points of damage, and is similar to" + " DIOS.",
|
||||
"BADIAL causes two to 16 hit points of damage in the same way as" + " BADIOS.",
|
||||
"LATUMOFIS makes a poisoned person whole and fit again. Note that"
|
||||
+ " poison causes a person to lose hit points steadily during"
|
||||
+ " movement and combat.",
|
||||
"MAPORFIC is an improved PORFIC, with effects that last for the" + " entire expedition.",
|
||||
"DIALMA restores three to 24 hit points.",
|
||||
"BADIALMA causes three to 24 hit points of damage.",
|
||||
"LITOKAN causes a pillar of flame to strike a group of monsters,"
|
||||
+ " doing three to 24 hits of damage to each. However, as with"
|
||||
+ " many spells that affect entire groups, there is a chance that"
|
||||
+ " individual monsters will be able to avoid or minimise its"
|
||||
+ " effects. And some monsters will be resistant to it.",
|
||||
"KANDI allows the user to locate characters in the maze. It tells on"
|
||||
+ " which level, and in which rough area the dead one can be found.",
|
||||
"DI causes a dead person to be resurrected. However, the renewed"
|
||||
+ " character has but one hit point. Also, this spell is not as"
|
||||
+ " effective or as safe as using the Temple.",
|
||||
"BADI gives the affected monster a coronary attack. It may or may"
|
||||
+ " not cause death to occur.",
|
||||
"LORTO causes sharp blades to slice through a group, causing six to"
|
||||
+ " 36 points of damage.",
|
||||
"MADI causes all hit points to be restored and cures any condition" + " but death.",
|
||||
"MABADI causes all but one to eight hit points to be removed from" + " the target.",
|
||||
"LOKTOFEIT causes all party members to be teleported back to the"
|
||||
+ " castle, minus all their equipment and most of their gold. There"
|
||||
+ " is also a good chance this spell will not function.",
|
||||
"MALIKTO causes 12 to 72 hit points of damage to all monsters. None"
|
||||
+ " can escape or minimise its effects.",
|
||||
"KADORTO restores the dead to life as does DI, but also restores all"
|
||||
+ " hit points. However, it has the same drawbacks as the DI spell."
|
||||
+ " KADORTO can be used to resurrect people even if they are ashes.",
|
||||
|
||||
"HALITO causes a flame ball the size of a baseball to hit a monster,"
|
||||
+ " doing from one to eight points of damage.",
|
||||
"MOGREF reduces the caster's AC by two. The effect lasts the entire" + " encounter.",
|
||||
"KATINO causes most of the monsters in a group to fall asleep."
|
||||
+ " Katino only effects normal, animal or humanoid monsters. The"
|
||||
+ " chance of the spell affecting an individual monster, and the"
|
||||
+ " duration of the effect, is inversely proportional to the power"
|
||||
+ " of the monster. While asleep, monsters are easier to hit and"
|
||||
+ " successful strikes do double damage.",
|
||||
"DUMAPIC informs you of the party's exact displacement from the"
|
||||
+ " stairs to the castle, vertically, and North and East, and also"
|
||||
+ " tells you what direction you are facing.",
|
||||
|
||||
"DILTO causes one group of monsters to be enveloped in darkness,"
|
||||
+ " which reduces their ability to defend against your attacks.",
|
||||
"SOPIC causes the caster to become transparent. This means that"
|
||||
+ " he is harder to see, and thus his AC is reduced by four.",
|
||||
|
||||
"MAHALITO causes a fiery explosion in a monster group, doing four"
|
||||
+ " to 24 hit points of damage. As with other similar spells,"
|
||||
+ " monsters may be able to minimise the damage done.",
|
||||
"MOLITO causes sparks to fly out and damage about half of the"
|
||||
+ " monsters in a group. Three to 18 hit points of damage are done"
|
||||
+ " with no chance of avoiding the sparks.",
|
||||
"MORLIS causes one group of monsters to fear the party greatly. The"
|
||||
+ " effects are the same as a double strength DILTO spell.",
|
||||
"DALTO is similar to MAHALITO except that cold replaces flames."
|
||||
+ " Also, six to 36 hit points of damage are done.",
|
||||
"LAHALITO is an improved MAHALITO, doing the same damage as DALTO.",
|
||||
"MAMORLIS is similar to MORLIS, except that all monster groups are" + " affected.",
|
||||
"Any monsters of less than eigth level (i.e. about 35-40 hit points)"
|
||||
+ " are killed by this spell outright.",
|
||||
"An improved DALTO causing eight to 64 hit points of damage.",
|
||||
"All monsters in the group affected by this spell die. Of course,"
|
||||
+ " there is a chance that some of the monsters will not be affected.",
|
||||
"This spell will destroy any one monster that is of the Undead" + " variety",
|
||||
"This spell duplicates the effects of SOPIC for the entire party.",
|
||||
"This spell is indeed terrible, and may backfire on the caster."
|
||||
+ " First, to even cast it, you must be of the thirteenth level or"
|
||||
+ " higher, and casting it will cost you one level of experience."
|
||||
+ " The effects of HAMAN are random, and usually help the party.",
|
||||
"This spell's effects depend on the situation the party is in when it"
|
||||
+ " is cast.Basically, MALOR will teleport the entire party from one"
|
||||
+ " location to another. When used in melee, the teleport is random,"
|
||||
+ " but when used in camp, where there is more chance for concentration"
|
||||
+ ", it can be used to move the party anywhere in the maze. Be warned,"
|
||||
+ " however, that if you teleport outside of the maze, or into an"
|
||||
+ " area that is solid rock, you will be lost forever, so this spell"
|
||||
+ " is to be used with the greatest of care. Combat use of MALOR will"
|
||||
+ " never put you outside of the maze, but it may move you deeper in,"
|
||||
+ " so it should be used only in panic situations.",
|
||||
"The same restrictions and qualifications apply to this spell as do"
|
||||
+ " to HAMAN. However, the effects are even greater. Generally these"
|
||||
+ " spells are only used when there is no other hope for survival.",
|
||||
"The effect of this spell can be described as similar to that of a"
|
||||
+ " nuclear fusion explosion. Luckily the party is shielded from its"
|
||||
+ " effects. Unluckily (for them) the monsters are not. This spell"
|
||||
+ " will do from 10-100 hit points of damage." };
|
||||
package com.bytezone.diskbrowser.wizardry;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class Spell extends AbstractFile
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private final SpellType spellType;
|
||||
private SpellThrown whenCast;
|
||||
private final int level;
|
||||
private String translation;
|
||||
private SpellTarget target;
|
||||
private String description;
|
||||
|
||||
public enum SpellType
|
||||
{
|
||||
MAGE, PRIEST
|
||||
};
|
||||
|
||||
public enum SpellTarget
|
||||
{
|
||||
PERSON, PARTY, MONSTER, MONSTER_GROUP, ALL_MONSTERS, VARIABLE, NONE, CASTER
|
||||
};
|
||||
|
||||
public enum SpellThrown
|
||||
{
|
||||
COMBAT, ANY_TIME, LOOTING, CAMP, COMBAT_OR_CAMP
|
||||
};
|
||||
|
||||
private static int lastSpellFound = -1;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private Spell (String spellName, SpellType type, int level, byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (spellName, buffer);
|
||||
this.spellType = type;
|
||||
this.level = level;
|
||||
|
||||
if (lastSpellFound + 1 < spellNames.length
|
||||
&& spellName.equals (spellNames[lastSpellFound + 1]))
|
||||
setSpell (++lastSpellFound);
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < spellNames.length; i++)
|
||||
if (spellName.equals (spellNames[i]))
|
||||
{
|
||||
setSpell (i);
|
||||
lastSpellFound = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void setSpell (int spellNo)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.translation = translations[spellNo];
|
||||
this.description = descriptions[spellNo];
|
||||
this.whenCast = when[spellNo];
|
||||
this.target = affects[spellNo];
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public static Spell getSpell (String spellName, SpellType type, int level,
|
||||
byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return new Spell (spellName, type, level, buffer);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getName ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public SpellType getType ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return spellType;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public int getLevel ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return level;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public String getTranslation ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return translation;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public String getWhenCast ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
switch (whenCast)
|
||||
{
|
||||
case COMBAT:
|
||||
return "Combat";
|
||||
case LOOTING:
|
||||
return "Looting";
|
||||
case ANY_TIME:
|
||||
return "Any time";
|
||||
case CAMP:
|
||||
return "Camp";
|
||||
case COMBAT_OR_CAMP:
|
||||
return "Combat or camp";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public String getArea ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
switch (target)
|
||||
{
|
||||
case PERSON:
|
||||
return "1 Person";
|
||||
case PARTY:
|
||||
return "Entire party";
|
||||
case MONSTER:
|
||||
return "1 Monster";
|
||||
case MONSTER_GROUP:
|
||||
return "1 Monster group";
|
||||
case ALL_MONSTERS:
|
||||
return "All monsters";
|
||||
case VARIABLE:
|
||||
return "Variable";
|
||||
case NONE:
|
||||
return "None";
|
||||
case CASTER:
|
||||
return "Caster";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public String toHTMLTable ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder ("<table border=\"1\"");
|
||||
text.append (" width=\"100%\">\n");
|
||||
|
||||
text.append (" <tr>\n <td width=\"110\">Spell name</td>\n");
|
||||
text.append (" <td>" + name + "</td>\n </tr>\n");
|
||||
|
||||
text.append (" <tr>\n <td>Translation</td>\n");
|
||||
text.append (" <td>" + translation + "</td>\n </tr>\n");
|
||||
|
||||
text.append (" <tr>\n <td>Spell level</td>\n");
|
||||
text.append (" <td>" + level + "</td>\n </tr>\n");
|
||||
|
||||
text.append (" <tr>\n <td>Spell type</td>\n");
|
||||
text.append (" <td>" + getWhenCast () + "</td>\n </tr>\n");
|
||||
|
||||
text.append (" <tr>\n <td>Area of effect</td>\n");
|
||||
text.append (" <td>" + getArea () + "</td>\n </tr>\n");
|
||||
|
||||
text.append (" <tr>\n <td>Description</td>\n");
|
||||
text.append (" <td>" + getText () + "</td>\n </tr>\n");
|
||||
|
||||
text.append ("</table>");
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String toString ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder (name);
|
||||
while (text.length () < 14)
|
||||
text.append (" ");
|
||||
if (spellType == SpellType.PRIEST)
|
||||
text.append ("P");
|
||||
else
|
||||
text.append ("M");
|
||||
text.append (level);
|
||||
while (text.length () < 20)
|
||||
text.append (" ");
|
||||
text.append (translation);
|
||||
while (text.length () < 40)
|
||||
text.append (" ");
|
||||
text.append (getArea ());
|
||||
while (text.length () < 60)
|
||||
text.append (" ");
|
||||
text.append (getWhenCast ());
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
private static String[] spellNames =
|
||||
{ "KALKI", "DIOS", "BADIOS", "MILWA", "PORFIC", "MATU", "CALFO", "MANIFO",
|
||||
"MONTINO", "LOMILWA", "DIALKO", "LATUMAPIC", "BAMATU", "DIAL", "BADIAL",
|
||||
"LATUMOFIS", "MAPORFIC", "DIALMA", "BADIALMA", "LITOKAN", "KANDI", "DI", "BADI",
|
||||
"LORTO", "MADI", "MABADI", "LOKTOFEIT", "MALIKTO", "KADORTO",
|
||||
|
||||
"HALITO", "MOGREF", "KATINO", "DUMAPIC", "DILTO", "SOPIC", "MAHALITO", "MOLITO",
|
||||
"MORLIS", "DALTO", "LAHALITO", "MAMORLIS", "MAKANITO", "MADALTO", "LAKANITO",
|
||||
"ZILWAN", "MASOPIC", "HAMAN", "MALOR", "MAHAMAN", "TILTOWAIT" };
|
||||
|
||||
private static String[] translations =
|
||||
{ "Blessings", "Heal", "Harm", "Light", "Shield", "Blessing & zeal", "X-ray vision",
|
||||
"Statue", "Still air", "More light", "Softness/supple", "Identification",
|
||||
"Prayer", "Heal (more)", "Hurt (more)", "Cure poison", "Shield (big)",
|
||||
"Heal (greatly)", "Hurt (greatly)", "Flame tower", "Location", "Life", "Death",
|
||||
"Blades", "Healing", "Harm (incredibly)", "Recall", "The Word of Death",
|
||||
"Resurrection",
|
||||
|
||||
"Little Fire", "Body Iron", "Bad Air", "Clarity", "Darkness", "Glass", "Big fire",
|
||||
"Spark storm", "Fear", "Blizzard blast", "Flame storm", "Terror", "Deadly air",
|
||||
"Frost", "Suffocation", "Dispell", "Big glass", "Change", "Apport",
|
||||
"Great change", "(untranslatable)" };
|
||||
|
||||
private static SpellThrown[] when =
|
||||
{ SpellThrown.COMBAT, SpellThrown.ANY_TIME, SpellThrown.COMBAT,
|
||||
SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.LOOTING,
|
||||
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.ANY_TIME,
|
||||
SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.COMBAT,
|
||||
SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.ANY_TIME,
|
||||
SpellThrown.ANY_TIME, SpellThrown.ANY_TIME, SpellThrown.COMBAT,
|
||||
SpellThrown.COMBAT, SpellThrown.CAMP, SpellThrown.CAMP, SpellThrown.COMBAT,
|
||||
SpellThrown.COMBAT, SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.COMBAT,
|
||||
SpellThrown.COMBAT, SpellThrown.ANY_TIME,
|
||||
|
||||
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.CAMP,
|
||||
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT,
|
||||
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT,
|
||||
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT,
|
||||
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT_OR_CAMP,
|
||||
SpellThrown.COMBAT, SpellThrown.COMBAT, };
|
||||
|
||||
private static SpellTarget[] affects =
|
||||
{ SpellTarget.PARTY, SpellTarget.PERSON, SpellTarget.MONSTER, SpellTarget.PARTY,
|
||||
SpellTarget.CASTER, SpellTarget.PARTY, SpellTarget.CASTER,
|
||||
SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP, SpellTarget.PARTY,
|
||||
SpellTarget.PERSON, SpellTarget.PARTY, SpellTarget.PARTY, SpellTarget.PERSON,
|
||||
SpellTarget.MONSTER, SpellTarget.PERSON, SpellTarget.PARTY, SpellTarget.PERSON,
|
||||
SpellTarget.MONSTER, SpellTarget.PARTY, SpellTarget.PERSON, SpellTarget.PERSON,
|
||||
SpellTarget.MONSTER, SpellTarget.MONSTER_GROUP, SpellTarget.PERSON,
|
||||
SpellTarget.MONSTER, SpellTarget.PARTY, SpellTarget.MONSTER_GROUP,
|
||||
SpellTarget.PERSON,
|
||||
|
||||
SpellTarget.MONSTER, SpellTarget.CASTER, SpellTarget.MONSTER_GROUP,
|
||||
SpellTarget.NONE, SpellTarget.MONSTER_GROUP, SpellTarget.CASTER,
|
||||
SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP,
|
||||
SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP, SpellTarget.ALL_MONSTERS,
|
||||
SpellTarget.ALL_MONSTERS, SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP,
|
||||
SpellTarget.MONSTER, SpellTarget.PARTY, SpellTarget.VARIABLE, SpellTarget.PARTY,
|
||||
SpellTarget.PARTY, SpellTarget.ALL_MONSTERS };
|
||||
|
||||
private static String[] descriptions =
|
||||
{ "KALKI reduces the AC of all party members by one, and thus makes"
|
||||
+ " them harder to hit.",
|
||||
"DIOS restores from one to eight hit points of damage from a party"
|
||||
+ "member. It will not bring dead back to life.",
|
||||
"BADIOS causes one to eight hit points of damage to a monster, and"
|
||||
+ " may kill it. It is the reverse of dios. Note the BA prefix which"
|
||||
+ " means 'not'.",
|
||||
"MILWA causes a softly glowing light to follow the party, allowing"
|
||||
+ " them to see further into the maze, and also revealing all secret"
|
||||
+ " doors. See also LOMILWA. This spell lasts only a short while.",
|
||||
"PORFIC lowers the AC of the caster considerably. The effects last"
|
||||
+ " for the duration of combat.",
|
||||
"MATU has the same effects as KALKI, but at double the strength.",
|
||||
"CALFO allows the caster to determine the exact nature of a trap"
|
||||
+ " on a chest 95% of the time.",
|
||||
"MANIFO causes some of the monsters in a group to become stiff as"
|
||||
+ " statues for one or more melee rounds. The chance of success,"
|
||||
+ " and the duration of the effects, depend on the power of the"
|
||||
+ " target monsters.",
|
||||
"MONTINO causes the air around a group of monsters to stop"
|
||||
+ " transmitting sound. Like MANIFO, only some of the monsters will"
|
||||
+ " be affected, and for varying lengths of time. Monsters and"
|
||||
+ " Party members under the influence of this spell cannot cast"
|
||||
+ " spells, as they cannot utter the spell words!",
|
||||
"LOMILWA is a MILWA spell with a much longer life span. Note that"
|
||||
+ " when this spell, or MILWA are active, the Q option while"
|
||||
+ " moving through the maze is active. If Q)UICK PLOTTING is on,"
|
||||
+ " only the square you are in, and the next two squares, will"
|
||||
+ " plot. Normally you might see five or six squares ahead with"
|
||||
+ " LOMILWA on. Quick Plotting lets you move fast through known"
|
||||
+ " areas. Note that it will be turned off when you enter camp or"
|
||||
+ " combat mode.",
|
||||
"DIALKO cures paralysis, and removes the effects of MANIFO and"
|
||||
+ " KATINO from one member of the party.",
|
||||
"LATUMAPIC makes it readily apparent exactly what the opposing"
|
||||
+ " monsters really are.",
|
||||
"BAMATU has the effects of MATU at twice the effectiveness.",
|
||||
"DIAL restores two to 16 hit points of damage, and is similar to" + " DIOS.",
|
||||
"BADIAL causes two to 16 hit points of damage in the same way as" + " BADIOS.",
|
||||
"LATUMOFIS makes a poisoned person whole and fit again. Note that"
|
||||
+ " poison causes a person to lose hit points steadily during"
|
||||
+ " movement and combat.",
|
||||
"MAPORFIC is an improved PORFIC, with effects that last for the"
|
||||
+ " entire expedition.",
|
||||
"DIALMA restores three to 24 hit points.",
|
||||
"BADIALMA causes three to 24 hit points of damage.",
|
||||
"LITOKAN causes a pillar of flame to strike a group of monsters,"
|
||||
+ " doing three to 24 hits of damage to each. However, as with"
|
||||
+ " many spells that affect entire groups, there is a chance that"
|
||||
+ " individual monsters will be able to avoid or minimise its"
|
||||
+ " effects. And some monsters will be resistant to it.",
|
||||
"KANDI allows the user to locate characters in the maze. It tells on"
|
||||
+ " which level, and in which rough area the dead one can be found.",
|
||||
"DI causes a dead person to be resurrected. However, the renewed"
|
||||
+ " character has but one hit point. Also, this spell is not as"
|
||||
+ " effective or as safe as using the Temple.",
|
||||
"BADI gives the affected monster a coronary attack. It may or may"
|
||||
+ " not cause death to occur.",
|
||||
"LORTO causes sharp blades to slice through a group, causing six to"
|
||||
+ " 36 points of damage.",
|
||||
"MADI causes all hit points to be restored and cures any condition"
|
||||
+ " but death.",
|
||||
"MABADI causes all but one to eight hit points to be removed from"
|
||||
+ " the target.",
|
||||
"LOKTOFEIT causes all party members to be teleported back to the"
|
||||
+ " castle, minus all their equipment and most of their gold. There"
|
||||
+ " is also a good chance this spell will not function.",
|
||||
"MALIKTO causes 12 to 72 hit points of damage to all monsters. None"
|
||||
+ " can escape or minimise its effects.",
|
||||
"KADORTO restores the dead to life as does DI, but also restores all"
|
||||
+ " hit points. However, it has the same drawbacks as the DI spell."
|
||||
+ " KADORTO can be used to resurrect people even if they are ashes.",
|
||||
|
||||
"HALITO causes a flame ball the size of a baseball to hit a monster,"
|
||||
+ " doing from one to eight points of damage.",
|
||||
"MOGREF reduces the caster's AC by two. The effect lasts the entire"
|
||||
+ " encounter.",
|
||||
"KATINO causes most of the monsters in a group to fall asleep."
|
||||
+ " Katino only effects normal, animal or humanoid monsters. The"
|
||||
+ " chance of the spell affecting an individual monster, and the"
|
||||
+ " duration of the effect, is inversely proportional to the power"
|
||||
+ " of the monster. While asleep, monsters are easier to hit and"
|
||||
+ " successful strikes do double damage.",
|
||||
"DUMAPIC informs you of the party's exact displacement from the"
|
||||
+ " stairs to the castle, vertically, and North and East, and also"
|
||||
+ " tells you what direction you are facing.",
|
||||
|
||||
"DILTO causes one group of monsters to be enveloped in darkness,"
|
||||
+ " which reduces their ability to defend against your attacks.",
|
||||
"SOPIC causes the caster to become transparent. This means that"
|
||||
+ " he is harder to see, and thus his AC is reduced by four.",
|
||||
|
||||
"MAHALITO causes a fiery explosion in a monster group, doing four"
|
||||
+ " to 24 hit points of damage. As with other similar spells,"
|
||||
+ " monsters may be able to minimise the damage done.",
|
||||
"MOLITO causes sparks to fly out and damage about half of the"
|
||||
+ " monsters in a group. Three to 18 hit points of damage are done"
|
||||
+ " with no chance of avoiding the sparks.",
|
||||
"MORLIS causes one group of monsters to fear the party greatly. The"
|
||||
+ " effects are the same as a double strength DILTO spell.",
|
||||
"DALTO is similar to MAHALITO except that cold replaces flames."
|
||||
+ " Also, six to 36 hit points of damage are done.",
|
||||
"LAHALITO is an improved MAHALITO, doing the same damage as DALTO.",
|
||||
"MAMORLIS is similar to MORLIS, except that all monster groups are"
|
||||
+ " affected.",
|
||||
"Any monsters of less than eigth level (i.e. about 35-40 hit points)"
|
||||
+ " are killed by this spell outright.",
|
||||
"An improved DALTO causing eight to 64 hit points of damage.",
|
||||
"All monsters in the group affected by this spell die. Of course,"
|
||||
+ " there is a chance that some of the monsters will not be affected.",
|
||||
"This spell will destroy any one monster that is of the Undead" + " variety",
|
||||
"This spell duplicates the effects of SOPIC for the entire party.",
|
||||
"This spell is indeed terrible, and may backfire on the caster."
|
||||
+ " First, to even cast it, you must be of the thirteenth level or"
|
||||
+ " higher, and casting it will cost you one level of experience."
|
||||
+ " The effects of HAMAN are random, and usually help the party.",
|
||||
"This spell's effects depend on the situation the party is in when it"
|
||||
+ " is cast.Basically, MALOR will teleport the entire party from one"
|
||||
+ " location to another. When used in melee, the teleport is random,"
|
||||
+ " but when used in camp, where there is more chance for concentration"
|
||||
+ ", it can be used to move the party anywhere in the maze. Be warned,"
|
||||
+ " however, that if you teleport outside of the maze, or into an"
|
||||
+ " area that is solid rock, you will be lost forever, so this spell"
|
||||
+ " is to be used with the greatest of care. Combat use of MALOR will"
|
||||
+ " never put you outside of the maze, but it may move you deeper in,"
|
||||
+ " so it should be used only in panic situations.",
|
||||
"The same restrictions and qualifications apply to this spell as do"
|
||||
+ " to HAMAN. However, the effects are even greater. Generally these"
|
||||
+ " spells are only used when there is no other hope for survival.",
|
||||
"The effect of this spell can be described as similar to that of a"
|
||||
+ " nuclear fusion explosion. Luckily the party is shielded from its"
|
||||
+ " effects. Unluckily (for them) the monsters are not. This spell"
|
||||
+ " will do from 10-100 hit points of damage." };
|
||||
}
|
@ -3,9 +3,13 @@ package com.bytezone.diskbrowser.wizardry;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBuffer;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class Wiz4Image extends AbstractImage
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public Wiz4Image (String name, byte[] buffer, int rows, int cols) // 5, 6
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
|
||||
|
@ -6,12 +6,16 @@ import java.util.List;
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class Wiz4Monsters extends AbstractFile
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
final List<Wiz4Image> images = new ArrayList<> ();
|
||||
final List<Integer> blocks = new ArrayList<> ();
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public Wiz4Monsters (String name, byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
|
||||
@ -30,8 +34,10 @@ public class Wiz4Monsters extends AbstractFile
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
|
@ -8,12 +8,16 @@ import com.bytezone.common.Utility;
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
public class Wiz5Monsters extends AbstractFile implements Iterable<Wiz5Monsters.Monster>
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class Wiz5Monsters extends AbstractFile implements Iterable<Wiz5Monsters.Monster>
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private static final int BLOCK_SIZE = 512;
|
||||
private final List<Monster> monsters = new ArrayList<> ();
|
||||
|
||||
public Wiz5Monsters (String name, byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
Wiz5Monsters (String name, byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
|
||||
@ -56,14 +60,18 @@ public class Wiz5Monsters extends AbstractFile implements Iterable<Wiz5Monsters.
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public Iterator<Monster> iterator ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return monsters.iterator ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
@ -90,7 +98,9 @@ public class Wiz5Monsters extends AbstractFile implements Iterable<Wiz5Monsters.
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
class Monster
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
private final int id;
|
||||
private final List<DataBuffer> dataBuffers = new ArrayList<> ();
|
||||
@ -151,7 +161,9 @@ public class Wiz5Monsters extends AbstractFile implements Iterable<Wiz5Monsters.
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
class DataBuffer
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
private final int block;
|
||||
private final int offset;
|
||||
|
@ -17,7 +17,9 @@ import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
import com.bytezone.diskbrowser.wizardry.Header.ScenarioData;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class Wizardry4BootDisk extends PascalDisk
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
public Header scenarioHeader;
|
||||
// private final List<AppleDisk> disks = new ArrayList<> ();
|
||||
@ -26,7 +28,9 @@ public class Wizardry4BootDisk extends PascalDisk
|
||||
private Huffman huffman;
|
||||
private final int version;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public Wizardry4BootDisk (AppleDisk[] dataDisks)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (dataDisks[0]);
|
||||
|
||||
@ -133,8 +137,10 @@ public class Wizardry4BootDisk extends PascalDisk
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void linkMonsterImages4 (DefaultMutableTreeNode monstersNode,
|
||||
FileEntry fileEntry)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
List<DiskAddress> pictureBlocks = fileEntry.getSectors ();
|
||||
|
||||
@ -151,8 +157,10 @@ public class Wizardry4BootDisk extends PascalDisk
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void linkMonsterImages5 (DefaultMutableTreeNode monstersNode,
|
||||
FileEntry fileEntry)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
List<DiskAddress> pictureBlocks = fileEntry.getSectors ();
|
||||
|
||||
@ -169,7 +177,9 @@ public class Wizardry4BootDisk extends PascalDisk
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void linkMazeLevels4 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
ScenarioData mazeData = scenarioHeader.data.get (Header.MAZE_AREA);
|
||||
|
||||
@ -191,7 +201,9 @@ public class Wizardry4BootDisk extends PascalDisk
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void linkMazeLevels5 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
byte[] buffer = fileEntry.getDataSource ().buffer;
|
||||
List<DiskAddress> blocks = fileEntry.getSectors ();
|
||||
@ -221,7 +233,9 @@ public class Wizardry4BootDisk extends PascalDisk
|
||||
afs.setSectors (allMazeBlocks);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void linkBlock1 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
byte[] buffer = fileEntry.getDataSource ().buffer;
|
||||
List<DiskAddress> blocks = fileEntry.getSectors ();
|
||||
@ -248,7 +262,9 @@ public class Wizardry4BootDisk extends PascalDisk
|
||||
afs.setSectors (allBlocks);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void linkBlock2 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
byte[] buffer = fileEntry.getDataSource ().buffer;
|
||||
List<DiskAddress> blocks = fileEntry.getSectors ();
|
||||
@ -275,7 +291,9 @@ public class Wizardry4BootDisk extends PascalDisk
|
||||
afs.setSectors (allBlocks);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void linkOracle (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
byte[] buffer = fileEntry.getDataSource ().buffer;
|
||||
List<DiskAddress> blocks = fileEntry.getSectors ();
|
||||
@ -309,8 +327,10 @@ public class Wizardry4BootDisk extends PascalDisk
|
||||
afs.setSectors (allOracleBlocks);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void addToNode (AbstractFile af, DefaultMutableTreeNode node,
|
||||
List<DiskAddress> blocks)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
DefaultAppleFileSource dafs =
|
||||
new DefaultAppleFileSource (af.getName (), af, this, blocks);
|
||||
@ -319,8 +339,10 @@ public class Wizardry4BootDisk extends PascalDisk
|
||||
node.add (childNode);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private DefaultMutableTreeNode linkNode (String name, String text,
|
||||
DefaultMutableTreeNode parent)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
DefaultAppleFileSource afs = new DefaultAppleFileSource (name, text, this);
|
||||
DefaultMutableTreeNode node = new DefaultMutableTreeNode (afs);
|
||||
@ -328,7 +350,9 @@ public class Wizardry4BootDisk extends PascalDisk
|
||||
return node;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public static boolean isWizardryIVorV (Disk disk, boolean debug)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
// Wizardry IV or V boot code
|
||||
byte[] header = { 0x00, (byte) 0xEA, (byte) 0xA9, 0x60, (byte) 0x8D, 0x01, 0x08 };
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user