diff options
Diffstat (limited to 'src/main/java/tlIItools/Affix.java')
| -rw-r--r-- | src/main/java/tlIItools/Affix.java | 431 |
1 files changed, 206 insertions, 225 deletions
diff --git a/src/main/java/tlIItools/Affix.java b/src/main/java/tlIItools/Affix.java index d90c0108..c49e6e2a 100644 --- a/src/main/java/tlIItools/Affix.java +++ b/src/main/java/tlIItools/Affix.java @@ -1,112 +1,79 @@ package tlIItools; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.Scanner; - -/** - * Represents a Torchlight II affix. - */ +import java.util.*; + +/** Represents a Torchlight II affix. + * + * @author Ben Culkin */ public class Affix { - /** - * Whether or not to record timing info. - */ + /** Details which sort of affix this is. + * + * @author Ben Culkin */ + public enum AffixType { + /** An affix that applies to a normal item. */ + ITEM, + /** An affix that applies to a socketable. */ + SOCKETABLE, + /** An affix that applies to a monster/person. */ + PERSONAL, + /** An affix that applies as an item enchantment. */ + ENCHANTMENT + } + + /** Whether or not to record timing info. */ public static boolean doTiming; - /** - * Internal name of the affix. - */ + + /** Internal name of the affix. */ public String intName; - /* - * The prefix/suffix attached to the affix. + /* The prefix/suffix attached to the affix. * * In general, only one of these is set for a given affix. * * NOTE: Some affixes have a mis-set suffix/prefix ordering, and may need to be - * changed in their files. - */ - /** - * The 'suffix name' attached to this affix. + * changed in their files. */ + + /** The 'suffix name' attached to this affix. * * Include the word [ITEM] to indicate where the item name should go. * * Note that it is not guaranteed that this is actually a suffix; it could be a - * prefix. - */ + * prefix. */ public String affixSuffix; - /** - * The 'prefix name' attached to this affix. + /** The 'prefix name' attached to this affix. * * Include the word [ITEM] to indicate where the item name should go. * * Note that it is not guaranteed that this is actually a prefix; it could be a - * suffix. - */ + * suffix. */ public String affixPrefix; - /* - * The min/max levels the affix can spawn at. - */ - /** - * The minimum level of an item this affix can spawn on. - */ - public int minLevel; - /** - * The maximum level of an item this affix can spawn on. - */ - public int maxLevel; - - /** - * The spawn weight for the affix. - */ + /** The min/max levels the affix can spawn at. */ + public LevelRange spawnRange = new LevelRange(); + + /** The spawn weight for the affix. */ public int weight; - /** - * The number of affix slots taken up. - */ + /** The number of affix slots taken up. */ public int slots; - /** - * Whether this is a socketable affix. - */ - public boolean isSocketable; - /** - * Whether this is an enchantment, instead of a standard affix. - */ - public boolean isEnchantment; - /** - * Whether this is a mob/player affix. - */ - public boolean isPerson; - - /** - * The types of equipment this can spawn on. - */ + /** The type of thing this affix applies to. */ + public AffixType type = AffixType.ITEM; + + /** The types of equipment this can spawn on. */ public List<String> equipTypes; - /** - * The types of equipment this can't spawn on. - */ + /** The types of equipment this can spawn on. */ public List<String> nonequipTypes; - - /** - * Places to get this enchantment from; - */ + /** The types of equipment this can spawn on. */ public List<String> enchantSources; - - /** - * The socketable types this spawns on. - */ + /** The types of equipment this can spawn on. */ public List<String> socketableTypes; - /** - * The effects attached to this affix. - */ + /** The effects attached to this affix. */ public List<Effect> effects; - /** - * Is this affix in an 'affix group' with another affix? + /** Determine whether this affix is in an 'affix group' with another affix. * * By 'affix group', what we mean is that it is essentially the same affix, with * generally just differing levels/values. @@ -115,50 +82,51 @@ public class Affix { * strength would be considered to be in the same affix group (assuming that * both of those strength bonuses had the same effect name). * - * @param afx - * The affix to check if we are in an affix group with. + * @param afx The affix to check if we are in an affix group with. * - * @return Whether or now we are in an affix group with the specified affix. - */ + * @return Whether or now we are in an affix group with the specified affix. */ public boolean isInAffixGroup(Affix afx) { if (effects == null) { - if (afx.effects != null) - return false; - } else if (!effects.equals(afx.effects)) // TODO this isn't actually an equals; - // maybe make this a 'isEquivalent' or - // 'isSimilarEffect'? - return false; + if (afx.effects != null) return false; + } else if (!effects.equals(afx.effects)) { + Iterator<Effect> leftIter = effects.iterator(); + Iterator<Effect> rightIter = afx.effects.iterator(); + + while (leftIter.hasNext() && rightIter.hasNext()) { + Effect left = leftIter.next(); + Effect right = rightIter.next(); + + if (!left.group.equals(right.group)) return false; + } + } + if (enchantSources == null) { - if (afx.enchantSources != null) - return false; - } else if (!enchantSources.equals(afx.enchantSources)) - return false; - if (equipTypes == null) { - if (afx.equipTypes != null) - return false; - } else if (!equipTypes.equals(afx.equipTypes)) + if (afx.enchantSources != null) return false; + } else if (!enchantSources.equals(afx.enchantSources)) { return false; - if (isEnchantment != afx.isEnchantment) + } else if (equipTypes == null) { + if (afx.equipTypes != null) return false; + } else if (!equipTypes.equals(afx.equipTypes)) { return false; - if (isPerson != afx.isPerson) + } else if (type == null) { + if (afx.type != null) return false; + } else if (type != afx.type) { return false; - if (isSocketable != afx.isSocketable) + } else if (nonequipTypes == null) { + if (afx.nonequipTypes != null) return false; + } else if (!nonequipTypes.equals(afx.nonequipTypes)) { return false; - if (nonequipTypes == null) { - if (afx.nonequipTypes != null) - return false; - } else if (!nonequipTypes.equals(afx.nonequipTypes)) - return false; - if (socketableTypes == null) { - if (afx.socketableTypes != null) - return false; - } else if (!socketableTypes.equals(afx.socketableTypes)) + } else if (socketableTypes == null) { + if (afx.socketableTypes != null) return false; + } else if (!socketableTypes.equals(afx.socketableTypes)) { return false; + } else { + return true; + } return true; } - - /** - * Gets the name of the 'affix group' that this affix is in. + + /** Gets the 'affix group' that this affix is in. * * By 'affix group', what we mean is that it is essentially the same affix, with * generally just differing levels/values. @@ -168,85 +136,62 @@ public class Affix { * both of those strength bonuses had the same effect name, and applied to the * same sorts of items). * - * @return The name of the affix group - */ - public String getAffixGroupName() { - StringBuilder sb = new StringBuilder(); - - for (Effect eft : effects) { - sb.append(eft.getEffectGroup()); - } - - for (String enchantSource : enchantSources) { - sb.append(enchantSource); - } - - for (String equipType : equipTypes) { - sb.append(equipType); - } - - for (String nonEquipType : nonequipTypes) { - sb.append(nonEquipType); - } - - for (String socketableType : socketableTypes) { - sb.append(socketableType); - } - - return sb.toString(); + * @return The affix group */ + public AffixGroup toAffixGroup() { + AffixGroup group = new AffixGroup(); + + group.type = type; + group.enchantSources = enchantSources; + group.equipTypes = equipTypes; + group.nonequipTypes = nonequipTypes; + group.socketableTypes = socketableTypes; + + for (Effect eff : effects) group.effects.add(eff.group); + + return group; } - /* - * Are invalid equip types being added? + /* Are invalid equip types being added? * * NOTE: This is kinda bad practice. It should really be handled via two * separate affix methods, one to add a valid affix, one to add an invalid, w/ - * the caller keeping tracking/calling the right one. - */ + * the caller keeping tracking/calling the right one. */ private boolean inNonEquip; - /** - * Create a new blank affix. - */ + /** Create a new blank affix. */ public Affix() { - equipTypes = new ArrayList<>(); - nonequipTypes = new ArrayList<>(); - enchantSources = new ArrayList<>(); + equipTypes = new ArrayList<>(); + nonequipTypes = new ArrayList<>(); + enchantSources = new ArrayList<>(); socketableTypes = new ArrayList<>(); - effects = new ArrayList<>(); + effects = new ArrayList<>(); } - /** - * Sets the set of equip types that is added to. + /** Sets the set of equip types that is added to. * - * @param nonequip - * True if the equip types being added are prohibited, or false - * if they are allowed. - */ + * @param nonequip True if the equip types being added are prohibited, or false + * if they are allowed. */ public void setEquipType(boolean nonequip) { inNonEquip = nonequip; } - /** - * Add an equip type to the right set of equip types. + /** Add an equip type to the right set of equip types. * - * @param type - * The equip type to add. - */ - public void addEquipType(String type) { + * @param equipType The equip type to add. */ + public void addEquipType(String equipType) { if (inNonEquip) { - nonequipTypes.add(type); + nonequipTypes.add(equipType); } else { - if (type.equals("SOCKETABLE") || type.contains(" EMBER")) { - isSocketable = true; - socketableTypes.add(type); - } else if (type.startsWith("ENCHANTER")) { - isEnchantment = true; - enchantSources.add(type.substring(10)); - } else if (type.equals("MONSTER") || type.equals("PLAYER")) { - isPerson = true; + if (equipType.equals("SOCKETABLE") || equipType.contains(" EMBER")) { + type = AffixType.SOCKETABLE; + socketableTypes.add(equipType); + } else if (equipType.startsWith("ENCHANTER")) { + type = AffixType.ENCHANTMENT; + enchantSources.add(equipType.substring(10)); + } else if (equipType.equals("MONSTER") || equipType.equals("PLAYER")) { + type = AffixType.PERSONAL; } else { - equipTypes.add(type); + equipTypes.add(equipType); } } } @@ -256,22 +201,71 @@ public class Affix { return intName; } - /** - * Print out the full details of this affix. + /** Print out a 'short-form' of this affix. + * + * @return The short form of this affix. */ + public String toShortString() { + StringBuilder sb = new StringBuilder(); + + sb.append(intName); + sb.append("\n"); + + if (affixSuffix != null) { + sb.append("\tSuffix: "); + sb.append(affixSuffix); + sb.append("\n"); + } + + if (affixPrefix != null) { + sb.append("\tPrefix: "); + sb.append(affixPrefix); + sb.append("\n"); + + } + + sb.append("\t"); + sb.append(spawnRange.toString()); + sb.append("\n"); + + sb.append("\tSpawn Weight: "); + sb.append(weight); + sb.append("\t"); + + if (slots == 0) { + sb.append("\tOccupies no slots\n"); + } else { + sb.append("\tSlots: "); + sb.append(slots); + sb.append("\n"); + } + + if (effects.size() != 0) { + sb.append("\tEffects: "); + for (Effect eft : effects) { + if (effects.size() > 1) sb.append("\n\t\t"); + sb.append(eft.toString()); + } + sb.append("\n"); + } + + return sb.toString(); + } + + /** Print out the full details of this affix. * - * @return The full details of the affix. - */ + * @return The full details of the affix. */ public String toLongString() { StringBuilder sb = new StringBuilder(); - if (isSocketable) { + + if (type == AffixType.SOCKETABLE) { sb.append("Socketable "); - } else if (isPerson || (intName != null && intName.startsWith("HERO_"))) { + } else if (type == AffixType.PERSONAL || (intName != null && intName.startsWith("HERO_"))) { sb.append("Personal "); } else if (intName != null & intName.startsWith("MAP_")) { sb.append("Area "); } - if (isEnchantment) { + if (type == AffixType.ENCHANTMENT) { sb.append("Enchantment: "); } else { sb.append("Affix: "); @@ -294,21 +288,7 @@ public class Affix { } sb.append("\t"); - if (minLevel <= 1 && maxLevel == 999) { - sb.append("No Level Range"); - } else if (minLevel != 1 && maxLevel != 999) { - sb.append("Level Range: "); - sb.append(minLevel); - sb.append("-"); - sb.append(maxLevel); - } else if (minLevel <= 1) { - sb.append("Max Level: "); - sb.append(maxLevel); - } else if (maxLevel == 999) { - sb.append("Minimum Level: "); - sb.append(minLevel); - } - + sb.append(spawnRange); sb.append("\n"); sb.append("\tSpawn Weight: "); @@ -324,18 +304,20 @@ public class Affix { } if (equipTypes.size() != 0) { - if (isSocketable) + if (type == AffixType.SOCKETABLE) { sb.append("\tSocketable Into: "); - else if (isEnchantment) + } else if (type == AffixType.ENCHANTMENT) { sb.append("\tEnchants Onto: "); - else + } else { sb.append("\tSpawns On: "); + } + sb.append(equipTypes); sb.append("\n"); } // Socketables & enchantments use this as a duplicate. - if (!isSocketable && !isEnchantment && nonequipTypes.size() != 0) { + if (type != AffixType.SOCKETABLE && type != AffixType.ENCHANTMENT && nonequipTypes.size() != 0) { sb.append("\tCan't Spawn On: "); sb.append(nonequipTypes); sb.append("\n"); @@ -362,6 +344,7 @@ public class Affix { sb.append("\n"); } + /* sb.append("Affix Group: "); String afxGroupName = getAffixGroupName(); sb.append(afxGroupName); @@ -369,36 +352,29 @@ public class Affix { sb.append(afxGroupName.hashCode()); sb.append(")"); sb.append("\n"); + */ return sb.toString(); } - /** - * Load an affix from an input source. + /** Load an affix from an input source. * - * @param scn - * The input source to load from. + * @param scn The input source to load from. * - * @param fName - * The name of the input source in question. + * @param fName The name of the input source in question. * - * @return The loaded affix. - */ + * @return The loaded affix. */ public static Affix loadAffix(Scanner scn, String fName) { return loadAffix(scn, fName, new ArrayList<>()); } - /** - * Load an affix from an input source. + /** Load an affix from an input source. * - * @param scn - * The input source to read from. - * @param scnName - * The name of the input source. - * @param errors - * A list to stick errors encountered during loading the affix. - * @return The affix, loaded from the file. - */ + * @param scn The input source to read from. + * @param scnName The name of the input source. + * @param errors A list to stick errors encountered during loading the affix. + * + * @return The affix, loaded from the file. */ public static Affix loadAffix(Scanner scn, String scnName, List<String> errors) { Affix afx = new Affix(); @@ -428,27 +404,32 @@ public class Affix { afx.affixPrefix = splits[1]; break; default: - errors.add( - String.format("Misformed affix translation: (%s) (%s) (%s)\n", - splits[0], splits[1], scnName)); + String msg = String.format( + "Misformed affix translation: (%s) (%s) (%s)\n", + splits[0], splits[1], scnName); + errors.add(msg); } } else if (ln.contains("MIN_SPAWN_RANGE")) { - afx.minLevel = Integer.parseInt(splits[1]); + afx.spawnRange.minLevel = Integer.parseInt(splits[1]); } else if (ln.contains("MAX_SPAWN_RANGE")) { - afx.maxLevel = Integer.parseInt(splits[1]); + afx.spawnRange.maxLevel = Integer.parseInt(splits[1]); } else if (ln.contains("WEIGHT:")) { afx.weight = Integer.parseInt(splits[1]); } else if (ln.contains("SLOTS_OCCUPY")) { afx.weight = Integer.parseInt(splits[1]); } else if (ln.contains("UNITTYPE") && !ln.contains("/")) { if (splits.length == 1) - errors.add(String.format("Malformed equip type: (%s) (%s)\n", + errors.add(String.format( + "Malformed equip type: (%s) (%s)\n", splits[0], scnName)); + afx.addEquipType(splits[1]); } else if (splits[0].equals("<STRING>NAME")) { if (splits.length == 1) - errors.add(String.format("Malformed name: (%s) (%s)\n", splits[0], - scnName)); + errors.add(String.format( + "Malformed name: (%s) (%s)\n", + splits[0], scnName)); + afx.intName = splits[1]; } else if (ln.contains("[EFFECT]")) { List<String> eftErrs = new ArrayList<>(); @@ -459,21 +440,21 @@ public class Affix { afx.effects.add(eft); } } + // Sort effects, so that they are in a stable order, even if specified out of // order afx.effects.sort(Comparator.comparingInt((val) -> val.hashCode())); long endTime = System.nanoTime(); if (doTiming) { - String fmt - = "\tProcessed affix %s from %s in %d nanoseconds (%.2f seconds)\n\n"; + String fmt = "\tProcessed affix %s from %s in %d nanoseconds (%.2f seconds)\n\n"; double seconds = ((double) (endTime - startTime) / 1000000000); - errors.add(String.format(fmt, afx.intName, scnName, endTime - startTime, - seconds)); + errors.add(String.format( + fmt, + afx.intName, scnName, endTime - startTime, seconds)); } return afx; } - } |
