Browse Source

Merge branch 'lakebane-mines' into lakebane-master

# Conflicts:
#	src/engine/gameManager/CombatManager.java
#	src/engine/mobileAI/utilities/MovementUtilities.java
#	src/engine/net/client/ClientMessagePump.java
#	src/engine/net/client/msg/VendorDialogMsg.java
#	src/engine/objects/CharacterItemManager.java
#	src/engine/objects/Mine.java
#	src/engine/objects/PlayerCharacter.java
#	src/engine/objects/Warehouse.java
lakebane-master
FatBoy-DOTC 7 months ago
parent
commit
5dee08d3ce
  1. 20
      src/engine/db/handlers/dbItemHandler.java
  2. 5
      src/engine/devcmd/cmds/SetLevelCmd.java
  3. 3
      src/engine/gameManager/CombatManager.java
  4. 556
      src/engine/gameManager/LootManager.java
  5. 132
      src/engine/gameManager/ZergManager.java
  6. 512
      src/engine/mobileAI/MobAI.java
  7. 212
      src/engine/mobileAI/utilities/CombatUtilities.java
  8. 11
      src/engine/mobileAI/utilities/MovementUtilities.java
  9. 80
      src/engine/net/client/ClientMessagePump.java
  10. 9
      src/engine/net/client/handlers/DestroyBuildingHandler.java
  11. 156
      src/engine/net/client/handlers/ManageCityAssetMsgHandler.java
  12. 2
      src/engine/net/client/msg/ApplyRuneMsg.java
  13. 18
      src/engine/net/client/msg/VendorDialogMsg.java
  14. 17
      src/engine/objects/AbstractCharacter.java
  15. 4
      src/engine/objects/Bane.java
  16. 12
      src/engine/objects/Building.java
  17. 85
      src/engine/objects/CharacterItemManager.java
  18. 51
      src/engine/objects/Experience.java
  19. 313
      src/engine/objects/Mine.java
  20. 2
      src/engine/objects/MineProduction.java
  21. 95
      src/engine/objects/PlayerCharacter.java
  22. 113
      src/engine/objects/Warehouse.java
  23. 2
      src/engine/server/MBServerStatics.java
  24. 10
      src/engine/server/world/WorldServer.java
  25. 35
      src/engine/workthreads/DestroyCityThread.java
  26. 83
      src/engine/workthreads/MineThread.java
  27. 138
      src/engine/workthreads/ZergMechanicThread.java

20
src/engine/db/handlers/dbItemHandler.java

@ -504,4 +504,24 @@ public class dbItemHandler extends dbHandlerBase {
return false; 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;
}
}
} }

5
src/engine/devcmd/cmds/SetLevelCmd.java

@ -14,6 +14,7 @@ import engine.devcmd.AbstractDevCmd;
import engine.gameManager.ChatManager; import engine.gameManager.ChatManager;
import engine.objects.AbstractGameObject; import engine.objects.AbstractGameObject;
import engine.objects.PlayerCharacter; import engine.objects.PlayerCharacter;
import engine.server.MBServerStatics;
public class SetLevelCmd extends AbstractDevCmd { public class SetLevelCmd extends AbstractDevCmd {
@ -46,7 +47,7 @@ public class SetLevelCmd extends AbstractDevCmd {
this.sendUsage(pc); this.sendUsage(pc);
return; return;
} }
if (level < 1 || level > 75) { if (level < 1 || level > MBServerStatics.LEVELCAP) {
this.sendHelp(pc); this.sendHelp(pc);
return; return;
} }
@ -62,7 +63,7 @@ public class SetLevelCmd extends AbstractDevCmd {
@Override @Override
protected String _getHelpString() { 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 @Override

3
src/engine/gameManager/CombatManager.java

@ -1277,6 +1277,9 @@ public enum CombatManager {
if(ac.getObjectType().equals(GameObjectType.PlayerCharacter)){ if(ac.getObjectType().equals(GameObjectType.PlayerCharacter)){
range += ((PlayerCharacter)ac).getCharacterHeight() * 0.5f; range += ((PlayerCharacter)ac).getCharacterHeight() * 0.5f;
if(ac.isMoving()){
range += ((PlayerCharacter) ac).getCharacterHeight();
}
} }
float magnitudeSquared = tl.distanceSquared(sl); float magnitudeSquared = tl.distanceSquared(sl);

556
src/engine/gameManager/LootManager.java

@ -73,38 +73,38 @@ public enum LootManager {
} }
public static void GenerateMobLoot(Mob mob) { public static void GenerateMobLoot(Mob mob) {
int mobBootySet = mob.getMobBase().bootySet;
if (mobBootySet != 0) {
RunBootySetIfPresent(mobBootySet, mob);
}
//iterate the booty sets mobBootySet = mob.bootySet;
if (mobBootySet != 0) {
if (mob.getMobBase().bootySet != 0 && _bootySetMap.containsKey(mob.getMobBase().bootySet) == true) RunBootySetIfPresent(mobBootySet, mob);
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()) {
ItemBase ib = it.getItemBase(); // Check mob's inventory for godly or disc runes to send a server announcement
if(ib == null) for (Item item : mob.getInventory()) {
break; ItemBase itemBase = item.getItemBase();
if (ib.getName().toLowerCase().contains("of the gods")) { if (itemBase != null && itemBase.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?"); 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.setMessageType(10);
chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID()); chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID());
DispatchMessage.dispatchMsgToAll(chatMsg); DispatchMessage.dispatchMsgToAll(chatMsg);
} }
} }
} }
private static void RunBootySet(ArrayList<BootySetEntry> entries, Mob mob) { private static void RunBootySet(ArrayList<BootySetEntry> entries, Mob mob) {
float dropRate = NORMAL_DROP_RATE; float dropRate = NORMAL_DROP_RATE;
//roll the geenric world drop table boolean isSafeZone = mob.parentZone.getSafeZone() == 0;
if(mob.parentZone.getSafeZone() == 0) {
if (isSafeZone) {
GenerateLootDrop(mob, 1300); GenerateLootDrop(mob, 1300);
if(ThreadLocalRandom.current().nextInt(1, 10000) == 5000) { if (ThreadLocalRandom.current().nextInt(1, 10000) == 5000) {
MobLoot extraLoot = rollForGlass(mob); MobLoot extraLoot = rollForGlass(mob);
if (extraLoot != null) { if (extraLoot != null) {
mob.getCharItemManager().addItemToInventory(extraLoot); mob.getCharItemManager().addItemToInventory(extraLoot);
@ -112,7 +112,6 @@ public enum LootManager {
} }
} }
// Iterate all entries in this bootySet and process accordingly
boolean hasExtraRolled = false; boolean hasExtraRolled = false;
for (BootySetEntry bse : entries) { for (BootySetEntry bse : entries) {
switch (bse.bootyType) { switch (bse.bootyType) {
@ -120,17 +119,13 @@ public enum LootManager {
GenerateGoldDrop(mob, bse); GenerateGoldDrop(mob, bse);
break; break;
case "LOOT": case "LOOT":
if (ThreadLocalRandom.current().nextInt(1, 100 + 1) < (bse.dropChance * dropRate)) if (ThreadLocalRandom.current().nextInt(1, 101) < (bse.dropChance * dropRate)) {
GenerateLootDrop(mob, bse.genTable); //generate normal loot drop GenerateLootDrop(mob, bse.genTable);
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 (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) { if (extraLoot != null) {
mob.getCharItemManager().addItemToInventory(extraLoot); mob.getCharItemManager().addItemToInventory(extraLoot);
} }
@ -142,45 +137,60 @@ public enum LootManager {
break; 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; MobLoot specialDrop = null;
switch(mob.getObjectUUID()) { int mobUUID = mob.getObjectUUID();
case 22595://elf 1 switch (mobUUID) {
specialDrop = new MobLoot(mob,ItemBase.getItemBase(252134),true); case 22595:
mob.setFirstName("Melandrach The Blood-Mage"); specialDrop = createSpecialDrop(mob, 252134, "Melandrach The Blood-Mage");
break; break;
case 22432: //elf 2 case 22432:
specialDrop = new MobLoot(mob,ItemBase.getItemBase(252135),true); specialDrop = createSpecialDrop(mob, 252135, "Kyrtaar The Blood-Mage");
mob.setFirstName("Kyrtaar The Blood-Mage");
break; break;
case 22537: //elf 3 case 22537:
specialDrop = new MobLoot(mob,ItemBase.getItemBase(252136),true); specialDrop = createSpecialDrop(mob, 252136, "Vamir The Blood-Mage");
mob.setFirstName("Vamir The Blood-Mage");
break; break;
case 16387: //human 4 DONE case 16387:
specialDrop = new MobLoot(mob,ItemBase.getItemBase(252129),true); specialDrop = createSpecialDrop(mob, 252129, "Alatar The Blood-Mage");
mob.setFirstName("Alatar The Blood-Mage");
break; break;
case 32724:// human 5 GOOD case 32724:
specialDrop = new MobLoot(mob,ItemBase.getItemBase(252130),true); specialDrop = createSpecialDrop(mob, 252130, "Elphaba The Blood-Mage");
mob.setFirstName("Elphaba The Blood-Mage");
break; break;
case 23379: //human 1 GOOD case 23379:
specialDrop = new MobLoot(mob,ItemBase.getItemBase(252131),true); specialDrop = createSpecialDrop(mob, 252131, "Bavmorda The Blood-Mage");
mob.setFirstName("Bavmorda The Blood-Mage");
break; break;
case 10826: //human 2 REDO case 10826:
specialDrop = new MobLoot(mob,ItemBase.getItemBase(252132),true); specialDrop = createSpecialDrop(mob, 252132, "Draco The Blood-Mage");
mob.setFirstName("Draco The Blood-Mage");
break; break;
case 15929: //human 3 GOOD case 15929:
specialDrop = new MobLoot(mob,ItemBase.getItemBase(252133),true); specialDrop = createSpecialDrop(mob, 252133, "Atlantes The Blood-Mage");
mob.setFirstName("Atlantes The Blood-Mage");
break; break;
} }
if(specialDrop != null) { return specialDrop;
}
private static MobLoot createSpecialDrop(Mob mob, int itemBaseId, String name) {
mob.setFirstName(name);
return new MobLoot(mob, ItemBase.getItemBase(itemBaseId), true);
}
private static void enhanceMob(Mob mob, MobLoot specialDrop) {
mob.setLevel((short) 65); mob.setLevel((short) 65);
mob.setSpawnTime(10800); mob.setSpawnTime(10800);
mob.healthMax = (7500); mob.healthMax = 7500;
mob.setHealth(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?"); 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.setMessageType(10);
@ -189,100 +199,81 @@ public enum LootManager {
mob.getCharItemManager().addItemToInventory(specialDrop); mob.getCharItemManager().addItemToInventory(specialDrop);
mob.setResists(new Resists("Dropper")); mob.setResists(new Resists("Dropper"));
} }
}
public static MobLoot getGenTableItem(int genTableID, AbstractCharacter mob) { public static MobLoot getGenTableItem(int genTableID, AbstractCharacter mob) {
if (mob == null || !_genTables.containsKey(genTableID)) {
if (mob == null || _genTables.containsKey(genTableID) == false)
return null; return null;
}
MobLoot outItem; int genRoll = ThreadLocalRandom.current().nextInt(1, 95);
int genRoll = ThreadLocalRandom.current().nextInt(1,94 + 1);
GenTableEntry selectedRow = GenTableEntry.rollTable(genTableID, genRoll, 1.0f); GenTableEntry selectedRow = GenTableEntry.rollTable(genTableID, genRoll, 1.0f);
if (selectedRow == null) if (selectedRow == null || !_itemTables.containsKey(selectedRow.itemTableID)) {
return null; 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) ItemTableEntry tableRow = ItemTableEntry.rollTable(selectedRow.itemTableID, itemTableRoll);
return null;
//gets the 1-320 roll for this mob if (tableRow == null || tableRow.cacheID == 0) {
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)
return null; return null;
}
int itemUUID = tableRow.cacheID; ItemBase itemBase = ItemBase.getItemBase(tableRow.cacheID);
if (itemBase == null) {
if (itemUUID == 0)
return null; return null;
}
if (ItemBase.getItemBase(itemUUID).getType().ordinal() == Enum.ItemType.RESOURCE.ordinal()) { if (itemBase.getType() == Enum.ItemType.RESOURCE) {
int chance = ThreadLocalRandom.current().nextInt(1,101); if (ThreadLocalRandom.current().nextInt(1, 101) > 10) {
if(chance > 10)
return null; 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); MobLoot outItem = new MobLoot(mob, itemBase, false);
Enum.ItemType outType = outItem.getItemBase().getType();
if(selectedRow.pModTable != 0){
try { try {
if (selectedRow.pModTable != 0) {
outItem = GeneratePrefix(mob, outItem, genTableID, genRoll); outItem = GeneratePrefix(mob, outItem, genTableID, genRoll);
outItem.setIsID(false); outItem.setIsID(false);
} catch (Exception e) {
Logger.error("Failed to GeneratePrefix for item: " + outItem.getName());
} }
} if (selectedRow.sModTable != 0) {
if(selectedRow.sModTable != 0){
try {
outItem = GenerateSuffix(mob, outItem, genTableID, genRoll); outItem = GenerateSuffix(mob, outItem, genTableID, genRoll);
outItem.setIsID(false); 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; return outItem;
} }
private static MobLoot GeneratePrefix(AbstractCharacter mob, MobLoot inItem, int genTableID, int genRoll) { private static MobLoot GeneratePrefix(AbstractCharacter mob, MobLoot inItem, int genTableID, int genRoll) {
GenTableEntry selectedRow = GenTableEntry.rollTable(genTableID, genRoll, 1.0f); GenTableEntry selectedRow = GenTableEntry.rollTable(genTableID, genRoll, 1.0f);
if (selectedRow == null) {
if (selectedRow == null)
return inItem; return inItem;
}
int prefixroll = ThreadLocalRandom.current().nextInt(1, 100 + 1); ModTypeTableEntry prefixTable = ModTypeTableEntry.rollTable(selectedRow.pModTable, ThreadLocalRandom.current().nextInt(1, 101));
if (prefixTable == null) {
ModTypeTableEntry prefixTable = ModTypeTableEntry.rollTable(selectedRow.pModTable, prefixroll);
if (prefixTable == null)
return inItem; 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; return inItem;
}
if (prefixMod.action.length() > 0) { if (!prefixMod.action.isEmpty()) {
inItem.setPrefix(prefixMod.action); inItem.setPrefix(prefixMod.action);
inItem.addPermanentEnchantment(prefixMod.action, 0, prefixMod.level, true); 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) { private static MobLoot GenerateSuffix(AbstractCharacter mob, MobLoot inItem, int genTableID, int genRoll) {
GenTableEntry selectedRow = GenTableEntry.rollTable(genTableID, genRoll, 1.0f); GenTableEntry selectedRow = GenTableEntry.rollTable(genTableID, genRoll, 1.0f);
if (selectedRow == null) {
if (selectedRow == null)
return inItem; return inItem;
}
int suffixRoll = ThreadLocalRandom.current().nextInt(1, 100 + 1); ModTypeTableEntry suffixTable = ModTypeTableEntry.rollTable(selectedRow.sModTable, ThreadLocalRandom.current().nextInt(1, 101));
if (suffixTable == null) {
ModTypeTableEntry suffixTable = ModTypeTableEntry.rollTable(selectedRow.sModTable, suffixRoll);
if (suffixTable == null)
return inItem; 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; return inItem;
}
if (suffixMod.action.length() > 0) { if (!suffixMod.action.isEmpty()) {
inItem.setSuffix(suffixMod.action); inItem.setSuffix(suffixMod.action);
inItem.addPermanentEnchantment(suffixMod.action, 0, suffixMod.level, false); inItem.addPermanentEnchantment(suffixMod.action, 0, suffixMod.level, false);
} }
@ -323,151 +310,142 @@ public enum LootManager {
} }
public static int TableRoll(int mobLevel) { public static int TableRoll(int mobLevel) {
mobLevel = Math.min(mobLevel, 65);
if (mobLevel > 65) int max = Math.min((int) (4.882 * mobLevel + 127.0), 319);
mobLevel = 65; int min = Math.max((int) (4.469 * mobLevel - 3.469), 70);
int max = (int) (4.882 * mobLevel + 127.0);
if (max > 319)
max = 319;
int min = (int) (4.469 * mobLevel - 3.469);
if (min < 70)
min = 70;
int roll = ThreadLocalRandom.current().nextInt(min, max + 1); return ThreadLocalRandom.current().nextInt(min, max + 1);
return roll;
} }
public static void GenerateGoldDrop(Mob mob, BootySetEntry bse) { 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 if failed to hit minimum chance roll
if (chanceRoll > bse.dropChance) {
//early exit, failed to hit minimum chance roll
if (chanceRoll > bse.dropChance)
return; return;
}
//determine and add gold to mob inventory // Determine and add gold to mob inventory
int high = (int) (bse.highGold * NORMAL_GOLD_RATE);
int high = (int)(bse.highGold * NORMAL_GOLD_RATE); int low = (int) (bse.lowGold * NORMAL_GOLD_RATE);
int low = (int)(bse.lowGold * NORMAL_GOLD_RATE);
int gold = ThreadLocalRandom.current().nextInt(low, high); int gold = ThreadLocalRandom.current().nextInt(low, high);
if (gold > 0) { if (gold > 0) {
MobLoot goldAmount = new MobLoot(mob, gold); MobLoot goldAmount = new MobLoot(mob, gold);
mob.getCharItemManager().addItemToInventory(goldAmount); mob.getCharItemManager().addItemToInventory(goldAmount);
} }
} }
public static void GenerateLootDrop(Mob mob, int tableID) { public static void GenerateLootDrop(Mob mob, int tableID) {
if (mob.parentZone.getSafeZone() == 1) {
return; // Exit early if in a safe zone
}
try { try {
if(mob.parentZone.getSafeZone() == 1) {
return;
}
MobLoot toAdd = getGenTableItem(tableID, mob); MobLoot toAdd = getGenTableItem(tableID, mob);
if(toAdd.getItemBase().getType().equals(Enum.ItemType.CONTRACT) || toAdd.getItemBase().getType().equals(Enum.ItemType.RUNE)) if (toAdd != null && !isContractOrRune(toAdd)) {
return;//block all contracts and runes that drop outside the confines of the new system
if (toAdd != null) {
toAdd.setIsID(true); toAdd.setIsID(true);
mob.getCharItemManager().addItemToInventory(toAdd); mob.getCharItemManager().addItemToInventory(toAdd);
} }
} catch (Exception e) { } 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; return;
} }
//do equipment here
int dropCount = 0; int dropCount = 0;
if (mob.getEquip() != null) if (mob.getEquip() != null) {
for (MobEquipment me : mob.getEquip().values()) { for (MobEquipment me : mob.getEquip().values()) {
if (me.getDropChance() == 0) {
if (me.getDropChance() == 0)
continue; 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; float dropChance = me.getDropChance() * 100;
if (equipmentRoll > dropChance)
if (equipmentRoll > dropChance) {
continue; continue;
}
ItemBase genericIB = me.getItemBase(); ItemBase genericIB = me.getItemBase();
if(genericIB.isVorg()){ if (genericIB.isVorg()) {
if(genericIB.isClothArmor()){ genericIB = getRandomVorgPiece(genericIB); // Replaced separate method calls with a single one
//get random cloth piece mob.spawnTime = ThreadLocalRandom.current().nextInt(300, 2700);
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);
} }
MobLoot ml = new MobLoot(mob, genericIB, false); MobLoot ml = new MobLoot(mob, genericIB, false);
if (ml != null && dropCount < 1 && genericIB.isVorg() == false) { if (ml != null && dropCount < 1) {
ml.setIsID(true); ml.setIsID(true);
ml.setDurabilityCurrent((short) (ml.getDurabilityCurrent() - ThreadLocalRandom.current().nextInt(5) + 1)); ml.setDurabilityCurrent((short) (ml.getDurabilityCurrent() - ThreadLocalRandom.current().nextInt(5) + 1));
mob.getCharItemManager().addItemToInventory(ml); mob.getCharItemManager().addItemToInventory(ml);
dropCount = 1; dropCount++;
//break; // Exit on first successful roll.
} }
if(ml != null && genericIB.isVorg() && mob.getMobBaseID() != 14062){
if (ml != null && genericIB.isVorg() && mob.getMobBaseID() != 14062) {
ml.setIsID(true); ml.setIsID(true);
ml.setDurabilityCurrent(ml.getDurabilityMax()); ml.setDurabilityCurrent(ml.getDurabilityMax());
mob.getCharItemManager().addItemToInventory(ml); 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()) { public static void GenerateInventoryDrop(Mob mob, BootySetEntry bse) {
if(!Mob.disciplineDroppers.contains(mob)) // Check if the item is a discipline rune
if (ItemBase.getItemBase(bse.itemBase).isDiscRune()) {
if (!Mob.disciplineDroppers.contains(mob)) {
Mob.disciplineDroppers.add(mob); Mob.disciplineDroppers.add(mob);
mob.setResists(new Resists("Dropper")); 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?"); 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.setMessageType(10);
chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID()); chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID());
DispatchMessage.dispatchMsgToAll(chatMsg); DispatchMessage.dispatchMsgToAll(chatMsg);
} }
}
//if((bse.itemBase == 3040 || bse.itemBase == 3021) && mob.level < 80){ // Skip drop if mob is in a safe zone
// chance = 100; if (mob.parentZone.getSafeZone() == 1) {
//}
if(mob.parentZone.getSafeZone() == 1) {
return; return;
} }
int chanceRoll = ThreadLocalRandom.current().nextInt(1, 99); // Roll for drop chance
int chanceRoll = ThreadLocalRandom.current().nextInt(1, 100); // Changed upper bound to 100
//early exit, failed to hit minimum chance roll
if (chanceRoll > bse.dropChance) // Check if the chance roll exceeds drop chance
return; 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); MobLoot lootItem = new MobLoot(mob, ItemBase.getItemBase(bse.itemBase), true);
if (lootItem != null) {
if (lootItem != null)
mob.getCharItemManager().addItemToInventory(lootItem); mob.getCharItemManager().addItemToInventory(lootItem);
} }
}
public static void peddleFate(PlayerCharacter playerCharacter, Item gift) { public static void peddleFate(PlayerCharacter playerCharacter, Item gift) {
@ -553,151 +531,75 @@ public enum LootManager {
itemMan.updateInventory(); itemMan.updateInventory();
} }
public static MobLoot rollForContract(int table, Mob mob){ public static MobLoot rollForContract(int table, Mob mob) {
int roll = (table == 1900 || table == 1500) ? 73 : 99;
int roll = 99;
if (table == 1900 || table == 1500)
roll = 73;
GenTableEntry selectedRow = GenTableEntry.rollTable(table, roll, 1.0f); GenTableEntry selectedRow = GenTableEntry.rollTable(table, roll, 1.0f);
if (selectedRow == null) if (selectedRow == null) {
return null; return null;
}
int itemTableId = selectedRow.itemTableID; int itemTableId = selectedRow.itemTableID;
if (!_itemTables.containsKey(itemTableId)) {
if (_itemTables.containsKey(itemTableId) == false)
return null;
ItemTableEntry tableRow = ItemTableEntry.rollTable(itemTableId, ThreadLocalRandom.current().nextInt(1,321));
if (tableRow == null)
return null;
int itemUUID = tableRow.cacheID;
if (itemUUID == 0)
return null; return null;
}
MobLoot outItem = new MobLoot(mob, ItemBase.getItemBase(itemUUID), false); ItemTableEntry tableRow = ItemTableEntry.rollTable(itemTableId, ThreadLocalRandom.current().nextInt(1, 321));
if(outItem != null) if (tableRow == null || tableRow.cacheID == 0) {
return outItem;
return null; return null;
} }
public static MobLoot rollForRune(int table, Mob mob){
int roll = 97; return new MobLoot(mob, ItemBase.getItemBase(tableRow.cacheID), false);
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); GenTableEntry selectedRow = GenTableEntry.rollTable(table, roll, 1.0f);
if (selectedRow == null) if (selectedRow == null) {
return null; return null;
}
int itemTableId = selectedRow.itemTableID; int itemTableId = selectedRow.itemTableID;
if (!_itemTables.containsKey(itemTableId)) {
if (_itemTables.containsKey(itemTableId) == false)
return null;
ItemTableEntry tableRow = ItemTableEntry.rollTable(itemTableId, ThreadLocalRandom.current().nextInt(1,321));
if (tableRow == null)
return null;
int itemUUID = tableRow.cacheID;
if (itemUUID == 0)
return null; return null;
}
MobLoot outItem = new MobLoot(mob, ItemBase.getItemBase(itemUUID), false); ItemTableEntry tableRow = ItemTableEntry.rollTable(itemTableId, ThreadLocalRandom.current().nextInt(1, 321));
if(outItem != null) if (tableRow == null || tableRow.cacheID == 0) {
return outItem;
return null; return null;
} }
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 new MobLoot(mob, ItemBase.getItemBase(tableRow.cacheID), false);
return null; }
MobLoot outItem = new MobLoot(mob, ItemBase.getItemBase(itemUUID), false); public static MobLoot rollForGlass(Mob mob) {
if(outItem != null) ItemTableEntry tableRow = ItemTableEntry.rollTable(126, ThreadLocalRandom.current().nextInt(1, 321));
return outItem; if (tableRow != null && tableRow.cacheID != 0) {
return new MobLoot(mob, ItemBase.getItemBase(tableRow.cacheID), false);
}
return null; return null;
} }
public static ItemBase getRandomVorgCloth(){ public static ItemBase getRandomVorgItem(int maxRandom, int... itemBaseIDs) {
int random = ThreadLocalRandom.current().nextInt(100); int random = ThreadLocalRandom.current().nextInt(maxRandom);
if(random < 20) int index = random / (maxRandom / itemBaseIDs.length);
return ItemBase.getItemBase(27600); if (index >= itemBaseIDs.length) {
if(random > 20 && random < 40) index = itemBaseIDs.length - 1;
return ItemBase.getItemBase(188700); }
if(random > 40 && random < 60) return ItemBase.getItemBase(itemBaseIDs[index]);
return ItemBase.getItemBase(188720); }
if(random > 60 && random < 80) public static ItemBase getRandomVorgCloth() {
return ItemBase.getItemBase(189550); return getRandomVorgItem(100, 27600, 188700, 188720, 189550, 189560);
if(random > 80)
return ItemBase.getItemBase(189560);
return null;
} }
public static ItemBase getRandomVorgLA(){ public static ItemBase getRandomVorgLA() {
int random = ThreadLocalRandom.current().nextInt(160); return getRandomVorgItem(160, 27550, 27560, 189100, 189110, 189120, 189130, 189140, 189150);
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 getRandomVorgMA(){
int random = ThreadLocalRandom.current().nextInt(160); public static ItemBase getRandomVorgMA() {
if(random < 20) return getRandomVorgItem(160, 27570, 188900, 188910, 188920, 188930, 188940, 188950, 189500);
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 getRandomVorgHA(){
int random = ThreadLocalRandom.current().nextInt(180); public static ItemBase getRandomVorgHA() {
if(random < 20) return getRandomVorgItem(180, 27580, 27590, 188500, 188510, 188520, 188530, 188540, 188550, 189510);
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;
} }
} }

132
src/engine/gameManager/ZergManager.java

@ -4,117 +4,51 @@ import engine.objects.Guild;
public class ZergManager { public class ZergManager {
public static int getBaneCap(Guild guild){ public static int getBaneCap(Guild guild) {
if(guild.getOwnedCity().getTOL().getRank() == 8) int cityRank = guild.getOwnedCity().getTOL().getRank();
return 20; return (cityRank == 8) ? 20 : ((guild.getNation().getSubGuildList().size() + 1 <= 4) ? 10 : 20);
if(guild.getNation().getSubGuildList().size() + 1 <= 4)
return 10;
return 20;
} }
public static float getMultiplier3Man(int count){ public static float getCurrentMultiplier(int count, int maxCount){
float multiplier = 1.0f; switch(maxCount) {
case 3:
if(count <= 3) return getMultiplier3Man(count);
return 1.0f;
if(count > 6)
return 0.0f;
switch(count){
case 4:
multiplier -= 0.37f;
break;
case 5: case 5:
multiplier -= 0.60f; return getMultiplier5Man(count);
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;
case 10: case 10:
multiplier -= 0.75f; return getMultiplier10Man(count);
break; 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){ public static float getMultiplier3Man(int count) {
float multiplier = 1.0f; float[] thresholds = {0.37f, 0.60f, 0.75f};
return getMultiplier(count, 3, thresholds);
if(count <= 10) }
return 1.0f;
if(count > 20)
return 0.0f;
switch(count){ public static float getMultiplier5Man(int count) {
case 11: float[] thresholds = {0.25f, 0.43f, 0.56f, 0.67f, 0.75f};
multiplier -= 0.14f; return getMultiplier(count, 5, thresholds);
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){ public static float getMultiplier20Man(int count) {
return getMultiplier10Man(((int)(count * 0.5f))); return getMultiplier10Man(count * 2);
} }
public static float getMultiplier40Man(int count){ public static float getMultiplier40Man(int count) {
return getMultiplier10Man(((int)(count * 0.25f))); return getMultiplier10Man(count * 4);
} }
} }

512
src/engine/mobileAI/MobAI.java

@ -18,17 +18,16 @@ import engine.mobileAI.Threads.MobAIThread;
import engine.mobileAI.utilities.CombatUtilities; import engine.mobileAI.utilities.CombatUtilities;
import engine.mobileAI.utilities.MovementUtilities; import engine.mobileAI.utilities.MovementUtilities;
import engine.net.DispatchMessage; import engine.net.DispatchMessage;
import engine.net.client.msg.PerformActionMsg;
import engine.net.client.msg.PowerProjectileMsg; import engine.net.client.msg.PowerProjectileMsg;
import engine.net.client.msg.UpdateStateMsg;
import engine.objects.*; import engine.objects.*;
import engine.powers.ActionsBase;
import engine.powers.PowersBase; import engine.powers.PowersBase;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
@ -54,18 +53,6 @@ public class MobAI {
return; 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)) if (!CombatUtilities.inRangeToAttack(mob, target))
return; return;
@ -85,8 +72,6 @@ public class MobAI {
break; break;
} }
mob.updateLocation();
} catch (Exception e) { } catch (Exception e) {
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackTarget" + " " + e.getMessage()); 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() != null)
if (target.getPet().getCombatTarget() == null && target.getPet().assist == true) if (target.getPet().getCombatTarget() == null && target.getPet().assist)
target.getPet().setCombatTarget(mob); target.getPet().setCombatTarget(mob);
} catch (Exception e) { } catch (Exception e) {
@ -251,7 +236,7 @@ public class MobAI {
if(target.isAlive()) if(target.isAlive())
target.setCombatTarget(mob); 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); mob.setCombatTarget(target.guardCaptain);
} }
if(mob.isPet()){ if(mob.isPet()){
@ -272,7 +257,7 @@ public class MobAI {
//early exit while waiting to patrol again //early exit while waiting to patrol again
if (mob.stopPatrolTime + (patrolDelay * 1000) > System.currentTimeMillis()) if (mob.stopPatrolTime + (patrolDelay * 1000L) > System.currentTimeMillis())
return; return;
//guard captains inherit barracks patrol points dynamically //guard captains inherit barracks patrol points dynamically
@ -302,7 +287,7 @@ public class MobAI {
//make sure mob is out of combat stance //make sure mob is out of combat stance
if (minion.getKey().despawned == false) { if (!minion.getKey().despawned) {
if (MovementUtilities.canMove(minion.getKey())) { if (MovementUtilities.canMove(minion.getKey())) {
Vector3f minionOffset = Formation.getOffset(2, minion.getValue() + 3); Vector3f minionOffset = Formation.getOffset(2, minion.getValue() + 3);
minion.getKey().updateLocation(); 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<Integer> powerTokens;
ArrayList<Integer> 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<Integer> powerTokens;
ArrayList<Integer> 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) { public static void MobCallForHelp(Mob mob) {
try { try {
@ -606,7 +344,7 @@ public class MobAI {
if (mob == null) if (mob == null)
return; return;
if (mob.getTimestamps().containsKey("lastExecution") == false) if (!mob.getTimestamps().containsKey("lastExecution"))
mob.getTimestamps().put("lastExecution", System.currentTimeMillis()); mob.getTimestamps().put("lastExecution", System.currentTimeMillis());
if (System.currentTimeMillis() < mob.getTimeStamp("lastExecution")) if (System.currentTimeMillis() < mob.getTimeStamp("lastExecution"))
@ -626,11 +364,11 @@ public class MobAI {
if (mob.despawned && mob.isPlayerGuard) { if (mob.despawned && mob.isPlayerGuard) {
if (mob.behaviourType.equals(Enum.MobBehaviourType.GuardMinion)) { 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 //minions don't respawn while guard captain is dead
if (mob.isAlive() == false) { if (!mob.isAlive()) {
mob.deathTime = System.currentTimeMillis(); mob.deathTime = System.currentTimeMillis();
return; 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 //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); CheckToSendMobHome(mob);
return; return;
@ -656,30 +394,16 @@ public class MobAI {
} }
//no players loaded, no need to proceed //no players loaded, no need to proceed
if (mob.playerAgroMap.isEmpty()) { if (mob.playerAgroMap.isEmpty()) {
//attempt to reload agro map
HashSet<AbstractWorldObject> 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; return;
} }
if (mob.behaviourType.equals(Enum.MobBehaviourType.Pet1) == false) if (!mob.behaviourType.equals(Enum.MobBehaviourType.Pet1))
CheckToSendMobHome(mob); CheckToSendMobHome(mob);
if (mob.getCombatTarget() != null) { if (mob.getCombatTarget() != null) {
if (mob.getCombatTarget().isAlive() == false) { if (!mob.getCombatTarget().isAlive()) {
mob.setCombatTarget(null); mob.setCombatTarget(null);
return; return;
} }
@ -688,19 +412,46 @@ public class MobAI {
PlayerCharacter target = (PlayerCharacter) mob.getCombatTarget(); PlayerCharacter target = (PlayerCharacter) mob.getCombatTarget();
if (mob.playerAgroMap.containsKey(target.getObjectUUID()) == false) { if (!mob.playerAgroMap.containsKey(target.getObjectUUID())) {
mob.setCombatTarget(null); mob.setCombatTarget(null);
return; return;
} }
if (mob.canSee((PlayerCharacter) mob.getCombatTarget()) == false) { if (!mob.canSee((PlayerCharacter) mob.getCombatTarget())) {
mob.setCombatTarget(null); mob.setCombatTarget(null);
return; 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) { switch (mob.behaviourType) {
case GuardCaptain: case GuardCaptain:
GuardCaptainLogic(mob); GuardCaptainLogic(mob);
@ -735,41 +486,34 @@ public class MobAI {
if (!aiAgent.isAlive()) if (!aiAgent.isAlive())
return; return;
if(!pets) { if(!pets) {
ConcurrentHashMap<Integer, Float> loadedPlayers = aiAgent.playerAgroMap; ConcurrentHashMap<Integer, Float> loadedPlayers = aiAgent.playerAgroMap;
for (Integer playerEntry : loadedPlayers.keySet()) {
for (Entry playerEntry : loadedPlayers.entrySet()) { PlayerCharacter loadedPlayer = PlayerCharacter.getFromCache(playerEntry);
int playerID = (int) playerEntry.getKey();
PlayerCharacter loadedPlayer = PlayerCharacter.getFromCache(playerID);
//Player is null, let's remove them from the list. //Player is null, let's remove them from the list.
if (loadedPlayer == null) { if (loadedPlayer == null) {
loadedPlayers.remove(playerID); loadedPlayers.remove(playerEntry);
continue; continue;
} }
//Player is Dead, Mob no longer needs to attempt to aggro. Remove them from aggro map. //Player is Dead, Mob no longer needs to attempt to aggro. Remove them from aggro map.
if (!loadedPlayer.isAlive() || loadedPlayer.getHidden() > 0) { if (!loadedPlayer.isAlive() || loadedPlayer.getHidden() > 0) {
loadedPlayers.remove(playerID); loadedPlayers.remove(playerEntry);
continue; continue;
} }
//Can't see target, skip aggro. //Can't see target, skip aggro.
if (!aiAgent.canSee(loadedPlayer)) if (!aiAgent.canSee(loadedPlayer))
continue; continue;
// No aggro for this race type // No aggro for this race type
if (aiAgent.notEnemy.size() > 0 && aiAgent.notEnemy.contains(loadedPlayer.getRace().getRaceType().getMonsterType()))
if (aiAgent.notEnemy.size() > 0 && aiAgent.notEnemy.contains(loadedPlayer.getRace().getRaceType().getMonsterType()) == true)
continue; continue;
//mob has enemies and this player race is not it //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; continue;
if (MovementUtilities.inRangeToAggro(aiAgent, loadedPlayer)) { if (MovementUtilities.inRangeToAggro(aiAgent, loadedPlayer)) {
@ -782,7 +526,7 @@ public class MobAI {
//look for pets to aggro if no players found to aggro //look for pets to aggro if no players found to aggro
HashSet<AbstractWorldObject> awoList = WorldGrid.getObjectsInRangePartial(aiAgent, MobAIThread.AI_BASE_AGGRO_RANGE, MBServerStatics.MASK_PET); HashSet<AbstractWorldObject> awoList = WorldGrid.getObjectsInRangePartial(aiAgent, MobAIThread.AI_BASE_AGGRO_RANGE, MBServerStatics.MASK_MOB);
for (AbstractWorldObject awoMob : awoList) { for (AbstractWorldObject awoMob : awoList) {
@ -791,6 +535,9 @@ public class MobAI {
if (aiAgent.equals(awoMob)) if (aiAgent.equals(awoMob))
continue; continue;
if(!((Mob)awoMob).isPet())
continue;
Mob aggroMob = (Mob) awoMob; Mob aggroMob = (Mob) awoMob;
aiAgent.setCombatTarget(aggroMob); aiAgent.setCombatTarget(aggroMob);
return; return;
@ -806,27 +553,27 @@ public class MobAI {
return; return;
try { try {
if(mob == null)
return;
if (!MovementUtilities.canMove(mob)) if (!MovementUtilities.canMove(mob))
return; return;
mob.updateLocation();
switch (mob.behaviourType) { switch (mob.behaviourType) {
case Pet1: case Pet1:
if ((PlayerCharacter) mob.guardCaptain == null) if (mob.guardCaptain == null)
return; 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 //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; return;
} }
if (mob.getCombatTarget() == null) { if (mob.getCombatTarget() == null) {
@ -834,11 +581,11 @@ public class MobAI {
//move back to owner //move back to owner
if (CombatUtilities.inRange2D(mob, (PlayerCharacter) mob.guardCaptain, 6)) if (CombatUtilities.inRange2D(mob, mob.guardCaptain, 6))
return; return;
mob.destination = ((PlayerCharacter) mob.guardCaptain).getLoc(); mob.destination = mob.guardCaptain.getLoc();
MovementUtilities.moveToLocation(mob, mob.destination, 5); MovementUtilities.moveToLocation(mob, mob.destination, 5);
} else } else
chaseTarget(mob); chaseTarget(mob);
@ -886,7 +633,6 @@ public class MobAI {
if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER_WITH_LOOT) { if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER_WITH_LOOT) {
aiAgent.despawn(); aiAgent.despawn();
aiAgent.deathTime = System.currentTimeMillis(); aiAgent.deathTime = System.currentTimeMillis();
return;
} }
//No items in inventory. //No items in inventory.
} else { } else {
@ -895,14 +641,12 @@ public class MobAI {
if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER_ONCE_LOOTED) { if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER_ONCE_LOOTED) {
aiAgent.despawn(); aiAgent.despawn();
aiAgent.deathTime = System.currentTimeMillis(); aiAgent.deathTime = System.currentTimeMillis();
return;
} }
//Mob never had Loot. //Mob never had Loot.
} else { } else {
if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER) { if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER) {
aiAgent.despawn(); aiAgent.despawn();
aiAgent.deathTime = System.currentTimeMillis(); aiAgent.deathTime = System.currentTimeMillis();
return;
} }
} }
} }
@ -922,14 +666,14 @@ public class MobAI {
//checks if mob can attack based on attack timer and range //checks if mob can attack based on attack timer and range
if (mob.isAlive() == false) if (!mob.isAlive())
return; return;
if (mob.getCombatTarget() == null) if (mob.getCombatTarget() == null)
return; return;
if (mob.getCombatTarget().getObjectType().equals(Enum.GameObjectType.PlayerCharacter) && MovementUtilities.inRangeDropAggro(mob, (PlayerCharacter) mob.getCombatTarget()) == false && if (mob.getCombatTarget().getObjectType().equals(Enum.GameObjectType.PlayerCharacter) && !MovementUtilities.inRangeDropAggro(mob, (PlayerCharacter) mob.getCombatTarget()) &&
mob.behaviourType.equals(Enum.MobBehaviourType.Pet1) == false) { !mob.behaviourType.equals(Enum.MobBehaviourType.Pet1)) {
mob.setCombatTarget(null); mob.setCombatTarget(null);
return; 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) { if (mob.isPlayerGuard() && !mob.despawned) {
City current = ZoneManager.getCityAtLocation(mob.getLoc()); 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); PowersBase recall = PowersManager.getPowerByToken(-1994153779);
PowersManager.useMobPower(mob, mob, recall, 40); 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); PowersBase recall = PowersManager.getPowerByToken(-1994153779);
PowersManager.useMobPower(mob, mob, recall, 40); PowersManager.useMobPower(mob, mob, recall, 40);
mob.setCombatTarget(null); mob.setCombatTarget(null);
for (Integer playerEntry : mob.playerAgroMap.keySet()) mob.playerAgroMap.replaceAll((e, v) -> 0f);
mob.playerAgroMap.put(playerEntry,0f);
} }
} catch (Exception e) { } catch (Exception e) {
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckToSendMobHome" + " " + e.getMessage()); Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckToSendMobHome" + " " + e.getMessage());
@ -1001,13 +741,16 @@ public class MobAI {
return; 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()); 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(); mob.destination = mob.getLoc();
MovementUtilities.moveToLocation(mob, mob.destination, 0); 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) { if (mob.getRange() > 15) {
mob.destination = mob.getCombatTarget().getLoc(); mob.destination = mob.getCombatTarget().getLoc();
MovementUtilities.moveToLocation(mob, mob.destination, 0); MovementUtilities.moveToLocation(mob, mob.destination, 0);
@ -1029,7 +772,6 @@ public class MobAI {
} }
} }
mob.updateMovementState(); mob.updateMovementState();
mob.updateLocation();
} catch (Exception e) { } catch (Exception e) {
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: chaseTarget" + " " + e.getMessage()); Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: chaseTarget" + " " + e.getMessage());
} }
@ -1044,7 +786,7 @@ public class MobAI {
//dont scan self. //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; continue;
Mob aggroMob = (Mob) awoMob; Mob aggroMob = (Mob) awoMob;
@ -1073,18 +815,6 @@ public class MobAI {
if (mob.getCombatTarget() == null) if (mob.getCombatTarget() == null)
CheckForPlayerGuardAggro(mob); 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); CheckMobMovement(mob);
CheckForAttack(mob); CheckForAttack(mob);
} catch (Exception e) { } catch (Exception e) {
@ -1099,19 +829,6 @@ public class MobAI {
if (mob.getCombatTarget() == null) { if (mob.getCombatTarget() == null) {
CheckForPlayerGuardAggro(mob); 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 { }else {
if (mob.guardCaptain.getCombatTarget() != null) if (mob.guardCaptain.getCombatTarget() != null)
@ -1143,7 +860,7 @@ public class MobAI {
try { 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)) if (ZoneManager.getSeaFloor().zoneMobSet.contains(mob))
mob.killCharacter("no owner"); mob.killCharacter("no owner");
@ -1154,7 +871,7 @@ public class MobAI {
//recover health //recover health
if (mob.getTimestamps().containsKey("HEALTHRECOVERED") == false) if (!mob.getTimestamps().containsKey("HEALTHRECOVERED"))
mob.getTimestamps().put("HEALTHRECOVERED", System.currentTimeMillis()); mob.getTimestamps().put("HEALTHRECOVERED", System.currentTimeMillis());
if (mob.isSit() && mob.getTimeStamp("HEALTHRECOVERED") < System.currentTimeMillis() + 3000) if (mob.isSit() && mob.getTimeStamp("HEALTHRECOVERED") < System.currentTimeMillis() + 3000)
@ -1179,7 +896,7 @@ public class MobAI {
if (mob.getCombatTarget() == null) if (mob.getCombatTarget() == null)
SafeGuardAggro(mob); SafeGuardAggro(mob);
else if (mob.getCombatTarget().isAlive() == false) else if (!mob.getCombatTarget().isAlive())
SafeGuardAggro(mob); SafeGuardAggro(mob);
CheckForAttack(mob); CheckForAttack(mob);
@ -1194,30 +911,22 @@ public class MobAI {
if(mob.combatTarget != null && mob.combatTarget.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)){ if(mob.combatTarget != null && mob.combatTarget.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)){
PlayerCharacter tar = (PlayerCharacter)mob.combatTarget; PlayerCharacter tar = (PlayerCharacter)mob.combatTarget;
if (mob.canSee(tar) == false) { if (!mob.canSee(tar)) {
mob.setCombatTarget(null); mob.setCombatTarget(null);
} }
} }
if (mob.behaviourType.isAgressive) { if (mob.behaviourType.isAgressive) {
//AbstractWorldObject newTarget = ChangeTargetFromHateValue(mob);
//if (newTarget != null)
// mob.setCombatTarget(newTarget);
//else {
if (mob.getCombatTarget() == null) { if (mob.getCombatTarget() == null) {
if (mob.behaviourType == Enum.MobBehaviourType.HamletGuard) { if (mob.behaviourType == Enum.MobBehaviourType.HamletGuard) {
SafeGuardAggro(mob); //safehold guard SafeGuardAggro(mob); //safehold guard
}else { } else {
CheckForAggro(mob,false); //normal aggro CheckForAggro(mob, false); //normal aggro
if(mob.combatTarget == null) if (mob.combatTarget == null)
CheckForAggro(mob,true); // look for pets if no players to aggro CheckForAggro(mob, true); // look for pets if no players to aggro
} }
} }
} }
//}
//check if mob can move for patrol or moving to target //check if mob can move for patrol or moving to target
@ -1245,22 +954,21 @@ public class MobAI {
ConcurrentHashMap<Integer, Float> loadedPlayers = mob.playerAgroMap; ConcurrentHashMap<Integer, Float> loadedPlayers = mob.playerAgroMap;
for (Entry playerEntry : loadedPlayers.entrySet()) { for (Integer playerEntry : loadedPlayers.keySet()) {
int playerID = (int) playerEntry.getKey(); PlayerCharacter loadedPlayer = PlayerCharacter.getFromCache(playerEntry);
PlayerCharacter loadedPlayer = PlayerCharacter.getFromCache(playerID);
//Player is null, let's remove them from the list. //Player is null, let's remove them from the list.
if (loadedPlayer == null) { if (loadedPlayer == null) {
loadedPlayers.remove(playerID); loadedPlayers.remove(playerEntry);
continue; continue;
} }
//Player is Dead, Mob no longer needs to attempt to aggro. Remove them from aggro map. //Player is Dead, Mob no longer needs to attempt to aggro. Remove them from aggro map.
if (!loadedPlayer.isAlive()) { if (!loadedPlayer.isAlive()) {
loadedPlayers.remove(playerID); loadedPlayers.remove(playerEntry);
continue; continue;
} }
@ -1271,7 +979,7 @@ public class MobAI {
// No aggro for this player // No aggro for this player
if (GuardCanAggro(mob, loadedPlayer) == false) if (!GuardCanAggro(mob, loadedPlayer))
continue; continue;
if (MovementUtilities.inRangeToAggro(mob, loadedPlayer) && mob.getCombatTarget() == null) { if (MovementUtilities.inRangeToAggro(mob, loadedPlayer) && mob.getCombatTarget() == null) {
@ -1292,17 +1000,17 @@ public class MobAI {
return false; return false;
if (mob.behaviourType.equals(Enum.MobBehaviourType.GuardMinion)) { 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; 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; return true;
} }
//first check condemn list for aggro allowed (allies button is checked) //first check condemn list for aggro allowed (allies button is checked)
if (ZoneManager.getCityAtLocation(mob.getLoc()).getTOL().reverseKOS) { if (Objects.requireNonNull(ZoneManager.getCityAtLocation(mob.getLoc())).getTOL().reverseKOS) {
for (Entry<Integer, Condemned> entry : ZoneManager.getCityAtLocation(mob.getLoc()).getTOL().getCondemned().entrySet()) { for (Entry<Integer, Condemned> entry : Objects.requireNonNull(ZoneManager.getCityAtLocation(mob.getLoc())).getTOL().getCondemned().entrySet()) {
//target is listed individually //target is listed individually
@ -1324,7 +1032,7 @@ public class MobAI {
//allies button is not checked //allies button is not checked
for (Entry<Integer, Condemned> entry : ZoneManager.getCityAtLocation(mob.getLoc()).getTOL().getCondemned().entrySet()) { for (Entry<Integer, Condemned> entry : Objects.requireNonNull(ZoneManager.getCityAtLocation(mob.getLoc())).getTOL().getCondemned().entrySet()) {
//target is listed individually //target is listed individually
@ -1355,7 +1063,7 @@ public class MobAI {
//early exit for a mob who is already moving to a patrol point //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 //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(); mob.stopPatrolTime = System.currentTimeMillis();
return; return;
} }
@ -1381,7 +1089,7 @@ public class MobAI {
//make sure mob is out of combat stance //make sure mob is out of combat stance
if (minion.getKey().despawned == false) { if (!minion.getKey().despawned) {
if (MovementUtilities.canMove(minion.getKey())) { if (MovementUtilities.canMove(minion.getKey())) {
Vector3f minionOffset = Formation.getOffset(2, minion.getValue() + 3); Vector3f minionOffset = Formation.getOffset(2, minion.getValue() + 3);
minion.getKey().updateLocation(); minion.getKey().updateLocation();
@ -1395,40 +1103,4 @@ public class MobAI {
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: randomGuardPatrolPoints" + " " + e.getMessage()); 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;
}
} }

212
src/engine/mobileAI/utilities/CombatUtilities.java

@ -12,13 +12,20 @@ package engine.mobileAI.utilities;
import engine.Enum.*; import engine.Enum.*;
import engine.gameManager.ChatManager; import engine.gameManager.ChatManager;
import engine.gameManager.CombatManager; import engine.gameManager.CombatManager;
import engine.gameManager.PowersManager;
import engine.math.Vector3fImmutable; import engine.math.Vector3fImmutable;
import engine.mobileAI.MobAI;
import engine.mobileAI.Threads.MobAIThread;
import engine.net.DispatchMessage; import engine.net.DispatchMessage;
import engine.net.client.msg.PerformActionMsg;
import engine.net.client.msg.TargetedActionMsg; import engine.net.client.msg.TargetedActionMsg;
import engine.objects.*; import engine.objects.*;
import engine.powers.ActionsBase;
import engine.powers.PowersBase;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.util.ArrayList;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
import static engine.math.FastMath.sqr; import static engine.math.FastMath.sqr;
@ -512,4 +519,209 @@ public class CombatUtilities {
return agent.getMaxDamageHandOne(); 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<Integer> powerTokens;
ArrayList<Integer> 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<Integer> powerTokens;
ArrayList<Integer> 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;
}
} }

11
src/engine/mobileAI/utilities/MovementUtilities.java

@ -135,7 +135,6 @@ public class MovementUtilities {
public static boolean canMove(Mob agent) { public static boolean canMove(Mob agent) {
if (agent.getMobBase() != null && Enum.MobFlagType.SENTINEL.elementOf(agent.getMobBase().getFlags())) if (agent.getMobBase() != null && Enum.MobFlagType.SENTINEL.elementOf(agent.getMobBase().getFlags()))
return false; return false;
@ -144,16 +143,6 @@ public class MovementUtilities {
public static void aiMove(Mob agent, Vector3fImmutable vect, boolean isWalking) { 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(); MoveToPointMsg msg = new MoveToPointMsg();

80
src/engine/net/client/ClientMessagePump.java

@ -148,6 +148,12 @@ public class ClientMessagePump implements NetMsgHandler {
pc.setActive(true); pc.setActive(true);
pc.setLastTarget(GameObjectType.values()[msg.getTargetType()], msg.getTargetID()); 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 { private static void social(SocialMsg msg, ClientConnection origin) throws MsgSendException {
@ -340,18 +346,11 @@ public class ClientMessagePump implements NetMsgHandler {
if (player == null) if (player == null)
return; return;
if (!NPCVaultBankRangeCheck(player, origin, "bank")) if (!NPCVaultBankRangeCheck(player, origin, "bank"))
return; return;
CharacterItemManager itemManager = player.getCharItemManager(); 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) if (itemManager == null)
return; return;
@ -404,17 +403,11 @@ public class ClientMessagePump implements NetMsgHandler {
if (player == null) if (player == null)
return; return;
if (!NPCVaultBankRangeCheck(player, origin, "bank")) if (!NPCVaultBankRangeCheck(player, origin, "bank"))
return; return;
CharacterItemManager itemManager = player.getCharItemManager(); 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) if (itemManager == null)
return; return;
@ -458,6 +451,7 @@ public class ClientMessagePump implements NetMsgHandler {
dispatch = Dispatch.borrow(player, msg); dispatch = Dispatch.borrow(player, msg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
} }
private static void transferItemFromVaultToInventory(TransferItemFromVaultToInventoryMsg msg, ClientConnection origin) { private static void transferItemFromVaultToInventory(TransferItemFromVaultToInventoryMsg msg, ClientConnection origin) {
@ -471,6 +465,8 @@ public class ClientMessagePump implements NetMsgHandler {
if (player.getAccount() == null) if (player.getAccount() == null)
return; return;
player.getAccount().transferItemFromVaultToInventory(msg, origin); player.getAccount().transferItemFromVaultToInventory(msg, origin);
} }
//call this if the transfer fails server side to kick the item back to inventory from vault //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); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
ChatManager.chatInfoError(player, "Can't transfer to vault: " + reason); ChatManager.chatInfoError(player, "Can't transfer to vault: " + reason);
player.getAccount().transferItemFromInventoryToVault(msg, origin);
} }
private static void transferGoldFromVaultToInventory(TransferGoldFromVaultToInventoryMsg msg, ClientConnection origin) { private static void transferGoldFromVaultToInventory(TransferGoldFromVaultToInventoryMsg msg, ClientConnection origin) {
@ -528,11 +523,6 @@ public class ClientMessagePump implements NetMsgHandler {
if (player == null) if (player == null)
return; 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(); Account account = player.getAccount();
if (account == null) if (account == null)
@ -549,11 +539,6 @@ public class ClientMessagePump implements NetMsgHandler {
if (player == null) if (player == null)
return; 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(); Account account = player.getAccount();
if (account == null) if (account == null)
@ -603,7 +588,7 @@ public class ClientMessagePump implements NetMsgHandler {
} }
if (itemManager.delete(i) == true) { if (itemManager.delete(i) == true) {
sourcePlayer.getCharItemManager().addGoldToInventory(value,false); sourcePlayer.getCharItemManager().addGoldToInventory(value,false);
sourcePlayer.getCharItemManager().StackResources(); sourcePlayer.getCharItemManager().updateInventory();
Dispatch dispatch = Dispatch.borrow(sourcePlayer, msg); Dispatch dispatch = Dispatch.borrow(sourcePlayer, msg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); 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); 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 //TODO send group loot message if player is grouped and visible
@ -969,9 +954,6 @@ public class ClientMessagePump implements NetMsgHandler {
return; return;
} }
if(item.getItemBase().getType().equals(ItemType.RESOURCE))
player.getCharItemManager().StackResources();
if (item.getItemBase().getType().equals(engine.Enum.ItemType.GOLD)) { if (item.getItemBase().getType().equals(engine.Enum.ItemType.GOLD)) {
// this is done to prevent the temporary goldItem item // this is done to prevent the temporary goldItem item
// (from the mob) from appearing in player's inventory. // (from the mob) from appearing in player's inventory.
@ -1005,7 +987,7 @@ public class ClientMessagePump implements NetMsgHandler {
dispatch = Dispatch.borrow(player, newItemMsg); dispatch = Dispatch.borrow(player, newItemMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
//player.getCharItemManager().StackResources(); //player.getCharItemManager().updateInventory();
} }
//TODO send group loot message if player is grouped and visible //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 + '.'; String text = player.getFirstName() + " has looted " + name + '.';
ChatManager.chatGroupInfoCanSee(player, text); ChatManager.chatGroupInfoCanSee(player, text);
} }
} catch (Exception e) { } catch (Exception e) {
Logger.info(e.getMessage()); Logger.info(e.getMessage());
} finally { } finally {
@ -1024,6 +1005,7 @@ public class ClientMessagePump implements NetMsgHandler {
} }
} }
} }
// called when player types /show // called when player types /show
@ -1488,11 +1470,39 @@ public class ClientMessagePump implements NetMsgHandler {
ChatManager.chatSystemError(sourcePlayer, "Failed To Buy Item"); ChatManager.chatSystemError(sourcePlayer, "Failed To Buy Item");
return; return;
} }
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); buy = Item.createItemForPlayer(sourcePlayer, ib);
if (buy != null) { if (buy != null) {
me.transferEnchants(buy); me.transferEnchants(buy);
itemMan.addItemToInventory(buy); itemMan.addItemToInventory(buy);
//itemMan.StackResources(); //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()); // msg.setItemID(buy.getObjectUUID());
Dispatch dispatch = Dispatch.borrow(sourcePlayer, msg); Dispatch dispatch = Dispatch.borrow(sourcePlayer, msg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
itemMan.StackResources(); itemMan.updateInventory();
} }
} finally { } finally {
origin.buyLock.unlock(); origin.buyLock.unlock();
} }
@ -1898,9 +1909,6 @@ public class ClientMessagePump implements NetMsgHandler {
s = SessionManager.getSession(origin); s = SessionManager.getSession(origin);
protocolMsg = msg.getProtocolMsg(); protocolMsg = msg.getProtocolMsg();
PlayerCharacter player = ((ClientConnection) msg.getOrigin()).getPlayerCharacter();
if(player != null)
player.lastAction = System.currentTimeMillis();
switch (protocolMsg) { switch (protocolMsg) {
case SETSELECTEDOBECT: case SETSELECTEDOBECT:

9
src/engine/net/client/handlers/DestroyBuildingHandler.java

@ -62,7 +62,7 @@ public class DestroyBuildingHandler extends AbstractClientMsgHandler {
if (city != null) if (city != null)
bane = city.getBane(); bane = city.getBane();
if (bane != null && bane.getSiegePhase() == Enum.SiegePhase.WAR) { if (bane != null) {
ErrorPopupMsg.sendErrorPopup(pc, 171); ErrorPopupMsg.sendErrorPopup(pc, 171);
return true; return true;
} }
@ -71,9 +71,12 @@ public class DestroyBuildingHandler extends AbstractClientMsgHandler {
if (blueprint.getBuildingGroup() == BuildingGroup.TOL) if (blueprint.getBuildingGroup() == BuildingGroup.TOL)
return true; return true;
// Can't destroy a shrine // destorying a shrine will yield a rubble pile for looting
if (blueprint.getBuildingGroup() == BuildingGroup.SHRINE) if (blueprint.getBuildingGroup() == BuildingGroup.SHRINE) {
building.modifyHealth(-building.getHealth(), origin.getPlayerCharacter());
building.destroyOrDerank(origin.getPlayerCharacter());
return true; return true;
}
// Cannot destroy mines outside of normal mine mechanics // Cannot destroy mines outside of normal mine mechanics

156
src/engine/net/client/handlers/ManageCityAssetMsgHandler.java

@ -5,6 +5,7 @@ import engine.Enum.DispatchChannel;
import engine.Enum.GameObjectType; import engine.Enum.GameObjectType;
import engine.exception.MsgSendException; import engine.exception.MsgSendException;
import engine.gameManager.BuildingManager; import engine.gameManager.BuildingManager;
import engine.gameManager.DbManager;
import engine.gameManager.SessionManager; import engine.gameManager.SessionManager;
import engine.gameManager.ZoneManager; import engine.gameManager.ZoneManager;
import engine.math.Bounds; import engine.math.Bounds;
@ -62,7 +63,6 @@ public class ManageCityAssetMsgHandler extends AbstractClientMsgHandler {
Building building; Building building;
msg = (ManageCityAssetsMsg) baseMsg; msg = (ManageCityAssetsMsg) baseMsg;
player = SessionManager.getPlayerCharacter(origin); player = SessionManager.getPlayerCharacter(origin);
if (player == null) if (player == null)
@ -72,34 +72,21 @@ public class ManageCityAssetMsgHandler extends AbstractClientMsgHandler {
if (building == null) { if (building == null) {
if (msg.actionType == 14) { if (msg.actionType == 14) {
Zone zone = ZoneManager.findSmallestZone(player.getLoc()); Zone zone = ZoneManager.findSmallestZone(player.getLoc());
if (!zone.isPlayerCity()) { if (!zone.isPlayerCity()) {
ErrorPopupMsg.sendErrorMsg(player, "Unable to find city to command."); ErrorPopupMsg.sendErrorMsg(player, "Unable to find city to command.");
return true; return true;
} }
City city = City.GetCityFromCache(zone.getPlayerCityUUID()); City city = City.GetCityFromCache(zone.getPlayerCityUUID());
if (city == null || !city.getGuild().equals(player.getGuild()) ||
if (city == null) { (!GuildStatusController.isInnerCouncil(player.getGuildStatus()) &&
ErrorPopupMsg.sendErrorMsg(player, "Unable to find city to command."); !GuildStatusController.isGuildLeader(player.getGuildStatus()))) {
return true;
}
if (!city.getGuild().equals(player.getGuild())) {
ErrorPopupMsg.sendErrorMsg(player, "You are not in the correct guild to command this city."); ErrorPopupMsg.sendErrorMsg(player, "You are not in the correct guild to command this city.");
return true; 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); ManageCityAssetsMsg mca = new ManageCityAssetsMsg(player, building);
mca.actionType = 15; mca.actionType = 15;
Dispatch dispatch = Dispatch.borrow(player, mca); DispatchMessage.dispatchMsgDispatch(Dispatch.borrow(player, mca), DispatchChannel.SECONDARY);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
} }
return true; return true;
} }
@ -111,20 +98,18 @@ public class ManageCityAssetMsgHandler extends AbstractClientMsgHandler {
outMsg.setTargetType(building.getObjectType().ordinal()); outMsg.setTargetType(building.getObjectType().ordinal());
outMsg.setTargetID(building.getObjectUUID()); outMsg.setTargetID(building.getObjectUUID());
outMsg.setAssetName(building.getName()); outMsg.setAssetName(building.getName());
Dispatch dispatch = Dispatch.borrow(player, outMsg); DispatchMessage.dispatchMsgDispatch(Dispatch.borrow(player, outMsg), DispatchChannel.SECONDARY);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
return true; return true;
} }
if (msg.actionType == 2 || msg.actionType == 22) { switch (msg.actionType) {
case 2:
case 22:
if (building.getBlueprint() != null && building.getBlueprint().getBuildingGroup() == engine.Enum.BuildingGroup.BANESTONE) { if (building.getBlueprint() != null && building.getBlueprint().getBuildingGroup() == engine.Enum.BuildingGroup.BANESTONE) {
outMsg.actionType = 18; outMsg.actionType = 18;
outMsg.setTargetType(building.getObjectType().ordinal()); outMsg.setTargetType(building.getObjectType().ordinal());
outMsg.setTargetID(building.getObjectUUID()); outMsg.setTargetID(building.getObjectUUID());
} else if (BuildingManager.playerCanManage(player, building)) {
} else if (BuildingManager.playerCanManage(player, building)) { //TODO allow Friends list.
configWindowState(player, building, outMsg); configWindowState(player, building, outMsg);
outMsg.actionType = 3; outMsg.actionType = 3;
outMsg.setTargetType(building.getObjectType().ordinal()); outMsg.setTargetType(building.getObjectType().ordinal());
@ -132,95 +117,58 @@ public class ManageCityAssetMsgHandler extends AbstractClientMsgHandler {
outMsg.setTargetType3(building.getObjectType().ordinal()); outMsg.setTargetType3(building.getObjectType().ordinal());
outMsg.setTargetID3(building.getObjectUUID()); outMsg.setTargetID3(building.getObjectUUID());
outMsg.setUnknown54(1); outMsg.setUnknown54(1);
} else { } else {
// Handle other cases
if (building.getBlueprintUUID() != 0)
switch (building.getBlueprint().getBuildingGroup()) {
case SHRINE:
if (building.getRank() == -1) { if (building.getRank() == -1) {
if (!Bounds.collide(player.getLoc(), building)) { if (!Bounds.collide(player.getLoc(), building)) {
ErrorPopupMsg.sendErrorPopup(player, 64); ErrorPopupMsg.sendErrorPopup(player, 64);
return true; return true;
} }
switch (building.getBlueprint().getBuildingGroup()) {
case SHRINE:
Shrine shrine = Shrine.shrinesByBuildingUUID.get(building.getObjectUUID()); Shrine shrine = Shrine.shrinesByBuildingUUID.get(building.getObjectUUID());
if (shrine == null || shrine.getFavors() == 0) {
if (shrine == null)
return true;
if (shrine.getFavors() == 0) {
ErrorPopupMsg.sendErrorPopup(player, 166); // There is no more favor in this shrine to loot ErrorPopupMsg.sendErrorPopup(player, 166); // There is no more favor in this shrine to loot
return true; return true;
} }
//loot elan stones
BuildingManager.lootBuilding(player, building); MobLoot elanStones = new MobLoot(player,ItemBase.getItemBase(1705032),1,false);
return true; 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; break;
case WAREHOUSE: case WAREHOUSE:
//TODO check
if (building.getRank() == -1) {
if (!Bounds.collide(player.getLoc(), building)) {
ErrorPopupMsg.sendErrorPopup(player, 64);
return true;
}
Warehouse warehouse = Warehouse.warehouseByBuildingUUID.get(building.getObjectUUID()); Warehouse warehouse = Warehouse.warehouseByBuildingUUID.get(building.getObjectUUID());
if (warehouse == null || warehouse.isEmpty()) {
if (warehouse == null)
return true;
if (warehouse.isEmpty()) {
ErrorPopupMsg.sendErrorPopup(player, 167); // no more resources. ErrorPopupMsg.sendErrorPopup(player, 167); // no more resources.
return true; return true;
} }
break;
BuildingManager.lootBuilding(player, building);
return true;
} }
} }
if (building.getRank() == -1)
return true;
AbstractCharacter owner = building.getOwner(); AbstractCharacter owner = building.getOwner();
//no owner, send building info
if (owner == null) { if (owner == null) {
msg.actionType = 4; msg.actionType = 4;
DispatchMessage.dispatchMsgDispatch(Dispatch.borrow(player, msg), DispatchChannel.SECONDARY);
Dispatch dispatch = Dispatch.borrow(player, msg); } else {
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
return true;
}
outMsg.actionType = 4; outMsg.actionType = 4;
outMsg.setTargetType(building.getObjectType().ordinal()); outMsg.setTargetType(building.getObjectType().ordinal());
outMsg.setTargetID(building.getObjectUUID()); outMsg.setTargetID(building.getObjectUUID());
outMsg.setAssetName(building.getName()); outMsg.setAssetName(building.getName());
} }
Dispatch dispatch = Dispatch.borrow(player, outMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
return true;
} }
DispatchMessage.dispatchMsgDispatch(Dispatch.borrow(player, outMsg), DispatchChannel.SECONDARY);
if (msg.actionType == 13) { return true;
case 13:
outMsg.actionType = 13; outMsg.actionType = 13;
Dispatch dispatch = Dispatch.borrow(player, outMsg); DispatchMessage.dispatchMsgDispatch(Dispatch.borrow(player, outMsg), DispatchChannel.SECONDARY);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
return true; return true;
} case 5:
//Rename Building.
if (msg.actionType == 5) {
//TODO we need to check names before allowing
building.setName(msg.getAssetName()); building.setName(msg.getAssetName());
configWindowState(player, building, outMsg); configWindowState(player, building, outMsg);
outMsg.actionType = 3; outMsg.actionType = 3;
outMsg.setTargetType(building.getObjectType().ordinal()); outMsg.setTargetType(building.getObjectType().ordinal());
outMsg.setTargetID(building.getObjectUUID()); outMsg.setTargetID(building.getObjectUUID());
@ -228,49 +176,36 @@ public class ManageCityAssetMsgHandler extends AbstractClientMsgHandler {
outMsg.setTargetID3(building.getObjectUUID()); outMsg.setTargetID3(building.getObjectUUID());
outMsg.setAssetName1(building.getName()); outMsg.setAssetName1(building.getName());
outMsg.setUnknown54(1); outMsg.setUnknown54(1);
DispatchMessage.dispatchMsgDispatch(Dispatch.borrow(player, outMsg), DispatchChannel.SECONDARY);
Dispatch dispatch = Dispatch.borrow(player, outMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
return true; return true;
case 14:
//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); ManageCityAssetsMsg mca = new ManageCityAssetsMsg(player, building);
mca.actionType = 15; mca.actionType = 15;
Dispatch dispatch = Dispatch.borrow(player, mca); DispatchMessage.dispatchMsgDispatch(Dispatch.borrow(player, mca), DispatchChannel.SECONDARY);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); return true;
case 20:
// Handle case 20
return handleCase20(player, outMsg, building, msg, origin);
default:
return true; return true;
} }
}
if (msg.actionType == 20) { private boolean handleCase20(PlayerCharacter player, ManageCityAssetsMsg outMsg, Building building, ManageCityAssetsMsg msg, ClientConnection origin) throws MsgSendException {
Zone baneZone = building.getParentZone(); Zone baneZone = building.getParentZone();
if (baneZone == null) if (baneZone == null)
return true; return true;
City banedCity = City.getCity(baneZone.getPlayerCityUUID()); City banedCity = City.getCity(baneZone.getPlayerCityUUID());
if (banedCity == null) if (banedCity == null)
return true; return true;
Bane bane = banedCity.getBane(); Bane bane = banedCity.getBane();
if (bane == null || bane.getLiveDate() != null || player.getGuild() != banedCity.getGuild() || !GuildStatusController.isInnerCouncil(player.getGuildStatus()))
if (bane == null || bane.getLiveDate() != null || player.getGuild() != banedCity.getGuild() || GuildStatusController.isInnerCouncil(player.getGuildStatus()) == false)
return true; return true;
int baneHour = msg.getBaneHour(); int baneHour = msg.getBaneHour();
if (baneHour < 16 || baneHour > 24) { if (baneHour < 16 || baneHour > 24) {
PlaceAssetMsg.sendPlaceAssetError(origin, 1, "A Serious error has occurred. Please post details for to ensure transaction integrity"); PlaceAssetMsg.sendPlaceAssetError(origin, 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
return true; return true;
} }
DateTime baneLive = new DateTime(bane.getPlacementDate()); DateTime baneLive = new DateTime(bane.getPlacementDate());
baneLive = baneHour == 24 ? baneLive.plusDays(3) : baneLive.plusDays(2); baneLive = baneHour == 24 ? baneLive.plusDays(3) : baneLive.plusDays(2);
baneLive = baneHour == 24 ? baneLive.hourOfDay().setCopy(0) : baneLive.hourOfDay().setCopy(baneHour); baneLive = baneHour == 24 ? baneLive.hourOfDay().setCopy(0) : baneLive.hourOfDay().setCopy(baneHour);
@ -278,14 +213,11 @@ public class ManageCityAssetMsgHandler extends AbstractClientMsgHandler {
baneLive = baneLive.secondOfMinute().setCopy(1); baneLive = baneLive.secondOfMinute().setCopy(1);
bane.setLiveDate(baneLive); bane.setLiveDate(baneLive);
outMsg.actionType = 18; outMsg.actionType = 18;
DispatchMessage.dispatchMsgDispatch(Dispatch.borrow(player, outMsg), DispatchChannel.SECONDARY);
Dispatch dispatch = Dispatch.borrow(player, outMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
return true;
}
return true; return true;
} }
public void configWindowState(PlayerCharacter player, Building building, ManageCityAssetsMsg manageCityAssetsMsg) { public void configWindowState(PlayerCharacter player, Building building, ManageCityAssetsMsg manageCityAssetsMsg) {
// Tests to turn on upgrade button if a building is not // Tests to turn on upgrade button if a building is not

2
src/engine/net/client/msg/ApplyRuneMsg.java

@ -306,6 +306,8 @@ public class ApplyRuneMsg extends ClientNetMsg {
} }
//if discipline, check number applied //if discipline, check number applied
if (isDiscipline(runeID)) { if (isDiscipline(runeID)) {
//if(playerCharacter.getLevel() == 80)
discCount -= 1; // level 80 characters get an extra disc rune
if (playerCharacter.getLevel() < 70) { if (playerCharacter.getLevel() < 70) {
if (discCount > 2) { if (discCount > 2) {
return false; return false;

18
src/engine/net/client/msg/VendorDialogMsg.java

@ -137,16 +137,20 @@ public class VendorDialogMsg extends ClientNetMsg {
} }
if(contract.getObjectUUID() == 1502040){ if(contract.getObjectUUID() == 1502040){
if(playerCharacter.isBoxed == false) { if(!playerCharacter.getTimestamps().containsKey("lastBoxChange"))
ChatManager.chatSystemInfo(playerCharacter, "You Are Already The Active Character."); playerCharacter.getTimestamps().put("lastBoxChange",System.currentTimeMillis() - 1000);
if(playerCharacter.getTimeStamp("lastBoxChange") + 30000L > System.currentTimeMillis()) {
return; return;
} }
if(playerCharacter.getTimestamps().containsKey("BoxChange") && playerCharacter.getTimeStamp("BoxChange") + 5000 > System.currentTimeMillis()) { if(playerCharacter.isBoxed == false) {
ChatManager.chatSystemInfo(playerCharacter, "You Are Enrolling Too Often."); ChatManager.chatSystemInfo(playerCharacter, "You Are Already The Active Character.");
return; return;
} }
playerCharacter.getTimestamps().put("BoxChange",System.currentTimeMillis());
playerCharacter.getTimestamps().put("lastBoxChange",System.currentTimeMillis());
playerCharacter.isBoxed = false; playerCharacter.isBoxed = false;
playerCharacter.removeEffectBySource(Enum.EffectSourceType.DeathShroud,50,true); playerCharacter.removeEffectBySource(Enum.EffectSourceType.DeathShroud,50,true);
ChatManager.chatSystemInfo(playerCharacter, "Promoting To Active Duty"); ChatManager.chatSystemInfo(playerCharacter, "Promoting To Active Duty");
@ -157,12 +161,12 @@ public class VendorDialogMsg extends ClientNetMsg {
} }
playerCharacter.isBoxed = false; playerCharacter.isBoxed = false;
playerCharacter.title = CharacterTitle.NONE; playerCharacter.title = CharacterTitle.NONE;
InterestManager.reloadCharacter(playerCharacter); InterestManager.setObjectDirty(playerCharacter);
playerCharacter.removeEffectBySource(Enum.EffectSourceType.DeathShroud,50,true); playerCharacter.removeEffectBySource(Enum.EffectSourceType.DeathShroud,50,true);
for(PlayerCharacter box : currentBoxes) { for(PlayerCharacter box : currentBoxes) {
box.isBoxed = true; box.isBoxed = true;
box.title = CharacterTitle.BOX; box.title = CharacterTitle.BOX;
InterestManager.reloadCharacter(box); InterestManager.setObjectDirty(box);
} }
} }
Dispatch dispatch = Dispatch.borrow(playerCharacter, msg); Dispatch dispatch = Dispatch.borrow(playerCharacter, msg);

17
src/engine/objects/AbstractCharacter.java

@ -1114,23 +1114,6 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
} }
public final void setCombatTarget(final AbstractWorldObject value) { 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; this.combatTarget = value;
} }

4
src/engine/objects/Bane.java

@ -607,6 +607,10 @@ public final class Bane {
DispatchMessage.dispatchMsgToAll(msg); 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; break;
case DESTROY: case DESTROY:

12
src/engine/objects/Building.java

@ -12,6 +12,7 @@ package engine.objects;
import engine.Enum; import engine.Enum;
import engine.Enum.*; import engine.Enum.*;
import engine.InterestManagement.HeightMap; import engine.InterestManagement.HeightMap;
import engine.InterestManagement.InterestManager;
import engine.InterestManagement.RealmMap; import engine.InterestManagement.RealmMap;
import engine.InterestManagement.WorldGrid; import engine.InterestManagement.WorldGrid;
import engine.db.archive.CityRecord; import engine.db.archive.CityRecord;
@ -394,7 +395,7 @@ public class Building extends AbstractWorldObject {
this.rank = newRank; this.rank = newRank;
// New rank means new mesh // New rank means new mesh
int oldMeshID = this.meshUUID;
newMeshUUID = this.getBlueprint().getMeshForRank(this.rank); newMeshUUID = this.getBlueprint().getMeshForRank(this.rank);
this.meshUUID = newMeshUUID; this.meshUUID = newMeshUUID;
@ -428,6 +429,15 @@ public class Building extends AbstractWorldObject {
BuildingManager.cleanupHirelings(this); BuildingManager.cleanupHirelings(this);
this.isDeranking.compareAndSet(true, false); 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() { public final int getOwnerUUID() {

85
src/engine/objects/CharacterItemManager.java

@ -12,7 +12,6 @@ package engine.objects;
import engine.Enum; import engine.Enum;
import engine.Enum.GameObjectType; import engine.Enum.GameObjectType;
import engine.Enum.ItemType; import engine.Enum.ItemType;
import engine.devcmd.cmds.MakeItemCmd;
import engine.gameManager.*; import engine.gameManager.*;
import engine.math.Vector3fImmutable; import engine.math.Vector3fImmutable;
import engine.net.Dispatch; import engine.net.Dispatch;
@ -24,7 +23,10 @@ import engine.powers.poweractions.AbstractPowerAction;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger; 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.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
@ -68,6 +70,8 @@ public class CharacterItemManager {
*/ */
private byte equipVer = (byte) 0; private byte equipVer = (byte) 0;
public boolean updateLock = false;
public CharacterItemManager(AbstractCharacter ac) { public CharacterItemManager(AbstractCharacter ac) {
super(); super();
this.absCharacter = ac; this.absCharacter = ac;
@ -103,7 +107,7 @@ public class CharacterItemManager {
return; return;
if (take != null) { if (take != null) {
itemMan.buyFromNPC(take, npc); itemMan.buyFromNPC(take, npc);
itemMan.StackResources(); itemMan.updateInventory();
} }
} }
@ -690,7 +694,7 @@ public class CharacterItemManager {
this.addGoldToTrade(amt); this.addGoldToTrade(amt);
// BONUS CODE BELOW: Thanks some unknown retard! // BONUS CODE BELOW: Thanks some unknown retard!
// sourceItemMan.StackResources(sourceItemMan.getInventory(), true); // sourceItemMan.updateInventory(sourceItemMan.getInventory(), true);
UpdateGoldMsg ugm = new UpdateGoldMsg(source); UpdateGoldMsg ugm = new UpdateGoldMsg(source);
ugm.configure(); ugm.configure();
@ -776,8 +780,6 @@ public class CharacterItemManager {
this.commitTrade(); this.commitTrade();
this.closeTradeWindow(ctwm1, false); this.closeTradeWindow(ctwm1, false);
other.getCharItemManager().closeTradeWindow(ctwm2, false); other.getCharItemManager().closeTradeWindow(ctwm2, false);
this.StackResources();
other.getCharItemManager().StackResources();
} }
return true; return true;
} }
@ -938,13 +940,13 @@ public class CharacterItemManager {
return junk(i, true); 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 (i.getItemBase().getType().equals(ItemType.GOLD)) {
if (this.getGoldInventory().getObjectUUID() == i.getObjectUUID()) if (this.getGoldInventory().getObjectUUID() == i.getObjectUUID())
if (DbManager.ItemQueries.UPDATE_GOLD(i, 0)) { if (DbManager.ItemQueries.UPDATE_GOLD(i, 0)) {
this.getGoldInventory().setNumOfItems(0); this.getGoldInventory().setNumOfItems(0);
if (StackResources) if (updateInventory)
StackResources(); updateInventory();
return true; return true;
} else { } else {
return false; return false;
@ -972,9 +974,9 @@ public class CharacterItemManager {
calculateWeights(); calculateWeights();
if (StackResources) if (updateInventory)
// Send the new inventory // 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); updateInventory(this.getInventory(), true);
return true; return true;
@ -1249,12 +1251,21 @@ public class CharacterItemManager {
} else { } else {
int amt = i.getNumOfItems(); int amt = i.getNumOfItems();
if (DbManager.ItemQueries.UPDATE_GOLD(this.goldInventory, this.goldInventory.getNumOfItems() + amt)) { if (DbManager.ItemQueries.UPDATE_GOLD(this.goldInventory, this.goldInventory.getNumOfItems() + amt)) {
StackResources(); updateInventory();
return true; return true;
} }
return false; 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.inventory.add(i);
this.itemIDtoType.put(i.getObjectUUID(), i.getObjectType().ordinal()); this.itemIDtoType.put(i.getObjectUUID(), i.getObjectType().ordinal());
return true; return true;
@ -1477,7 +1488,7 @@ public class CharacterItemManager {
if (sdrMerchant) { if (sdrMerchant) {
this.delete(itemToSell); this.delete(itemToSell);
this.StackResources(); this.updateInventory();
} else if (!itemToSell.moveItemToInventory(npc)) } else if (!itemToSell.moveItemToInventory(npc))
return false; return false;
@ -2276,10 +2287,13 @@ public class CharacterItemManager {
if (this.absCharacter.getObjectType().equals(GameObjectType.PlayerCharacter) == false) if (this.absCharacter.getObjectType().equals(GameObjectType.PlayerCharacter) == false)
return; return;
if(this.updateLock)
return;
PlayerCharacter pc = (PlayerCharacter) this.absCharacter; PlayerCharacter pc = (PlayerCharacter) this.absCharacter;
UpdateInventoryMsg StackResourcesMsg = new UpdateInventoryMsg(inventory, this.getBank(), this.getGoldInventory(), add); UpdateInventoryMsg updateInventoryMsg = new UpdateInventoryMsg(inventory, this.getBank(), this.getGoldInventory(), add);
Dispatch dispatch = Dispatch.borrow(pc, StackResourcesMsg); Dispatch dispatch = Dispatch.borrow(pc, updateInventoryMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); 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<Item> resources = new ArrayList<>();
HashMap<Integer,Integer> 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();
}
} }

51
src/engine/objects/Experience.java

@ -9,7 +9,9 @@
package engine.objects; package engine.objects;
import engine.Enum;
import engine.Enum.TargetColor; import engine.Enum.TargetColor;
import engine.gameManager.LootManager;
import engine.gameManager.ZoneManager; import engine.gameManager.ZoneManager;
import engine.math.Vector3fImmutable; import engine.math.Vector3fImmutable;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
@ -117,6 +119,11 @@ public class Experience {
159932666, // Level 74 159932666, // Level 74
169707808, // Level 75 169707808, // Level 75
179921247, // Level 76 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 235166.21f, // Level 72
246039.34f, // Level 73 246039.34f, // Level 73
257240.58f, // Level 74 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 // Used to calcuate the amount of experience a monster grants in the
// following formula // following formula
// expGranted = a(moblevel)^2 + b(moblevel) + c // expGranted = a(moblevel)^2 + b(moblevel) + c
@ -268,8 +287,8 @@ public class Experience {
if (level < 1) if (level < 1)
level = 1; level = 1;
if (level > 75) if (level > MBServerStatics.LEVELCAP)
level = 75; level = MBServerStatics.LEVELCAP;
return MaxExpPerLevel[level]; return MaxExpPerLevel[level];
} }
@ -354,8 +373,8 @@ public class Experience {
if (leaderskill != null) if (leaderskill != null)
leadership = leaderskill.getNumTrains(); leadership = leaderskill.getNumTrains();
if (leadership > 90) //if (leadership > 90)
leadership = 90; // leadership caps at 90% // leadership = 90; // leadership caps at 90%
} }
// Check every group member for distance to see if they get xp // Check every group member for distance to see if they get xp
@ -393,6 +412,8 @@ public class Experience {
// Process XP for this member // Process XP for this member
grantedExperience *= (1/giveEXPTo.size()+0.9);
penalty = getGroupMemberPenalty(leadership, playerCharacter, giveEXPTo, penalty = getGroupMemberPenalty(leadership, playerCharacter, giveEXPTo,
highestLevel); highestLevel);
@ -423,8 +444,14 @@ public class Experience {
if (grantedExperience == 0) if (grantedExperience == 0)
grantedExperience = 1; grantedExperience = 1;
grantedExperience *= LootManager.NORMAL_EXP_RATE;
// Grant the player the EXP // 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 } else { // Give EXP to a single character
@ -435,7 +462,8 @@ public class Experience {
return; return;
// Get XP and adjust for Mob Level with world xp modifier taken into account // 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); grantedExperience *= getConMod(killer, mob);
// Modify for hotzone // Modify for hotzone
@ -448,7 +476,12 @@ public class Experience {
grantedExperience *= .6; grantedExperience *= .6;
// Grant XP // 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);
}
} }
} }
} }

313
src/engine/objects/Mine.java

@ -16,17 +16,15 @@ import engine.net.ByteBufferWriter;
import engine.net.client.msg.ErrorPopupMsg; import engine.net.client.msg.ErrorPopupMsg;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
import engine.workthreads.ZergMechanicThread; import engine.workthreads.ZergMechanicThread;
import org.joda.time.DateTime;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Time;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom;
import static engine.gameManager.DbManager.MineQueries; import static engine.gameManager.DbManager.MineQueries;
import static engine.gameManager.DbManager.getObject; import static engine.gameManager.DbManager.getObject;
@ -60,7 +58,8 @@ public class Mine extends AbstractGameObject {
public boolean hasProduced = false; public boolean hasProduced = false;
public int liveTime; public int liveHour;
public int liveMinute;
public Boolean firstThirty = true; public Boolean firstThirty = true;
public static ArrayList<Mine> ChinaMines = new ArrayList<>(); public static ArrayList<Mine> ChinaMines = new ArrayList<>();
@ -115,142 +114,20 @@ public class Mine extends AbstractGameObject {
this.production = Resource.valueOf(rs.getString("mine_resource")); this.production = Resource.valueOf(rs.getString("mine_resource"));
this.lastClaimer = null; this.lastClaimer = null;
} this.liveHour = rs.getInt("mineLiveHour");
} this.liveMinute = rs.getInt("mineLiveMinute");
this.capSize = rs.getInt("capSize");
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;
if(BuildingManager.getBuilding(mine.buildingID) != null) { if(BuildingManager.getBuilding(this.buildingID) != null) {
Building mineTower = BuildingManager.getBuilding(mine.buildingID); Building mineTower = BuildingManager.getBuilding(this.buildingID);
if (mineTower != null) { if (mineTower != null) {
mineTower.setMaxHitPoints(5000 * mine.capSize); mineTower.setMaxHitPoints(5000 * this.capSize);
mineTower.setCurrentHitPoints((float) 5000 * mine.capSize); mineTower.setCurrentHitPoints((float) 5000 * this.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);
}
}
}
}
public static void releaseMineClaims(PlayerCharacter playerCharacter) { public static void releaseMineClaims(PlayerCharacter playerCharacter) {
if (playerCharacter == null) if (playerCharacter == null)
@ -306,89 +183,8 @@ public class Mine extends AbstractGameObject {
//mine.mineType = MineProduction.LUMBER; //mine.mineType = MineProduction.LUMBER;
} }
try { }catch(Exception e) {
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();
}
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); 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) { public static void serializeForClientMsg(Mine mine, ByteBufferWriter writer) {
writer.putInt(mine.getObjectType().ordinal()); writer.putInt(mine.getObjectType().ordinal());
writer.putInt(mine.getObjectUUID()); writer.putInt(mine.getObjectUUID());
writer.putInt(mine.getObjectUUID()); //actually a hash of mine writer.putInt(mine.getObjectUUID()); //actually a hash of mine
writer.putString(mine.mineType.name); writer.putString(mine.mineType.name);
if(ChinaMines.contains((mine))) { writer.putString(Mine.getMineNationality(mine.liveHour) + " " + mine.capSize + " Man ");
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.putInt(mine.production.hash); writer.putInt(mine.production.hash);
writer.putInt(mine.getModifiedProductionAmount()); writer.putInt(mine.getModifiedProductionAmount());
writer.putInt(mine.getModifiedProductionAmount()); //TODO calculate range penalty here 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. // Errant mines are currently open. Set time to now.
LocalDateTime mineOpenTime;// = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0); LocalDateTime mineOpenTime = LocalDateTime.now().withHour(mine.liveHour).withMinute(mine.liveMinute);
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 mineCloseTime = mineOpenTime.plusMinutes(30); LocalDateTime mineCloseTime = mineOpenTime.plusMinutes(30);
if(LocalDateTime.now().isAfter(mineCloseTime)){ if(LocalDateTime.now().isAfter(mineCloseTime) && mine.isActive == false){
mineOpenTime = mineOpenTime.plusDays(1); mineOpenTime = mineOpenTime.plusDays(1);
mineCloseTime = mineCloseTime.plusDays(1); mineCloseTime = mineCloseTime.plusDays(1);
} }
writer.putLocalDateTime(mineOpenTime); writer.putLocalDateTime(mineOpenTime);
writer.putLocalDateTime(mineCloseTime); writer.putLocalDateTime(mineCloseTime);
writer.put(mine.isActive ? (byte) 0x01 : (byte) 0x00); writer.put(mine.isActive ? (byte) 0x01 : (byte) 0x00);
Building mineTower = BuildingManager.getBuilding(mine.buildingID); 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.putInt(mine.isExpansion() ? mine.mineType.xpacHash : mine.mineType.hash);
writer.putString(mine.guildName);
GuildTag._serializeForDisplay(mine.guildTag, writer);
writer.putString(mine.nationName); 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); GuildTag._serializeForDisplay(mine.nationTag, writer);
} }

2
src/engine/objects/MineProduction.java

@ -13,7 +13,7 @@ import java.util.HashMap;
public enum MineProduction { 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), ORE("Ore Mine", new HashMap<>(), Resource.OBSIDIAN, 518103023, -788976428),
GOLD("Gold Mine", new HashMap<>(), Resource.GALVOR, -662193002, -1227205358), GOLD("Gold Mine", new HashMap<>(), Resource.GALVOR, -662193002, -1227205358),
MAGIC("Magic Mine", new HashMap<>(), Resource.BLOODSTONE, 504746863, -1753567069), MAGIC("Magic Mine", new HashMap<>(), Resource.BLOODSTONE, 504746863, -1753567069),

95
src/engine/objects/PlayerCharacter.java

@ -160,7 +160,7 @@ public class PlayerCharacter extends AbstractCharacter {
private boolean asciiLastName = true; private boolean asciiLastName = true;
private int spamCount = 0; private int spamCount = 0;
private boolean initialized = false; private boolean initialized = false;
public boolean enteredWorld = false; private boolean enteredWorld = false;
private boolean canBreathe = true; private boolean canBreathe = true;
private String hash; private String hash;
private ArrayList<GuildHistory> guildHistory = new ArrayList<>(); private ArrayList<GuildHistory> guildHistory = new ArrayList<>();
@ -178,9 +178,11 @@ public class PlayerCharacter extends AbstractCharacter {
public float ZergMultiplier = 1.0f; public float ZergMultiplier = 1.0f;
public int mineAppliedID = 0; public int mineAppliedID = 0;
public long lastAction = 0; public boolean depositingWarehouse = false;
public Building warehouseBuilding;
public ArrayList<PlayerCharacter> killedCharacters = new ArrayList<>();
public long nextBoxCheck = System.currentTimeMillis();
/** /**
* No Id Constructor * No Id Constructor
*/ */
@ -1827,20 +1829,18 @@ public class PlayerCharacter extends AbstractCharacter {
//see if we shold grant xp to attacker //see if we shold grant xp to attacker
boolean doPVPEXP = false; boolean doPVPEXP = false;
long lastKill = att.getLastKillOfTarget(this.getObjectUUID()); 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 aN = null;
Guild tN = null; Guild tN = null;
if (attacker.getGuild() != null) if (attacker.getGuild() != null)
aN = attacker.getGuild().getNation(); aN = attacker.getGuild().getNation();
if (this.getGuild() != null) if (this.getGuild() != null)
tN = this.getGuild().getNation(); 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. if (aN != null || tN != null || !aN.equals(tN) || !this.isDeathShroud()) {
} else {
doPVPEXP = true; doPVPEXP = true;
} }
}
//apply death shroud to non safeholds. //apply death shroud to non safeholds.
Zone zone = ZoneManager.findSmallestZone(this.getLoc()); Zone zone = ZoneManager.findSmallestZone(this.getLoc());
@ -2916,14 +2916,21 @@ public class PlayerCharacter extends AbstractCharacter {
return endSpeed; 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; xp *= 2;
}
if(GroupManager.getGroup(this) == null)
xp *= 1.9f;
// Stop players from getting experience past the cap // Stop players from getting experience past the cap
if (this.exp + xp >= Experience.getBaseExperience(MBServerStatics.LEVELCAP)) int levelCap = MBServerStatics.LEVELCAP;
xp = Experience.getBaseExperience(MBServerStatics.LEVELCAP) - this.exp + 1; if (this.exp + xp >= Experience.getBaseExperience(levelCap))
xp = Experience.getBaseExperience(levelCap) - this.exp + 1;
if (xp == 0) if (xp == 0)
xp = 1; xp = 1;
@ -4633,10 +4640,10 @@ public class PlayerCharacter extends AbstractCharacter {
tmpLevel = targetLevel; tmpLevel = targetLevel;
tmpLevel = (short) Math.min(tmpLevel, 75); tmpLevel = (short) Math.min(tmpLevel, MBServerStatics.LEVELCAP);
while (this.level < tmpLevel) { 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 //if(this.isBoxed && this.containsEffect(429611355) == false) {//pathfinding
// PowersManager.applyPower(this, this, Vector3fImmutable.ZERO, 429611355, 40, false); // PowersManager.applyPower(this, this, Vector3fImmutable.ZERO, 429611355, 40, false);
//} //}
if(enteredWorld && this.isActive() && this.isAlive()){ if(this.isEnteredWorld() && this.isActive()){
if( this.getLevel() < 10) { if( this.getLevel() < 10) {
this.setLevel((short) 10); this.setLevel((short) 10);
boolean hasConc = false; boolean hasConc = false;
@ -4865,25 +4872,19 @@ public class PlayerCharacter extends AbstractCharacter {
ItemFactory.fillInventory(this, 980066, 1); ItemFactory.fillInventory(this, 980066, 1);
} }
} }
if(!this.isBoxed && System.currentTimeMillis() < this.nextBoxCheck) {
checkIfBoxed(this);
}
if(this.isBoxed) { if(this.isBoxed) {
if(!this.title.equals(CharacterTitle.BOX)) { if(this.title.equals(CharacterTitle.BOX) == false) {
this.title = CharacterTitle.BOX; this.title = CharacterTitle.BOX;
//InterestManager.reloadCharacter(this); InterestManager.reloadCharacter(this);
} }
if (this.containsEffect(1672601862) == false) {//Deathshroud
if (!this.containsEffect(1672601862)) {//Deathshroud
PowersManager.applyPower(this, this, Vector3fImmutable.ZERO, 1672601862, 40, false); PowersManager.applyPower(this, this, Vector3fImmutable.ZERO, 1672601862, 40, false);
if(!this.getEffects().containsKey("MoveBuff")){
PowersManager.applyPower(this, this, this.loc, 1514898036, 40, false);
}
} }
}else{ }else{
if(!this.title.equals(CharacterTitle.NONE)) { if(this.title.equals(CharacterTitle.NONE) == false) {
this.title = CharacterTitle.NONE; this.title = CharacterTitle.NONE;
//InterestManager.reloadCharacter(this); InterestManager.reloadCharacter(this);
} }
} }
} }
@ -4894,11 +4895,23 @@ public class PlayerCharacter extends AbstractCharacter {
this.updateLock.writeLock().unlock(); 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){ public static boolean checkIfBoxed(PlayerCharacter player){
player.nextBoxCheck = System.currentTimeMillis() + 10000;
try { try {
for (PlayerCharacter pc : SessionManager.getAllActivePlayers()) { for (PlayerCharacter pc : SessionManager.getAllActivePlayers()) {
if(pc.getClientConnection().machineID.equals(player.getClientConnection().machineID) == false) if(pc.getClientConnection().machineID.equals(player.getClientConnection().machineID) == false)
@ -4910,17 +4923,15 @@ public class PlayerCharacter extends AbstractCharacter {
if (pc.equals(player)) if (pc.equals(player))
continue; continue;
if (pc.isBoxed == false) { if (pc.isBoxed == false) {
player.isBoxed = true; player.title = CharacterTitle.BOX;
InterestManager.setObjectDirty(player); return true;
return;
} }
} }
player.isBoxed = false; player.title = CharacterTitle.NONE;
InterestManager.setObjectDirty(player); return false;
}catch(Exception e){ }catch(Exception e){
player.isBoxed = false; return false;
InterestManager.setObjectDirty(player);
} }
} }
@ -5554,6 +5565,14 @@ public class PlayerCharacter extends AbstractCharacter {
this.centerHeight = centerHeight; this.centerHeight = centerHeight;
} }
public boolean isEnteredWorld() {
return enteredWorld;
}
public void setEnteredWorld(boolean enteredWorld) {
this.enteredWorld = enteredWorld;
}
public long getChannelMute() { public long getChannelMute() {
return channelMute; return channelMute;
} }

113
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) { public static void warehouseDeposit(MerchantMsg msg, PlayerCharacter player, NPC npc, ClientConnection origin) {
long nextAllowedAction = player.lastAction + 5000; Building warehouseBuilding = npc.getBuilding();
if(nextAllowedAction > System.currentTimeMillis()){ if (warehouseBuilding == null) {
ChatManager.chatSystemInfo(player, "You Must Wait To Do This");
return; return;
} }
player.lastAction = System.currentTimeMillis();
Building warehouseBuilding;
Warehouse warehouse;
int depositAmount;
Dispatch dispatch;
player.getTimestamps().put("lastDepositWarehouse", System.currentTimeMillis());
player.depositingWarehouse = true;
player.warehouseBuilding = warehouseBuilding;
player.getCharItemManager().updateLock = true;
Item resource = Item.getFromCache(msg.getItemID()); Item resource = Item.getFromCache(msg.getItemID());
if (resource == null) if (resource == null) {
return; return;
depositAmount = msg.getAmount();
if(depositAmount < 1){
ChatManager.chatSystemInfo(player, "You Have Attempted To Dupe. Please Don't");
} }
int depositAmount = msg.getAmount();
CharacterItemManager itemMan = player.getCharItemManager(); CharacterItemManager itemMan = player.getCharItemManager();
if (itemMan.doesCharOwnThisItem(resource.getObjectUUID()) == false) if (!itemMan.doesCharOwnThisItem(resource.getObjectUUID())) {
return; return;
}
warehouseBuilding = npc.getBuilding(); Warehouse warehouse = warehouseByBuildingUUID.get(warehouseBuilding.getObjectUUID());
if (warehouse == null) {
if (warehouseBuilding == null)
return;
warehouse = warehouseByBuildingUUID.get(warehouseBuilding.getObjectUUID());
if (warehouse == null)
return; return;
}
ItemBase ib = resource.getItemBase();
if (!warehouse.deposit(player, resource, depositAmount, true, true)) { 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; return;
} }
ViewResourcesMessage vrm = new ViewResourcesMessage(player); //ViewResourcesMessage vrm = new ViewResourcesMessage(player);
vrm.setGuild(player.getGuild()); //vrm.setGuild(player.getGuild());
vrm.setWarehouseBuilding(warehouseBuilding); //vrm.setWarehouseBuilding(warehouseBuilding);
vrm.configure(); //vrm.configure();
dispatch = Dispatch.borrow(player, vrm); //Dispatch dispatch = Dispatch.borrow(player, vrm);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); //DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
} }
public static void warehouseWithdraw(MerchantMsg msg, PlayerCharacter player, NPC npc, ClientConnection origin) { 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; int withdrawAmount;
Building warehouseBuilding; Building warehouseBuilding;
Warehouse warehouse; Warehouse warehouse;
@ -479,6 +459,59 @@ public class Warehouse extends AbstractWorldObject {
return true; 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 //for mine deposit
public synchronized boolean depositFromMine(Mine mine, ItemBase resource, int amount) { public synchronized boolean depositFromMine(Mine mine, ItemBase resource, int amount) {

2
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_DODGE = 20;
public static final int COMBAT_SEND_BLOCK = 21; public static final int COMBAT_SEND_BLOCK = 21;
public static final int COMBAT_SEND_PARRY = 22; 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 LEVEL_CON_WHITE = 7;
public static final int RESPAWN_TIMER = 90 * 1000; public static final int RESPAWN_TIMER = 90 * 1000;
public static final int DESPAWN_TIMER = 12 * 1000; public static final int DESPAWN_TIMER = 12 * 1000;

10
src/engine/server/world/WorldServer.java

@ -250,11 +250,11 @@ public class WorldServer {
if(LocalDateTime.now().isAfter(nextDiscSpawn)) { if(LocalDateTime.now().isAfter(nextDiscSpawn)) {
switch (LocalDateTime.now().getHour()) { switch (LocalDateTime.now().getHour()) {
case 0: case 0:
case 4: case 3:
case 8: case 7:
case 12: case 11:
case 16: case 15:
case 20: case 19:
for (Mob dropper : Mob.disciplineDroppers) { for (Mob dropper : Mob.disciplineDroppers) {
if (!dropper.isAlive()) { if (!dropper.isAlive()) {
Zone.respawnQue.add(dropper); Zone.respawnQue.add(dropper);

35
src/engine/workthreads/DestroyCityThread.java

@ -19,6 +19,7 @@ package engine.workthreads;
*/ */
import engine.Enum; import engine.Enum;
import engine.gameManager.BuildingManager;
import engine.gameManager.DbManager; import engine.gameManager.DbManager;
import engine.gameManager.GuildManager; import engine.gameManager.GuildManager;
import engine.gameManager.ZoneManager; import engine.gameManager.ZoneManager;
@ -53,7 +54,6 @@ public class DestroyCityThread implements Runnable {
// Member variable assignment // Member variable assignment
cityZone = city.getParent(); cityZone = city.getParent();
newParent = cityZone.getParent();
formerGuild = city.getTOL().getGuild(); formerGuild = city.getTOL().getGuild();
// Former guild loses it's tree! // Former guild loses it's tree!
@ -99,36 +99,15 @@ public class DestroyCityThread implements Runnable {
if (cityBuilding.getBlueprint().getBuildingGroup().equals(Enum.BuildingGroup.BANESTONE)) if (cityBuilding.getBlueprint().getBuildingGroup().equals(Enum.BuildingGroup.BANESTONE))
continue; continue;
// All buildings are moved to a location relative //destroy all buildings if we are destroying the city itself
// 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)) {
if (cityBuilding.getRank() != -1) if (cityBuilding.getRank() != -1)
cityBuilding.setRank(-1); cityBuilding.setRank(-1);
if(BuildingManager.getBuildingFromCache(cityBuilding.getObjectUUID()) != null){
cityBuilding.removeFromCache();
DbManager.BuildingQueries.DELETE_FROM_DATABASE(cityBuilding);
} }
} }
if (city.getRealm() != null) if (city.getRealm() != null)

83
src/engine/workthreads/MineThread.java

@ -13,52 +13,19 @@ import engine.objects.Guild;
import engine.objects.Mine; import engine.objects.Mine;
import engine.objects.PlayerCharacter; import engine.objects.PlayerCharacter;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.time.LocalDateTime; import java.time.LocalDateTime;
public class MineThread implements Runnable { public class MineThread implements Runnable {
public static LocalDateTime nextPulse;
public MineThread(){ public MineThread(){
} }
@Override @Override
public void run() { public void run() {
LocalDateTime nextPulse = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0); nextPulse = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0);
while (true){ while (true) {
if(LocalDateTime.now().isAfter(nextPulse)) { if(LocalDateTime.now().isAfter(nextPulse)) {
for (Mine mine : Mine.getMines()) { processMineWindows();
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);
} }
} }
} }
@ -66,7 +33,6 @@ public class MineThread implements Runnable {
public static void mineWindowOpen(Mine mine) { public static void mineWindowOpen(Mine mine) {
mine.setActive(true); mine.setActive(true);
ChatManager.chatSystemChannel(mine.getParentZone().getName() + "'s Mine is now Active!");
Logger.info(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; mine.wasClaimed = true;
return 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);
}
} }

138
src/engine/workthreads/ZergMechanicThread.java

@ -8,33 +8,20 @@
package engine.workthreads; package engine.workthreads;
import engine.Enum; import engine.Enum;
import engine.InterestManagement.WorldGrid; import engine.InterestManagement.WorldGrid;
import engine.db.archive.DataWarehouse;
import engine.db.archive.MineRecord;
import engine.gameManager.*; 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.objects.*;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
import engine.server.world.WorldServer;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.concurrent.ConcurrentHashMap;
import static engine.server.MBServerStatics.MINE_LATE_WINDOW; public class ZergMechanicThread implements Runnable {
private final Mine mine;
public class ZergMechanicThread implements Runnable { private final Bane bane;
public Bane bane = null; private final HashSet<PlayerCharacter> affectedPlayers = new HashSet<>();
public Mine mine = null;
public ArrayList<PlayerCharacter> affectedPlayers = new ArrayList<>();
public ZergMechanicThread(Bane b, Mine m) { public ZergMechanicThread(Bane b, Mine m) {
this.mine = m; this.mine = m;
@ -43,79 +30,49 @@ public ArrayList<PlayerCharacter> affectedPlayers = new ArrayList<>();
@Override @Override
public void run() { public void run() {
if (mine != null) if (mine != null)
RunMineMechanic(); RunMineMechanic();
if (bane != null) if (bane != null)
RunBaneMechanic(); RunBaneMechanic();
} }
public void RunMineMechanic(){ private void RunMineMechanic() {
while(mine.isActive) {
HashSet<AbstractWorldObject> currentPlayers;
PlayerCharacter player;
// Gather current list of players within the zone bounds
Building tower = BuildingManager.getBuildingFromCache(mine.getBuildingID()); 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) {
if (playerObject == null) while (mine.isActive) {
continue; HashSet<AbstractWorldObject> currentPlayers = WorldGrid.getObjectsInRangePartial(tower.loc, zoneBounds, MBServerStatics.MASK_PLAYER);
player = (PlayerCharacter) playerObject; for (AbstractWorldObject playerObject : currentPlayers) {
PlayerCharacter player = (PlayerCharacter) playerObject;
if(!this.affectedPlayers.contains(player)) affectedPlayers.add(player);
this.affectedPlayers.add(player);
//ChatManager.chatSystemInfo(player, "TESTING ZERG MECHANIC");
if (mine._recentMemory.containsKey(player.getObjectUUID()))
mine._recentMemory.remove(player.getObjectUUID()); mine._recentMemory.remove(player.getObjectUUID());
if (mine._playerMemory.contains(player.getObjectUUID()))
continue;
mine._playerMemory.add(player.getObjectUUID()); mine._playerMemory.add(player.getObjectUUID());
} }
boolean updated = false;
try { try {
mine.onExit(currentPlayers); mine.onExit(currentPlayers);
} catch (Exception e) { } catch (Exception e) {
Logger.error(e.getMessage()); Logger.error(e.getMessage());
} }
mine.dividedPlayers = new HashMap<>(); mine.dividedPlayers = new HashMap<>();
for (Integer playerID : mine._playerMemory) { for (Integer playerID : mine._playerMemory) {
player = PlayerCharacter.getFromCache(playerID); PlayerCharacter player = PlayerCharacter.getFromCache(playerID);
Guild nation = player.getGuild().getNation(); Guild nation = player.getGuild().getNation();
Guild entry; mine.dividedPlayers.computeIfAbsent(nation, k -> new ArrayList<>()).add(playerID);
if (mine.dividedPlayers.containsKey(nation)) {
mine.dividedPlayers.get(nation).add(playerID);
} else {
ArrayList<Integer> newEntry = new ArrayList<>();
newEntry.add(playerID);
mine.dividedPlayers.put(nation, newEntry);
}
} }
for (Integer playerID : mine._playerMemory) { for (Integer playerID : mine._playerMemory) {
player = PlayerCharacter.getFromCache(playerID); PlayerCharacter player = PlayerCharacter.getFromCache(playerID);
if (mine.dividedPlayers.containsKey(player.getGuild().getNation())) { Guild nation = player.getGuild().getNation();
int count = mine.dividedPlayers.get(player.getGuild().getNation()).size();
switch (mine.capSize) { if (mine.dividedPlayers.containsKey(nation)) {
case 3: int count = mine.dividedPlayers.get(nation).size();
player.ZergMultiplier = ZergManager.getMultiplier3Man(count); player.ZergMultiplier = ZergManager.getCurrentMultiplier(count, mine.capSize);
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;
}
player.mineAppliedID = mine.getObjectUUID(); player.mineAppliedID = mine.getObjectUUID();
} else { } else {
player.ZergMultiplier = 1.0f; player.ZergMultiplier = 1.0f;
@ -124,28 +81,21 @@ public ArrayList<PlayerCharacter> affectedPlayers = new ArrayList<>();
} }
} }
for(PlayerCharacter player : this.affectedPlayers) resetZergMultiplier();
player.ZergMultiplier = 1.0f;
} }
public void RunBaneMechanic(){ private void RunBaneMechanic() {
while(bane.getSiegePhase().equals(Enum.SiegePhase.WAR)) { while (bane.getSiegePhase().equals(Enum.SiegePhase.WAR)) {
HashSet<AbstractWorldObject> currentPlayers; HashSet<AbstractWorldObject> currentPlayers = WorldGrid.getObjectsInRangePartial(bane.getCity().loc, Enum.CityBoundsType.GRID.extents * 2.0f, MBServerStatics.MASK_PLAYER);
currentPlayers = WorldGrid.getObjectsInRangePartial(bane.getCity().loc, Enum.CityBoundsType.GRID.extents * 2.0f, MBServerStatics.MASK_PLAYER);
Guild attacker = bane.getStone().getGuild().getNation(); Guild attacker = bane.getStone().getGuild().getNation();
Guild defender = bane.getCity().getGuild().getNation(); Guild defender = bane.getCity().getGuild().getNation();
ArrayList<PlayerCharacter> attackers = new ArrayList<>(); ArrayList<PlayerCharacter> attackers = new ArrayList<>();
ArrayList<PlayerCharacter> defenders = new ArrayList<>(); ArrayList<PlayerCharacter> defenders = new ArrayList<>();
for (AbstractWorldObject awo : currentPlayers) { for (AbstractWorldObject awo : currentPlayers) {
if(!this.affectedPlayers.contains((PlayerCharacter)awo))
this.affectedPlayers.add((PlayerCharacter)awo);
PlayerCharacter pc = (PlayerCharacter) awo; PlayerCharacter pc = (PlayerCharacter) awo;
affectedPlayers.add(pc);
if (!pc.getGuild().getNation().equals(attacker) && !pc.getGuild().getNation().equals(defender)) { if (!pc.getGuild().getNation().equals(attacker) && !pc.getGuild().getNation().equals(defender)) {
pc.teleport(pc.bindLoc); pc.teleport(pc.bindLoc);
pc.ZergMultiplier = 1.0f; pc.ZergMultiplier = 1.0f;
@ -158,46 +108,32 @@ public ArrayList<PlayerCharacter> affectedPlayers = new ArrayList<>();
defenders.add(pc); defenders.add(pc);
} }
//int treeRank = bane.getCity().getTOL().getRank();
for (PlayerCharacter pc : attackers) { for (PlayerCharacter pc : attackers) {
switch(bane.capSize){ pc.ZergMultiplier = ZergManager.getCurrentMultiplier(attackers.size(), bane.capSize);
case 10:
pc.ZergMultiplier = ZergManager.getMultiplier10Man(attackers.size());
break;
case 20:
pc.ZergMultiplier = ZergManager.getMultiplier20Man(attackers.size());
break;
}
} }
for (PlayerCharacter pc : defenders) { for (PlayerCharacter pc : defenders) {
switch(bane.capSize){ pc.ZergMultiplier = ZergManager.getCurrentMultiplier(defenders.size(), bane.capSize);
case 10:
pc.ZergMultiplier = ZergManager.getMultiplier10Man(defenders.size());
break;
case 20:
pc.ZergMultiplier = ZergManager.getMultiplier20Man(defenders.size());
break;
} }
} }
resetZergMultiplier();
} }
for(PlayerCharacter player : this.affectedPlayers) private void resetZergMultiplier() {
for (PlayerCharacter player : affectedPlayers)
player.ZergMultiplier = 1.0f; player.ZergMultiplier = 1.0f;
} }
public static void startZergThreadMine(Mine mine) { public static void startZergThreadMine(Mine mine) {
Thread zergMechanicThread; Thread zergMechanicThread = new Thread(new ZergMechanicThread(null, mine));
zergMechanicThread = new Thread(new ZergMechanicThread(null, mine));
zergMechanicThread.setName(mine.getParentZone().getName() + "Mine"); zergMechanicThread.setName(mine.getParentZone().getName() + "Mine");
zergMechanicThread.start(); zergMechanicThread.start();
} }
public static void startZergThreadBane(Bane bane) { public static void startZergThreadBane(Bane bane) {
Thread zergMechanicThread; Thread zergMechanicThread = new Thread(new ZergMechanicThread(bane, null));
zergMechanicThread = new Thread(new ZergMechanicThread(bane, null));
zergMechanicThread.setName(bane.getCity().getGuild().getName() + "Bane"); zergMechanicThread.setName(bane.getCity().getGuild().getName() + "Bane");
zergMechanicThread.start(); zergMechanicThread.start();
} }
} }

Loading…
Cancel
Save