// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . // ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· // ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ // ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ // ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ // Magicbane Emulator Project © 2013 - 2022 // www.magicbane.com package engine.objects; import engine.Enum.ItemContainerType; import engine.Enum.ItemType; import engine.Enum.OwnerType; import engine.gameManager.ConfigManager; import engine.gameManager.DbManager; import engine.gameManager.NPCManager; import engine.gameManager.ZoneManager; import engine.server.MBServerStatics; import org.pmw.tinylog.Logger; import java.util.ArrayList; import java.util.HashMap; import java.util.Random; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadLocalRandom; public class LootTable { private static final ConcurrentHashMap lootGroups = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW); private static final ConcurrentHashMap lootTables = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW); private static final ConcurrentHashMap modTables = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW); private static final ConcurrentHashMap modGroups = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW); private static final ConcurrentHashMap statRuneChances = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW); private final ConcurrentHashMap lootTable = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW); private static final int oneDrop = 95; private static final int twoDrop = 100; private static final int noDropHotZone = 79; private static final int oneDropHotZone = 98; public float minRoll = 320; public float maxRoll = 1; public static boolean initialized = false; public int lootTableID = 0; public static HashMap itemsDroppedMap = new HashMap<>(); public static HashMap resourceDroppedMap = new HashMap<>(); public static HashMap runeDroppedMap = new HashMap<>(); public static HashMap contractDroppedMap = new HashMap<>(); public static HashMap glassDroppedMap = new HashMap<>(); public static int rollCount = 0; public static int dropCount = 0; public static int runeCount = 0; public static int contractCount = 0; public static int resourceCount = 0; public static int glassCount = 0; /** * Generic Constructor */ public LootTable(int lootTableID) { this.lootTableID = lootTableID; } public void addRow(float min, float max, int valueOne, int valueTwo, int valueThree, String action) { //hackey way to set the minimum roll for SHIAT! if (min < this.minRoll) this.minRoll = min; if (max > this.maxRoll) this.maxRoll = max; int minInt = (int) min; int maxInt = (int) max; //Round up min if (minInt != min){ min = minInt + 1; } //Round down max; if (maxInt != max) max = maxInt; LootRow lootRow = new LootRow(valueOne, valueTwo, valueThree, action); for (int i = (int) min; i <= max; i++) { lootTable.put(i, lootRow); } } public static LootTable getLootGroup(int UUID) { if (lootGroups.containsKey(UUID)) return lootGroups.get(UUID); LootTable lootGroup = new LootTable(UUID); lootGroups.put(UUID, lootGroup); return lootGroup; } public static LootTable getLootTable(int UUID) { if (lootTables.containsKey(UUID)) return lootTables.get(UUID); LootTable lootTable = new LootTable(UUID); lootTables.put(UUID, lootTable); return lootTable; } /** * @return the lootGroups */ public static ConcurrentHashMap getLootGroups() { return lootGroups; } /** * @return the lootTables */ public static ConcurrentHashMap getLootTables() { return lootTables; } /** * @return the modTables */ public static ConcurrentHashMap getModTables() { return modTables; } /** * @return the modGroups */ public static ConcurrentHashMap getModGroups() { return modGroups; } public static LootTable getModGroup(int UUID) { if (modGroups.containsKey(UUID)) return modGroups.get(UUID); LootTable modTable = new LootTable(UUID); modGroups.put(UUID, modTable); return modTable; } public static LootTable getModTable(int UUID) { if (modTables.containsKey(UUID)) return modTables.get(UUID); LootTable modTypeTable = new LootTable(UUID); modTables.put(UUID, modTypeTable); return modTypeTable; } public LootRow getLootRow(int probability) { if (lootTable.containsKey(probability)) return lootTable.get(probability); return null; } //call this on server startup to populate the tables public static void populateLootTables() { DbManager.LootQueries.populateLootGroups(); DbManager.LootQueries.populateLootTables(); DbManager.LootQueries.populateModTables(); DbManager.LootQueries.populateModGroups(); //preset chances for rune drops populateStatRuneChances(); } //Returns a list of random loot for a mob based on level, lootTable and hotzone public static ArrayList getMobLoot(Mob mobile, int mobLevel, int lootTable, boolean hotzone) { ArrayList mobLoot; int calculatedLootTable; int randomRoll; mobLoot = new ArrayList<>(); // Setup default loot table if none exists calculatedLootTable = lootTable; LootTable.rollCount++; if (MobLootBase.MobLootSet.get(mobile.getMobBase().getLoadID()).isEmpty()){ randomRoll = ThreadLocalRandom.current().nextInt(100); if (randomRoll > 90) if (randomRoll > LootTable.oneDropHotZone) addMobLoot(mobile, mobLoot, mobLevel, calculatedLootTable, 1, true); else addMobLoot(mobile, mobLoot, mobLevel, calculatedLootTable, 1, true); }else{ for (MobLootBase mlb:MobLootBase.MobLootSet.get(mobile.getMobBase().getLoadID())){ float chance = mlb.getChance() *.01f; chance *= Float.parseFloat(ConfigManager.MB_NORMAL_DROP_RATE.getValue()); calculatedLootTable = mlb.getLootTableID(); if (ThreadLocalRandom.current().nextFloat() > chance) continue; addMobLoot(mobile, mobLoot, mobLevel, calculatedLootTable, 1, false); } } //calculatedLootTable = lootTable; if (calculatedLootTable <= 1) calculatedLootTable = 1300; // GENERIC WORLD //handle hotzone random loot if (hotzone) { LootTable.rollCount++; if (!MobLootBase.MobLootSet.get(mobile.getMobBase().getLoadID()).isEmpty()) for (MobLootBase mlb : MobLootBase.MobLootSet.get(mobile.getMobBase().getLoadID())) { if (!LootTable.lootGroups.containsKey(mlb.getLootTableID() + 1)) continue; calculatedLootTable = mlb.getLootTableID(); break; } randomRoll = ThreadLocalRandom.current().nextInt(100); if (randomRoll > 90) if (randomRoll > LootTable.oneDropHotZone) addMobLoot(mobile, mobLoot, mobLevel, calculatedLootTable + 1, 1, true); else addMobLoot(mobile, mobLoot, mobLevel, calculatedLootTable + 1, 1, true); } //handle mob specific special loot ArrayList bootyLoot = getBootyLoot(mobile); mobLoot.addAll(bootyLoot); return mobLoot; } public static ArrayList getMobLootDeath(Mob mobile, int mobLevel, int lootTable) { ArrayList mobLoot = new ArrayList<>(); if (mobile == null) return mobLoot; //handle hotzone random loot boolean hotzone = ZoneManager.inHotZone(mobile.getLoc()); if (hotzone) { if (MobLootBase.MobLootSet.get(mobile.getMobBase().getLoadID()).isEmpty()){ lootTable += 1; if (lootTable <= 1) lootTable = 1301; // GENERIC WORLD int roll = ThreadLocalRandom.current().nextInt(100); if (roll > 90) if (roll > LootTable.oneDropHotZone) addMobLoot(mobile, mobLoot, mobLevel, lootTable, 1, true); else addMobLoot(mobile, mobLoot, mobLevel, lootTable, 1, true); }else{ for (MobLootBase mlb:MobLootBase.MobLootSet.get(mobile.getMobBase().getLoadID())){ lootTable = mlb.getLootTableID() + 1; if (!LootTable.lootGroups.containsKey(lootTable)) continue; int roll = ThreadLocalRandom.current().nextInt(100); if (roll > 90) if (roll > LootTable.oneDropHotZone) addMobLoot(mobile, mobLoot, mobLevel, (lootTable), 1, true); else addMobLoot(mobile, mobLoot, mobLevel, (lootTable), 1, true); break; } } if (mobLoot.isEmpty()){ LootTable.rollCount++; //add another rollCount here. int resourceRoll = ThreadLocalRandom.current().nextInt(100); if (resourceRoll <=5) addMobLootResources(mobile, mobLoot, mobLevel, (lootTable), 1, true); } } //handle mob specific booty on death ArrayList bootyLoot = getBootyLoot(mobile); mobLoot.addAll(bootyLoot); return mobLoot; } private static ArrayList getBootyLoot(Mob mob) { ArrayList bootySetList; ArrayList mobLootList = new ArrayList<>(); if (mob.bootySet == 0) return mobLootList; bootySetList = NPCManager._bootySetMap.get(mob.bootySet); for (BootySetEntry bootyEntry : bootySetList) if (ThreadLocalRandom.current().nextInt(100) < bootyEntry.dropChance) { ItemBase itemBase = ItemBase.getItemBase(bootyEntry.itemBase); if (itemBase != null) { MobLoot mobLoot = new MobLoot(mob, itemBase, true); mobLootList.add(mobLoot); } } return mobLootList; } //called by getMobLoot to add the actual loot private static void addMobLoot(Mob mob, ArrayList loot, int mobLevel, int lootTableID, int cnt, boolean hotzone) { // Member variable declaration float calculatedMobLevel; int minSpawn; int maxSpawn; int spawnQuanity = 0; int prefixValue = 0; int suffixValue = 0; int subTableID; String modifierPrefix = ""; String modifierSuffix = ""; // Lookup Table Variables LootTable lootTable; LootRow lootRow; LootTable lootGroup; LootRow groupRow = null; LootTable modTable; LootTable modGroup; LootRow modRow = null; // Used for actual generation of items int itemBaseUUID; ItemBase itemBase = null; MobLoot mobLoot; if (!LootTable.lootGroups.containsKey(lootTableID)) return; lootGroup = LootTable.lootGroups.get(lootTableID); calculatedMobLevel = mobLevel; if (calculatedMobLevel > 49) calculatedMobLevel = 49; int randomRoll = 0; for (int i = 0; i < cnt; i++) { Random random = new Random(); randomRoll = random.nextInt(100) + 1; //random roll between 1 and 100 groupRow = lootGroup.getLootRow(randomRoll); if (groupRow == null) return; //get loot table for this group if (!LootTable.lootTables.containsKey(groupRow.getValueOne())) return; lootTable = LootTable.lootTables.get(groupRow.getValueOne()); int minRoll = (int) ((calculatedMobLevel - 5) * 5); int maxRoll = (int) ((calculatedMobLevel + 15) * 5); if (minRoll < (int)lootTable.minRoll) minRoll = (int)lootTable.minRoll; if (maxRoll < minRoll) maxRoll = minRoll; if (maxRoll > lootTable.maxRoll) maxRoll = (int) lootTable.maxRoll; if (maxRoll > 320) maxRoll = 320; randomRoll = (int) ThreadLocalRandom.current().nextDouble(minRoll, maxRoll + 1); //Does not return Max, but does return min? lootRow = lootTable.getLootRow(randomRoll); //get the item row from the bell's curve of level +-15 if (lootRow == null) continue; //no item found for roll itemBaseUUID = lootRow.getValueOne(); if (lootRow.getValueOne() == 0) continue; //handle quantities > 1 for resource drops minSpawn = lootRow.getValueTwo(); maxSpawn = lootRow.getValueThree(); // spawnQuantity between min spawn (inclusive) and max spawn (inclusive) if (maxSpawn > 1) spawnQuanity = ThreadLocalRandom.current().nextInt((maxSpawn + 1 - minSpawn)) + minSpawn; //get modifierPrefix calculatedMobLevel = mobLevel; if (calculatedMobLevel < 16) calculatedMobLevel = 16; if (calculatedMobLevel > 49) calculatedMobLevel = 49; int chanceMod = ThreadLocalRandom.current().nextInt(100) + 1; if (chanceMod < 25) { modGroup = LootTable.modGroups.get(groupRow.getValueTwo()); if (modGroup != null) { for (int a = 0;a<10;a++){ randomRoll = ThreadLocalRandom.current().nextInt(100) + 1; modRow = modGroup.getLootRow(randomRoll); if (modRow != null) break; } if (modRow != null) { subTableID = modRow.getValueOne(); if (LootTable.modTables.containsKey(subTableID)) { modTable = LootTable.modTables.get(subTableID); randomRoll = gaussianLevel((int)calculatedMobLevel); if (randomRoll < modTable.minRoll) randomRoll = (int) modTable.minRoll; if (randomRoll > modTable.maxRoll) randomRoll = (int) modTable.maxRoll; modRow = modTable.getLootRow(randomRoll); if (modRow != null) { prefixValue = modRow.getValueOne(); modifierPrefix = modRow.getAction(); } } } } }else if(chanceMod < 50) { modGroup = LootTable.modGroups.get(groupRow.getValueThree()); if (modGroup != null) { for (int a = 0;a<10;a++){ randomRoll = ThreadLocalRandom.current().nextInt(100) + 1; modRow = modGroup.getLootRow(randomRoll); if (modRow != null) break; } if (modRow != null) { subTableID = modRow.getValueOne(); if (LootTable.modTables.containsKey(subTableID)) { modTable = LootTable.modTables.get(subTableID); randomRoll = gaussianLevel((int)calculatedMobLevel); if (randomRoll < modTable.minRoll) randomRoll = (int) modTable.minRoll; if (randomRoll > modTable.maxRoll) randomRoll = (int) modTable.maxRoll; modRow = modTable.getLootRow(randomRoll); if (modRow == null) modRow = modTable.getLootRow((int) ((modTable.minRoll + modTable.maxRoll) *.05f)); if (modRow != null) { suffixValue = modRow.getValueOne(); modifierSuffix = modRow.getAction(); } } } } }else{ modGroup = LootTable.modGroups.get(groupRow.getValueTwo()); if (modGroup != null) { for (int a = 0;a<10;a++) { randomRoll = ThreadLocalRandom.current().nextInt(100) + 1; modRow = modGroup.getLootRow(randomRoll); if (modRow != null) break; } if (modRow != null) { subTableID = modRow.getValueOne(); if (LootTable.modTables.containsKey(subTableID)) { modTable = LootTable.modTables.get(subTableID); randomRoll = gaussianLevel((int)calculatedMobLevel); if (randomRoll < modTable.minRoll) randomRoll = (int) modTable.minRoll; if (randomRoll > modTable.maxRoll) randomRoll = (int) modTable.maxRoll; modRow = modTable.getLootRow(randomRoll); if (modRow == null) modRow = modTable.getLootRow((int) ((modTable.minRoll + modTable.maxRoll) *.05f)); if (modRow != null) { prefixValue = modRow.getValueOne(); modifierPrefix = modRow.getAction(); } } } } //get modifierSuffix modGroup = LootTable.modGroups.get(groupRow.getValueThree()); if (modGroup != null) { for (int a = 0;a<10;a++){ randomRoll = ThreadLocalRandom.current().nextInt(100) + 1; modRow = modGroup.getLootRow(randomRoll); if (modRow != null) break; } if (modRow != null) { subTableID = modRow.getValueOne(); if (LootTable.modTables.containsKey(subTableID)) { modTable = LootTable.modTables.get(subTableID); randomRoll = gaussianLevel((int)calculatedMobLevel); if (randomRoll < modTable.minRoll) randomRoll = (int) modTable.minRoll; if (randomRoll > modTable.maxRoll) randomRoll = (int) modTable.maxRoll; modRow = modTable.getLootRow(randomRoll); if (modRow == null) modRow = modTable.getLootRow((int) ((modTable.minRoll + modTable.maxRoll) *.05f)); if (modRow != null) { suffixValue = modRow.getValueOne(); modifierSuffix = modRow.getAction(); } } } } } itemBase = ItemBase.getItemBase(itemBaseUUID); if (itemBase == null) return; //Handle logging of drops LootTable.HandleDropLogs(itemBase); if (itemBase.getType() == ItemType.OFFERING) spawnQuanity = 1; if (spawnQuanity > 0) mobLoot = new MobLoot(mob, itemBase, spawnQuanity, false); else mobLoot = new MobLoot(mob, itemBase, false); if (!modifierPrefix.isEmpty()) mobLoot.addPermanentEnchantment(modifierPrefix, 0, prefixValue, true); if (!modifierSuffix.isEmpty()) mobLoot.addPermanentEnchantment(modifierSuffix, 0, suffixValue, false); mobLoot.loadEnchantments(); loot.add(mobLoot); } } private static void addMobLootResources(Mob mob, ArrayList loot, int mobLevel, int lootTableID, int cnt, boolean hotzone) { // Member variable declaration float calculatedMobLevel; int minSpawn; int maxSpawn; int spawnQuanity = 0; // Lookup Table Variables LootTable lootTable; LootRow lootRow; LootTable lootGroup; LootRow groupRow = null; // Used for actual generation of items int itemBaseUUID; ItemBase itemBase; MobLoot mobLoot; if (!LootTable.lootGroups.containsKey(lootTableID)) return; lootGroup = LootTable.lootGroups.get(lootTableID); calculatedMobLevel = mobLevel; if (calculatedMobLevel > 49) calculatedMobLevel = 49; int roll = 0; for (int i = 0; i < cnt; i++) { if (lootTableID == 1901) groupRow = lootGroup.getLootRow(66); else if (lootTableID == 1501) groupRow = lootGroup.getLootRow(98); else groupRow = lootGroup.getLootRow(80); if (groupRow == null) return; //get loot table for this group if (!LootTable.lootTables.containsKey(groupRow.getValueOne())) return; lootTable = LootTable.lootTables.get(groupRow.getValueOne()); int minRoll = (int) ((calculatedMobLevel-5) * 5); int maxRoll = (int) ((calculatedMobLevel + 15) *5); if (minRoll < (int)lootTable.minRoll) minRoll = (int)lootTable.minRoll; if (maxRoll < minRoll) maxRoll = minRoll; if (maxRoll > 320) maxRoll = 320; roll = ThreadLocalRandom.current().nextInt(minRoll, maxRoll + 1); //Does not return Max, but does return min? lootRow = lootTable.getLootRow(roll); //get the item row from the bell's curve of level +-15 if (lootRow == null) continue; //no item found for roll itemBaseUUID = lootRow.getValueOne(); if (lootRow.getValueOne() == 0) continue; //handle quantities > 1 for resource drops minSpawn = lootRow.getValueTwo(); maxSpawn = lootRow.getValueThree(); // spawnQuanity between minspawn (inclusive) and maxspawn (inclusive) if (maxSpawn > 1) spawnQuanity = ThreadLocalRandom.current().nextInt((maxSpawn + 1 - minSpawn)) + minSpawn; itemBase = ItemBase.getItemBase(itemBaseUUID); if (itemBase == null) return; LootTable.HandleDropLogs(itemBase); switch (itemBase.getUUID()){ case 19290: continue; case 19291: continue; case 19292: continue; case 27530: continue; case 973000: continue; case 973200: continue; case 26360: continue; } // Handle drop rates of resources/runes/contracts. // We intentionally drop them in half if (itemBase.getType() == ItemType.OFFERING) spawnQuanity = 1; if (spawnQuanity > 0) mobLoot = new MobLoot(mob, itemBase, spawnQuanity, false); else mobLoot = new MobLoot(mob, itemBase, false); loot.add(mobLoot); } } public static int gaussianLevel(int level) { int ret = -76; while (ret < -75 || ret > 75) { ret = (int) (ThreadLocalRandom.current().nextGaussian() * 75); } return (level * 5) + ret; } //This set's the drop chances for stat runes. public static void populateStatRuneChances() { //+3, Increased statRuneChances.put(250018, 60); statRuneChances.put(250009, 60); statRuneChances.put(250027, 60); statRuneChances.put(250036, 60); statRuneChances.put(250000, 60); //+5, Enhanced statRuneChances.put(250019, 60); statRuneChances.put(250010, 60); statRuneChances.put(250028, 60); statRuneChances.put(250037, 60); statRuneChances.put(250001, 60); //+10 Exceptional statRuneChances.put(250020, 60); statRuneChances.put(250011, 60); statRuneChances.put(250029, 60); statRuneChances.put(250038, 60); statRuneChances.put(250002, 60); //+15, Amazing statRuneChances.put(250021, 60); statRuneChances.put(250012, 60); statRuneChances.put(250030, 60); statRuneChances.put(250039, 60); statRuneChances.put(250003, 60); //+20, Incredible statRuneChances.put(250022, 60); statRuneChances.put(250013, 60); statRuneChances.put(250031, 60); statRuneChances.put(250040, 60); statRuneChances.put(250004, 60); //+25, Great statRuneChances.put(250023, 60); statRuneChances.put(250014, 60); statRuneChances.put(250032, 60); statRuneChances.put(250041, 60); statRuneChances.put(250005, 60); //+30, Heroic statRuneChances.put(250024, 60); statRuneChances.put(250015, 60); statRuneChances.put(250033, 60); statRuneChances.put(250042, 60); statRuneChances.put(250006, 60); //+35, Legendary statRuneChances.put(250025, 60); statRuneChances.put(250016, 60); statRuneChances.put(250034, 60); statRuneChances.put(250043, 60); statRuneChances.put(250007, 60); //+40, of the Gods statRuneChances.put(250026, 60); statRuneChances.put(250017, 60); statRuneChances.put(250035, 60); statRuneChances.put(250044, 60); statRuneChances.put(250008, 60); } public ConcurrentHashMap getLootTable() { return lootTable; } private static void HandleDropLogs(ItemBase itemBase){ if (itemBase == null) return; LootTable.dropCount++; //item dropped, add to all item count. if (LootTable.itemsDroppedMap.get(itemBase) == null){ LootTable.itemsDroppedMap.put(itemBase, 1); //First time dropping, make count 1. }else{ int dropCount = LootTable.itemsDroppedMap.get(itemBase); dropCount++; LootTable.itemsDroppedMap.put(itemBase, dropCount); } switch (itemBase.getType()){ case RESOURCE: LootTable.resourceCount++; if (LootTable.resourceDroppedMap.get(itemBase) == null){ LootTable.resourceDroppedMap.put(itemBase, 1); //First time dropping, make count 1. }else{ int dropCount = LootTable.resourceDroppedMap.get(itemBase); dropCount++; LootTable.resourceDroppedMap.put(itemBase, dropCount); } break; case RUNE: LootTable.runeCount++; if (LootTable.runeDroppedMap.get(itemBase) == null){ LootTable.runeDroppedMap.put(itemBase, 1); //First time dropping, make count 1. }else{ int dropCount = LootTable.runeDroppedMap.get(itemBase); dropCount++; LootTable.runeDroppedMap.put(itemBase, dropCount); } break; case CONTRACT: LootTable.contractCount++; if (LootTable.contractDroppedMap.get(itemBase) == null){ LootTable.contractDroppedMap.put(itemBase, 1); //First time dropping, make count 1. }else{ int dropCount = LootTable.contractDroppedMap.get(itemBase); dropCount++; LootTable.contractDroppedMap.put(itemBase, dropCount); } break; case WEAPON: //Glass Drop if (itemBase.isGlass()){ LootTable.glassCount++; if (LootTable.glassDroppedMap.get(itemBase) == null){ LootTable.glassDroppedMap.put(itemBase, 1); //First time dropping, make count 1. }else{ int dropCount = LootTable.glassDroppedMap.get(itemBase); dropCount++; LootTable.glassDroppedMap.put(itemBase, dropCount); } } break; } } public static Item CreateGamblerItem(Item item, PlayerCharacter gambler){ if (item == null) return null; int groupID = 0; switch (item.getItemBase().getUUID()){ case 971050: //Wrapped Axe groupID = 3000; break; case 971051://Wrapped Great Axe groupID = 3005; break; case 971052://Wrapped Throwing Axe groupID = 3010; break; case 971053:// Wrapped Bow groupID = 3015; break; case 971054://Wrapped Crossbow groupID = 3020; break; case 971055: //Wrapped Dagger groupID = 3025; break; case 971056: // Wrapped Throwing Dagger groupID = 3030; break; case 971057: // Wrapped Hammer groupID = 3035; break; case 971058:// Wrapped Great Hammer groupID = 3040; break; case 971059:// Wrapped Throwing Hammer groupID = 3045; break; case 971060:// Wrapped Polearm groupID = 3050; break; case 971061:// Wrapped Spear groupID = 3055; break; case 971062:// Wrapped Staff groupID = 3060; break; case 971063:// Wrapped Sword groupID = 3065; break; case 971064:// Wrapped Great Sword groupID = 3070; break; case 971065:// Wrapped Unarmed Weapon groupID = 3075; break; case 971066:// Wrapped Cloth Armor groupID = 3100; break; case 971067:// Wrapped Light Armor groupID = 3105; break; case 971068:// Wrapped Medium Armor groupID = 3110; break; case 971069:// Wrapped Heavy Armor groupID = 3115; break; case 971070:// Wrapped Rune groupID = 3200; break; case 971071:// Wrapped City Improvement groupID = 3210; break; } //couldnt find group if (groupID == 0) return null; LootTable lootGroup = LootTable.lootGroups.get(groupID); if (lootGroup == null) return null; float calculatedMobLevel; int minSpawn; int maxSpawn; int spawnQuanity = 0; int prefixValue = 0; int suffixValue = 0; int subTableID; String modifierPrefix = ""; String modifierSuffix = ""; // Lookup Table Variables LootTable lootTable; LootRow lootRow; LootRow groupRow = null; LootTable modTable; LootTable modGroup; LootRow modRow = null; // Used for actual generation of items int itemBaseUUID; ItemBase itemBase = null; MobLoot mobLoot; int roll = ThreadLocalRandom.current().nextInt(100) + 1; //Does not return Max, but does return min? groupRow = lootGroup.getLootRow(roll); lootTable = LootTable.lootTables.get(groupRow.getValueOne()); roll = ThreadLocalRandom.current().nextInt(100) + 1; lootRow = lootTable.getLootRow(roll + 220); //get the item row from the bell's curve of level +-15 if (lootRow == null) return null; //no item found for roll itemBaseUUID = lootRow.getValueOne(); if (lootRow.getValueOne() == 0) return null; //handle quantities > 1 for resource drops minSpawn = lootRow.getValueTwo(); maxSpawn = lootRow.getValueThree(); // spawnQuanity between minspawn (inclusive) and maxspawn (inclusive) if (maxSpawn > 1) spawnQuanity = ThreadLocalRandom.current().nextInt((maxSpawn + 1 - minSpawn)) + minSpawn; //get modifierPrefix calculatedMobLevel = 49; int chanceMod = ThreadLocalRandom.current().nextInt(100) + 1; if (chanceMod < 25){ modGroup = LootTable.modGroups.get(groupRow.getValueTwo()); if (modGroup != null) { for (int a = 0;a<10;a++){ roll = ThreadLocalRandom.current().nextInt(100) + 1; modRow = modGroup.getLootRow(roll); if (modRow != null) break; } if (modRow != null) { subTableID = modRow.getValueOne(); if (LootTable.modTables.containsKey(subTableID)) { modTable = LootTable.modTables.get(subTableID); roll = gaussianLevel((int)calculatedMobLevel); if (roll < modTable.minRoll) roll = (int) modTable.minRoll; if (roll > modTable.maxRoll) roll = (int) modTable.maxRoll; modRow = modTable.getLootRow(roll); if (modRow != null) { prefixValue = modRow.getValueOne(); modifierPrefix = modRow.getAction(); } } } } }else if(chanceMod < 50){ modGroup = LootTable.modGroups.get(groupRow.getValueThree()); if (modGroup != null) { for (int a = 0;a<10;a++){ roll = ThreadLocalRandom.current().nextInt(100) + 1; modRow = modGroup.getLootRow(roll); if (modRow != null) break; } if (modRow != null) { subTableID = modRow.getValueOne(); if (LootTable.modTables.containsKey(subTableID)) { modTable = LootTable.modTables.get(subTableID); roll = gaussianLevel((int)calculatedMobLevel); if (roll < modTable.minRoll) roll = (int) modTable.minRoll; if (roll > modTable.maxRoll) roll = (int) modTable.maxRoll; modRow = modTable.getLootRow(roll); if (modRow == null){ modRow = modTable.getLootRow((int) ((modTable.minRoll + modTable.maxRoll) *.05f)); } if (modRow != null) { suffixValue = modRow.getValueOne(); modifierSuffix = modRow.getAction(); } } } } }else{ modGroup = LootTable.modGroups.get(groupRow.getValueTwo()); if (modGroup != null) { for (int a = 0;a<10;a++){ roll = ThreadLocalRandom.current().nextInt(100) + 1; modRow = modGroup.getLootRow(roll); if (modRow != null) break; } if (modRow != null) { subTableID = modRow.getValueOne(); if (LootTable.modTables.containsKey(subTableID)) { modTable = LootTable.modTables.get(subTableID); roll = gaussianLevel((int)calculatedMobLevel); if (roll < modTable.minRoll) roll = (int) modTable.minRoll; if (roll > modTable.maxRoll) roll = (int) modTable.maxRoll; modRow = modTable.getLootRow(roll); if (modRow == null){ modRow = modTable.getLootRow((int) ((modTable.minRoll + modTable.maxRoll) *.05f)); } if (modRow != null) { prefixValue = modRow.getValueOne(); modifierPrefix = modRow.getAction(); } } } } //get modifierSuffix modGroup = LootTable.modGroups.get(groupRow.getValueThree()); if (modGroup != null) { for (int a = 0;a<10;a++){ roll = ThreadLocalRandom.current().nextInt(100) + 1; modRow = modGroup.getLootRow(roll); if (modRow != null) break; } if (modRow != null) { subTableID = modRow.getValueOne(); if (LootTable.modTables.containsKey(subTableID)) { modTable = LootTable.modTables.get(subTableID); roll = gaussianLevel((int)calculatedMobLevel); if (roll < modTable.minRoll) roll = (int) modTable.minRoll; if (roll > modTable.maxRoll) roll = (int) modTable.maxRoll; modRow = modTable.getLootRow(roll); if (modRow == null){ modRow = modTable.getLootRow((int) ((modTable.minRoll + modTable.maxRoll) *.05f)); } if (modRow != null) { suffixValue = modRow.getValueOne(); modifierSuffix = modRow.getAction(); } } } } } itemBase = ItemBase.getItemBase(itemBaseUUID); byte charges = (byte) itemBase.getNumCharges(); short dur = (short) itemBase.getDurability(); short weight = itemBase.getWeight(); if (!gambler.getCharItemManager().hasRoomInventory(weight)) { return null; } Item gambledItem = new Item(itemBase, gambler.getObjectUUID(), OwnerType.PlayerCharacter, charges, charges, dur, dur, true, false,ItemContainerType.INVENTORY,(byte) 0, new ArrayList<>(),""); if (spawnQuanity == 0 && itemBase.getType().equals(ItemType.RESOURCE)) spawnQuanity = 1; if (spawnQuanity > 0) item.setNumOfItems(spawnQuanity); try { gambledItem = DbManager.ItemQueries.ADD_ITEM(gambledItem); } catch (Exception e) { Logger.error(e); } if (gambledItem == null) { return null; } if (!modifierPrefix.isEmpty()) gambledItem.addPermanentEnchantment(modifierPrefix, 0); if (!modifierSuffix.isEmpty()) gambledItem.addPermanentEnchantment(modifierSuffix, 0); //add item to inventory gambler.getCharItemManager().addItemToInventory(gambledItem); gambler.getCharItemManager().updateInventory(); return gambledItem; } }