diff --git a/src/engine/db/handlers/dbItemHandler.java b/src/engine/db/handlers/dbItemHandler.java index 2fc9b64e..4cd9f336 100644 --- a/src/engine/db/handlers/dbItemHandler.java +++ b/src/engine/db/handlers/dbItemHandler.java @@ -504,4 +504,24 @@ public class dbItemHandler extends dbHandlerBase { return false; } } + + public boolean UPDATE_NUM_ITEMS(final Item item, int newValue, int oldValue) { + + if (item.getItemBase().getType().equals(ItemType.GOLD)) + return false; + + try (Connection connection = DbManager.getConnection(); + PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `obj_item` SET `item_numberOfItems`=? WHERE `UID`=?")) { + + preparedStatement.setInt(1, newValue); + preparedStatement.setLong(2, item.getObjectUUID()); + + return (preparedStatement.executeUpdate() > 0); + + } catch (SQLException e) { + Logger.error(e); + return false; + } + + } } diff --git a/src/engine/devcmd/cmds/SetLevelCmd.java b/src/engine/devcmd/cmds/SetLevelCmd.java index 47be4ff6..df3e2ee2 100644 --- a/src/engine/devcmd/cmds/SetLevelCmd.java +++ b/src/engine/devcmd/cmds/SetLevelCmd.java @@ -14,6 +14,7 @@ import engine.devcmd.AbstractDevCmd; import engine.gameManager.ChatManager; import engine.objects.AbstractGameObject; import engine.objects.PlayerCharacter; +import engine.server.MBServerStatics; public class SetLevelCmd extends AbstractDevCmd { @@ -46,7 +47,7 @@ public class SetLevelCmd extends AbstractDevCmd { this.sendUsage(pc); return; } - if (level < 1 || level > 75) { + if (level < 1 || level > MBServerStatics.LEVELCAP) { this.sendHelp(pc); return; } @@ -62,7 +63,7 @@ public class SetLevelCmd extends AbstractDevCmd { @Override protected String _getHelpString() { - return "Sets your character's level to 'amount'. 'amount' must be between 1-75"; + return "Sets your character's level to 'amount'. 'amount' must be between 1-" + MBServerStatics.LEVELCAP; } @Override diff --git a/src/engine/gameManager/CombatManager.java b/src/engine/gameManager/CombatManager.java index 269d807f..c1f7b3a3 100644 --- a/src/engine/gameManager/CombatManager.java +++ b/src/engine/gameManager/CombatManager.java @@ -1277,6 +1277,9 @@ public enum CombatManager { if(ac.getObjectType().equals(GameObjectType.PlayerCharacter)){ range += ((PlayerCharacter)ac).getCharacterHeight() * 0.5f; + if(ac.isMoving()){ + range += ((PlayerCharacter) ac).getCharacterHeight(); + } } float magnitudeSquared = tl.distanceSquared(sl); diff --git a/src/engine/gameManager/LootManager.java b/src/engine/gameManager/LootManager.java index b0cc259b..538e69ff 100644 --- a/src/engine/gameManager/LootManager.java +++ b/src/engine/gameManager/LootManager.java @@ -73,38 +73,38 @@ public enum LootManager { } public static void GenerateMobLoot(Mob mob) { + int mobBootySet = mob.getMobBase().bootySet; + if (mobBootySet != 0) { + RunBootySetIfPresent(mobBootySet, mob); + } - //iterate the booty sets - - if (mob.getMobBase().bootySet != 0 && _bootySetMap.containsKey(mob.getMobBase().bootySet) == true) - RunBootySet(_bootySetMap.get(mob.getMobBase().bootySet), mob); - - if (mob.bootySet != 0 && _bootySetMap.containsKey(mob.bootySet) == true) - RunBootySet(_bootySetMap.get(mob.bootySet), mob); - - //lastly, check mobs inventory for godly or disc runes to send a server announcement - for (Item it : mob.getInventory()) { + mobBootySet = mob.bootySet; + if (mobBootySet != 0) { + RunBootySetIfPresent(mobBootySet, mob); + } - ItemBase ib = it.getItemBase(); - if(ib == null) - break; - if (ib.getName().toLowerCase().contains("of the gods")) { - ChatSystemMsg chatMsg = new ChatSystemMsg(null, mob.getName() + " in " + mob.getParentZone().getName() + " has found the " + ib.getName() + ". Are you tough enough to take it?"); - chatMsg.setMessageType(10); - chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID()); - DispatchMessage.dispatchMsgToAll(chatMsg); - } + // Check mob's inventory for godly or disc runes to send a server announcement + for (Item item : mob.getInventory()) { + ItemBase itemBase = item.getItemBase(); + if (itemBase != null && itemBase.getName().toLowerCase().contains("of the gods")) { + ChatSystemMsg chatMsg = new ChatSystemMsg( + null, + mob.getName() + " in " + mob.getParentZone().getName() + " has found the " + itemBase.getName() + ". Are you tough enough to take it?" + ); + chatMsg.setMessageType(10); + chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID()); + DispatchMessage.dispatchMsgToAll(chatMsg); } - + } } private static void RunBootySet(ArrayList entries, Mob mob) { - float dropRate = NORMAL_DROP_RATE; - //roll the geenric world drop table - if(mob.parentZone.getSafeZone() == 0) { + boolean isSafeZone = mob.parentZone.getSafeZone() == 0; + + if (isSafeZone) { GenerateLootDrop(mob, 1300); - if(ThreadLocalRandom.current().nextInt(1, 10000) == 5000) { + if (ThreadLocalRandom.current().nextInt(1, 10000) == 5000) { MobLoot extraLoot = rollForGlass(mob); if (extraLoot != null) { mob.getCharItemManager().addItemToInventory(extraLoot); @@ -112,7 +112,6 @@ public enum LootManager { } } - // Iterate all entries in this bootySet and process accordingly boolean hasExtraRolled = false; for (BootySetEntry bse : entries) { switch (bse.bootyType) { @@ -120,169 +119,161 @@ public enum LootManager { GenerateGoldDrop(mob, bse); break; case "LOOT": - if (ThreadLocalRandom.current().nextInt(1, 100 + 1) < (bse.dropChance * dropRate)) - GenerateLootDrop(mob, bse.genTable); //generate normal loot drop - if (mob.parentZone.getSafeZone() == 0 && hasExtraRolled == false && ThreadLocalRandom.current().nextInt(1, 5000) < 15 * dropRate) { - int roll = ThreadLocalRandom.current().nextInt(1, 101); - MobLoot extraLoot = null; - if (roll <= 50) { - extraLoot = rollForContract(bse.genTable, mob); - } - if (roll >= 51) { - extraLoot = rollForRune(bse.genTable, mob); - } - if (extraLoot != null) { - mob.getCharItemManager().addItemToInventory(extraLoot); - } - hasExtraRolled = true; + if (ThreadLocalRandom.current().nextInt(1, 101) < (bse.dropChance * dropRate)) { + GenerateLootDrop(mob, bse.genTable); + } + if (isSafeZone && !hasExtraRolled && ThreadLocalRandom.current().nextInt(1, 5000) < 15 * dropRate) { + MobLoot extraLoot = (ThreadLocalRandom.current().nextInt(1, 101) <= 50) + ? rollForContract(bse.genTable, mob) + : rollForRune(bse.genTable, mob); + if (extraLoot != null) { + mob.getCharItemManager().addItemToInventory(extraLoot); } + hasExtraRolled = true; + } break; case "ITEM": GenerateInventoryDrop(mob, bse); break; } } + + MobLoot specialDrop = getSpecialDropForMob(mob); + if (specialDrop != null) { + enhanceMob(mob, specialDrop); + } + } + + private static void RunBootySetIfPresent(int bootySet, Mob mob) { + if (_bootySetMap.containsKey(bootySet)) { + RunBootySet(_bootySetMap.get(bootySet), mob); + } + } + + private static MobLoot getSpecialDropForMob(Mob mob) { MobLoot specialDrop = null; - switch(mob.getObjectUUID()) { - case 22595://elf 1 - specialDrop = new MobLoot(mob,ItemBase.getItemBase(252134),true); - mob.setFirstName("Melandrach The Blood-Mage"); + int mobUUID = mob.getObjectUUID(); + switch (mobUUID) { + case 22595: + specialDrop = createSpecialDrop(mob, 252134, "Melandrach The Blood-Mage"); break; - case 22432: //elf 2 - specialDrop = new MobLoot(mob,ItemBase.getItemBase(252135),true); - mob.setFirstName("Kyrtaar The Blood-Mage"); + case 22432: + specialDrop = createSpecialDrop(mob, 252135, "Kyrtaar The Blood-Mage"); break; - case 22537: //elf 3 - specialDrop = new MobLoot(mob,ItemBase.getItemBase(252136),true); - mob.setFirstName("Vamir The Blood-Mage"); + case 22537: + specialDrop = createSpecialDrop(mob, 252136, "Vamir The Blood-Mage"); break; - case 16387: //human 4 DONE - specialDrop = new MobLoot(mob,ItemBase.getItemBase(252129),true); - mob.setFirstName("Alatar The Blood-Mage"); + case 16387: + specialDrop = createSpecialDrop(mob, 252129, "Alatar The Blood-Mage"); break; - case 32724:// human 5 GOOD - specialDrop = new MobLoot(mob,ItemBase.getItemBase(252130),true); - mob.setFirstName("Elphaba The Blood-Mage"); + case 32724: + specialDrop = createSpecialDrop(mob, 252130, "Elphaba The Blood-Mage"); break; - case 23379: //human 1 GOOD - specialDrop = new MobLoot(mob,ItemBase.getItemBase(252131),true); - mob.setFirstName("Bavmorda The Blood-Mage"); + case 23379: + specialDrop = createSpecialDrop(mob, 252131, "Bavmorda The Blood-Mage"); break; - case 10826: //human 2 REDO - specialDrop = new MobLoot(mob,ItemBase.getItemBase(252132),true); - mob.setFirstName("Draco The Blood-Mage"); + case 10826: + specialDrop = createSpecialDrop(mob, 252132, "Draco The Blood-Mage"); break; - case 15929: //human 3 GOOD - specialDrop = new MobLoot(mob,ItemBase.getItemBase(252133),true); - mob.setFirstName("Atlantes The Blood-Mage"); + case 15929: + specialDrop = createSpecialDrop(mob, 252133, "Atlantes The Blood-Mage"); break; } - if(specialDrop != null) { - mob.setLevel((short) 65); - mob.setSpawnTime(10800); - mob.healthMax = (7500); - mob.setHealth(7500); - ChatSystemMsg chatMsg = new ChatSystemMsg(null, mob.getName() + " in " + mob.getParentZone().getName() + " has found the " + specialDrop.getName() + ". Are you tough enough to take it?"); - chatMsg.setMessageType(10); - chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID()); - DispatchMessage.dispatchMsgToAll(chatMsg); - mob.getCharItemManager().addItemToInventory(specialDrop); - mob.setResists(new Resists("Dropper")); - } + return specialDrop; } - public static MobLoot getGenTableItem(int genTableID, AbstractCharacter mob) { - - if (mob == null || _genTables.containsKey(genTableID) == false) - return null; + private static MobLoot createSpecialDrop(Mob mob, int itemBaseId, String name) { + mob.setFirstName(name); + return new MobLoot(mob, ItemBase.getItemBase(itemBaseId), true); + } - MobLoot outItem; + private static void enhanceMob(Mob mob, MobLoot specialDrop) { + mob.setLevel((short) 65); + mob.setSpawnTime(10800); + mob.healthMax = 7500; + mob.setHealth(7500); + ChatSystemMsg chatMsg = new ChatSystemMsg(null, mob.getName() + " in " + mob.getParentZone().getName() + " has found the " + specialDrop.getName() + ". Are you tough enough to take it?"); + chatMsg.setMessageType(10); + chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID()); + DispatchMessage.dispatchMsgToAll(chatMsg); + mob.getCharItemManager().addItemToInventory(specialDrop); + mob.setResists(new Resists("Dropper")); + } - int genRoll = ThreadLocalRandom.current().nextInt(1,94 + 1); + public static MobLoot getGenTableItem(int genTableID, AbstractCharacter mob) { + if (mob == null || !_genTables.containsKey(genTableID)) { + return null; + } + int genRoll = ThreadLocalRandom.current().nextInt(1, 95); GenTableEntry selectedRow = GenTableEntry.rollTable(genTableID, genRoll, 1.0f); - if (selectedRow == null) + if (selectedRow == null || !_itemTables.containsKey(selectedRow.itemTableID)) { return null; + } - int itemTableId = selectedRow.itemTableID; + int itemTableRoll = (mob.getObjectType().ordinal() == 52) ? + ThreadLocalRandom.current().nextInt(1, 321) : + TableRoll(mob.level); - if (_itemTables.containsKey(itemTableId) == false) - return null; + ItemTableEntry tableRow = ItemTableEntry.rollTable(selectedRow.itemTableID, itemTableRoll); - //gets the 1-320 roll for this mob - int itemTableRoll = 0; - int objectType = mob.getObjectType().ordinal(); - if(mob.getObjectType().ordinal() == 52) { //52 = player character - itemTableRoll = ThreadLocalRandom.current().nextInt(1,320 + 1); - } else{ - itemTableRoll = TableRoll(mob.level); - } - ItemTableEntry tableRow = ItemTableEntry.rollTable(itemTableId, itemTableRoll); - if (tableRow == null) + if (tableRow == null || tableRow.cacheID == 0) { return null; + } - int itemUUID = tableRow.cacheID; - - if (itemUUID == 0) + ItemBase itemBase = ItemBase.getItemBase(tableRow.cacheID); + if (itemBase == null) { return null; + } - if (ItemBase.getItemBase(itemUUID).getType().ordinal() == Enum.ItemType.RESOURCE.ordinal()) { - int chance = ThreadLocalRandom.current().nextInt(1,101); - if(chance > 10) + if (itemBase.getType() == Enum.ItemType.RESOURCE) { + if (ThreadLocalRandom.current().nextInt(1, 101) > 10) { return null; - int amount = ThreadLocalRandom.current().nextInt((int)(tableRow.minSpawn * 0.5f), (int)((tableRow.maxSpawn + 1) * 0.5f)); - return new MobLoot(mob, ItemBase.getItemBase(itemUUID), amount, false); + } + int amount = ThreadLocalRandom.current().nextInt((int) (tableRow.minSpawn * 0.5f), + (int) ((tableRow.maxSpawn + 1) * 0.5f)); + return new MobLoot(mob, itemBase, amount, false); } - outItem = new MobLoot(mob, ItemBase.getItemBase(itemUUID), false); - Enum.ItemType outType = outItem.getItemBase().getType(); - - - if(selectedRow.pModTable != 0){ - try { + MobLoot outItem = new MobLoot(mob, itemBase, false); + try { + if (selectedRow.pModTable != 0) { outItem = GeneratePrefix(mob, outItem, genTableID, genRoll); outItem.setIsID(false); - } catch (Exception e) { - Logger.error("Failed to GeneratePrefix for item: " + outItem.getName()); } - } - if(selectedRow.sModTable != 0){ - try { + if (selectedRow.sModTable != 0) { outItem = GenerateSuffix(mob, outItem, genTableID, genRoll); outItem.setIsID(false); - } catch (Exception e) { - Logger.error("Failed to GenerateSuffix for item: " + outItem.getName()); } + } catch (Exception e) { + Logger.error("Failed to generate mod for item: " + outItem.getName(), e); } + return outItem; } private static MobLoot GeneratePrefix(AbstractCharacter mob, MobLoot inItem, int genTableID, int genRoll) { - GenTableEntry selectedRow = GenTableEntry.rollTable(genTableID, genRoll, 1.0f); - - if (selectedRow == null) + if (selectedRow == null) { return inItem; + } - int prefixroll = ThreadLocalRandom.current().nextInt(1, 100 + 1); - - ModTypeTableEntry prefixTable = ModTypeTableEntry.rollTable(selectedRow.pModTable, prefixroll); - - if (prefixTable == null) + ModTypeTableEntry prefixTable = ModTypeTableEntry.rollTable(selectedRow.pModTable, ThreadLocalRandom.current().nextInt(1, 101)); + if (prefixTable == null) { return inItem; - int prefixTableRoll = 0; - if(mob.getObjectType().ordinal() == 52) { - prefixTableRoll = ThreadLocalRandom.current().nextInt(1,320 + 1); - } else{ - prefixTableRoll = TableRoll(mob.level); } - ModTableEntry prefixMod = ModTableEntry.rollTable(prefixTable.modTableID, prefixTableRoll); - if (prefixMod == null) + int prefixTableRoll = (mob.getObjectType().ordinal() == 52) ? + ThreadLocalRandom.current().nextInt(1, 321) : + TableRoll(mob.level); + + ModTableEntry prefixMod = ModTableEntry.rollTable(prefixTable.modTableID, prefixTableRoll); + if (prefixMod == null) { return inItem; + } - if (prefixMod.action.length() > 0) { + if (!prefixMod.action.isEmpty()) { inItem.setPrefix(prefixMod.action); inItem.addPermanentEnchantment(prefixMod.action, 0, prefixMod.level, true); } @@ -291,30 +282,26 @@ public enum LootManager { } private static MobLoot GenerateSuffix(AbstractCharacter mob, MobLoot inItem, int genTableID, int genRoll) { - GenTableEntry selectedRow = GenTableEntry.rollTable(genTableID, genRoll, 1.0f); - - if (selectedRow == null) + if (selectedRow == null) { return inItem; + } - int suffixRoll = ThreadLocalRandom.current().nextInt(1, 100 + 1); - - ModTypeTableEntry suffixTable = ModTypeTableEntry.rollTable(selectedRow.sModTable, suffixRoll); - - if (suffixTable == null) + ModTypeTableEntry suffixTable = ModTypeTableEntry.rollTable(selectedRow.sModTable, ThreadLocalRandom.current().nextInt(1, 101)); + if (suffixTable == null) { return inItem; - int suffixTableRoll = 0; - if(mob.getObjectType().ordinal() == 52) { - suffixTableRoll = ThreadLocalRandom.current().nextInt(1,320 + 1); - } else{ - suffixTableRoll = TableRoll(mob.level); } - ModTableEntry suffixMod = ModTableEntry.rollTable(suffixTable.modTableID, suffixTableRoll); - if (suffixMod == null) + int suffixTableRoll = (mob.getObjectType().ordinal() == 52) ? + ThreadLocalRandom.current().nextInt(1, 321) : + TableRoll(mob.level); + + ModTableEntry suffixMod = ModTableEntry.rollTable(suffixTable.modTableID, suffixTableRoll); + if (suffixMod == null) { return inItem; + } - if (suffixMod.action.length() > 0) { + if (!suffixMod.action.isEmpty()) { inItem.setSuffix(suffixMod.action); inItem.addPermanentEnchantment(suffixMod.action, 0, suffixMod.level, false); } @@ -323,150 +310,141 @@ public enum LootManager { } public static int TableRoll(int mobLevel) { + mobLevel = Math.min(mobLevel, 65); - if (mobLevel > 65) - mobLevel = 65; - - int max = (int) (4.882 * mobLevel + 127.0); - - if (max > 319) - max = 319; + int max = Math.min((int) (4.882 * mobLevel + 127.0), 319); + int min = Math.max((int) (4.469 * mobLevel - 3.469), 70); - int min = (int) (4.469 * mobLevel - 3.469); - - if (min < 70) - min = 70; - - int roll = ThreadLocalRandom.current().nextInt(min, max + 1); - - return roll; + return ThreadLocalRandom.current().nextInt(min, max + 1); } public static void GenerateGoldDrop(Mob mob, BootySetEntry bse) { + int chanceRoll = ThreadLocalRandom.current().nextInt(1, 101); // Simplified the chance roll to be out of 100 directly - int chanceRoll = ThreadLocalRandom.current().nextInt(1, 100 + 1); - - //early exit, failed to hit minimum chance roll - - if (chanceRoll > bse.dropChance) + // Early exit if failed to hit minimum chance roll + if (chanceRoll > bse.dropChance) { return; + } - //determine and add gold to mob inventory - - int high = (int)(bse.highGold * NORMAL_GOLD_RATE); - int low = (int)(bse.lowGold * NORMAL_GOLD_RATE); + // Determine and add gold to mob inventory + int high = (int) (bse.highGold * NORMAL_GOLD_RATE); + int low = (int) (bse.lowGold * NORMAL_GOLD_RATE); int gold = ThreadLocalRandom.current().nextInt(low, high); if (gold > 0) { MobLoot goldAmount = new MobLoot(mob, gold); mob.getCharItemManager().addItemToInventory(goldAmount); } - } public static void GenerateLootDrop(Mob mob, int tableID) { + if (mob.parentZone.getSafeZone() == 1) { + return; // Exit early if in a safe zone + } try { - if(mob.parentZone.getSafeZone() == 1) { - return; - } MobLoot toAdd = getGenTableItem(tableID, mob); - if(toAdd.getItemBase().getType().equals(Enum.ItemType.CONTRACT) || toAdd.getItemBase().getType().equals(Enum.ItemType.RUNE)) - return;//block all contracts and runes that drop outside the confines of the new system - - if (toAdd != null) { + if (toAdd != null && !isContractOrRune(toAdd)) { toAdd.setIsID(true); mob.getCharItemManager().addItemToInventory(toAdd); } } catch (Exception e) { - //TODO chase down loot generation error, affects roughly 2% of drops + // Handle exceptions if necessary } } - public static void GenerateEquipmentDrop(Mob mob) { + private static boolean isContractOrRune(MobLoot loot) { + Enum.ItemType type = loot.getItemBase().getType(); + return type == Enum.ItemType.CONTRACT || type == Enum.ItemType.RUNE; + } - if(mob.parentZone.getSafeZone() == 1) { + public static void GenerateEquipmentDrop(Mob mob) { + if (mob.parentZone.getSafeZone() == 1) { return; } - //do equipment here int dropCount = 0; - if (mob.getEquip() != null) + if (mob.getEquip() != null) { for (MobEquipment me : mob.getEquip().values()) { - - if (me.getDropChance() == 0) + if (me.getDropChance() == 0) { continue; + } - float equipmentRoll = ThreadLocalRandom.current().nextInt(1, 100 + 1); + float equipmentRoll = ThreadLocalRandom.current().nextInt(1, 101); // Simplified the roll to be out of 100 directly float dropChance = me.getDropChance() * 100; - if (equipmentRoll > dropChance) + + if (equipmentRoll > dropChance) { continue; + } + ItemBase genericIB = me.getItemBase(); - if(genericIB.isVorg()){ - if(genericIB.isClothArmor()){ - //get random cloth piece - genericIB = getRandomVorgCloth();//ItemBase.getItemBase(vorg_cloth_uuids.get(ThreadLocalRandom.current().nextInt(0,vorg_cloth_uuids.size() - 1))); - } else if(genericIB.isHeavyArmor()){ - //get random heavy armor piece - genericIB = getRandomVorgHA();//ItemBase.getItemBase(vorg_ha_uuids.get(ThreadLocalRandom.current().nextInt(0,vorg_ha_uuids.size() - 1))); - } else if(genericIB.isMediumArmor()){ - //get random medium armor piece - genericIB = getRandomVorgMA();//ItemBase.getItemBase(vorg_ma_uuids.get(ThreadLocalRandom.current().nextInt(0,vorg_ma_uuids.size() - 1))); - } else if(genericIB.isLightArmor()){ - //get random light armor piece - genericIB = getRandomVorgLA();//ItemBase.getItemBase(vorg_la_uuids.get(ThreadLocalRandom.current().nextInt(0,vorg_la_uuids.size() - 1))); - } - mob.spawnTime = ThreadLocalRandom.current().nextInt(300,2700); + if (genericIB.isVorg()) { + genericIB = getRandomVorgPiece(genericIB); // Replaced separate method calls with a single one + mob.spawnTime = ThreadLocalRandom.current().nextInt(300, 2700); } - MobLoot ml = new MobLoot(mob, genericIB, false); - if (ml != null && dropCount < 1 && genericIB.isVorg() == false) { + MobLoot ml = new MobLoot(mob, genericIB, false); + + if (ml != null && dropCount < 1) { ml.setIsID(true); ml.setDurabilityCurrent((short) (ml.getDurabilityCurrent() - ThreadLocalRandom.current().nextInt(5) + 1)); mob.getCharItemManager().addItemToInventory(ml); - dropCount = 1; - //break; // Exit on first successful roll. + dropCount++; } - if(ml != null && genericIB.isVorg() && mob.getMobBaseID() != 14062){ + + if (ml != null && genericIB.isVorg() && mob.getMobBaseID() != 14062) { ml.setIsID(true); ml.setDurabilityCurrent(ml.getDurabilityMax()); mob.getCharItemManager().addItemToInventory(ml); } } + } } - public static void GenerateInventoryDrop(Mob mob, BootySetEntry bse) { + private static ItemBase getRandomVorgPiece(ItemBase genericIB) { + if (genericIB.isClothArmor()) { + return getRandomVorgCloth(); + } else if (genericIB.isHeavyArmor()) { + return getRandomVorgHA(); + } else if (genericIB.isMediumArmor()) { + return getRandomVorgMA(); + } else if (genericIB.isLightArmor()) { + return getRandomVorgLA(); + } + return genericIB; // Return the original item base if it's not a vorg piece + } - if(ItemBase.getItemBase(bse.itemBase).isDiscRune()) { - if(!Mob.disciplineDroppers.contains(mob)) + public static void GenerateInventoryDrop(Mob mob, BootySetEntry bse) { + // Check if the item is a discipline rune + if (ItemBase.getItemBase(bse.itemBase).isDiscRune()) { + if (!Mob.disciplineDroppers.contains(mob)) { Mob.disciplineDroppers.add(mob); - - mob.setResists(new Resists("Dropper")); - ChatSystemMsg chatMsg = new ChatSystemMsg(null, mob.getName() + " in " + mob.getParentZone().getName() + " has found the " + ItemBase.getItemBase(bse.itemBase).getName() + ". Are you tough enough to take it?"); - chatMsg.setMessageType(10); - chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID()); - DispatchMessage.dispatchMsgToAll(chatMsg); + mob.setResists(new Resists("Dropper")); + ChatSystemMsg chatMsg = new ChatSystemMsg(null, mob.getName() + " in " + mob.getParentZone().getName() + " has found the " + ItemBase.getItemBase(bse.itemBase).getName() + ". Are you tough enough to take it?"); + chatMsg.setMessageType(10); + chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID()); + DispatchMessage.dispatchMsgToAll(chatMsg); + } } - //if((bse.itemBase == 3040 || bse.itemBase == 3021) && mob.level < 80){ - // chance = 100; - //} - - if(mob.parentZone.getSafeZone() == 1) { + // Skip drop if mob is in a safe zone + if (mob.parentZone.getSafeZone() == 1) { return; } - int chanceRoll = ThreadLocalRandom.current().nextInt(1, 99); - - //early exit, failed to hit minimum chance roll + // Roll for drop chance + int chanceRoll = ThreadLocalRandom.current().nextInt(1, 100); // Changed upper bound to 100 - if (chanceRoll > bse.dropChance) - return; + // Check if the chance roll exceeds drop chance + if (chanceRoll > bse.dropChance) { + return; // Early exit if the drop chance fails + } + // Create and add the loot item to the mob's inventory MobLoot lootItem = new MobLoot(mob, ItemBase.getItemBase(bse.itemBase), true); - - if (lootItem != null) + if (lootItem != null) { mob.getCharItemManager().addItemToInventory(lootItem); + } } public static void peddleFate(PlayerCharacter playerCharacter, Item gift) { @@ -553,151 +531,75 @@ public enum LootManager { itemMan.updateInventory(); } - public static MobLoot rollForContract(int table, Mob mob){ - - int roll = 99; - if (table == 1900 || table == 1500) - roll = 73; + public static MobLoot rollForContract(int table, Mob mob) { + int roll = (table == 1900 || table == 1500) ? 73 : 99; GenTableEntry selectedRow = GenTableEntry.rollTable(table, roll, 1.0f); - if (selectedRow == null) + if (selectedRow == null) { return null; + } int itemTableId = selectedRow.itemTableID; - - if (_itemTables.containsKey(itemTableId) == false) - return null; - ItemTableEntry tableRow = ItemTableEntry.rollTable(itemTableId, ThreadLocalRandom.current().nextInt(1,321)); - if (tableRow == null) + if (!_itemTables.containsKey(itemTableId)) { return null; + } - int itemUUID = tableRow.cacheID; - - if (itemUUID == 0) + ItemTableEntry tableRow = ItemTableEntry.rollTable(itemTableId, ThreadLocalRandom.current().nextInt(1, 321)); + if (tableRow == null || tableRow.cacheID == 0) { return null; + } - MobLoot outItem = new MobLoot(mob, ItemBase.getItemBase(itemUUID), false); - if(outItem != null) - return outItem; - return null; + return new MobLoot(mob, ItemBase.getItemBase(tableRow.cacheID), false); } - public static MobLoot rollForRune(int table, Mob mob){ - int roll = 97; - if(table == 1900 || table == 1500){ - roll = 77; - } + + public static MobLoot rollForRune(int table, Mob mob) { + int roll = (table == 1900 || table == 1500) ? 77 : 97; GenTableEntry selectedRow = GenTableEntry.rollTable(table, roll, 1.0f); - if (selectedRow == null) + if (selectedRow == null) { return null; + } int itemTableId = selectedRow.itemTableID; - - if (_itemTables.containsKey(itemTableId) == false) + if (!_itemTables.containsKey(itemTableId)) { return null; - ItemTableEntry tableRow = ItemTableEntry.rollTable(itemTableId, ThreadLocalRandom.current().nextInt(1,321)); - if (tableRow == null) - return null; - - int itemUUID = tableRow.cacheID; + } - if (itemUUID == 0) + ItemTableEntry tableRow = ItemTableEntry.rollTable(itemTableId, ThreadLocalRandom.current().nextInt(1, 321)); + if (tableRow == null || tableRow.cacheID == 0) { return null; + } - MobLoot outItem = new MobLoot(mob, ItemBase.getItemBase(itemUUID), false); - if(outItem != null) - return outItem; - return null; + return new MobLoot(mob, ItemBase.getItemBase(tableRow.cacheID), false); } - public static MobLoot rollForGlass( Mob mob){ - ItemTableEntry tableRow = ItemTableEntry.rollTable(126, ThreadLocalRandom.current().nextInt(1,321)); - if (tableRow == null) - return null; - int itemUUID = tableRow.cacheID; - - if (itemUUID == 0) - return null; - - MobLoot outItem = new MobLoot(mob, ItemBase.getItemBase(itemUUID), false); - if(outItem != null) - return outItem; + public static MobLoot rollForGlass(Mob mob) { + ItemTableEntry tableRow = ItemTableEntry.rollTable(126, ThreadLocalRandom.current().nextInt(1, 321)); + if (tableRow != null && tableRow.cacheID != 0) { + return new MobLoot(mob, ItemBase.getItemBase(tableRow.cacheID), false); + } return null; } - public static ItemBase getRandomVorgCloth(){ - int random = ThreadLocalRandom.current().nextInt(100); - if(random < 20) - return ItemBase.getItemBase(27600); - if(random > 20 && random < 40) - return ItemBase.getItemBase(188700); - if(random > 40 && random < 60) - return ItemBase.getItemBase(188720); - if(random > 60 && random < 80) - return ItemBase.getItemBase(189550); - if(random > 80) - return ItemBase.getItemBase(189560); - return null; + public static ItemBase getRandomVorgItem(int maxRandom, int... itemBaseIDs) { + int random = ThreadLocalRandom.current().nextInt(maxRandom); + int index = random / (maxRandom / itemBaseIDs.length); + if (index >= itemBaseIDs.length) { + index = itemBaseIDs.length - 1; + } + return ItemBase.getItemBase(itemBaseIDs[index]); + } + public static ItemBase getRandomVorgCloth() { + return getRandomVorgItem(100, 27600, 188700, 188720, 189550, 189560); } - public static ItemBase getRandomVorgLA(){ - int random = ThreadLocalRandom.current().nextInt(160); - if(random < 20) - return ItemBase.getItemBase(27550); - if(random > 20 && random < 40) - return ItemBase.getItemBase(27560); - if(random > 40 && random < 60) - return ItemBase.getItemBase(189100); - if(random > 60 && random < 80) - return ItemBase.getItemBase(189110); - if(random > 80 && random < 100) - return ItemBase.getItemBase(189120); - if(random > 100 && random < 120) - return ItemBase.getItemBase(189130); - if(random > 120 && random < 140) - return ItemBase.getItemBase(189140); - if(random > 140) - return ItemBase.getItemBase(189150); - return null; + public static ItemBase getRandomVorgLA() { + return getRandomVorgItem(160, 27550, 27560, 189100, 189110, 189120, 189130, 189140, 189150); } - public static ItemBase getRandomVorgMA(){ - int random = ThreadLocalRandom.current().nextInt(160); - if(random < 20) - return ItemBase.getItemBase(27570); - if(random > 20 && random < 40) - return ItemBase.getItemBase(188900); - if(random > 40 && random < 60) - return ItemBase.getItemBase(188910); - if(random > 60 && random < 80) - return ItemBase.getItemBase(188920); - if(random > 80 && random < 100) - return ItemBase.getItemBase(188930); - if(random > 100 && random < 120) - return ItemBase.getItemBase(188940); - if(random > 120 && random < 140) - return ItemBase.getItemBase(188950); - if(random > 140) - return ItemBase.getItemBase(189500); - return null; + + public static ItemBase getRandomVorgMA() { + return getRandomVorgItem(160, 27570, 188900, 188910, 188920, 188930, 188940, 188950, 189500); } - public static ItemBase getRandomVorgHA(){ - int random = ThreadLocalRandom.current().nextInt(180); - if(random < 20) - return ItemBase.getItemBase(27580); - if(random > 20 && random < 40) - return ItemBase.getItemBase(27590); - if(random > 40 && random < 60) - return ItemBase.getItemBase(188500); - if(random > 60 && random < 80) - return ItemBase.getItemBase(188510); - if(random > 80 && random < 100) - return ItemBase.getItemBase(188520); - if(random > 100 && random < 120) - return ItemBase.getItemBase(188530); - if(random > 120 && random < 140) - return ItemBase.getItemBase(188540); - if(random > 140 && random < 160) - return ItemBase.getItemBase(188550); - if(random > 160) - return ItemBase.getItemBase(189510); - return null; + + public static ItemBase getRandomVorgHA() { + return getRandomVorgItem(180, 27580, 27590, 188500, 188510, 188520, 188530, 188540, 188550, 189510); } } diff --git a/src/engine/gameManager/ZergManager.java b/src/engine/gameManager/ZergManager.java index 337bc4ed..c92f28d8 100644 --- a/src/engine/gameManager/ZergManager.java +++ b/src/engine/gameManager/ZergManager.java @@ -4,117 +4,51 @@ import engine.objects.Guild; public class ZergManager { - public static int getBaneCap(Guild guild){ - if(guild.getOwnedCity().getTOL().getRank() == 8) - return 20; - - if(guild.getNation().getSubGuildList().size() + 1 <= 4) - return 10; - - return 20; + public static int getBaneCap(Guild guild) { + int cityRank = guild.getOwnedCity().getTOL().getRank(); + return (cityRank == 8) ? 20 : ((guild.getNation().getSubGuildList().size() + 1 <= 4) ? 10 : 20); } - public static float getMultiplier3Man(int count){ - float multiplier = 1.0f; - - if(count <= 3) - return 1.0f; - - if(count > 6) - return 0.0f; - - switch(count){ - case 4: - multiplier -= 0.37f; - break; + public static float getCurrentMultiplier(int count, int maxCount){ + switch(maxCount) { + case 3: + return getMultiplier3Man(count); case 5: - multiplier -= 0.60f; - break; - case 6: - multiplier -= 0.75f; - break; - } - return multiplier; - } - - public static float getMultiplier5Man(int count){ - float multiplier = 1.0f; - - if(count <= 5) - return 1.0f; - - if(count > 10) - return 0.0f; - - switch(count){ - case 6: - multiplier -= 0.25f; - break; - case 7: - multiplier -= 0.43f; - break; - case 8: - multiplier -= 0.56f; - break; - case 9: - multiplier -= 0.67f; - break; + return getMultiplier5Man(count); case 10: - multiplier -= 0.75f; - break; + return getMultiplier10Man(count); + case 20: + return getMultiplier20Man(count); + default: + return getMultiplier40Man(count); } - return multiplier; + } + public static float getMultiplier(int count, int maxCount, float[] thresholds) { + if (count <= maxCount) return 1.0f; + if (count > thresholds.length) return 0.0f; + return 1.0f - thresholds[count - maxCount - 1]; } - public static float getMultiplier10Man(int count){ - float multiplier = 1.0f; - - if(count <= 10) - return 1.0f; + public static float getMultiplier3Man(int count) { + float[] thresholds = {0.37f, 0.60f, 0.75f}; + return getMultiplier(count, 3, thresholds); + } - if(count > 20) - return 0.0f; + public static float getMultiplier5Man(int count) { + float[] thresholds = {0.25f, 0.43f, 0.56f, 0.67f, 0.75f}; + return getMultiplier(count, 5, thresholds); + } - switch(count){ - case 11: - multiplier -= 0.14f; - break; - case 12: - multiplier -= 0.25f; - break; - case 13: - multiplier -= 0.35f; - break; - case 14: - multiplier -= 0.43f; - break; - case 15: - multiplier -= 0.50f; - break; - case 16: - multiplier -= 0.56f; - break; - case 17: - multiplier -= 0.62f; - break; - case 18: - multiplier -= 0.67f; - break; - case 19: - multiplier -= 0.71f; - break; - case 20: - multiplier -= 0.75f; - break; - } - return multiplier; + public static float getMultiplier10Man(int count) { + float[] thresholds = {0.14f, 0.25f, 0.35f, 0.43f, 0.50f, 0.56f, 0.62f, 0.67f, 0.71f, 0.75f}; + return getMultiplier(count, 10, thresholds); } - public static float getMultiplier20Man(int count){ - return getMultiplier10Man(((int)(count * 0.5f))); + public static float getMultiplier20Man(int count) { + return getMultiplier10Man(count * 2); } - public static float getMultiplier40Man(int count){ - return getMultiplier10Man(((int)(count * 0.25f))); + public static float getMultiplier40Man(int count) { + return getMultiplier10Man(count * 4); } -} +} \ No newline at end of file diff --git a/src/engine/mobileAI/MobAI.java b/src/engine/mobileAI/MobAI.java index 571532a0..29fec4ef 100644 --- a/src/engine/mobileAI/MobAI.java +++ b/src/engine/mobileAI/MobAI.java @@ -18,17 +18,16 @@ import engine.mobileAI.Threads.MobAIThread; import engine.mobileAI.utilities.CombatUtilities; import engine.mobileAI.utilities.MovementUtilities; import engine.net.DispatchMessage; -import engine.net.client.msg.PerformActionMsg; import engine.net.client.msg.PowerProjectileMsg; +import engine.net.client.msg.UpdateStateMsg; import engine.objects.*; -import engine.powers.ActionsBase; import engine.powers.PowersBase; import engine.server.MBServerStatics; import org.pmw.tinylog.Logger; -import java.util.ArrayList; import java.util.HashSet; import java.util.Map.Entry; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadLocalRandom; @@ -54,18 +53,6 @@ public class MobAI { return; } } - if (target.getObjectType() == Enum.GameObjectType.PlayerCharacter && canCast(mob)) { - - if (mob.isPlayerGuard() == false && MobCast(mob)) { - mob.updateLocation(); - return; - } - - if (mob.isPlayerGuard() == true && GuardCast(mob)) { - mob.updateLocation(); - return; - } - } if (!CombatUtilities.inRangeToAttack(mob, target)) return; @@ -85,8 +72,6 @@ public class MobAI { break; } - mob.updateLocation(); - } catch (Exception e) { Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackTarget" + " " + e.getMessage()); } @@ -148,7 +133,7 @@ public class MobAI { } if (target.getPet() != null) - if (target.getPet().getCombatTarget() == null && target.getPet().assist == true) + if (target.getPet().getCombatTarget() == null && target.getPet().assist) target.getPet().setCombatTarget(mob); } catch (Exception e) { @@ -251,7 +236,7 @@ public class MobAI { if(target.isAlive()) target.setCombatTarget(mob); - if(target.isPet() && target.isAlive() == false && target.guardCaptain.isAlive() == true){ + if(target.isPet() && !target.isAlive() && target.guardCaptain.isAlive()){ mob.setCombatTarget(target.guardCaptain); } if(mob.isPet()){ @@ -272,7 +257,7 @@ public class MobAI { //early exit while waiting to patrol again - if (mob.stopPatrolTime + (patrolDelay * 1000) > System.currentTimeMillis()) + if (mob.stopPatrolTime + (patrolDelay * 1000L) > System.currentTimeMillis()) return; //guard captains inherit barracks patrol points dynamically @@ -302,7 +287,7 @@ public class MobAI { //make sure mob is out of combat stance - if (minion.getKey().despawned == false) { + if (!minion.getKey().despawned) { if (MovementUtilities.canMove(minion.getKey())) { Vector3f minionOffset = Formation.getOffset(2, minion.getValue() + 3); minion.getKey().updateLocation(); @@ -315,253 +300,6 @@ public class MobAI { } } - public static boolean canCast(Mob mob) { - return false; - //try { - - // Performs validation to determine if a - // mobile in the proper state to cast. - - //if (mob == null) - // return false; - - //if(mob.isPlayerGuard == true){ - - /// int contractID; - - // if (mob.behaviourType.equals(Enum.MobBehaviourType.GuardMinion)) - // contractID = mob.guardCaptain.contract.getContractID(); - // else - // contractID = mob.contract.getContractID(); - - // if(Enum.MinionType.ContractToMinionMap.get(contractID).isMage() == false) - // return false; - //} - - //if (mob.mobPowers.isEmpty()) - // return false; - - //if (!mob.canSee((PlayerCharacter) mob.getCombatTarget())) { - // mob.setCombatTarget(null); - // return false; - // } - // if (mob.nextCastTime == 0) - // mob.nextCastTime = System.currentTimeMillis(); - - // return mob.nextCastTime >= System.currentTimeMillis(); - - //} catch (Exception e) { - // Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: canCast" + " " + e.getMessage()); - //} - //return false; - } - - public static boolean MobCast(Mob mob) { - - try { - // Method picks a random spell from a mobile's list of powers - // and casts it on the current target (or itself). Validation - // (including empty lists) is done previously within canCast(); - - ArrayList powerTokens; - ArrayList purgeTokens; - AbstractCharacter target = (AbstractCharacter) mob.getCombatTarget(); - - if (mob.behaviourType.callsForHelp) - MobCallForHelp(mob); - - // Generate a list of tokens from the mob powers for this mobile. - - powerTokens = new ArrayList<>(mob.mobPowers.keySet()); - purgeTokens = new ArrayList<>(); - - // If player has this effect on them currently then remove - // this token from our list. - - for (int powerToken : powerTokens) { - - PowersBase powerBase = PowersManager.getPowerByToken(powerToken); - - for (ActionsBase actionBase : powerBase.getActions()) { - - String stackType = actionBase.stackType; - - if (target.getEffects() != null && target.getEffects().containsKey(stackType)) - purgeTokens.add(powerToken); - } - } - - powerTokens.removeAll(purgeTokens); - - // Sanity check - - if (powerTokens.isEmpty()) - return false; - - // Pick random spell from our list of powers - - int powerToken = powerTokens.get(ThreadLocalRandom.current().nextInt(powerTokens.size())); - int powerRank = mob.mobPowers.get(powerToken); - - PowersBase mobPower = PowersManager.getPowerByToken(powerToken); - - //check for hit-roll - - if (mobPower.requiresHitRoll) - if (CombatUtilities.triggerDefense(mob, mob.getCombatTarget())) - return false; - - // Cast the spell - - if (CombatUtilities.inRange2D(mob, mob.getCombatTarget(), mobPower.getRange())) { - - PerformActionMsg msg; - - if (!mobPower.isHarmful() || mobPower.targetSelf) { - PowersManager.useMobPower(mob, mob, mobPower, powerRank); - msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, mob); - } else { - PowersManager.useMobPower(mob, target, mobPower, powerRank); - msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target); - } - - msg.setUnknown04(2); - - PowersManager.finishUseMobPower(msg, mob, 0, 0); - long randomCooldown = (long)((ThreadLocalRandom.current().nextInt(10,15) * 1000) * MobAIThread.AI_CAST_FREQUENCY); - - mob.nextCastTime = System.currentTimeMillis() + randomCooldown; - return true; - } - } catch (Exception e) { - Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: MobCast" + " " + e.getMessage()); - } - return false; - } - - public static boolean GuardCast(Mob mob) { - - try { - // Method picks a random spell from a mobile's list of powers - // and casts it on the current target (or itself). Validation - // (including empty lists) is done previously within canCast(); - - ArrayList powerTokens; - ArrayList purgeTokens; - AbstractCharacter target = (AbstractCharacter) mob.getCombatTarget(); - - if (mob.behaviourType.callsForHelp) - MobCallForHelp(mob); - - // Generate a list of tokens from the mob powers for this mobile. - - powerTokens = new ArrayList<>(mob.mobPowers.keySet()); - purgeTokens = new ArrayList<>(); - - // If player has this effect on them currently then remove - // this token from our list. - - for (int powerToken : powerTokens) { - - PowersBase powerBase = PowersManager.getPowerByToken(powerToken); - - for (ActionsBase actionBase : powerBase.getActions()) { - - String stackType = actionBase.stackType; - - if (target.getEffects() != null && target.getEffects().containsKey(stackType)) - purgeTokens.add(powerToken); - } - } - - powerTokens.removeAll(purgeTokens); - - // Sanity check - - if (powerTokens.isEmpty()) - return false; - - int powerToken = 0; - int nukeRoll = ThreadLocalRandom.current().nextInt(1,100); - - if (nukeRoll < 55) { - - //use direct damage spell - powerToken = powerTokens.get(powerTokens.size() - 1); - - } else { - //use random spell - powerToken = powerTokens.get(ThreadLocalRandom.current().nextInt(powerTokens.size())); - } - - int powerRank = 1; - - switch(mob.getRank()){ - case 1: - powerRank = 10; - break; - case 2: - powerRank = 15; - break; - case 3: - powerRank = 20; - break; - case 4: - powerRank = 25; - break; - case 5: - powerRank = 30; - break; - case 6: - powerRank = 35; - break; - case 7: - powerRank = 40; - break; - } - - PowersBase mobPower = PowersManager.getPowerByToken(powerToken); - - //check for hit-roll - - if (mobPower.requiresHitRoll) - if (CombatUtilities.triggerDefense(mob, mob.getCombatTarget())) - return false; - - // Cast the spell - - if (CombatUtilities.inRange2D(mob, mob.getCombatTarget(), mobPower.getRange())) { - - PerformActionMsg msg; - - if (!mobPower.isHarmful() || mobPower.targetSelf) { - - if (mobPower.category.equals("DISPEL")) { - PowersManager.useMobPower(mob, target, mobPower, powerRank); - msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target); - } else { - PowersManager.useMobPower(mob, mob, mobPower, powerRank); - msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, mob); - } - } else { - PowersManager.useMobPower(mob, target, mobPower, powerRank); - msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target); - } - - msg.setUnknown04(2); - - PowersManager.finishUseMobPower(msg, mob, 0, 0); - - long randomCooldown = (long)((ThreadLocalRandom.current().nextInt(10,15) * 1000) * MobAIThread.AI_CAST_FREQUENCY); - mob.nextCastTime = System.currentTimeMillis() + randomCooldown; - return true; - } - } catch (Exception e) { - Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: MobCast" + " " + e.getMessage()); - } - return false; - } - public static void MobCallForHelp(Mob mob) { try { @@ -606,7 +344,7 @@ public class MobAI { if (mob == null) return; - if (mob.getTimestamps().containsKey("lastExecution") == false) + if (!mob.getTimestamps().containsKey("lastExecution")) mob.getTimestamps().put("lastExecution", System.currentTimeMillis()); if (System.currentTimeMillis() < mob.getTimeStamp("lastExecution")) @@ -626,11 +364,11 @@ public class MobAI { if (mob.despawned && mob.isPlayerGuard) { if (mob.behaviourType.equals(Enum.MobBehaviourType.GuardMinion)) { - if (mob.guardCaptain.isAlive() == false || ((Mob) mob.guardCaptain).despawned == true) { + if (!mob.guardCaptain.isAlive() || ((Mob) mob.guardCaptain).despawned) { //minions don't respawn while guard captain is dead - if (mob.isAlive() == false) { + if (!mob.isAlive()) { mob.deathTime = System.currentTimeMillis(); return; } @@ -642,7 +380,7 @@ public class MobAI { //check to send mob home for player guards to prevent exploit of dragging guards away and then teleporting - if (mob.behaviourType.equals(Enum.MobBehaviourType.Pet1) == false) + if (!mob.behaviourType.equals(Enum.MobBehaviourType.Pet1)) CheckToSendMobHome(mob); return; @@ -656,30 +394,16 @@ public class MobAI { } //no players loaded, no need to proceed - if (mob.playerAgroMap.isEmpty()) { - //attempt to reload agro map - HashSet players = WorldGrid.getObjectsInRangePartial(mob.loc, mob.getAggroRange(), MBServerStatics.MASK_PLAYER); - if(players.size() > 0){ - for(AbstractWorldObject player : players){ - if(mob.playerAgroMap.containsKey(player.getObjectUUID()) == false) { - PlayerCharacter pc = (PlayerCharacter) player; - mob.playerAgroMap.put(pc.getObjectUUID(), 0.0f); - } - } - } - - if(mob.getCombatTarget() != null) - mob.setCombatTarget(null); return; } - if (mob.behaviourType.equals(Enum.MobBehaviourType.Pet1) == false) + if (!mob.behaviourType.equals(Enum.MobBehaviourType.Pet1)) CheckToSendMobHome(mob); if (mob.getCombatTarget() != null) { - if (mob.getCombatTarget().isAlive() == false) { + if (!mob.getCombatTarget().isAlive()) { mob.setCombatTarget(null); return; } @@ -688,19 +412,46 @@ public class MobAI { PlayerCharacter target = (PlayerCharacter) mob.getCombatTarget(); - if (mob.playerAgroMap.containsKey(target.getObjectUUID()) == false) { + if (!mob.playerAgroMap.containsKey(target.getObjectUUID())) { mob.setCombatTarget(null); return; } - if (mob.canSee((PlayerCharacter) mob.getCombatTarget()) == false) { + if (!mob.canSee((PlayerCharacter) mob.getCombatTarget())) { mob.setCombatTarget(null); return; } } } + if (mob.isMoving()) { + mob.updateLocation(); + } + if(!mob.isPet()) { + boolean combatState = mob.isCombat(); + mob.setCombat(mob.combatTarget != null); + if (combatState != mob.isCombat()) { + //send message to update combat state + UpdateStateMsg rwss = new UpdateStateMsg(); + rwss.setPlayer(mob); + DispatchMessage.sendToAllInRange(mob, rwss); + } + + boolean walking = mob.isWalk(); + mob.setWalkMode(mob.combatTarget == null); + if (walking != mob.isWalk()) { + //send message to update run/walk state + MovementManager.sendRWSSMsg(mob); + } + }else { + boolean walking = mob.isWalk(); + mob.setWalkMode(mob.guardCaptain.isWalk()); + if (walking != mob.isWalk()) { + //send message to update run/walk state + MovementManager.sendRWSSMsg(mob); + } + } switch (mob.behaviourType) { case GuardCaptain: GuardCaptainLogic(mob); @@ -735,41 +486,34 @@ public class MobAI { if (!aiAgent.isAlive()) return; + if(!pets) { ConcurrentHashMap loadedPlayers = aiAgent.playerAgroMap; + for (Integer playerEntry : loadedPlayers.keySet()) { - for (Entry playerEntry : loadedPlayers.entrySet()) { - - int playerID = (int) playerEntry.getKey(); - PlayerCharacter loadedPlayer = PlayerCharacter.getFromCache(playerID); - + PlayerCharacter loadedPlayer = PlayerCharacter.getFromCache(playerEntry); //Player is null, let's remove them from the list. - if (loadedPlayer == null) { - loadedPlayers.remove(playerID); + loadedPlayers.remove(playerEntry); continue; } - //Player is Dead, Mob no longer needs to attempt to aggro. Remove them from aggro map. - if (!loadedPlayer.isAlive() || loadedPlayer.getHidden() > 0) { - loadedPlayers.remove(playerID); + loadedPlayers.remove(playerEntry); continue; } //Can't see target, skip aggro. - if (!aiAgent.canSee(loadedPlayer)) continue; // No aggro for this race type - - if (aiAgent.notEnemy.size() > 0 && aiAgent.notEnemy.contains(loadedPlayer.getRace().getRaceType().getMonsterType()) == true) + if (aiAgent.notEnemy.size() > 0 && aiAgent.notEnemy.contains(loadedPlayer.getRace().getRaceType().getMonsterType())) continue; //mob has enemies and this player race is not it - if (aiAgent.enemy.size() > 0 && aiAgent.enemy.contains(loadedPlayer.getRace().getRaceType().getMonsterType()) == false) + if (aiAgent.enemy.size() > 0 && !aiAgent.enemy.contains(loadedPlayer.getRace().getRaceType().getMonsterType())) continue; if (MovementUtilities.inRangeToAggro(aiAgent, loadedPlayer)) { @@ -782,7 +526,7 @@ public class MobAI { //look for pets to aggro if no players found to aggro - HashSet awoList = WorldGrid.getObjectsInRangePartial(aiAgent, MobAIThread.AI_BASE_AGGRO_RANGE, MBServerStatics.MASK_PET); + HashSet awoList = WorldGrid.getObjectsInRangePartial(aiAgent, MobAIThread.AI_BASE_AGGRO_RANGE, MBServerStatics.MASK_MOB); for (AbstractWorldObject awoMob : awoList) { @@ -791,6 +535,9 @@ public class MobAI { if (aiAgent.equals(awoMob)) continue; + if(!((Mob)awoMob).isPet()) + continue; + Mob aggroMob = (Mob) awoMob; aiAgent.setCombatTarget(aggroMob); return; @@ -806,27 +553,27 @@ public class MobAI { return; try { + if(mob == null) + return; if (!MovementUtilities.canMove(mob)) return; - mob.updateLocation(); - switch (mob.behaviourType) { case Pet1: - if ((PlayerCharacter) mob.guardCaptain == null) + if (mob.guardCaptain == null) return; - if (!mob.playerAgroMap.containsKey(((PlayerCharacter) mob.guardCaptain).getObjectUUID())) { + if (!mob.playerAgroMap.containsKey(mob.guardCaptain.getObjectUUID())) { //mob no longer has its owner loaded, translocate pet to owner - MovementManager.translocate(mob, ((PlayerCharacter) mob.guardCaptain).getLoc(), null); + MovementManager.translocate(mob, mob.guardCaptain.getLoc(), null); return; } if (mob.getCombatTarget() == null) { @@ -834,11 +581,11 @@ public class MobAI { //move back to owner - if (CombatUtilities.inRange2D(mob, (PlayerCharacter) mob.guardCaptain, 6)) + if (CombatUtilities.inRange2D(mob, mob.guardCaptain, 6)) return; - mob.destination = ((PlayerCharacter) mob.guardCaptain).getLoc(); + mob.destination = mob.guardCaptain.getLoc(); MovementUtilities.moveToLocation(mob, mob.destination, 5); } else chaseTarget(mob); @@ -886,7 +633,6 @@ public class MobAI { if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER_WITH_LOOT) { aiAgent.despawn(); aiAgent.deathTime = System.currentTimeMillis(); - return; } //No items in inventory. } else { @@ -895,14 +641,12 @@ public class MobAI { if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER_ONCE_LOOTED) { aiAgent.despawn(); aiAgent.deathTime = System.currentTimeMillis(); - return; } //Mob never had Loot. } else { if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER) { aiAgent.despawn(); aiAgent.deathTime = System.currentTimeMillis(); - return; } } } @@ -922,14 +666,14 @@ public class MobAI { //checks if mob can attack based on attack timer and range - if (mob.isAlive() == false) + if (!mob.isAlive()) return; if (mob.getCombatTarget() == null) return; - if (mob.getCombatTarget().getObjectType().equals(Enum.GameObjectType.PlayerCharacter) && MovementUtilities.inRangeDropAggro(mob, (PlayerCharacter) mob.getCombatTarget()) == false && - mob.behaviourType.equals(Enum.MobBehaviourType.Pet1) == false) { + if (mob.getCombatTarget().getObjectType().equals(Enum.GameObjectType.PlayerCharacter) && !MovementUtilities.inRangeDropAggro(mob, (PlayerCharacter) mob.getCombatTarget()) && + !mob.behaviourType.equals(Enum.MobBehaviourType.Pet1)) { mob.setCombatTarget(null); return; @@ -955,14 +699,11 @@ public class MobAI { } } - //if (mob.getCombatTarget() != null && CombatUtilities.inRange2D(mob, mob.getCombatTarget(), MobAIThread.AI_BASE_AGGRO_RANGE * 0.5f)) - //return; - if (mob.isPlayerGuard() && !mob.despawned) { City current = ZoneManager.getCityAtLocation(mob.getLoc()); - if (current == null || current.equals(mob.getGuild().getOwnedCity()) == false) { + if (current == null || !current.equals(mob.getGuild().getOwnedCity())) { PowersBase recall = PowersManager.getPowerByToken(-1994153779); PowersManager.useMobPower(mob, mob, recall, 40); @@ -978,14 +719,13 @@ public class MobAI { } } } - } else if (MovementUtilities.inRangeOfBindLocation(mob) == false) { + } else if (!MovementUtilities.inRangeOfBindLocation(mob)) { PowersBase recall = PowersManager.getPowerByToken(-1994153779); PowersManager.useMobPower(mob, mob, recall, 40); mob.setCombatTarget(null); - for (Integer playerEntry : mob.playerAgroMap.keySet()) - mob.playerAgroMap.put(playerEntry,0f); + mob.playerAgroMap.replaceAll((e, v) -> 0f); } } catch (Exception e) { Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckToSendMobHome" + " " + e.getMessage()); @@ -1001,13 +741,16 @@ public class MobAI { return; } } - float rangeSquared = mob.getRange() * mob.getRange(); + float range = mob.getRange(); + if(range < 6) + range = 6; + float rangeSquared = range * range; float distanceSquared = mob.getLoc().distanceSquared2D(mob.getCombatTarget().getLoc()); - if(mob.isMoving() == true && distanceSquared < rangeSquared - 50) { + if(mob.isMoving() && distanceSquared < rangeSquared - 50) { mob.destination = mob.getLoc(); MovementUtilities.moveToLocation(mob, mob.destination, 0); - } else if (CombatUtilities.inRange2D(mob, mob.getCombatTarget(), mob.getRange()) == false) { + } else if (!CombatUtilities.inRange2D(mob, mob.getCombatTarget(), mob.getRange())) { if (mob.getRange() > 15) { mob.destination = mob.getCombatTarget().getLoc(); MovementUtilities.moveToLocation(mob, mob.destination, 0); @@ -1029,7 +772,6 @@ public class MobAI { } } mob.updateMovementState(); - mob.updateLocation(); } catch (Exception e) { Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: chaseTarget" + " " + e.getMessage()); } @@ -1044,7 +786,7 @@ public class MobAI { //dont scan self. - if (mob.equals(awoMob) || (mob.agentType.equals(Enum.AIAgentType.GUARD)) == true || awoMob.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) + if (mob.equals(awoMob) || (mob.agentType.equals(Enum.AIAgentType.GUARD)) || awoMob.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) continue; Mob aggroMob = (Mob) awoMob; @@ -1073,18 +815,6 @@ public class MobAI { if (mob.getCombatTarget() == null) CheckForPlayerGuardAggro(mob); - AbstractWorldObject newTarget = ChangeTargetFromHateValue(mob); - - if (newTarget != null) { - - if (newTarget.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) { - if (GuardCanAggro(mob, (PlayerCharacter) newTarget)) - mob.setCombatTarget(newTarget); - } else - mob.setCombatTarget(newTarget); - - } - CheckMobMovement(mob); CheckForAttack(mob); } catch (Exception e) { @@ -1099,19 +829,6 @@ public class MobAI { if (mob.getCombatTarget() == null) { CheckForPlayerGuardAggro(mob); - } else { - - AbstractWorldObject newTarget = ChangeTargetFromHateValue(mob); - - if (newTarget != null) { - - if (newTarget.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) { - if (GuardCanAggro(mob, (PlayerCharacter) newTarget)) - mob.setCombatTarget(newTarget); - } else - mob.setCombatTarget(newTarget); - - } } }else { if (mob.guardCaptain.getCombatTarget() != null) @@ -1143,7 +860,7 @@ public class MobAI { try { - if (mob.guardCaptain == null && mob.isNecroPet() == false && mob.isSiege() == false) + if (mob.guardCaptain == null && !mob.isNecroPet() && !mob.isSiege()) if (ZoneManager.getSeaFloor().zoneMobSet.contains(mob)) mob.killCharacter("no owner"); @@ -1154,7 +871,7 @@ public class MobAI { //recover health - if (mob.getTimestamps().containsKey("HEALTHRECOVERED") == false) + if (!mob.getTimestamps().containsKey("HEALTHRECOVERED")) mob.getTimestamps().put("HEALTHRECOVERED", System.currentTimeMillis()); if (mob.isSit() && mob.getTimeStamp("HEALTHRECOVERED") < System.currentTimeMillis() + 3000) @@ -1179,7 +896,7 @@ public class MobAI { if (mob.getCombatTarget() == null) SafeGuardAggro(mob); - else if (mob.getCombatTarget().isAlive() == false) + else if (!mob.getCombatTarget().isAlive()) SafeGuardAggro(mob); CheckForAttack(mob); @@ -1194,30 +911,22 @@ public class MobAI { if(mob.combatTarget != null && mob.combatTarget.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)){ PlayerCharacter tar = (PlayerCharacter)mob.combatTarget; - if (mob.canSee(tar) == false) { + if (!mob.canSee(tar)) { mob.setCombatTarget(null); } } if (mob.behaviourType.isAgressive) { - - //AbstractWorldObject newTarget = ChangeTargetFromHateValue(mob); - - //if (newTarget != null) - // mob.setCombatTarget(newTarget); - //else { - - if (mob.getCombatTarget() == null) { - if (mob.behaviourType == Enum.MobBehaviourType.HamletGuard) { - SafeGuardAggro(mob); //safehold guard - }else { - CheckForAggro(mob,false); //normal aggro - if(mob.combatTarget == null) - CheckForAggro(mob,true); // look for pets if no players to aggro - } + if (mob.getCombatTarget() == null) { + if (mob.behaviourType == Enum.MobBehaviourType.HamletGuard) { + SafeGuardAggro(mob); //safehold guard + } else { + CheckForAggro(mob, false); //normal aggro + if (mob.combatTarget == null) + CheckForAggro(mob, true); // look for pets if no players to aggro } } - //} + } //check if mob can move for patrol or moving to target @@ -1245,22 +954,21 @@ public class MobAI { ConcurrentHashMap loadedPlayers = mob.playerAgroMap; - for (Entry playerEntry : loadedPlayers.entrySet()) { + for (Integer playerEntry : loadedPlayers.keySet()) { - int playerID = (int) playerEntry.getKey(); - PlayerCharacter loadedPlayer = PlayerCharacter.getFromCache(playerID); + PlayerCharacter loadedPlayer = PlayerCharacter.getFromCache(playerEntry); //Player is null, let's remove them from the list. if (loadedPlayer == null) { - loadedPlayers.remove(playerID); + loadedPlayers.remove(playerEntry); continue; } //Player is Dead, Mob no longer needs to attempt to aggro. Remove them from aggro map. if (!loadedPlayer.isAlive()) { - loadedPlayers.remove(playerID); + loadedPlayers.remove(playerEntry); continue; } @@ -1271,7 +979,7 @@ public class MobAI { // No aggro for this player - if (GuardCanAggro(mob, loadedPlayer) == false) + if (!GuardCanAggro(mob, loadedPlayer)) continue; if (MovementUtilities.inRangeToAggro(mob, loadedPlayer) && mob.getCombatTarget() == null) { @@ -1292,17 +1000,17 @@ public class MobAI { return false; if (mob.behaviourType.equals(Enum.MobBehaviourType.GuardMinion)) { - if (((Mob) mob.guardCaptain).building.getCity().cityOutlaws.contains(target.getObjectUUID()) == true) { + if (Objects.requireNonNull(mob.guardCaptain.building.getCity()).cityOutlaws.contains(target.getObjectUUID())) { return true; } - } else if (mob.building.getCity().cityOutlaws.contains(target.getObjectUUID()) == true) { + } else if (Objects.requireNonNull(mob.building.getCity()).cityOutlaws.contains(target.getObjectUUID())) { return true; } //first check condemn list for aggro allowed (allies button is checked) - if (ZoneManager.getCityAtLocation(mob.getLoc()).getTOL().reverseKOS) { - for (Entry entry : ZoneManager.getCityAtLocation(mob.getLoc()).getTOL().getCondemned().entrySet()) { + if (Objects.requireNonNull(ZoneManager.getCityAtLocation(mob.getLoc())).getTOL().reverseKOS) { + for (Entry entry : Objects.requireNonNull(ZoneManager.getCityAtLocation(mob.getLoc())).getTOL().getCondemned().entrySet()) { //target is listed individually @@ -1324,7 +1032,7 @@ public class MobAI { //allies button is not checked - for (Entry entry : ZoneManager.getCityAtLocation(mob.getLoc()).getTOL().getCondemned().entrySet()) { + for (Entry entry : Objects.requireNonNull(ZoneManager.getCityAtLocation(mob.getLoc())).getTOL().getCondemned().entrySet()) { //target is listed individually @@ -1355,7 +1063,7 @@ public class MobAI { //early exit for a mob who is already moving to a patrol point //while mob moving, update lastPatrolTime so that when they stop moving the 10 second timer can begin - if (mob.isMoving() == true) { + if (mob.isMoving()) { mob.stopPatrolTime = System.currentTimeMillis(); return; } @@ -1381,7 +1089,7 @@ public class MobAI { //make sure mob is out of combat stance - if (minion.getKey().despawned == false) { + if (!minion.getKey().despawned) { if (MovementUtilities.canMove(minion.getKey())) { Vector3f minionOffset = Formation.getOffset(2, minion.getValue() + 3); minion.getKey().updateLocation(); @@ -1395,40 +1103,4 @@ public class MobAI { Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: randomGuardPatrolPoints" + " " + e.getMessage()); } } - - public static AbstractWorldObject ChangeTargetFromHateValue(Mob mob) { - - if(mob.combatTarget != null) - return mob.combatTarget; - //try { - - // float CurrentHateValue = 0; - // if (mob.getCombatTarget() != null && mob.getCombatTarget().getObjectType().equals(Enum.GameObjectType.Mob)){ - // return mob.getCombatTarget(); - // } - - // if (mob.getCombatTarget() != null && mob.getCombatTarget().getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) - // CurrentHateValue = mob.playerAgroMap.get(mob.combatTarget.getObjectUUID()).floatValue(); - - // AbstractWorldObject mostHatedTarget = null; - - // for (Entry playerEntry : mob.playerAgroMap.entrySet()) { - - // PlayerCharacter potentialTarget = PlayerCharacter.getFromCache((int) playerEntry.getKey()); - - // if (potentialTarget.equals(mob.getCombatTarget())) - // continue; - - // if (potentialTarget != null && mob.playerAgroMap.get(potentialTarget.getObjectUUID()).floatValue() > CurrentHateValue && MovementUtilities.inRangeToAggro(mob, potentialTarget)) { - // CurrentHateValue = mob.playerAgroMap.get(potentialTarget.getObjectUUID()).floatValue(); - // mostHatedTarget = potentialTarget; - // } - - // } - // return mostHatedTarget; - //} catch (Exception e) { - // Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: ChangeTargetFromMostHated" + " " + e.getMessage()); - //} - return null; - } } \ No newline at end of file diff --git a/src/engine/mobileAI/utilities/CombatUtilities.java b/src/engine/mobileAI/utilities/CombatUtilities.java index b5cc958a..ac78f4b1 100644 --- a/src/engine/mobileAI/utilities/CombatUtilities.java +++ b/src/engine/mobileAI/utilities/CombatUtilities.java @@ -12,13 +12,20 @@ package engine.mobileAI.utilities; import engine.Enum.*; import engine.gameManager.ChatManager; import engine.gameManager.CombatManager; +import engine.gameManager.PowersManager; import engine.math.Vector3fImmutable; +import engine.mobileAI.MobAI; +import engine.mobileAI.Threads.MobAIThread; import engine.net.DispatchMessage; +import engine.net.client.msg.PerformActionMsg; import engine.net.client.msg.TargetedActionMsg; import engine.objects.*; +import engine.powers.ActionsBase; +import engine.powers.PowersBase; import engine.server.MBServerStatics; import org.pmw.tinylog.Logger; +import java.util.ArrayList; import java.util.concurrent.ThreadLocalRandom; import static engine.math.FastMath.sqr; @@ -512,4 +519,209 @@ public class CombatUtilities { return agent.getMaxDamageHandOne(); } + public static boolean MobCast(Mob mob) { + + try { + // Method picks a random spell from a mobile's list of powers + // and casts it on the current target (or itself). Validation + // (including empty lists) is done previously within canCast(); + + ArrayList powerTokens; + ArrayList purgeTokens; + AbstractCharacter target = (AbstractCharacter) mob.getCombatTarget(); + + if (mob.behaviourType.callsForHelp) + MobAI.MobCallForHelp(mob); + + // Generate a list of tokens from the mob powers for this mobile. + + powerTokens = new ArrayList<>(mob.mobPowers.keySet()); + purgeTokens = new ArrayList<>(); + + // If player has this effect on them currently then remove + // this token from our list. + + for (int powerToken : powerTokens) { + + PowersBase powerBase = PowersManager.getPowerByToken(powerToken); + + for (ActionsBase actionBase : powerBase.getActions()) { + + String stackType = actionBase.stackType; + + if (target.getEffects() != null && target.getEffects().containsKey(stackType)) + purgeTokens.add(powerToken); + } + } + + powerTokens.removeAll(purgeTokens); + + // Sanity check + + if (powerTokens.isEmpty()) + return false; + + // Pick random spell from our list of powers + + int powerToken = powerTokens.get(ThreadLocalRandom.current().nextInt(powerTokens.size())); + int powerRank = mob.mobPowers.get(powerToken); + + PowersBase mobPower = PowersManager.getPowerByToken(powerToken); + + //check for hit-roll + + if (mobPower.requiresHitRoll) + if (triggerDefense(mob, mob.getCombatTarget())) + return false; + + // Cast the spell + + if (inRange2D(mob, mob.getCombatTarget(), mobPower.getRange())) { + + PerformActionMsg msg; + + if (!mobPower.isHarmful() || mobPower.targetSelf) { + PowersManager.useMobPower(mob, mob, mobPower, powerRank); + msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, mob); + } else { + PowersManager.useMobPower(mob, target, mobPower, powerRank); + msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target); + } + + msg.setUnknown04(2); + + PowersManager.finishUseMobPower(msg, mob, 0, 0); + long randomCooldown = (long)((ThreadLocalRandom.current().nextInt(10,15) * 1000L) * MobAIThread.AI_CAST_FREQUENCY); + + mob.nextCastTime = System.currentTimeMillis() + randomCooldown; + return true; + } + } catch (Exception e) { + Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: MobCast" + " " + e.getMessage()); + } + return false; + } + + public static boolean GuardCast(Mob mob) { + + try { + // Method picks a random spell from a mobile's list of powers + // and casts it on the current target (or itself). Validation + // (including empty lists) is done previously within canCast(); + + ArrayList powerTokens; + ArrayList purgeTokens; + AbstractCharacter target = (AbstractCharacter) mob.getCombatTarget(); + + if (mob.behaviourType.callsForHelp) + MobAI.MobCallForHelp(mob); + + // Generate a list of tokens from the mob powers for this mobile. + + powerTokens = new ArrayList<>(mob.mobPowers.keySet()); + purgeTokens = new ArrayList<>(); + + // If player has this effect on them currently then remove + // this token from our list. + + for (int powerToken : powerTokens) { + + PowersBase powerBase = PowersManager.getPowerByToken(powerToken); + + for (ActionsBase actionBase : powerBase.getActions()) { + + String stackType = actionBase.stackType; + + if (target.getEffects() != null && target.getEffects().containsKey(stackType)) + purgeTokens.add(powerToken); + } + } + + powerTokens.removeAll(purgeTokens); + + // Sanity check + + if (powerTokens.isEmpty()) + return false; + + int powerToken; + int nukeRoll = ThreadLocalRandom.current().nextInt(1,100); + + if (nukeRoll < 55) { + + //use direct damage spell + powerToken = powerTokens.get(powerTokens.size() - 1); + + } else { + //use random spell + powerToken = powerTokens.get(ThreadLocalRandom.current().nextInt(powerTokens.size())); + } + + int powerRank = 1; + + switch(mob.getRank()){ + case 1: + powerRank = 10; + break; + case 2: + powerRank = 15; + break; + case 3: + powerRank = 20; + break; + case 4: + powerRank = 25; + break; + case 5: + powerRank = 30; + break; + case 6: + powerRank = 35; + break; + case 7: + powerRank = 40; + break; + } + + PowersBase mobPower = PowersManager.getPowerByToken(powerToken); + + //check for hit-roll + + if (mobPower.requiresHitRoll) + if (triggerDefense(mob, mob.getCombatTarget())) + return false; + + // Cast the spell + + if (inRange2D(mob, mob.getCombatTarget(), mobPower.getRange())) { + + PerformActionMsg msg; + + if (!mobPower.isHarmful() || mobPower.targetSelf) { + + if (mobPower.category.equals("DISPEL")) { + PowersManager.useMobPower(mob, target, mobPower, powerRank); + msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target); + } else { + PowersManager.useMobPower(mob, mob, mobPower, powerRank); + msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, mob); + } + } else { + PowersManager.useMobPower(mob, target, mobPower, powerRank); + msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target); + } + + msg.setUnknown04(2); + + PowersManager.finishUseMobPower(msg, mob, 0, 0); + + long randomCooldown = (long)((ThreadLocalRandom.current().nextInt(10,15) * 1000L) * MobAIThread.AI_CAST_FREQUENCY); + mob.nextCastTime = System.currentTimeMillis() + randomCooldown; + return true; + } + } catch (Exception e) { + Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: MobCast" + " " + e.getMessage()); + } + return false; + } } diff --git a/src/engine/mobileAI/utilities/MovementUtilities.java b/src/engine/mobileAI/utilities/MovementUtilities.java index 222178c1..088c2a2e 100644 --- a/src/engine/mobileAI/utilities/MovementUtilities.java +++ b/src/engine/mobileAI/utilities/MovementUtilities.java @@ -135,7 +135,6 @@ public class MovementUtilities { public static boolean canMove(Mob agent) { - if (agent.getMobBase() != null && Enum.MobFlagType.SENTINEL.elementOf(agent.getMobBase().getFlags())) return false; @@ -144,16 +143,6 @@ public class MovementUtilities { public static void aiMove(Mob agent, Vector3fImmutable vect, boolean isWalking) { - agent.updateLocation(); - //update our walk/run state. - if (isWalking && !agent.isWalk()) { - agent.setWalkMode(true); - MovementManager.sendRWSSMsg(agent); - } else if (!isWalking && agent.isWalk()) { - agent.setWalkMode(false); - MovementManager.sendRWSSMsg(agent); - } - MoveToPointMsg msg = new MoveToPointMsg(); diff --git a/src/engine/net/client/ClientMessagePump.java b/src/engine/net/client/ClientMessagePump.java index 9a3459b0..ec4ab4ed 100644 --- a/src/engine/net/client/ClientMessagePump.java +++ b/src/engine/net/client/ClientMessagePump.java @@ -148,6 +148,12 @@ public class ClientMessagePump implements NetMsgHandler { pc.setActive(true); pc.setLastTarget(GameObjectType.values()[msg.getTargetType()], msg.getTargetID()); + + if(!pc.getTimestamps().containsKey("lastTab")) + pc.getTimestamps().put("lastTab",System.currentTimeMillis()); + + if(System.currentTimeMillis() - pc.getTimestamps().get("lastTab") < 100) + Logger.error("USE OF /TAR SUSPECTED BY PLAYER: " + pc.getName()); } private static void social(SocialMsg msg, ClientConnection origin) throws MsgSendException { @@ -340,18 +346,11 @@ public class ClientMessagePump implements NetMsgHandler { if (player == null) return; - - if (!NPCVaultBankRangeCheck(player, origin, "bank")) return; CharacterItemManager itemManager = player.getCharItemManager(); - if(msg.getNumItems() < 1 && itemManager.getItemByUUID(msg.getUUID()).getItemBaseID() == 7) { - ChatManager.chatSystemInfo(player, "You Have Attempted To Dupe. Please Don't"); - return;//catch gold dupe for negative numbers - } - if (itemManager == null) return; @@ -404,17 +403,11 @@ public class ClientMessagePump implements NetMsgHandler { if (player == null) return; - if (!NPCVaultBankRangeCheck(player, origin, "bank")) return; CharacterItemManager itemManager = player.getCharItemManager(); - if(msg.getNumItems() < 1 && itemManager.getItemByUUID(msg.getUUID()).getItemBaseID() == 7) { - ChatManager.chatSystemInfo(player, "You Have Attempted To Dupe. Please Don't"); - return;//catch gold dupe for negative numbers - } - if (itemManager == null) return; @@ -458,6 +451,7 @@ public class ClientMessagePump implements NetMsgHandler { dispatch = Dispatch.borrow(player, msg); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); + } private static void transferItemFromVaultToInventory(TransferItemFromVaultToInventoryMsg msg, ClientConnection origin) { @@ -471,6 +465,8 @@ public class ClientMessagePump implements NetMsgHandler { if (player.getAccount() == null) return; player.getAccount().transferItemFromVaultToInventory(msg, origin); + + } //call this if the transfer fails server side to kick the item back to inventory from vault @@ -517,7 +513,6 @@ public class ClientMessagePump implements NetMsgHandler { DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); ChatManager.chatInfoError(player, "Can't transfer to vault: " + reason); - player.getAccount().transferItemFromInventoryToVault(msg, origin); } private static void transferGoldFromVaultToInventory(TransferGoldFromVaultToInventoryMsg msg, ClientConnection origin) { @@ -528,11 +523,6 @@ public class ClientMessagePump implements NetMsgHandler { if (player == null) return; - if(msg.getAmount() < 1) { - ChatManager.chatSystemInfo(player, "You Have Attempted To Dupe. Please Don't"); - return;//catch gold dupe for negative numbers - } - Account account = player.getAccount(); if (account == null) @@ -549,11 +539,6 @@ public class ClientMessagePump implements NetMsgHandler { if (player == null) return; - if(msg.getAmount() < 1) { - ChatManager.chatSystemInfo(player, "You Have Attempted To Dupe. Please Don't"); - return;//catch gold dupe for negative numbers - } - Account account = player.getAccount(); if (account == null) @@ -603,7 +588,7 @@ public class ClientMessagePump implements NetMsgHandler { } if (itemManager.delete(i) == true) { sourcePlayer.getCharItemManager().addGoldToInventory(value,false); - sourcePlayer.getCharItemManager().StackResources(); + sourcePlayer.getCharItemManager().updateInventory(); Dispatch dispatch = Dispatch.borrow(sourcePlayer, msg); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); } @@ -945,7 +930,7 @@ public class ClientMessagePump implements NetMsgHandler { DispatchMessage.dispatchMsgToInterestArea(corpse, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, true); - //player.getCharItemManager().StackResources(); + //player.getCharItemManager().updateInventory(); } //TODO send group loot message if player is grouped and visible @@ -969,9 +954,6 @@ public class ClientMessagePump implements NetMsgHandler { return; } - if(item.getItemBase().getType().equals(ItemType.RESOURCE)) - player.getCharItemManager().StackResources(); - if (item.getItemBase().getType().equals(engine.Enum.ItemType.GOLD)) { // this is done to prevent the temporary goldItem item // (from the mob) from appearing in player's inventory. @@ -1005,7 +987,7 @@ public class ClientMessagePump implements NetMsgHandler { dispatch = Dispatch.borrow(player, newItemMsg); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY); - //player.getCharItemManager().StackResources(); + //player.getCharItemManager().updateInventory(); } //TODO send group loot message if player is grouped and visible @@ -1016,7 +998,6 @@ public class ClientMessagePump implements NetMsgHandler { String text = player.getFirstName() + " has looted " + name + '.'; ChatManager.chatGroupInfoCanSee(player, text); } - } catch (Exception e) { Logger.info(e.getMessage()); } finally { @@ -1024,6 +1005,7 @@ public class ClientMessagePump implements NetMsgHandler { } } + } // called when player types /show @@ -1488,11 +1470,39 @@ public class ClientMessagePump implements NetMsgHandler { ChatManager.chatSystemError(sourcePlayer, "Failed To Buy Item"); return; } - buy = Item.createItemForPlayer(sourcePlayer, ib); - if (buy != null) { - me.transferEnchants(buy); - itemMan.addItemToInventory(buy); - //itemMan.StackResources(); + if(me.getItemBase().getType().equals(ItemType.RESOURCE) && npc.getContractID() == 900){ + boolean stacked = false; + for(Item item : itemMan.getInventory()){ + int itemID = item.getItemBaseID(); + int meID = me.getItemBase().getUUID(); + if(itemID == meID){ + if(Warehouse.maxResources.isEmpty()) + Warehouse.getMaxResources(); + int maxStack = Warehouse.maxResources.get(itemID); + if(maxStack > item.getNumOfItems() + 1){ + item.setNumOfItems(item.getNumOfItems() + 1); + stacked = true; + itemMan.updateInventory(); + DbManager.ItemQueries.UPDATE_NUM_ITEMS(item,item.getNumOfItems(),0); + break; + } + } + } + if(!stacked){ + buy = Item.createItemForPlayer(sourcePlayer, ib); + if (buy != null) { + me.transferEnchants(buy); + itemMan.addItemToInventory(buy); + //itemMan.updateInventory(); + } + } + }else { + buy = Item.createItemForPlayer(sourcePlayer, ib); + if (buy != null) { + me.transferEnchants(buy); + itemMan.addItemToInventory(buy); + //itemMan.updateInventory(); + } } } } @@ -1632,8 +1642,9 @@ public class ClientMessagePump implements NetMsgHandler { // msg.setItemID(buy.getObjectUUID()); Dispatch dispatch = Dispatch.borrow(sourcePlayer, msg); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); - itemMan.StackResources(); + itemMan.updateInventory(); } + } finally { origin.buyLock.unlock(); } @@ -1898,9 +1909,6 @@ public class ClientMessagePump implements NetMsgHandler { s = SessionManager.getSession(origin); protocolMsg = msg.getProtocolMsg(); - PlayerCharacter player = ((ClientConnection) msg.getOrigin()).getPlayerCharacter(); - if(player != null) - player.lastAction = System.currentTimeMillis(); switch (protocolMsg) { case SETSELECTEDOBECT: diff --git a/src/engine/net/client/handlers/DestroyBuildingHandler.java b/src/engine/net/client/handlers/DestroyBuildingHandler.java index 18ce4d05..bf97f9f5 100644 --- a/src/engine/net/client/handlers/DestroyBuildingHandler.java +++ b/src/engine/net/client/handlers/DestroyBuildingHandler.java @@ -62,7 +62,7 @@ public class DestroyBuildingHandler extends AbstractClientMsgHandler { if (city != null) bane = city.getBane(); - if (bane != null && bane.getSiegePhase() == Enum.SiegePhase.WAR) { + if (bane != null) { ErrorPopupMsg.sendErrorPopup(pc, 171); return true; } @@ -71,9 +71,12 @@ public class DestroyBuildingHandler extends AbstractClientMsgHandler { if (blueprint.getBuildingGroup() == BuildingGroup.TOL) return true; - // Can't destroy a shrine - if (blueprint.getBuildingGroup() == BuildingGroup.SHRINE) + // destorying a shrine will yield a rubble pile for looting + if (blueprint.getBuildingGroup() == BuildingGroup.SHRINE) { + building.modifyHealth(-building.getHealth(), origin.getPlayerCharacter()); + building.destroyOrDerank(origin.getPlayerCharacter()); return true; + } // Cannot destroy mines outside of normal mine mechanics diff --git a/src/engine/net/client/handlers/ManageCityAssetMsgHandler.java b/src/engine/net/client/handlers/ManageCityAssetMsgHandler.java index 0fe3c58d..7ba982c1 100644 --- a/src/engine/net/client/handlers/ManageCityAssetMsgHandler.java +++ b/src/engine/net/client/handlers/ManageCityAssetMsgHandler.java @@ -5,6 +5,7 @@ import engine.Enum.DispatchChannel; import engine.Enum.GameObjectType; import engine.exception.MsgSendException; import engine.gameManager.BuildingManager; +import engine.gameManager.DbManager; import engine.gameManager.SessionManager; import engine.gameManager.ZoneManager; import engine.math.Bounds; @@ -62,7 +63,6 @@ public class ManageCityAssetMsgHandler extends AbstractClientMsgHandler { Building building; msg = (ManageCityAssetsMsg) baseMsg; - player = SessionManager.getPlayerCharacter(origin); if (player == null) @@ -72,34 +72,21 @@ public class ManageCityAssetMsgHandler extends AbstractClientMsgHandler { if (building == null) { if (msg.actionType == 14) { - Zone zone = ZoneManager.findSmallestZone(player.getLoc()); - if (!zone.isPlayerCity()) { ErrorPopupMsg.sendErrorMsg(player, "Unable to find city to command."); return true; } - City city = City.GetCityFromCache(zone.getPlayerCityUUID()); - - if (city == null) { - ErrorPopupMsg.sendErrorMsg(player, "Unable to find city to command."); - return true; - } - - if (!city.getGuild().equals(player.getGuild())) { + if (city == null || !city.getGuild().equals(player.getGuild()) || + (!GuildStatusController.isInnerCouncil(player.getGuildStatus()) && + !GuildStatusController.isGuildLeader(player.getGuildStatus()))) { ErrorPopupMsg.sendErrorMsg(player, "You are not in the correct guild to command this city."); return true; } - - if (!GuildStatusController.isInnerCouncil(player.getGuildStatus()) && !GuildStatusController.isGuildLeader(player.getGuildStatus())) { - ErrorPopupMsg.sendErrorMsg(player, "You must be an Inner Council or Guild leader to access city commands."); - return true; - } ManageCityAssetsMsg mca = new ManageCityAssetsMsg(player, building); mca.actionType = 15; - Dispatch dispatch = Dispatch.borrow(player, mca); - DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); + DispatchMessage.dispatchMsgDispatch(Dispatch.borrow(player, mca), DispatchChannel.SECONDARY); } return true; } @@ -111,181 +98,126 @@ public class ManageCityAssetMsgHandler extends AbstractClientMsgHandler { outMsg.setTargetType(building.getObjectType().ordinal()); outMsg.setTargetID(building.getObjectUUID()); outMsg.setAssetName(building.getName()); - Dispatch dispatch = Dispatch.borrow(player, outMsg); - DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); + DispatchMessage.dispatchMsgDispatch(Dispatch.borrow(player, outMsg), DispatchChannel.SECONDARY); return true; } - if (msg.actionType == 2 || msg.actionType == 22) { - - if (building.getBlueprint() != null && building.getBlueprint().getBuildingGroup() == engine.Enum.BuildingGroup.BANESTONE) { - - outMsg.actionType = 18; - outMsg.setTargetType(building.getObjectType().ordinal()); - outMsg.setTargetID(building.getObjectUUID()); - - } else if (BuildingManager.playerCanManage(player, building)) { //TODO allow Friends list. - configWindowState(player, building, outMsg); - outMsg.actionType = 3; - outMsg.setTargetType(building.getObjectType().ordinal()); - outMsg.setTargetID(building.getObjectUUID()); - outMsg.setTargetType3(building.getObjectType().ordinal()); - outMsg.setTargetID3(building.getObjectUUID()); - outMsg.setUnknown54(1); - - } else { - - if (building.getBlueprintUUID() != 0) - switch (building.getBlueprint().getBuildingGroup()) { - case SHRINE: - if (building.getRank() == -1) { - if (!Bounds.collide(player.getLoc(), building)) { - ErrorPopupMsg.sendErrorPopup(player, 64); - return true; - } - + switch (msg.actionType) { + case 2: + case 22: + if (building.getBlueprint() != null && building.getBlueprint().getBuildingGroup() == engine.Enum.BuildingGroup.BANESTONE) { + outMsg.actionType = 18; + outMsg.setTargetType(building.getObjectType().ordinal()); + outMsg.setTargetID(building.getObjectUUID()); + } else if (BuildingManager.playerCanManage(player, building)) { + configWindowState(player, building, outMsg); + outMsg.actionType = 3; + outMsg.setTargetType(building.getObjectType().ordinal()); + outMsg.setTargetID(building.getObjectUUID()); + outMsg.setTargetType3(building.getObjectType().ordinal()); + outMsg.setTargetID3(building.getObjectUUID()); + outMsg.setUnknown54(1); + } else { + // Handle other cases + if (building.getRank() == -1) { + if (!Bounds.collide(player.getLoc(), building)) { + ErrorPopupMsg.sendErrorPopup(player, 64); + return true; + } + switch (building.getBlueprint().getBuildingGroup()) { + case SHRINE: Shrine shrine = Shrine.shrinesByBuildingUUID.get(building.getObjectUUID()); - - if (shrine == null) - return true; - - if (shrine.getFavors() == 0) { + if (shrine == null || shrine.getFavors() == 0) { ErrorPopupMsg.sendErrorPopup(player, 166); // There is no more favor in this shrine to loot return true; } - - BuildingManager.lootBuilding(player, building); - return true; - } - break; - case WAREHOUSE: - //TODO check - if (building.getRank() == -1) { - if (!Bounds.collide(player.getLoc(), building)) { - ErrorPopupMsg.sendErrorPopup(player, 64); - return true; - } - + //loot elan stones + MobLoot elanStones = new MobLoot(player,ItemBase.getItemBase(1705032),1,false); + Item promotedItem = elanStones.promoteToItem(player); + promotedItem.setNumOfItems(shrine.getFavors()); + player.getCharItemManager().addItemToInventory(promotedItem); + DbManager.ItemQueries.UPDATE_NUM_ITEMS(promotedItem,promotedItem.getNumOfItems(),1); + player.getCharItemManager().updateInventory(); + shrine.setFavors(0); + break; + case WAREHOUSE: Warehouse warehouse = Warehouse.warehouseByBuildingUUID.get(building.getObjectUUID()); - - if (warehouse == null) - return true; - - if (warehouse.isEmpty()) { + if (warehouse == null || warehouse.isEmpty()) { ErrorPopupMsg.sendErrorPopup(player, 167); // no more resources. return true; } - - BuildingManager.lootBuilding(player, building); - return true; - } + break; + } + } + AbstractCharacter owner = building.getOwner(); + if (owner == null) { + msg.actionType = 4; + DispatchMessage.dispatchMsgDispatch(Dispatch.borrow(player, msg), DispatchChannel.SECONDARY); + } else { + outMsg.actionType = 4; + outMsg.setTargetType(building.getObjectType().ordinal()); + outMsg.setTargetID(building.getObjectUUID()); + outMsg.setAssetName(building.getName()); } - - if (building.getRank() == -1) - return true; - - AbstractCharacter owner = building.getOwner(); - - //no owner, send building info - if (owner == null) { - msg.actionType = 4; - - Dispatch dispatch = Dispatch.borrow(player, msg); - DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); - return true; } - outMsg.actionType = 4; + DispatchMessage.dispatchMsgDispatch(Dispatch.borrow(player, outMsg), DispatchChannel.SECONDARY); + return true; + case 13: + outMsg.actionType = 13; + DispatchMessage.dispatchMsgDispatch(Dispatch.borrow(player, outMsg), DispatchChannel.SECONDARY); + return true; + case 5: + building.setName(msg.getAssetName()); + configWindowState(player, building, outMsg); + outMsg.actionType = 3; outMsg.setTargetType(building.getObjectType().ordinal()); outMsg.setTargetID(building.getObjectUUID()); - outMsg.setAssetName(building.getName()); - - } - Dispatch dispatch = Dispatch.borrow(player, outMsg); - DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); - return true; + outMsg.setTargetType3(GameObjectType.Building.ordinal()); + outMsg.setTargetID3(building.getObjectUUID()); + outMsg.setAssetName1(building.getName()); + outMsg.setUnknown54(1); + DispatchMessage.dispatchMsgDispatch(Dispatch.borrow(player, outMsg), DispatchChannel.SECONDARY); + return true; + case 14: + ManageCityAssetsMsg mca = new ManageCityAssetsMsg(player, building); + mca.actionType = 15; + DispatchMessage.dispatchMsgDispatch(Dispatch.borrow(player, mca), DispatchChannel.SECONDARY); + return true; + case 20: + // Handle case 20 + return handleCase20(player, outMsg, building, msg, origin); + default: + return true; } + } - if (msg.actionType == 13) { - outMsg.actionType = 13; - Dispatch dispatch = Dispatch.borrow(player, outMsg); - DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); + private boolean handleCase20(PlayerCharacter player, ManageCityAssetsMsg outMsg, Building building, ManageCityAssetsMsg msg, ClientConnection origin) throws MsgSendException { + Zone baneZone = building.getParentZone(); + if (baneZone == null) return true; - } - - - //Rename Building. - - if (msg.actionType == 5) { - - //TODO we need to check names before allowing - building.setName(msg.getAssetName()); - configWindowState(player, building, outMsg); - - outMsg.actionType = 3; - outMsg.setTargetType(building.getObjectType().ordinal()); - outMsg.setTargetID(building.getObjectUUID()); - outMsg.setTargetType3(GameObjectType.Building.ordinal()); - outMsg.setTargetID3(building.getObjectUUID()); - outMsg.setAssetName1(building.getName()); - outMsg.setUnknown54(1); - - Dispatch dispatch = Dispatch.borrow(player, outMsg); - DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); - + City banedCity = City.getCity(baneZone.getPlayerCityUUID()); + if (banedCity == null) return true; - - //TOL, update city name also - //TODO update city and zone in database - //TODO update city map data in game server - } - - if (msg.actionType == 14) { - ManageCityAssetsMsg mca = new ManageCityAssetsMsg(player, building); - mca.actionType = 15; - Dispatch dispatch = Dispatch.borrow(player, mca); - DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); + Bane bane = banedCity.getBane(); + if (bane == null || bane.getLiveDate() != null || player.getGuild() != banedCity.getGuild() || !GuildStatusController.isInnerCouncil(player.getGuildStatus())) return true; - } - - if (msg.actionType == 20) { - - Zone baneZone = building.getParentZone(); - - if (baneZone == null) - return true; - - City banedCity = City.getCity(baneZone.getPlayerCityUUID()); - - if (banedCity == null) - return true; - - Bane bane = banedCity.getBane(); - - if (bane == null || bane.getLiveDate() != null || player.getGuild() != banedCity.getGuild() || GuildStatusController.isInnerCouncil(player.getGuildStatus()) == false) - return true; - - int baneHour = msg.getBaneHour(); - - if (baneHour < 16 || baneHour > 24) { - PlaceAssetMsg.sendPlaceAssetError(origin, 1, "A Serious error has occurred. Please post details for to ensure transaction integrity"); - return true; - } - - DateTime baneLive = new DateTime(bane.getPlacementDate()); - baneLive = baneHour == 24 ? baneLive.plusDays(3) : baneLive.plusDays(2); - baneLive = baneHour == 24 ? baneLive.hourOfDay().setCopy(0) : baneLive.hourOfDay().setCopy(baneHour); - baneLive = baneLive.minuteOfHour().setCopy(0); - baneLive = baneLive.secondOfMinute().setCopy(1); - bane.setLiveDate(baneLive); - outMsg.actionType = 18; - - Dispatch dispatch = Dispatch.borrow(player, outMsg); - DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); + int baneHour = msg.getBaneHour(); + if (baneHour < 16 || baneHour > 24) { + PlaceAssetMsg.sendPlaceAssetError(origin, 1, "A Serious error has occurred. Please post details for to ensure transaction integrity"); return true; } + DateTime baneLive = new DateTime(bane.getPlacementDate()); + baneLive = baneHour == 24 ? baneLive.plusDays(3) : baneLive.plusDays(2); + baneLive = baneHour == 24 ? baneLive.hourOfDay().setCopy(0) : baneLive.hourOfDay().setCopy(baneHour); + baneLive = baneLive.minuteOfHour().setCopy(0); + baneLive = baneLive.secondOfMinute().setCopy(1); + bane.setLiveDate(baneLive); + outMsg.actionType = 18; + DispatchMessage.dispatchMsgDispatch(Dispatch.borrow(player, outMsg), DispatchChannel.SECONDARY); return true; } + public void configWindowState(PlayerCharacter player, Building building, ManageCityAssetsMsg manageCityAssetsMsg) { // Tests to turn on upgrade button if a building is not diff --git a/src/engine/net/client/msg/ApplyRuneMsg.java b/src/engine/net/client/msg/ApplyRuneMsg.java index f62d4df6..defde65a 100644 --- a/src/engine/net/client/msg/ApplyRuneMsg.java +++ b/src/engine/net/client/msg/ApplyRuneMsg.java @@ -306,6 +306,8 @@ public class ApplyRuneMsg extends ClientNetMsg { } //if discipline, check number applied if (isDiscipline(runeID)) { + //if(playerCharacter.getLevel() == 80) + discCount -= 1; // level 80 characters get an extra disc rune if (playerCharacter.getLevel() < 70) { if (discCount > 2) { return false; diff --git a/src/engine/net/client/msg/VendorDialogMsg.java b/src/engine/net/client/msg/VendorDialogMsg.java index 4e11b41a..11014670 100644 --- a/src/engine/net/client/msg/VendorDialogMsg.java +++ b/src/engine/net/client/msg/VendorDialogMsg.java @@ -137,16 +137,20 @@ public class VendorDialogMsg extends ClientNetMsg { } if(contract.getObjectUUID() == 1502040){ - if(playerCharacter.isBoxed == false) { - ChatManager.chatSystemInfo(playerCharacter, "You Are Already The Active Character."); + if(!playerCharacter.getTimestamps().containsKey("lastBoxChange")) + playerCharacter.getTimestamps().put("lastBoxChange",System.currentTimeMillis() - 1000); + + if(playerCharacter.getTimeStamp("lastBoxChange") + 30000L > System.currentTimeMillis()) { return; } - if(playerCharacter.getTimestamps().containsKey("BoxChange") && playerCharacter.getTimeStamp("BoxChange") + 5000 > System.currentTimeMillis()) { - ChatManager.chatSystemInfo(playerCharacter, "You Are Enrolling Too Often."); + if(playerCharacter.isBoxed == false) { + ChatManager.chatSystemInfo(playerCharacter, "You Are Already The Active Character."); return; } - playerCharacter.getTimestamps().put("BoxChange",System.currentTimeMillis()); + + playerCharacter.getTimestamps().put("lastBoxChange",System.currentTimeMillis()); + playerCharacter.isBoxed = false; playerCharacter.removeEffectBySource(Enum.EffectSourceType.DeathShroud,50,true); ChatManager.chatSystemInfo(playerCharacter, "Promoting To Active Duty"); @@ -157,12 +161,12 @@ public class VendorDialogMsg extends ClientNetMsg { } playerCharacter.isBoxed = false; playerCharacter.title = CharacterTitle.NONE; - InterestManager.reloadCharacter(playerCharacter); + InterestManager.setObjectDirty(playerCharacter); playerCharacter.removeEffectBySource(Enum.EffectSourceType.DeathShroud,50,true); for(PlayerCharacter box : currentBoxes) { box.isBoxed = true; box.title = CharacterTitle.BOX; - InterestManager.reloadCharacter(box); + InterestManager.setObjectDirty(box); } } Dispatch dispatch = Dispatch.borrow(playerCharacter, msg); diff --git a/src/engine/objects/AbstractCharacter.java b/src/engine/objects/AbstractCharacter.java index ccad17aa..931fc704 100644 --- a/src/engine/objects/AbstractCharacter.java +++ b/src/engine/objects/AbstractCharacter.java @@ -1114,23 +1114,6 @@ public abstract class AbstractCharacter extends AbstractWorldObject { } public final void setCombatTarget(final AbstractWorldObject value) { - if(this.getObjectTypeMask() == 2050) {//MOB? - if (value == null) { - if (this.isCombat()) { - this.setCombat(false); - UpdateStateMsg rwss = new UpdateStateMsg(); - rwss.setPlayer(this); - DispatchMessage.sendToAllInRange(this, rwss); - } - }else { - if (!this.isCombat()) { - this.setCombat(true); - UpdateStateMsg rwss = new UpdateStateMsg(); - rwss.setPlayer(this); - DispatchMessage.sendToAllInRange(this, rwss); - } - } - } this.combatTarget = value; } diff --git a/src/engine/objects/Bane.java b/src/engine/objects/Bane.java index f7f23751..ed564cd9 100644 --- a/src/engine/objects/Bane.java +++ b/src/engine/objects/Bane.java @@ -607,6 +607,10 @@ public final class Bane { DispatchMessage.dispatchMsgToAll(msg); } + for(AbstractWorldObject awo : WorldGrid.getObjectsInRangePartial(this.getCity().loc,1500,MBServerStatics.MASK_BUILDING)){ + Building building = (Building)awo; + if(building.setOwner(this.getOwner())); + } break; case DESTROY: diff --git a/src/engine/objects/Building.java b/src/engine/objects/Building.java index e7728433..71c883da 100644 --- a/src/engine/objects/Building.java +++ b/src/engine/objects/Building.java @@ -12,6 +12,7 @@ package engine.objects; import engine.Enum; import engine.Enum.*; import engine.InterestManagement.HeightMap; +import engine.InterestManagement.InterestManager; import engine.InterestManagement.RealmMap; import engine.InterestManagement.WorldGrid; import engine.db.archive.CityRecord; @@ -394,7 +395,7 @@ public class Building extends AbstractWorldObject { this.rank = newRank; // New rank means new mesh - + int oldMeshID = this.meshUUID; newMeshUUID = this.getBlueprint().getMeshForRank(this.rank); this.meshUUID = newMeshUUID; @@ -428,6 +429,15 @@ public class Building extends AbstractWorldObject { BuildingManager.cleanupHirelings(this); this.isDeranking.compareAndSet(true, false); + + if(oldMeshID != this.meshUUID) { + //move NPCs to new slot locations if the mesh was changed and force reload them + int index = 0; + for (AbstractCharacter hireling : this.hirelings.keySet()) { + hireling.setLoc(BuildingManager._slotLocations.get(newMeshUUID).get(index).getLocation()); + InterestManager.reloadCharacter(hireling); + } + } } public final int getOwnerUUID() { diff --git a/src/engine/objects/CharacterItemManager.java b/src/engine/objects/CharacterItemManager.java index ecbb20ab..d33531b9 100644 --- a/src/engine/objects/CharacterItemManager.java +++ b/src/engine/objects/CharacterItemManager.java @@ -12,7 +12,6 @@ package engine.objects; import engine.Enum; import engine.Enum.GameObjectType; import engine.Enum.ItemType; -import engine.devcmd.cmds.MakeItemCmd; import engine.gameManager.*; import engine.math.Vector3fImmutable; import engine.net.Dispatch; @@ -24,7 +23,10 @@ import engine.powers.poweractions.AbstractPowerAction; import engine.server.MBServerStatics; import org.pmw.tinylog.Logger; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadLocalRandom; @@ -68,6 +70,8 @@ public class CharacterItemManager { */ private byte equipVer = (byte) 0; + public boolean updateLock = false; + public CharacterItemManager(AbstractCharacter ac) { super(); this.absCharacter = ac; @@ -103,7 +107,7 @@ public class CharacterItemManager { return; if (take != null) { itemMan.buyFromNPC(take, npc); - itemMan.StackResources(); + itemMan.updateInventory(); } } @@ -690,7 +694,7 @@ public class CharacterItemManager { this.addGoldToTrade(amt); // BONUS CODE BELOW: Thanks some unknown retard! - // sourceItemMan.StackResources(sourceItemMan.getInventory(), true); + // sourceItemMan.updateInventory(sourceItemMan.getInventory(), true); UpdateGoldMsg ugm = new UpdateGoldMsg(source); ugm.configure(); @@ -776,8 +780,6 @@ public class CharacterItemManager { this.commitTrade(); this.closeTradeWindow(ctwm1, false); other.getCharItemManager().closeTradeWindow(ctwm2, false); - this.StackResources(); - other.getCharItemManager().StackResources(); } return true; } @@ -938,13 +940,13 @@ public class CharacterItemManager { return junk(i, true); } - private synchronized boolean junk(Item i, boolean StackResources) { + private synchronized boolean junk(Item i, boolean updateInventory) { if (i.getItemBase().getType().equals(ItemType.GOLD)) { if (this.getGoldInventory().getObjectUUID() == i.getObjectUUID()) if (DbManager.ItemQueries.UPDATE_GOLD(i, 0)) { this.getGoldInventory().setNumOfItems(0); - if (StackResources) - StackResources(); + if (updateInventory) + updateInventory(); return true; } else { return false; @@ -972,9 +974,9 @@ public class CharacterItemManager { calculateWeights(); - if (StackResources) + if (updateInventory) // Send the new inventory - //StackResources(i, false); this line was causing entire inventory to disappear + //updateInventory(i, false); this line was causing entire inventory to disappear updateInventory(this.getInventory(), true); return true; @@ -1249,12 +1251,21 @@ public class CharacterItemManager { } else { int amt = i.getNumOfItems(); if (DbManager.ItemQueries.UPDATE_GOLD(this.goldInventory, this.goldInventory.getNumOfItems() + amt)) { - StackResources(); + updateInventory(); return true; } return false; } - } + } //else if (i.getItemBase().getType().equals(ItemType.RESOURCE)) { + // if(this.inventoryContainsResource(i)){ + // Item resource = getResource(i); + // if(resource != null){ + // resource.setNumOfItems(resource.getNumOfItems() + i.getNumOfItems()); + // return true; + // } + //} + // } + this.inventory.add(i); this.itemIDtoType.put(i.getObjectUUID(), i.getObjectType().ordinal()); return true; @@ -1477,7 +1488,7 @@ public class CharacterItemManager { if (sdrMerchant) { this.delete(itemToSell); - this.StackResources(); + this.updateInventory(); } else if (!itemToSell.moveItemToInventory(npc)) return false; @@ -2276,10 +2287,13 @@ public class CharacterItemManager { if (this.absCharacter.getObjectType().equals(GameObjectType.PlayerCharacter) == false) return; + + if(this.updateLock) + return; PlayerCharacter pc = (PlayerCharacter) this.absCharacter; - UpdateInventoryMsg StackResourcesMsg = new UpdateInventoryMsg(inventory, this.getBank(), this.getGoldInventory(), add); - Dispatch dispatch = Dispatch.borrow(pc, StackResourcesMsg); + UpdateInventoryMsg updateInventoryMsg = new UpdateInventoryMsg(inventory, this.getBank(), this.getGoldInventory(), add); + Dispatch dispatch = Dispatch.borrow(pc, updateInventoryMsg); DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); } @@ -2616,43 +2630,4 @@ public class CharacterItemManager { } - public void StackResources(){ - if(!this.getOwner().getObjectType().equals(GameObjectType.PlayerCharacter)) - return; - ArrayList resources = new ArrayList<>(); - HashMap newStacks = new HashMap<>(); - for(Item item : this.getInventory()){ - if(item.getItemBase().getType().equals(ItemType.RESOURCE)){ - resources.add(item); - if(newStacks.containsKey(item.getItemBaseID())){ - newStacks.put(item.getItemBaseID(),newStacks.get(item.getItemBaseID()) + item.getNumOfItems()); - }else{ - newStacks.put(item.getItemBaseID(),item.getNumOfItems()); - } - } - } - //do stacking here - PlayerCharacter pc = PlayerCharacter.getFromCache(this.getOwner().getObjectUUID()); - for(Integer id : newStacks.keySet()){ - ItemBase ib = ItemBase.getItemBase(id); - Item item = new Item(ib, pc.getObjectUUID(), - Enum.OwnerType.PlayerCharacter, (byte) 0, (byte) 0, (short) ib.getDurability(), (short) ib.getDurability(), - true, false, Enum.ItemContainerType.INVENTORY, (byte) 0, - new ArrayList<>(), ""); - - item.setNumOfItems(newStacks.get(id)); - try{ - item = DbManager.ItemQueries.ADD_ITEM(item); - this.addItemToInventory(item); - }catch(Exception e){ - ChatManager.chatSystemError(pc, "Failed To Stack Resources"); - } - - } - for(Item item : resources) - this.delete(item); - - this.updateInventory(); - } - } diff --git a/src/engine/objects/Experience.java b/src/engine/objects/Experience.java index 3d33c68d..07c9e709 100644 --- a/src/engine/objects/Experience.java +++ b/src/engine/objects/Experience.java @@ -9,7 +9,9 @@ package engine.objects; +import engine.Enum; import engine.Enum.TargetColor; +import engine.gameManager.LootManager; import engine.gameManager.ZoneManager; import engine.math.Vector3fImmutable; import engine.server.MBServerStatics; @@ -117,6 +119,11 @@ public class Experience { 159932666, // Level 74 169707808, // Level 75 179921247, // Level 76 + 190548651, // Level 77 + 201590020, // Level 78 + 213045354, // Level 79 + 224914653, // Level 80 + 237197917 // Level 81 }; @@ -214,9 +221,21 @@ public class Experience { 235166.21f, // Level 72 246039.34f, // Level 73 257240.58f, // Level 74 - 1 // 268774.71 //Level 75 + 268765.03f, // Level 75 + 280612.69f, // Level 76 + 292783.56f, // Level 77 + 305277.64f, // Level 78 + 318094.93f, // Level 79 + 1, // Level 80 - }; + + + + + + + +}; // Used to calcuate the amount of experience a monster grants in the // following formula // expGranted = a(moblevel)^2 + b(moblevel) + c @@ -268,8 +287,8 @@ public class Experience { if (level < 1) level = 1; - if (level > 75) - level = 75; + if (level > MBServerStatics.LEVELCAP) + level = MBServerStatics.LEVELCAP; return MaxExpPerLevel[level]; } @@ -354,8 +373,8 @@ public class Experience { if (leaderskill != null) leadership = leaderskill.getNumTrains(); - if (leadership > 90) - leadership = 90; // leadership caps at 90% + //if (leadership > 90) + // leadership = 90; // leadership caps at 90% } // Check every group member for distance to see if they get xp @@ -393,6 +412,8 @@ public class Experience { // Process XP for this member + grantedExperience *= (1/giveEXPTo.size()+0.9); + penalty = getGroupMemberPenalty(leadership, playerCharacter, giveEXPTo, highestLevel); @@ -423,8 +444,14 @@ public class Experience { if (grantedExperience == 0) grantedExperience = 1; + grantedExperience *= LootManager.NORMAL_EXP_RATE; // Grant the player the EXP - playerCharacter.grantXP((int) Math.floor(grantedExperience)); + if(mob.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) { + if (((PlayerCharacter) mob).pvpDeaths.contains(killer.getObjectUUID()) == false) + playerCharacter.grantXP((int) Math.floor(grantedExperience), true); + }else { + playerCharacter.grantXP((int) Math.floor(grantedExperience), false); + } } } else { // Give EXP to a single character @@ -435,7 +462,8 @@ public class Experience { return; // Get XP and adjust for Mob Level with world xp modifier taken into account - grantedExperience = (double) LOOTMANAGER.NORMAL_EXP_RATE * maxXPPerKill(killer.getLevel()); + float mdofier = LOOTMANAGER.NORMAL_EXP_RATE; + grantedExperience = maxXPPerKill(killer.getLevel()); grantedExperience *= getConMod(killer, mob); // Modify for hotzone @@ -448,7 +476,12 @@ public class Experience { grantedExperience *= .6; // Grant XP - killer.grantXP((int) Math.floor(grantedExperience)); + if(mob.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) { + if (((PlayerCharacter) mob).pvpDeaths.contains(killer.getObjectUUID()) == false) + killer.grantXP((int) Math.floor(grantedExperience), true); + }else { + killer.grantXP((int) Math.floor(grantedExperience), false); + } } } } diff --git a/src/engine/objects/Mine.java b/src/engine/objects/Mine.java index 25d181f4..f172bba1 100644 --- a/src/engine/objects/Mine.java +++ b/src/engine/objects/Mine.java @@ -16,17 +16,15 @@ import engine.net.ByteBufferWriter; import engine.net.client.msg.ErrorPopupMsg; import engine.server.MBServerStatics; import engine.workthreads.ZergMechanicThread; -import org.joda.time.DateTime; import org.pmw.tinylog.Logger; import java.net.UnknownHostException; +import java.nio.charset.StandardCharsets; import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Time; import java.time.LocalDateTime; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ThreadLocalRandom; import static engine.gameManager.DbManager.MineQueries; import static engine.gameManager.DbManager.getObject; @@ -60,7 +58,8 @@ public class Mine extends AbstractGameObject { public boolean hasProduced = false; - public int liveTime; + public int liveHour; + public int liveMinute; public Boolean firstThirty = true; public static ArrayList ChinaMines = new ArrayList<>(); @@ -115,142 +114,20 @@ public class Mine extends AbstractGameObject { this.production = Resource.valueOf(rs.getString("mine_resource")); this.lastClaimer = null; - } - } - - public static void SetTimes(){ - try { - EuroMines.get(0).liveTime = 20; - EuroMines.get(1).liveTime = 20; - EuroMines.get(2).liveTime = 20; - EuroMines.get(3).liveTime = 20; - EuroMines.get(4).liveTime = 20; - EuroMines.get(5).liveTime = 20; - EuroMines.get(6).liveTime = 20; - }catch(Exception e){ - - } - try{ - ChinaMines.get(0).liveTime = 11; - ChinaMines.get(1).liveTime = 11; - ChinaMines.get(2).liveTime = 11; - ChinaMines.get(3).liveTime = 12; - ChinaMines.get(4).liveTime = 12; - ChinaMines.get(5).liveTime = 12; - ChinaMines.get(6).liveTime = 12; - ChinaMines.get(7).liveTime = 12; - ChinaMines.get(8).liveTime = 12; - ChinaMines.get(9).liveTime = 12; - ChinaMines.get(10).liveTime = 13; - ChinaMines.get(11).liveTime = 13; - ChinaMines.get(12).liveTime = 13; - ChinaMines.get(13).liveTime = 13; - }catch(Exception e){ - - } - try{ - AmericaMines.get(0).liveTime = 1; - AmericaMines.get(1).liveTime = 1; - AmericaMines.get(2).liveTime = 1; - AmericaMines.get(3).liveTime = 2; - AmericaMines.get(4).liveTime = 2; - AmericaMines.get(5).liveTime = 2; - AmericaMines.get(6).liveTime = 2; - AmericaMines.get(7).liveTime = 2; - AmericaMines.get(8).liveTime = 2; - AmericaMines.get(9).liveTime = 2; - AmericaMines.get(10).liveTime = 3; - AmericaMines.get(11).liveTime = 3; - AmericaMines.get(12).liveTime = 3; - AmericaMines.get(13).liveTime = 3; - }catch(Exception e){ - - } - - int count = 1; - for(Mine mine : EuroMines){ - switch(count){ - case 1: - mine.capSize = 3; - break; - case 2: - mine.capSize = 5; - break; - case 3: - mine.capSize = 10; - break; - case 4: - mine.capSize = 3; - break; - } - count ++; - if(count == 5) - count = 1; - if(BuildingManager.getBuilding(mine.buildingID) != null) { - Building mineTower = BuildingManager.getBuilding(mine.buildingID); - if (mineTower != null) { - mineTower.setMaxHitPoints(5000 * mine.capSize); - mineTower.setCurrentHitPoints((float) 5000 * mine.capSize); - } - } - } - - for(Mine mine : ChinaMines){ - switch(count){ - case 1: - mine.capSize = 3; - break; - case 2: - mine.capSize = 5; - break; - case 3: - mine.capSize = 10; - break; - case 4: - mine.capSize = 3; - break; - } - count ++; - if(count == 5) - count = 1; + this.liveHour = rs.getInt("mineLiveHour"); + this.liveMinute = rs.getInt("mineLiveMinute"); + this.capSize = rs.getInt("capSize"); - if(BuildingManager.getBuilding(mine.buildingID) != null) { - Building mineTower = BuildingManager.getBuilding(mine.buildingID); + if(BuildingManager.getBuilding(this.buildingID) != null) { + Building mineTower = BuildingManager.getBuilding(this.buildingID); if (mineTower != null) { - mineTower.setMaxHitPoints(5000 * mine.capSize); - mineTower.setCurrentHitPoints((float) 5000 * mine.capSize); - } - } - } - - for(Mine mine : AmericaMines){ - switch(count){ - case 1: - mine.capSize = 3; - break; - case 2: - mine.capSize = 5; - break; - case 3: - mine.capSize = 10; - break; - case 4: - mine.capSize = 3; - break; - } - count ++; - if(count == 5) - count = 1; - - if(BuildingManager.getBuilding(mine.buildingID) != null) { - Building mineTower = BuildingManager.getBuilding(mine.buildingID); - if (mineTower != null) { - mineTower.setMaxHitPoints(5000 * mine.capSize); - mineTower.setCurrentHitPoints((float) 5000 * mine.capSize); + mineTower.setMaxHitPoints(5000 * this.capSize); + mineTower.setCurrentHitPoints((float) 5000 * this.capSize); } } } } + public static void releaseMineClaims(PlayerCharacter playerCharacter) { if (playerCharacter == null) @@ -306,89 +183,8 @@ public class Mine extends AbstractGameObject { //mine.mineType = MineProduction.LUMBER; } - try { - ChinaMines.add(serverMines.get(0)); - ChinaMines.add(serverMines.get(3)); - ChinaMines.add(serverMines.get(6)); - ChinaMines.add(serverMines.get(9)); - ChinaMines.add(serverMines.get(12)); - ChinaMines.add(serverMines.get(15)); - ChinaMines.add(serverMines.get(18)); - ChinaMines.add(serverMines.get(21)); - ChinaMines.add(serverMines.get(23)); - ChinaMines.add(serverMines.get(25)); - ChinaMines.add(serverMines.get(27)); - ChinaMines.add(serverMines.get(29)); - ChinaMines.add(serverMines.get(31)); - ChinaMines.add(serverMines.get(33)); - }catch(Exception e){ - - } - try{ - AmericaMines.add(serverMines.get(1)); - AmericaMines.add(serverMines.get(4)); - AmericaMines.add(serverMines.get(7)); - AmericaMines.add(serverMines.get(10)); - AmericaMines.add(serverMines.get(13)); - AmericaMines.add(serverMines.get(16)); - AmericaMines.add(serverMines.get(19)); - AmericaMines.add(serverMines.get(22)); - AmericaMines.add(serverMines.get(24)); - AmericaMines.add(serverMines.get(26)); - AmericaMines.add(serverMines.get(28)); - AmericaMines.add(serverMines.get(30)); - AmericaMines.add(serverMines.get(32)); - AmericaMines.add(serverMines.get(34)); - }catch(Exception e){ - - } - try{ - EuroMines.add(serverMines.get(2)); - EuroMines.add(serverMines.get(5)); - EuroMines.add(serverMines.get(8)); - EuroMines.add(serverMines.get(11)); - EuroMines.add(serverMines.get(14)); - EuroMines.add(serverMines.get(17)); - EuroMines.add(serverMines.get(20)); - }catch(Exception e){ - - } - - - SetTimes(); - for(Mine mine : EuroMines){ - if(EuroMines.indexOf(mine) %2 == 0 ){ - mine.firstThirty = true; - } else{ - mine.firstThirty = false; - } - } - for(Mine mine : AmericaMines){ - if(AmericaMines.indexOf(mine) %2 == 0 ){ - mine.firstThirty = true; - } else{ - mine.firstThirty = false; - } - } - for(Mine mine : ChinaMines){ - if(ChinaMines.indexOf(mine) %2 == 0 ){ - mine.firstThirty = true; - } else{ - mine.firstThirty = false; - } - } - } catch (Exception e) { - e.printStackTrace(); - } + }catch(Exception e) { - for(Mine mine : Mine.getMines()){ - int minute = 0; - if (mine.firstThirty == false) - minute = 30; - LocalDateTime openTime = LocalDateTime.now().withHour(mine.liveTime).withMinute(minute).withSecond(0); - LocalDateTime closeTime = openTime.plusMinutes(30); - if(LocalDateTime.now().isAfter(closeTime)) - mine.wasOpened = true; } } @@ -400,20 +196,30 @@ public class Mine extends AbstractGameObject { return Mine.towerMap.get(towerID); } + public static String getMineNationality(int time){ + switch(time){ + case 7: + case 8: + case 9: + return "CN"; + case 14: + case 15: + case 16: + return "EU"; + case 20: + case 21: + case 22: + return "NA"; + default: + return "Unknown"; + } + } public static void serializeForClientMsg(Mine mine, ByteBufferWriter writer) { writer.putInt(mine.getObjectType().ordinal()); writer.putInt(mine.getObjectUUID()); writer.putInt(mine.getObjectUUID()); //actually a hash of mine writer.putString(mine.mineType.name); - if(ChinaMines.contains((mine))) { - writer.putString("Chinese" + " {" + mine.capSize + " Man}"); - } else if(AmericaMines.contains(mine)){ - writer.putString("American" + " {" + mine.capSize + " Man}"); - } else if(EuroMines.contains(mine)){ - writer.putString("European" + " {" + mine.capSize + " Man}"); - }else{ - writer.putString("Unknown" + " {" + mine.capSize + " Man}"); - } + writer.putString(Mine.getMineNationality(mine.liveHour) + " " + mine.capSize + " Man "); writer.putInt(mine.production.hash); writer.putInt(mine.getModifiedProductionAmount()); writer.putInt(mine.getModifiedProductionAmount()); //TODO calculate range penalty here @@ -421,21 +227,16 @@ public class Mine extends AbstractGameObject { // Errant mines are currently open. Set time to now. - LocalDateTime mineOpenTime;// = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0); - if(mine.firstThirty == true){ - mineOpenTime = LocalDateTime.now().withHour(mine.liveTime).withMinute(0).withSecond(0).withNano(0); - } - else{ - mineOpenTime = LocalDateTime.now().withHour(mine.liveTime).withMinute(30).withSecond(0).withNano(0); - } + LocalDateTime mineOpenTime = LocalDateTime.now().withHour(mine.liveHour).withMinute(mine.liveMinute); LocalDateTime mineCloseTime = mineOpenTime.plusMinutes(30); - if(LocalDateTime.now().isAfter(mineCloseTime)){ + if(LocalDateTime.now().isAfter(mineCloseTime) && mine.isActive == false){ mineOpenTime = mineOpenTime.plusDays(1); mineCloseTime = mineCloseTime.plusDays(1); } writer.putLocalDateTime(mineOpenTime); writer.putLocalDateTime(mineCloseTime); + writer.put(mine.isActive ? (byte) 0x01 : (byte) 0x00); Building mineTower = BuildingManager.getBuilding(mine.buildingID); @@ -445,9 +246,51 @@ public class Mine extends AbstractGameObject { writer.putInt(mine.isExpansion() ? mine.mineType.xpacHash : mine.mineType.hash); - writer.putString(mine.guildName); - GuildTag._serializeForDisplay(mine.guildTag, writer); writer.putString(mine.nationName); + GuildTag._serializeForDisplay(mine.guildTag, writer); + + boolean isPM = false; + if(mineOpenTime.getHour() > 11) + isPM = true; + + int hourOpen = mineOpenTime.getHour(); + int minuteOpen = mineOpenTime.getMinute(); + int hourClose = mineCloseTime.getHour(); + int minuteClose = mineCloseTime.getMinute(); + + if(isPM){ + hourOpen -= 12; + hourClose -= 12; + } + String timeString = hourOpen + ":"; + if(minuteOpen == 0){ + timeString += "00 "; + }else{ + timeString += "30 "; + } + + if(isPM){ + timeString += "PM "; + }else{ + timeString += "AM "; + } + + timeString += " to "; + + timeString += hourClose + ":"; + + if(minuteClose == 0){ + timeString += "00 "; + }else{ + timeString += "30 "; + } + + if(isPM){ + timeString += "PM CST"; + }else{ + timeString += "AM CST"; + } + writer.putString(timeString); GuildTag._serializeForDisplay(mine.nationTag, writer); } diff --git a/src/engine/objects/MineProduction.java b/src/engine/objects/MineProduction.java index a74e2fe7..a103c0a4 100644 --- a/src/engine/objects/MineProduction.java +++ b/src/engine/objects/MineProduction.java @@ -13,7 +13,7 @@ import java.util.HashMap; public enum MineProduction { - LUMBER("Universal Mine", new HashMap<>(), Resource.WORMWOOD, 1618637196, 1663491950), + LUMBER("Lumber Mine", new HashMap<>(), Resource.WORMWOOD, 1618637196, 1663491950), ORE("Ore Mine", new HashMap<>(), Resource.OBSIDIAN, 518103023, -788976428), GOLD("Gold Mine", new HashMap<>(), Resource.GALVOR, -662193002, -1227205358), MAGIC("Magic Mine", new HashMap<>(), Resource.BLOODSTONE, 504746863, -1753567069), diff --git a/src/engine/objects/PlayerCharacter.java b/src/engine/objects/PlayerCharacter.java index 37626d73..9ddb8231 100644 --- a/src/engine/objects/PlayerCharacter.java +++ b/src/engine/objects/PlayerCharacter.java @@ -160,7 +160,7 @@ public class PlayerCharacter extends AbstractCharacter { private boolean asciiLastName = true; private int spamCount = 0; private boolean initialized = false; - public boolean enteredWorld = false; + private boolean enteredWorld = false; private boolean canBreathe = true; private String hash; private ArrayList guildHistory = new ArrayList<>(); @@ -178,9 +178,11 @@ public class PlayerCharacter extends AbstractCharacter { public float ZergMultiplier = 1.0f; public int mineAppliedID = 0; - public long lastAction = 0; + public boolean depositingWarehouse = false; + public Building warehouseBuilding; + + public ArrayList killedCharacters = new ArrayList<>(); - public long nextBoxCheck = System.currentTimeMillis(); /** * No Id Constructor */ @@ -1827,20 +1829,18 @@ public class PlayerCharacter extends AbstractCharacter { //see if we shold grant xp to attacker boolean doPVPEXP = false; long lastKill = att.getLastKillOfTarget(this.getObjectUUID()); - if ((System.currentTimeMillis() - lastKill) > MBServerStatics.PLAYER_KILL_XP_TIMER) - if (attacker.getLevel() > 39 && this.getLevel() > 39) { - Guild aN = null; - Guild tN = null; - if (attacker.getGuild() != null) - aN = attacker.getGuild().getNation(); - if (this.getGuild() != null) - tN = this.getGuild().getNation(); - if (aN == null || tN == null || aN.isEmptyGuild() || Guild.sameGuild(aN, tN) || this.isDeathShroud()) { - //skip giving xp if same guild or attacker is errant, or target is in death shroud. - } else { - doPVPEXP = true; - } - } + + Guild aN = null; + Guild tN = null; + if (attacker.getGuild() != null) + aN = attacker.getGuild().getNation(); + if (this.getGuild() != null) + tN = this.getGuild().getNation(); + + if (aN != null || tN != null || !aN.equals(tN) || !this.isDeathShroud()) { + doPVPEXP = true; + } + //apply death shroud to non safeholds. Zone zone = ZoneManager.findSmallestZone(this.getLoc()); @@ -2916,14 +2916,21 @@ public class PlayerCharacter extends AbstractCharacter { return endSpeed; } - public synchronized void grantXP(int xp) { + public synchronized void grantXP(int xp, boolean fromPVP) { - if(GroupManager.getGroup(this) == null) + if(this.level > 75 && !fromPVP){ + return; + } else{ xp *= 2; + } + + if(GroupManager.getGroup(this) == null) + xp *= 1.9f; // Stop players from getting experience past the cap - if (this.exp + xp >= Experience.getBaseExperience(MBServerStatics.LEVELCAP)) - xp = Experience.getBaseExperience(MBServerStatics.LEVELCAP) - this.exp + 1; + int levelCap = MBServerStatics.LEVELCAP; + if (this.exp + xp >= Experience.getBaseExperience(levelCap)) + xp = Experience.getBaseExperience(levelCap) - this.exp + 1; if (xp == 0) xp = 1; @@ -4633,10 +4640,10 @@ public class PlayerCharacter extends AbstractCharacter { tmpLevel = targetLevel; - tmpLevel = (short) Math.min(tmpLevel, 75); + tmpLevel = (short) Math.min(tmpLevel, MBServerStatics.LEVELCAP); while (this.level < tmpLevel) { - grantXP(Experience.getBaseExperience(tmpLevel) - this.exp); + grantXP(Experience.getBaseExperience(tmpLevel) - this.exp, false); } } @@ -4852,7 +4859,7 @@ public class PlayerCharacter extends AbstractCharacter { //if(this.isBoxed && this.containsEffect(429611355) == false) {//pathfinding // PowersManager.applyPower(this, this, Vector3fImmutable.ZERO, 429611355, 40, false); //} - if(enteredWorld && this.isActive() && this.isAlive()){ + if(this.isEnteredWorld() && this.isActive()){ if( this.getLevel() < 10) { this.setLevel((short) 10); boolean hasConc = false; @@ -4865,25 +4872,19 @@ public class PlayerCharacter extends AbstractCharacter { ItemFactory.fillInventory(this, 980066, 1); } } - if(!this.isBoxed && System.currentTimeMillis() < this.nextBoxCheck) { - checkIfBoxed(this); - } + if(this.isBoxed) { - if(!this.title.equals(CharacterTitle.BOX)) { + if(this.title.equals(CharacterTitle.BOX) == false) { this.title = CharacterTitle.BOX; - //InterestManager.reloadCharacter(this); + InterestManager.reloadCharacter(this); } - - if (!this.containsEffect(1672601862)) {//Deathshroud + if (this.containsEffect(1672601862) == false) {//Deathshroud PowersManager.applyPower(this, this, Vector3fImmutable.ZERO, 1672601862, 40, false); - if(!this.getEffects().containsKey("MoveBuff")){ - PowersManager.applyPower(this, this, this.loc, 1514898036, 40, false); - } } }else{ - if(!this.title.equals(CharacterTitle.NONE)) { + if(this.title.equals(CharacterTitle.NONE) == false) { this.title = CharacterTitle.NONE; - //InterestManager.reloadCharacter(this); + InterestManager.reloadCharacter(this); } } } @@ -4894,11 +4895,23 @@ public class PlayerCharacter extends AbstractCharacter { this.updateLock.writeLock().unlock(); } } + if(this.depositingWarehouse){ + long sinceLast = System.currentTimeMillis() - this.getTimestamps().get("lastDepositWarehouse"); + if(sinceLast > 1000) { + this.depositingWarehouse = false; + ViewResourcesMessage vrm = new ViewResourcesMessage(this); + vrm.setGuild(this.getGuild()); + vrm.setWarehouseBuilding(this.warehouseBuilding); + vrm.configure(); + Dispatch dispatch = Dispatch.borrow(this, vrm); + DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); + this.charItemManager.updateLock = false; + this.charItemManager.updateInventory(); + } + } } - public static void checkIfBoxed(PlayerCharacter player){ - - player.nextBoxCheck = System.currentTimeMillis() + 10000; + public static boolean checkIfBoxed(PlayerCharacter player){ try { for (PlayerCharacter pc : SessionManager.getAllActivePlayers()) { if(pc.getClientConnection().machineID.equals(player.getClientConnection().machineID) == false) @@ -4910,17 +4923,15 @@ public class PlayerCharacter extends AbstractCharacter { if (pc.equals(player)) continue; if (pc.isBoxed == false) { - player.isBoxed = true; - InterestManager.setObjectDirty(player); - return; + player.title = CharacterTitle.BOX; + return true; } } - player.isBoxed = false; - InterestManager.setObjectDirty(player); + player.title = CharacterTitle.NONE; + return false; }catch(Exception e){ - player.isBoxed = false; - InterestManager.setObjectDirty(player); + return false; } } @@ -5554,6 +5565,14 @@ public class PlayerCharacter extends AbstractCharacter { this.centerHeight = centerHeight; } + public boolean isEnteredWorld() { + return enteredWorld; + } + + public void setEnteredWorld(boolean enteredWorld) { + this.enteredWorld = enteredWorld; + } + public long getChannelMute() { return channelMute; } diff --git a/src/engine/objects/Warehouse.java b/src/engine/objects/Warehouse.java index 9c17c39f..5db69727 100644 --- a/src/engine/objects/Warehouse.java +++ b/src/engine/objects/Warehouse.java @@ -129,67 +129,47 @@ public class Warehouse extends AbstractWorldObject { public static void warehouseDeposit(MerchantMsg msg, PlayerCharacter player, NPC npc, ClientConnection origin) { - long nextAllowedAction = player.lastAction + 5000; - if(nextAllowedAction > System.currentTimeMillis()){ - ChatManager.chatSystemInfo(player, "You Must Wait To Do This"); + Building warehouseBuilding = npc.getBuilding(); + if (warehouseBuilding == null) { return; } - player.lastAction = System.currentTimeMillis(); - Building warehouseBuilding; - Warehouse warehouse; - int depositAmount; - Dispatch dispatch; - - Item resource = Item.getFromCache(msg.getItemID()); - - if (resource == null) - return; - - depositAmount = msg.getAmount(); - if(depositAmount < 1){ - ChatManager.chatSystemInfo(player, "You Have Attempted To Dupe. Please Don't"); - } - CharacterItemManager itemMan = player.getCharItemManager(); - - if (itemMan.doesCharOwnThisItem(resource.getObjectUUID()) == false) - return; - - warehouseBuilding = npc.getBuilding(); + player.getTimestamps().put("lastDepositWarehouse", System.currentTimeMillis()); + player.depositingWarehouse = true; + player.warehouseBuilding = warehouseBuilding; + player.getCharItemManager().updateLock = true; + Item resource = Item.getFromCache(msg.getItemID()); - if (warehouseBuilding == null) - return; + if (resource == null) { + return; + } - warehouse = warehouseByBuildingUUID.get(warehouseBuilding.getObjectUUID()); + int depositAmount = msg.getAmount(); + CharacterItemManager itemMan = player.getCharItemManager(); - if (warehouse == null) - return; + if (!itemMan.doesCharOwnThisItem(resource.getObjectUUID())) { + return; + } - ItemBase ib = resource.getItemBase(); + Warehouse warehouse = warehouseByBuildingUUID.get(warehouseBuilding.getObjectUUID()); + if (warehouse == null) { + return; + } - if (!warehouse.deposit(player, resource, depositAmount, true, true)) { - // ChatManager.chatGuildError(player, "Failed to deposit " + ib.getName() +"."); - // Logger.debug("OpenWindow", player.getName() + " Failed to deposit Item with ID " + resource.getObjectUUID() + " from Warehouse With ID = " + warehouseBuilding.getObjectUUID()); - return; - } + if (!warehouse.deposit(player, resource, depositAmount, true, true)) { + return; + } - ViewResourcesMessage vrm = new ViewResourcesMessage(player); - vrm.setGuild(player.getGuild()); - vrm.setWarehouseBuilding(warehouseBuilding); - vrm.configure(); - dispatch = Dispatch.borrow(player, vrm); - DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); + //ViewResourcesMessage vrm = new ViewResourcesMessage(player); + //vrm.setGuild(player.getGuild()); + //vrm.setWarehouseBuilding(warehouseBuilding); + //vrm.configure(); + //Dispatch dispatch = Dispatch.borrow(player, vrm); + //DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); } public static void warehouseWithdraw(MerchantMsg msg, PlayerCharacter player, NPC npc, ClientConnection origin) { - long nextAllowedAction = player.lastAction + 5000; - if(nextAllowedAction > System.currentTimeMillis()){ - ChatManager.chatSystemInfo(player, "You Must Wait To Do This"); - return; - } - player.lastAction = System.currentTimeMillis(); - int withdrawAmount; Building warehouseBuilding; Warehouse warehouse; @@ -479,6 +459,59 @@ public class Warehouse extends AbstractWorldObject { return true; } + private boolean removeFromInventory(CharacterItemManager itemMan, ItemBase ib, int amount, PlayerCharacter pc) { + if (ib.getUUID() == 7) { + if (!itemMan.modifyInventoryGold(-amount)) { + // ChatManager.chatSystemError(pc, "You do not have this Gold."); + return false; + } + UpdateGoldMsg ugm = new UpdateGoldMsg(pc); + ugm.configure(); + Dispatch dispatch = Dispatch.borrow(pc, ugm); + DispatchMessage.dispatchMsgDispatch(dispatch, engine.Enum.DispatchChannel.SECONDARY); + } else { + Item resource = itemMan.getItemByUUID(ib.getUUID()); + if (resource == null) return false; + itemMan.delete(resource); + } + return true; + } + + private boolean updateDatabase(int itemID, int newAmount) { + switch (itemID) { + case 7: return DbManager.WarehouseQueries.updateGold(this, newAmount); + case 1580000: return DbManager.WarehouseQueries.updateStone(this, newAmount); + case 1580001: return DbManager.WarehouseQueries.updateTruesteel(this, newAmount); + case 1580002: return DbManager.WarehouseQueries.updateIron(this, newAmount); + case 1580003: return DbManager.WarehouseQueries.updateAdamant(this, newAmount); + case 1580004: return DbManager.WarehouseQueries.updateLumber(this, newAmount); + case 1580005: return DbManager.WarehouseQueries.updateOak(this, newAmount); + case 1580006: return DbManager.WarehouseQueries.updateBronzewood(this, newAmount); + case 1580007: return DbManager.WarehouseQueries.updateMandrake(this, newAmount); + case 1580008: return DbManager.WarehouseQueries.updateCoal(this, newAmount); + case 1580009: return DbManager.WarehouseQueries.updateAgate(this, newAmount); + case 1580010: return DbManager.WarehouseQueries.updateDiamond(this, newAmount); + case 1580011: return DbManager.WarehouseQueries.updateOnyx(this, newAmount); + case 1580012: return DbManager.WarehouseQueries.updateAzoth(this, newAmount); + case 1580013: return DbManager.WarehouseQueries.updateOrichalk(this, newAmount); + case 1580014: return DbManager.WarehouseQueries.updateAntimony(this, newAmount); + case 1580015: return DbManager.WarehouseQueries.updateSulfur(this, newAmount); + case 1580016: return DbManager.WarehouseQueries.updateQuicksilver(this, newAmount); + case 1580017: return DbManager.WarehouseQueries.updateGalvor(this, newAmount); + case 1580018: return DbManager.WarehouseQueries.updateWormwood(this, newAmount); + case 1580019: return DbManager.WarehouseQueries.updateObsidian(this, newAmount); + case 1580020: return DbManager.WarehouseQueries.updateBloodstone(this, newAmount); + case 1580021: return DbManager.WarehouseQueries.updateMithril(this, newAmount); + default: return false; + } + } + + private Resource getResourceType(Item resource) { + return resource.getItemBase().getType().equals(engine.Enum.ItemType.GOLD) + ? Resource.GOLD + : Resource.valueOf(resource.getItemBase().getName().toUpperCase()); + } + //for mine deposit public synchronized boolean depositFromMine(Mine mine, ItemBase resource, int amount) { diff --git a/src/engine/server/MBServerStatics.java b/src/engine/server/MBServerStatics.java index 80338e63..6e387800 100644 --- a/src/engine/server/MBServerStatics.java +++ b/src/engine/server/MBServerStatics.java @@ -357,7 +357,7 @@ public class MBServerStatics { public static final int COMBAT_SEND_DODGE = 20; public static final int COMBAT_SEND_BLOCK = 21; public static final int COMBAT_SEND_PARRY = 22; - public static final short LEVELCAP = 75; + public static final short LEVELCAP = 80; public static final int LEVEL_CON_WHITE = 7; public static final int RESPAWN_TIMER = 90 * 1000; public static final int DESPAWN_TIMER = 12 * 1000; diff --git a/src/engine/server/world/WorldServer.java b/src/engine/server/world/WorldServer.java index 7b7d3839..2dee14ac 100644 --- a/src/engine/server/world/WorldServer.java +++ b/src/engine/server/world/WorldServer.java @@ -250,11 +250,11 @@ public class WorldServer { if(LocalDateTime.now().isAfter(nextDiscSpawn)) { switch (LocalDateTime.now().getHour()) { case 0: - case 4: - case 8: - case 12: - case 16: - case 20: + case 3: + case 7: + case 11: + case 15: + case 19: for (Mob dropper : Mob.disciplineDroppers) { if (!dropper.isAlive()) { Zone.respawnQue.add(dropper); diff --git a/src/engine/workthreads/DestroyCityThread.java b/src/engine/workthreads/DestroyCityThread.java index aeb46a6c..c42741fa 100644 --- a/src/engine/workthreads/DestroyCityThread.java +++ b/src/engine/workthreads/DestroyCityThread.java @@ -19,6 +19,7 @@ package engine.workthreads; */ import engine.Enum; +import engine.gameManager.BuildingManager; import engine.gameManager.DbManager; import engine.gameManager.GuildManager; import engine.gameManager.ZoneManager; @@ -53,7 +54,6 @@ public class DestroyCityThread implements Runnable { // Member variable assignment cityZone = city.getParent(); - newParent = cityZone.getParent(); formerGuild = city.getTOL().getGuild(); // Former guild loses it's tree! @@ -99,36 +99,15 @@ public class DestroyCityThread implements Runnable { if (cityBuilding.getBlueprint().getBuildingGroup().equals(Enum.BuildingGroup.BANESTONE)) continue; - // All buildings are moved to a location relative - // to their new parent zone - - localCoords = ZoneManager.worldToLocal(cityBuilding.getLoc(), newParent); - - DbManager.BuildingQueries.MOVE_BUILDING(cityBuilding.getObjectUUID(), newParent.getObjectUUID(), localCoords.x, localCoords.y, localCoords.z); - - // All buildings are re-parented to a zone one node - // higher in the tree (continent) as we will be - // deleting the city zone very shortly. - - if (cityBuilding.getParentZoneID() != newParent.getParentZoneID()) - cityBuilding.setParentZone(newParent); - - // No longer a tree, no longer any protection contract! - - cityBuilding.setProtectionState(Enum.ProtectionState.NONE); - - // Destroy all remaining city assets - - if ((cityBuilding.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.BARRACK) - || (cityBuilding.getBlueprint().isWallPiece()) - || (cityBuilding.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.SHRINE) - || (cityBuilding.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.TOL) - || (cityBuilding.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.SPIRE) - || (cityBuilding.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.WAREHOUSE)) { - + //destroy all buildings if we are destroying the city itself if (cityBuilding.getRank() != -1) cityBuilding.setRank(-1); - } + + if(BuildingManager.getBuildingFromCache(cityBuilding.getObjectUUID()) != null){ + cityBuilding.removeFromCache(); + DbManager.BuildingQueries.DELETE_FROM_DATABASE(cityBuilding); + } + } if (city.getRealm() != null) diff --git a/src/engine/workthreads/MineThread.java b/src/engine/workthreads/MineThread.java index 281e21f0..ea0e3bf6 100644 --- a/src/engine/workthreads/MineThread.java +++ b/src/engine/workthreads/MineThread.java @@ -13,52 +13,19 @@ import engine.objects.Guild; import engine.objects.Mine; import engine.objects.PlayerCharacter; import org.pmw.tinylog.Logger; - import java.time.LocalDateTime; public class MineThread implements Runnable { + public static LocalDateTime nextPulse; public MineThread(){ } @Override public void run() { - LocalDateTime nextPulse = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0); - while (true){ + nextPulse = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0); + while (true) { if(LocalDateTime.now().isAfter(nextPulse)) { - for (Mine mine : Mine.getMines()) { - - if(nextPulse.getHour() == 2 && nextPulse.getMinute() == 0){ - mine.wasClaimed = false; - mine.hasProduced = false; - - } - Building mineTower = BuildingManager.getBuilding(mine.getBuildingID()); - - if (mineTower == null) - continue; - - int minute = 0; - if (mine.firstThirty == false) - minute = 30; - - LocalDateTime openTime = LocalDateTime.now().withHour(mine.liveTime).withMinute(minute).withSecond(0); - LocalDateTime closeTime = openTime.plusMinutes(29); - - //current time is after start time and before close time, open mine window - if (LocalDateTime.now().isAfter(openTime.minusMinutes(1)) && !mine.wasClaimed && !mine.wasOpened) { - mineWindowOpen(mine); - continue; - } - if (mine.isActive) { - - if (LocalDateTime.now().isAfter(closeTime) && mineTower.getRank() > 0) - mineWindowClose(mine); //mine was never knocked down, close window - - if (LocalDateTime.now().isAfter(closeTime) && mineTower.getRank() < 1 && mine.lastClaimer != null) - mineWindowClose(mine); //mine was knocked down and was claimed, close window - } - } - nextPulse = nextPulse.plusMinutes(30); + processMineWindows(); } } } @@ -66,7 +33,6 @@ public class MineThread implements Runnable { public static void mineWindowOpen(Mine mine) { mine.setActive(true); - ChatManager.chatSystemChannel(mine.getParentZone().getName() + "'s Mine is now Active!"); Logger.info(mine.getParentZone().getName() + "'s Mine is now Active!"); } @@ -137,4 +103,45 @@ public class MineThread implements Runnable { mine.wasClaimed = true; return true; } + + public static void processMineWindows(){ + for (Mine mine : Mine.getMines()) { + Building tower = BuildingManager.getBuildingFromCache(mine.getBuildingID()); + //if the tower comes back null, skip this mine + if(tower == null) + continue; + + //log the current time right now + LocalDateTime currentTime = LocalDateTime.now().plusMinutes(1); + + //check if this mine needs to open + LocalDateTime openTime = LocalDateTime.now().withHour(mine.liveHour).withMinute(mine.liveMinute).withSecond(0).withNano(0); + if(currentTime.isAfter(openTime) && currentTime.isBefore(openTime.plusMinutes(30)) && !mine.wasOpened){ + mineWindowOpen(mine); //hour and minute match, time to open the window + ChatManager.chatSystemChannel(mine.getParentZone().getName() + " " + mine.getMineType() + "MINE is now vulnerable to attack!"); + continue; + } + + //check to see if the window shoul dbe closing now + if(currentTime.isAfter(openTime.plusMinutes(29)) && mine.isActive) { + //check to see if the tower was destoryed + boolean towerDestroyed = tower.getRank() < 1; + if(towerDestroyed){ + //check if a valid claimer exists to close the window and claim the mine since the tower was destroyed + if(mine.lastClaimer != null) { + mineWindowClose(mine); + ChatManager.chatSystemChannel("The fight for " + mine.getParentZone().getName() + " " + mine.getMineType() + " MINE has concluded. " + mine.lastClaimer.getName() + " has seized it in the name of " + mine.lastClaimer.getGuild().getNation()); + }else{ + ChatManager.chatSystemChannel("The " + mine.getParentZone().getName() + " " + mine.getMineType() + " MINE is still unclaimed. The battle continues."); + } + }else{ + //tower was not destroyed, mine window closes + mineWindowClose(mine); + ChatManager.chatSystemChannel(tower.getGuild().getNation().getName() + " has successfully defended the " + mine.getParentZone().getName() + " " + mine.getMineType() + " MINE, and retains their claim."); + } + + } + } + nextPulse = nextPulse.plusMinutes(30); + } } diff --git a/src/engine/workthreads/ZergMechanicThread.java b/src/engine/workthreads/ZergMechanicThread.java index 58e6231e..27cb9493 100644 --- a/src/engine/workthreads/ZergMechanicThread.java +++ b/src/engine/workthreads/ZergMechanicThread.java @@ -8,196 +8,132 @@ package engine.workthreads; - import engine.Enum; import engine.InterestManagement.WorldGrid; -import engine.db.archive.DataWarehouse; -import engine.db.archive.MineRecord; import engine.gameManager.*; -import engine.mobileAI.Threads.MobAIThread; -import engine.net.DispatchMessage; -import engine.net.MessageDispatcher; -import engine.net.client.msg.chat.ChatSystemMsg; import engine.objects.*; import engine.server.MBServerStatics; -import engine.server.world.WorldServer; import org.pmw.tinylog.Logger; - -import java.time.LocalDateTime; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.concurrent.ConcurrentHashMap; - -import static engine.server.MBServerStatics.MINE_LATE_WINDOW; -public class ZergMechanicThread implements Runnable { -public Bane bane = null; -public Mine mine = null; -public ArrayList affectedPlayers = new ArrayList<>(); - - public ZergMechanicThread(Bane b, Mine m) { - this.mine = m; - this.bane = b; - } + public class ZergMechanicThread implements Runnable { + private final Mine mine; + private final Bane bane; + private final HashSet affectedPlayers = new HashSet<>(); - @Override - public void run() { + public ZergMechanicThread(Bane b, Mine m) { + this.mine = m; + this.bane = b; + } + @Override + public void run() { if (mine != null) RunMineMechanic(); if (bane != null) RunBaneMechanic(); - } - - public void RunMineMechanic(){ - while(mine.isActive) { - HashSet currentPlayers; - PlayerCharacter player; + } - // Gather current list of players within the zone bounds + private void RunMineMechanic() { Building tower = BuildingManager.getBuildingFromCache(mine.getBuildingID()); - currentPlayers = WorldGrid.getObjectsInRangePartial(tower.loc, Enum.CityBoundsType.GRID.extents * 0.5f, MBServerStatics.MASK_PLAYER); + float zoneBounds = Enum.CityBoundsType.GRID.extents * 0.5f; - for (AbstractWorldObject playerObject : currentPlayers) { + while (mine.isActive) { + HashSet currentPlayers = WorldGrid.getObjectsInRangePartial(tower.loc, zoneBounds, MBServerStatics.MASK_PLAYER); - if (playerObject == null) - continue; + for (AbstractWorldObject playerObject : currentPlayers) { + PlayerCharacter player = (PlayerCharacter) playerObject; - player = (PlayerCharacter) playerObject; + affectedPlayers.add(player); - if(!this.affectedPlayers.contains(player)) - this.affectedPlayers.add(player); - - //ChatManager.chatSystemInfo(player, "TESTING ZERG MECHANIC"); - if (mine._recentMemory.containsKey(player.getObjectUUID())) mine._recentMemory.remove(player.getObjectUUID()); - if (mine._playerMemory.contains(player.getObjectUUID())) - continue; + mine._playerMemory.add(player.getObjectUUID()); + } - mine._playerMemory.add(player.getObjectUUID()); + try { + mine.onExit(currentPlayers); + } catch (Exception e) { + Logger.error(e.getMessage()); + } - } - boolean updated = false; - try { - mine.onExit(currentPlayers); - } catch (Exception e) { - Logger.error(e.getMessage()); - } - mine.dividedPlayers = new HashMap<>(); - for (Integer playerID : mine._playerMemory) { - player = PlayerCharacter.getFromCache(playerID); - Guild nation = player.getGuild().getNation(); - Guild entry; - if (mine.dividedPlayers.containsKey(nation)) { - mine.dividedPlayers.get(nation).add(playerID); - } else { - ArrayList newEntry = new ArrayList<>(); - newEntry.add(playerID); - mine.dividedPlayers.put(nation, newEntry); + mine.dividedPlayers = new HashMap<>(); + for (Integer playerID : mine._playerMemory) { + PlayerCharacter player = PlayerCharacter.getFromCache(playerID); + Guild nation = player.getGuild().getNation(); + mine.dividedPlayers.computeIfAbsent(nation, k -> new ArrayList<>()).add(playerID); } - } - for (Integer playerID : mine._playerMemory) { - player = PlayerCharacter.getFromCache(playerID); - if (mine.dividedPlayers.containsKey(player.getGuild().getNation())) { - int count = mine.dividedPlayers.get(player.getGuild().getNation()).size(); - switch (mine.capSize) { - case 3: - player.ZergMultiplier = ZergManager.getMultiplier3Man(count); - break; - case 5: - player.ZergMultiplier = ZergManager.getMultiplier5Man(count); - break; - case 10: - player.ZergMultiplier = ZergManager.getMultiplier10Man(count); - break; - case 20: - player.ZergMultiplier = ZergManager.getMultiplier20Man(count); - break; + + for (Integer playerID : mine._playerMemory) { + PlayerCharacter player = PlayerCharacter.getFromCache(playerID); + Guild nation = player.getGuild().getNation(); + + if (mine.dividedPlayers.containsKey(nation)) { + int count = mine.dividedPlayers.get(nation).size(); + player.ZergMultiplier = ZergManager.getCurrentMultiplier(count, mine.capSize); + player.mineAppliedID = mine.getObjectUUID(); + } else { + player.ZergMultiplier = 1.0f; + player.mineAppliedID = 0; } - player.mineAppliedID = mine.getObjectUUID(); - } else { - player.ZergMultiplier = 1.0f; - player.mineAppliedID = 0; } } - } - for(PlayerCharacter player : this.affectedPlayers) - player.ZergMultiplier = 1.0f; - } - - public void RunBaneMechanic(){ - while(bane.getSiegePhase().equals(Enum.SiegePhase.WAR)) { - HashSet currentPlayers; - - currentPlayers = WorldGrid.getObjectsInRangePartial(bane.getCity().loc, Enum.CityBoundsType.GRID.extents * 2.0f, MBServerStatics.MASK_PLAYER); - - Guild attacker = bane.getStone().getGuild().getNation(); - Guild defender = bane.getCity().getGuild().getNation(); - - ArrayList attackers = new ArrayList<>(); - ArrayList defenders = new ArrayList<>(); + resetZergMultiplier(); + } - for (AbstractWorldObject awo : currentPlayers) { + private void RunBaneMechanic() { + while (bane.getSiegePhase().equals(Enum.SiegePhase.WAR)) { + HashSet currentPlayers = WorldGrid.getObjectsInRangePartial(bane.getCity().loc, Enum.CityBoundsType.GRID.extents * 2.0f, MBServerStatics.MASK_PLAYER); + Guild attacker = bane.getStone().getGuild().getNation(); + Guild defender = bane.getCity().getGuild().getNation(); + ArrayList attackers = new ArrayList<>(); + ArrayList defenders = new ArrayList<>(); + + for (AbstractWorldObject awo : currentPlayers) { + PlayerCharacter pc = (PlayerCharacter) awo; + affectedPlayers.add(pc); + + if (!pc.getGuild().getNation().equals(attacker) && !pc.getGuild().getNation().equals(defender)) { + pc.teleport(pc.bindLoc); + pc.ZergMultiplier = 1.0f; + } - if(!this.affectedPlayers.contains((PlayerCharacter)awo)) - this.affectedPlayers.add((PlayerCharacter)awo); + if (pc.getGuild().getNation().equals(attacker)) + attackers.add(pc); - PlayerCharacter pc = (PlayerCharacter) awo; - if (!pc.getGuild().getNation().equals(attacker) && !pc.getGuild().getNation().equals(defender)) { - pc.teleport(pc.bindLoc); - pc.ZergMultiplier = 1.0f; + if (pc.getGuild().getNation().equals(defender)) + defenders.add(pc); } - if (pc.getGuild().getNation().equals(attacker)) - attackers.add(pc); - - if (pc.getGuild().getNation().equals(defender)) - defenders.add(pc); - } - - //int treeRank = bane.getCity().getTOL().getRank(); - - for (PlayerCharacter pc : attackers) { - switch(bane.capSize){ - case 10: - pc.ZergMultiplier = ZergManager.getMultiplier10Man(attackers.size()); - break; - case 20: - pc.ZergMultiplier = ZergManager.getMultiplier20Man(attackers.size()); - break; + for (PlayerCharacter pc : attackers) { + pc.ZergMultiplier = ZergManager.getCurrentMultiplier(attackers.size(), bane.capSize); } - } - for (PlayerCharacter pc : defenders) { - switch(bane.capSize){ - case 10: - pc.ZergMultiplier = ZergManager.getMultiplier10Man(defenders.size()); - break; - case 20: - pc.ZergMultiplier = ZergManager.getMultiplier20Man(defenders.size()); - break; + for (PlayerCharacter pc : defenders) { + pc.ZergMultiplier = ZergManager.getCurrentMultiplier(defenders.size(), bane.capSize); } } + + resetZergMultiplier(); } - for(PlayerCharacter player : this.affectedPlayers) - player.ZergMultiplier = 1.0f; - } + private void resetZergMultiplier() { + for (PlayerCharacter player : affectedPlayers) + player.ZergMultiplier = 1.0f; + } - public static void startZergThreadMine(Mine mine) { - Thread zergMechanicThread; - zergMechanicThread = new Thread(new ZergMechanicThread(null, mine)); - zergMechanicThread.setName(mine.getParentZone().getName() + "Mine"); - zergMechanicThread.start(); - } + public static void startZergThreadMine(Mine mine) { + Thread zergMechanicThread = new Thread(new ZergMechanicThread(null, mine)); + zergMechanicThread.setName(mine.getParentZone().getName() + "Mine"); + zergMechanicThread.start(); + } - public static void startZergThreadBane(Bane bane) { - Thread zergMechanicThread; - zergMechanicThread = new Thread(new ZergMechanicThread(bane, null)); - zergMechanicThread.setName(bane.getCity().getGuild().getName() + "Bane"); - zergMechanicThread.start(); + public static void startZergThreadBane(Bane bane) { + Thread zergMechanicThread = new Thread(new ZergMechanicThread(bane, null)); + zergMechanicThread.setName(bane.getCity().getGuild().getName() + "Bane"); + zergMechanicThread.start(); + } } -}