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 // -----------------------------------------------------------------------------------// { public final String genericName; public final String realName; public final int monsterID; List 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 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 rewards, List 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).getName ()); 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 String toString () // ---------------------------------------------------------------------------------// { return realName; } }