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. 522
      src/engine/gameManager/LootManager.java
  5. 124
      src/engine/gameManager/ZergManager.java
  6. 504
      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. 49
      src/engine/objects/Experience.java
  19. 309
      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. 81
      src/engine/workthreads/MineThread.java
  27. 132
      src/engine/workthreads/ZergMechanicThread.java

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

@ -504,4 +504,24 @@ public class dbItemHandler extends dbHandlerBase { @@ -504,4 +504,24 @@ public class dbItemHandler extends dbHandlerBase {
return false;
}
}
public boolean UPDATE_NUM_ITEMS(final Item item, int newValue, int oldValue) {
if (item.getItemBase().getType().equals(ItemType.GOLD))
return false;
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `obj_item` SET `item_numberOfItems`=? WHERE `UID`=?")) {
preparedStatement.setInt(1, newValue);
preparedStatement.setLong(2, item.getObjectUUID());
return (preparedStatement.executeUpdate() > 0);
} catch (SQLException e) {
Logger.error(e);
return false;
}
}
}

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

@ -14,6 +14,7 @@ import engine.devcmd.AbstractDevCmd; @@ -14,6 +14,7 @@ import engine.devcmd.AbstractDevCmd;
import engine.gameManager.ChatManager;
import engine.objects.AbstractGameObject;
import engine.objects.PlayerCharacter;
import engine.server.MBServerStatics;
public class SetLevelCmd extends AbstractDevCmd {
@ -46,7 +47,7 @@ public class SetLevelCmd extends AbstractDevCmd { @@ -46,7 +47,7 @@ public class SetLevelCmd extends AbstractDevCmd {
this.sendUsage(pc);
return;
}
if (level < 1 || level > 75) {
if (level < 1 || level > MBServerStatics.LEVELCAP) {
this.sendHelp(pc);
return;
}
@ -62,7 +63,7 @@ public class SetLevelCmd extends AbstractDevCmd { @@ -62,7 +63,7 @@ public class SetLevelCmd extends AbstractDevCmd {
@Override
protected String _getHelpString() {
return "Sets your character's level to 'amount'. 'amount' must be between 1-75";
return "Sets your character's level to 'amount'. 'amount' must be between 1-" + MBServerStatics.LEVELCAP;
}
@Override

3
src/engine/gameManager/CombatManager.java

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

522
src/engine/gameManager/LootManager.java

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

124
src/engine/gameManager/ZergManager.java

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

504
src/engine/mobileAI/MobAI.java

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

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

@ -12,13 +12,20 @@ package engine.mobileAI.utilities; @@ -12,13 +12,20 @@ package engine.mobileAI.utilities;
import engine.Enum.*;
import engine.gameManager.ChatManager;
import engine.gameManager.CombatManager;
import engine.gameManager.PowersManager;
import engine.math.Vector3fImmutable;
import engine.mobileAI.MobAI;
import engine.mobileAI.Threads.MobAIThread;
import engine.net.DispatchMessage;
import engine.net.client.msg.PerformActionMsg;
import engine.net.client.msg.TargetedActionMsg;
import engine.objects.*;
import engine.powers.ActionsBase;
import engine.powers.PowersBase;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;
import java.util.ArrayList;
import java.util.concurrent.ThreadLocalRandom;
import static engine.math.FastMath.sqr;
@ -512,4 +519,209 @@ public class CombatUtilities { @@ -512,4 +519,209 @@ public class CombatUtilities {
return agent.getMaxDamageHandOne();
}
public static boolean MobCast(Mob mob) {
try {
// Method picks a random spell from a mobile's list of powers
// and casts it on the current target (or itself). Validation
// (including empty lists) is done previously within canCast();
ArrayList<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 { @@ -135,7 +135,6 @@ public class MovementUtilities {
public static boolean canMove(Mob agent) {
if (agent.getMobBase() != null && Enum.MobFlagType.SENTINEL.elementOf(agent.getMobBase().getFlags()))
return false;
@ -144,16 +143,6 @@ public class MovementUtilities { @@ -144,16 +143,6 @@ public class MovementUtilities {
public static void aiMove(Mob agent, Vector3fImmutable vect, boolean isWalking) {
agent.updateLocation();
//update our walk/run state.
if (isWalking && !agent.isWalk()) {
agent.setWalkMode(true);
MovementManager.sendRWSSMsg(agent);
} else if (!isWalking && agent.isWalk()) {
agent.setWalkMode(false);
MovementManager.sendRWSSMsg(agent);
}
MoveToPointMsg msg = new MoveToPointMsg();

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

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

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

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

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

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

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

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

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

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

17
src/engine/objects/AbstractCharacter.java

@ -1114,23 +1114,6 @@ public abstract class AbstractCharacter extends AbstractWorldObject { @@ -1114,23 +1114,6 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
}
public final void setCombatTarget(final AbstractWorldObject value) {
if(this.getObjectTypeMask() == 2050) {//MOB?
if (value == null) {
if (this.isCombat()) {
this.setCombat(false);
UpdateStateMsg rwss = new UpdateStateMsg();
rwss.setPlayer(this);
DispatchMessage.sendToAllInRange(this, rwss);
}
}else {
if (!this.isCombat()) {
this.setCombat(true);
UpdateStateMsg rwss = new UpdateStateMsg();
rwss.setPlayer(this);
DispatchMessage.sendToAllInRange(this, rwss);
}
}
}
this.combatTarget = value;
}

4
src/engine/objects/Bane.java

@ -607,6 +607,10 @@ public final class Bane { @@ -607,6 +607,10 @@ public final class Bane {
DispatchMessage.dispatchMsgToAll(msg);
}
for(AbstractWorldObject awo : WorldGrid.getObjectsInRangePartial(this.getCity().loc,1500,MBServerStatics.MASK_BUILDING)){
Building building = (Building)awo;
if(building.setOwner(this.getOwner()));
}
break;
case DESTROY:

12
src/engine/objects/Building.java

@ -12,6 +12,7 @@ package engine.objects; @@ -12,6 +12,7 @@ package engine.objects;
import engine.Enum;
import engine.Enum.*;
import engine.InterestManagement.HeightMap;
import engine.InterestManagement.InterestManager;
import engine.InterestManagement.RealmMap;
import engine.InterestManagement.WorldGrid;
import engine.db.archive.CityRecord;
@ -394,7 +395,7 @@ public class Building extends AbstractWorldObject { @@ -394,7 +395,7 @@ public class Building extends AbstractWorldObject {
this.rank = newRank;
// New rank means new mesh
int oldMeshID = this.meshUUID;
newMeshUUID = this.getBlueprint().getMeshForRank(this.rank);
this.meshUUID = newMeshUUID;
@ -428,6 +429,15 @@ public class Building extends AbstractWorldObject { @@ -428,6 +429,15 @@ public class Building extends AbstractWorldObject {
BuildingManager.cleanupHirelings(this);
this.isDeranking.compareAndSet(true, false);
if(oldMeshID != this.meshUUID) {
//move NPCs to new slot locations if the mesh was changed and force reload them
int index = 0;
for (AbstractCharacter hireling : this.hirelings.keySet()) {
hireling.setLoc(BuildingManager._slotLocations.get(newMeshUUID).get(index).getLocation());
InterestManager.reloadCharacter(hireling);
}
}
}
public final int getOwnerUUID() {

85
src/engine/objects/CharacterItemManager.java

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

49
src/engine/objects/Experience.java

@ -9,7 +9,9 @@ @@ -9,7 +9,9 @@
package engine.objects;
import engine.Enum;
import engine.Enum.TargetColor;
import engine.gameManager.LootManager;
import engine.gameManager.ZoneManager;
import engine.math.Vector3fImmutable;
import engine.server.MBServerStatics;
@ -117,6 +119,11 @@ public class Experience { @@ -117,6 +119,11 @@ public class Experience {
159932666, // Level 74
169707808, // Level 75
179921247, // Level 76
190548651, // Level 77
201590020, // Level 78
213045354, // Level 79
224914653, // Level 80
237197917 // Level 81
};
@ -214,7 +221,19 @@ public class Experience { @@ -214,7 +221,19 @@ public class Experience {
235166.21f, // Level 72
246039.34f, // Level 73
257240.58f, // Level 74
1 // 268774.71 //Level 75
268765.03f, // Level 75
280612.69f, // Level 76
292783.56f, // Level 77
305277.64f, // Level 78
318094.93f, // Level 79
1, // Level 80
};
// Used to calcuate the amount of experience a monster grants in the
@ -268,8 +287,8 @@ public class Experience { @@ -268,8 +287,8 @@ public class Experience {
if (level < 1)
level = 1;
if (level > 75)
level = 75;
if (level > MBServerStatics.LEVELCAP)
level = MBServerStatics.LEVELCAP;
return MaxExpPerLevel[level];
}
@ -354,8 +373,8 @@ public class Experience { @@ -354,8 +373,8 @@ public class Experience {
if (leaderskill != null)
leadership = leaderskill.getNumTrains();
if (leadership > 90)
leadership = 90; // leadership caps at 90%
//if (leadership > 90)
// leadership = 90; // leadership caps at 90%
}
// Check every group member for distance to see if they get xp
@ -393,6 +412,8 @@ public class Experience { @@ -393,6 +412,8 @@ public class Experience {
// Process XP for this member
grantedExperience *= (1/giveEXPTo.size()+0.9);
penalty = getGroupMemberPenalty(leadership, playerCharacter, giveEXPTo,
highestLevel);
@ -423,8 +444,14 @@ public class Experience { @@ -423,8 +444,14 @@ public class Experience {
if (grantedExperience == 0)
grantedExperience = 1;
grantedExperience *= LootManager.NORMAL_EXP_RATE;
// Grant the player the EXP
playerCharacter.grantXP((int) Math.floor(grantedExperience));
if(mob.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) {
if (((PlayerCharacter) mob).pvpDeaths.contains(killer.getObjectUUID()) == false)
playerCharacter.grantXP((int) Math.floor(grantedExperience), true);
}else {
playerCharacter.grantXP((int) Math.floor(grantedExperience), false);
}
}
} else { // Give EXP to a single character
@ -435,7 +462,8 @@ public class Experience { @@ -435,7 +462,8 @@ public class Experience {
return;
// Get XP and adjust for Mob Level with world xp modifier taken into account
grantedExperience = (double) LOOTMANAGER.NORMAL_EXP_RATE * maxXPPerKill(killer.getLevel());
float mdofier = LOOTMANAGER.NORMAL_EXP_RATE;
grantedExperience = maxXPPerKill(killer.getLevel());
grantedExperience *= getConMod(killer, mob);
// Modify for hotzone
@ -448,7 +476,12 @@ public class Experience { @@ -448,7 +476,12 @@ public class Experience {
grantedExperience *= .6;
// Grant XP
killer.grantXP((int) Math.floor(grantedExperience));
if(mob.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) {
if (((PlayerCharacter) mob).pvpDeaths.contains(killer.getObjectUUID()) == false)
killer.grantXP((int) Math.floor(grantedExperience), true);
}else {
killer.grantXP((int) Math.floor(grantedExperience), false);
}
}
}
}

309
src/engine/objects/Mine.java

@ -16,17 +16,15 @@ import engine.net.ByteBufferWriter; @@ -16,17 +16,15 @@ import engine.net.ByteBufferWriter;
import engine.net.client.msg.ErrorPopupMsg;
import engine.server.MBServerStatics;
import engine.workthreads.ZergMechanicThread;
import org.joda.time.DateTime;
import org.pmw.tinylog.Logger;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom;
import static engine.gameManager.DbManager.MineQueries;
import static engine.gameManager.DbManager.getObject;
@ -60,7 +58,8 @@ public class Mine extends AbstractGameObject { @@ -60,7 +58,8 @@ public class Mine extends AbstractGameObject {
public boolean hasProduced = false;
public int liveTime;
public int liveHour;
public int liveMinute;
public Boolean firstThirty = true;
public static ArrayList<Mine> ChinaMines = new ArrayList<>();
@ -115,142 +114,20 @@ public class Mine extends AbstractGameObject { @@ -115,142 +114,20 @@ public class Mine extends AbstractGameObject {
this.production = Resource.valueOf(rs.getString("mine_resource"));
this.lastClaimer = null;
}
}
public static void SetTimes(){
try {
EuroMines.get(0).liveTime = 20;
EuroMines.get(1).liveTime = 20;
EuroMines.get(2).liveTime = 20;
EuroMines.get(3).liveTime = 20;
EuroMines.get(4).liveTime = 20;
EuroMines.get(5).liveTime = 20;
EuroMines.get(6).liveTime = 20;
}catch(Exception e){
}
try{
ChinaMines.get(0).liveTime = 11;
ChinaMines.get(1).liveTime = 11;
ChinaMines.get(2).liveTime = 11;
ChinaMines.get(3).liveTime = 12;
ChinaMines.get(4).liveTime = 12;
ChinaMines.get(5).liveTime = 12;
ChinaMines.get(6).liveTime = 12;
ChinaMines.get(7).liveTime = 12;
ChinaMines.get(8).liveTime = 12;
ChinaMines.get(9).liveTime = 12;
ChinaMines.get(10).liveTime = 13;
ChinaMines.get(11).liveTime = 13;
ChinaMines.get(12).liveTime = 13;
ChinaMines.get(13).liveTime = 13;
}catch(Exception e){
}
try{
AmericaMines.get(0).liveTime = 1;
AmericaMines.get(1).liveTime = 1;
AmericaMines.get(2).liveTime = 1;
AmericaMines.get(3).liveTime = 2;
AmericaMines.get(4).liveTime = 2;
AmericaMines.get(5).liveTime = 2;
AmericaMines.get(6).liveTime = 2;
AmericaMines.get(7).liveTime = 2;
AmericaMines.get(8).liveTime = 2;
AmericaMines.get(9).liveTime = 2;
AmericaMines.get(10).liveTime = 3;
AmericaMines.get(11).liveTime = 3;
AmericaMines.get(12).liveTime = 3;
AmericaMines.get(13).liveTime = 3;
}catch(Exception e){
}
int count = 1;
for(Mine mine : EuroMines){
switch(count){
case 1:
mine.capSize = 3;
break;
case 2:
mine.capSize = 5;
break;
case 3:
mine.capSize = 10;
break;
case 4:
mine.capSize = 3;
break;
}
count ++;
if(count == 5)
count = 1;
if(BuildingManager.getBuilding(mine.buildingID) != null) {
Building mineTower = BuildingManager.getBuilding(mine.buildingID);
if (mineTower != null) {
mineTower.setMaxHitPoints(5000 * mine.capSize);
mineTower.setCurrentHitPoints((float) 5000 * mine.capSize);
}
}
}
this.liveHour = rs.getInt("mineLiveHour");
this.liveMinute = rs.getInt("mineLiveMinute");
this.capSize = rs.getInt("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) {
Building mineTower = BuildingManager.getBuilding(mine.buildingID);
if(BuildingManager.getBuilding(this.buildingID) != null) {
Building mineTower = BuildingManager.getBuilding(this.buildingID);
if (mineTower != null) {
mineTower.setMaxHitPoints(5000 * mine.capSize);
mineTower.setCurrentHitPoints((float) 5000 * mine.capSize);
mineTower.setMaxHitPoints(5000 * this.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) {
if (playerCharacter == null)
@ -306,90 +183,9 @@ public class Mine extends AbstractGameObject { @@ -306,90 +183,9 @@ public class Mine extends AbstractGameObject {
//mine.mineType = MineProduction.LUMBER;
}
try {
ChinaMines.add(serverMines.get(0));
ChinaMines.add(serverMines.get(3));
ChinaMines.add(serverMines.get(6));
ChinaMines.add(serverMines.get(9));
ChinaMines.add(serverMines.get(12));
ChinaMines.add(serverMines.get(15));
ChinaMines.add(serverMines.get(18));
ChinaMines.add(serverMines.get(21));
ChinaMines.add(serverMines.get(23));
ChinaMines.add(serverMines.get(25));
ChinaMines.add(serverMines.get(27));
ChinaMines.add(serverMines.get(29));
ChinaMines.add(serverMines.get(31));
ChinaMines.add(serverMines.get(33));
}catch(Exception e) {
}
try{
AmericaMines.add(serverMines.get(1));
AmericaMines.add(serverMines.get(4));
AmericaMines.add(serverMines.get(7));
AmericaMines.add(serverMines.get(10));
AmericaMines.add(serverMines.get(13));
AmericaMines.add(serverMines.get(16));
AmericaMines.add(serverMines.get(19));
AmericaMines.add(serverMines.get(22));
AmericaMines.add(serverMines.get(24));
AmericaMines.add(serverMines.get(26));
AmericaMines.add(serverMines.get(28));
AmericaMines.add(serverMines.get(30));
AmericaMines.add(serverMines.get(32));
AmericaMines.add(serverMines.get(34));
}catch(Exception e){
}
try{
EuroMines.add(serverMines.get(2));
EuroMines.add(serverMines.get(5));
EuroMines.add(serverMines.get(8));
EuroMines.add(serverMines.get(11));
EuroMines.add(serverMines.get(14));
EuroMines.add(serverMines.get(17));
EuroMines.add(serverMines.get(20));
}catch(Exception e){
}
SetTimes();
for(Mine mine : EuroMines){
if(EuroMines.indexOf(mine) %2 == 0 ){
mine.firstThirty = true;
} else{
mine.firstThirty = false;
}
}
for(Mine mine : AmericaMines){
if(AmericaMines.indexOf(mine) %2 == 0 ){
mine.firstThirty = true;
} else{
mine.firstThirty = false;
}
}
for(Mine mine : ChinaMines){
if(ChinaMines.indexOf(mine) %2 == 0 ){
mine.firstThirty = true;
} else{
mine.firstThirty = false;
}
}
} catch (Exception e) {
e.printStackTrace();
}
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 { @@ -400,20 +196,30 @@ public class Mine extends AbstractGameObject {
return Mine.towerMap.get(towerID);
}
public static String getMineNationality(int time){
switch(time){
case 7:
case 8:
case 9:
return "CN";
case 14:
case 15:
case 16:
return "EU";
case 20:
case 21:
case 22:
return "NA";
default:
return "Unknown";
}
}
public static void serializeForClientMsg(Mine mine, ByteBufferWriter writer) {
writer.putInt(mine.getObjectType().ordinal());
writer.putInt(mine.getObjectUUID());
writer.putInt(mine.getObjectUUID()); //actually a hash of mine
writer.putString(mine.mineType.name);
if(ChinaMines.contains((mine))) {
writer.putString("Chinese" + " {" + mine.capSize + " Man}");
} else if(AmericaMines.contains(mine)){
writer.putString("American" + " {" + mine.capSize + " Man}");
} else if(EuroMines.contains(mine)){
writer.putString("European" + " {" + mine.capSize + " Man}");
}else{
writer.putString("Unknown" + " {" + mine.capSize + " Man}");
}
writer.putString(Mine.getMineNationality(mine.liveHour) + " " + mine.capSize + " Man ");
writer.putInt(mine.production.hash);
writer.putInt(mine.getModifiedProductionAmount());
writer.putInt(mine.getModifiedProductionAmount()); //TODO calculate range penalty here
@ -421,21 +227,16 @@ public class Mine extends AbstractGameObject { @@ -421,21 +227,16 @@ public class Mine extends AbstractGameObject {
// Errant mines are currently open. Set time to now.
LocalDateTime mineOpenTime;// = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0);
if(mine.firstThirty == true){
mineOpenTime = LocalDateTime.now().withHour(mine.liveTime).withMinute(0).withSecond(0).withNano(0);
}
else{
mineOpenTime = LocalDateTime.now().withHour(mine.liveTime).withMinute(30).withSecond(0).withNano(0);
}
LocalDateTime mineOpenTime = LocalDateTime.now().withHour(mine.liveHour).withMinute(mine.liveMinute);
LocalDateTime mineCloseTime = mineOpenTime.plusMinutes(30);
if(LocalDateTime.now().isAfter(mineCloseTime)){
if(LocalDateTime.now().isAfter(mineCloseTime) && mine.isActive == false){
mineOpenTime = mineOpenTime.plusDays(1);
mineCloseTime = mineCloseTime.plusDays(1);
}
writer.putLocalDateTime(mineOpenTime);
writer.putLocalDateTime(mineCloseTime);
writer.put(mine.isActive ? (byte) 0x01 : (byte) 0x00);
Building mineTower = BuildingManager.getBuilding(mine.buildingID);
@ -445,9 +246,51 @@ public class Mine extends AbstractGameObject { @@ -445,9 +246,51 @@ public class Mine extends AbstractGameObject {
writer.putInt(mine.isExpansion() ? mine.mineType.xpacHash : mine.mineType.hash);
writer.putString(mine.guildName);
GuildTag._serializeForDisplay(mine.guildTag, writer);
writer.putString(mine.nationName);
GuildTag._serializeForDisplay(mine.guildTag, writer);
boolean isPM = false;
if(mineOpenTime.getHour() > 11)
isPM = true;
int hourOpen = mineOpenTime.getHour();
int minuteOpen = mineOpenTime.getMinute();
int hourClose = mineCloseTime.getHour();
int minuteClose = mineCloseTime.getMinute();
if(isPM){
hourOpen -= 12;
hourClose -= 12;
}
String timeString = hourOpen + ":";
if(minuteOpen == 0){
timeString += "00 ";
}else{
timeString += "30 ";
}
if(isPM){
timeString += "PM ";
}else{
timeString += "AM ";
}
timeString += " to ";
timeString += hourClose + ":";
if(minuteClose == 0){
timeString += "00 ";
}else{
timeString += "30 ";
}
if(isPM){
timeString += "PM CST";
}else{
timeString += "AM CST";
}
writer.putString(timeString);
GuildTag._serializeForDisplay(mine.nationTag, writer);
}

2
src/engine/objects/MineProduction.java

@ -13,7 +13,7 @@ import java.util.HashMap; @@ -13,7 +13,7 @@ import java.util.HashMap;
public enum MineProduction {
LUMBER("Universal Mine", new HashMap<>(), Resource.WORMWOOD, 1618637196, 1663491950),
LUMBER("Lumber Mine", new HashMap<>(), Resource.WORMWOOD, 1618637196, 1663491950),
ORE("Ore Mine", new HashMap<>(), Resource.OBSIDIAN, 518103023, -788976428),
GOLD("Gold Mine", new HashMap<>(), Resource.GALVOR, -662193002, -1227205358),
MAGIC("Magic Mine", new HashMap<>(), Resource.BLOODSTONE, 504746863, -1753567069),

95
src/engine/objects/PlayerCharacter.java

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

113
src/engine/objects/Warehouse.java

@ -129,67 +129,47 @@ public class Warehouse extends AbstractWorldObject { @@ -129,67 +129,47 @@ public class Warehouse extends AbstractWorldObject {
public static void warehouseDeposit(MerchantMsg msg, PlayerCharacter player, NPC npc, ClientConnection origin) {
long nextAllowedAction = player.lastAction + 5000;
if(nextAllowedAction > System.currentTimeMillis()){
ChatManager.chatSystemInfo(player, "You Must Wait To Do This");
Building warehouseBuilding = npc.getBuilding();
if (warehouseBuilding == null) {
return;
}
player.lastAction = System.currentTimeMillis();
Building warehouseBuilding;
Warehouse warehouse;
int depositAmount;
Dispatch dispatch;
player.getTimestamps().put("lastDepositWarehouse", System.currentTimeMillis());
player.depositingWarehouse = true;
player.warehouseBuilding = warehouseBuilding;
player.getCharItemManager().updateLock = true;
Item resource = Item.getFromCache(msg.getItemID());
if (resource == null)
if (resource == null) {
return;
depositAmount = msg.getAmount();
if(depositAmount < 1){
ChatManager.chatSystemInfo(player, "You Have Attempted To Dupe. Please Don't");
}
CharacterItemManager itemMan = player.getCharItemManager();
if (itemMan.doesCharOwnThisItem(resource.getObjectUUID()) == false)
return;
warehouseBuilding = npc.getBuilding();
int depositAmount = msg.getAmount();
CharacterItemManager itemMan = player.getCharItemManager();
if (warehouseBuilding == null)
if (!itemMan.doesCharOwnThisItem(resource.getObjectUUID())) {
return;
}
warehouse = warehouseByBuildingUUID.get(warehouseBuilding.getObjectUUID());
if (warehouse == null)
Warehouse warehouse = warehouseByBuildingUUID.get(warehouseBuilding.getObjectUUID());
if (warehouse == null) {
return;
ItemBase ib = resource.getItemBase();
}
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;
}
ViewResourcesMessage vrm = new ViewResourcesMessage(player);
vrm.setGuild(player.getGuild());
vrm.setWarehouseBuilding(warehouseBuilding);
vrm.configure();
dispatch = Dispatch.borrow(player, vrm);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
//ViewResourcesMessage vrm = new ViewResourcesMessage(player);
//vrm.setGuild(player.getGuild());
//vrm.setWarehouseBuilding(warehouseBuilding);
//vrm.configure();
//Dispatch dispatch = Dispatch.borrow(player, vrm);
//DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
}
public static void warehouseWithdraw(MerchantMsg msg, PlayerCharacter player, NPC npc, ClientConnection origin) {
long nextAllowedAction = player.lastAction + 5000;
if(nextAllowedAction > System.currentTimeMillis()){
ChatManager.chatSystemInfo(player, "You Must Wait To Do This");
return;
}
player.lastAction = System.currentTimeMillis();
int withdrawAmount;
Building warehouseBuilding;
Warehouse warehouse;
@ -479,6 +459,59 @@ public class Warehouse extends AbstractWorldObject { @@ -479,6 +459,59 @@ public class Warehouse extends AbstractWorldObject {
return true;
}
private boolean removeFromInventory(CharacterItemManager itemMan, ItemBase ib, int amount, PlayerCharacter pc) {
if (ib.getUUID() == 7) {
if (!itemMan.modifyInventoryGold(-amount)) {
// ChatManager.chatSystemError(pc, "You do not have this Gold.");
return false;
}
UpdateGoldMsg ugm = new UpdateGoldMsg(pc);
ugm.configure();
Dispatch dispatch = Dispatch.borrow(pc, ugm);
DispatchMessage.dispatchMsgDispatch(dispatch, engine.Enum.DispatchChannel.SECONDARY);
} else {
Item resource = itemMan.getItemByUUID(ib.getUUID());
if (resource == null) return false;
itemMan.delete(resource);
}
return true;
}
private boolean updateDatabase(int itemID, int newAmount) {
switch (itemID) {
case 7: return DbManager.WarehouseQueries.updateGold(this, newAmount);
case 1580000: return DbManager.WarehouseQueries.updateStone(this, newAmount);
case 1580001: return DbManager.WarehouseQueries.updateTruesteel(this, newAmount);
case 1580002: return DbManager.WarehouseQueries.updateIron(this, newAmount);
case 1580003: return DbManager.WarehouseQueries.updateAdamant(this, newAmount);
case 1580004: return DbManager.WarehouseQueries.updateLumber(this, newAmount);
case 1580005: return DbManager.WarehouseQueries.updateOak(this, newAmount);
case 1580006: return DbManager.WarehouseQueries.updateBronzewood(this, newAmount);
case 1580007: return DbManager.WarehouseQueries.updateMandrake(this, newAmount);
case 1580008: return DbManager.WarehouseQueries.updateCoal(this, newAmount);
case 1580009: return DbManager.WarehouseQueries.updateAgate(this, newAmount);
case 1580010: return DbManager.WarehouseQueries.updateDiamond(this, newAmount);
case 1580011: return DbManager.WarehouseQueries.updateOnyx(this, newAmount);
case 1580012: return DbManager.WarehouseQueries.updateAzoth(this, newAmount);
case 1580013: return DbManager.WarehouseQueries.updateOrichalk(this, newAmount);
case 1580014: return DbManager.WarehouseQueries.updateAntimony(this, newAmount);
case 1580015: return DbManager.WarehouseQueries.updateSulfur(this, newAmount);
case 1580016: return DbManager.WarehouseQueries.updateQuicksilver(this, newAmount);
case 1580017: return DbManager.WarehouseQueries.updateGalvor(this, newAmount);
case 1580018: return DbManager.WarehouseQueries.updateWormwood(this, newAmount);
case 1580019: return DbManager.WarehouseQueries.updateObsidian(this, newAmount);
case 1580020: return DbManager.WarehouseQueries.updateBloodstone(this, newAmount);
case 1580021: return DbManager.WarehouseQueries.updateMithril(this, newAmount);
default: return false;
}
}
private Resource getResourceType(Item resource) {
return resource.getItemBase().getType().equals(engine.Enum.ItemType.GOLD)
? Resource.GOLD
: Resource.valueOf(resource.getItemBase().getName().toUpperCase());
}
//for mine deposit
public synchronized boolean depositFromMine(Mine mine, ItemBase resource, int amount) {

2
src/engine/server/MBServerStatics.java

@ -357,7 +357,7 @@ public class MBServerStatics { @@ -357,7 +357,7 @@ public class MBServerStatics {
public static final int COMBAT_SEND_DODGE = 20;
public static final int COMBAT_SEND_BLOCK = 21;
public static final int COMBAT_SEND_PARRY = 22;
public static final short LEVELCAP = 75;
public static final short LEVELCAP = 80;
public static final int LEVEL_CON_WHITE = 7;
public static final int RESPAWN_TIMER = 90 * 1000;
public static final int DESPAWN_TIMER = 12 * 1000;

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

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

35
src/engine/workthreads/DestroyCityThread.java

@ -19,6 +19,7 @@ package engine.workthreads; @@ -19,6 +19,7 @@ package engine.workthreads;
*/
import engine.Enum;
import engine.gameManager.BuildingManager;
import engine.gameManager.DbManager;
import engine.gameManager.GuildManager;
import engine.gameManager.ZoneManager;
@ -53,7 +54,6 @@ public class DestroyCityThread implements Runnable { @@ -53,7 +54,6 @@ public class DestroyCityThread implements Runnable {
// Member variable assignment
cityZone = city.getParent();
newParent = cityZone.getParent();
formerGuild = city.getTOL().getGuild();
// Former guild loses it's tree!
@ -99,36 +99,15 @@ public class DestroyCityThread implements Runnable { @@ -99,36 +99,15 @@ public class DestroyCityThread implements Runnable {
if (cityBuilding.getBlueprint().getBuildingGroup().equals(Enum.BuildingGroup.BANESTONE))
continue;
// All buildings are moved to a location relative
// to their new parent zone
localCoords = ZoneManager.worldToLocal(cityBuilding.getLoc(), newParent);
DbManager.BuildingQueries.MOVE_BUILDING(cityBuilding.getObjectUUID(), newParent.getObjectUUID(), localCoords.x, localCoords.y, localCoords.z);
// All buildings are re-parented to a zone one node
// higher in the tree (continent) as we will be
// deleting the city zone very shortly.
if (cityBuilding.getParentZoneID() != newParent.getParentZoneID())
cityBuilding.setParentZone(newParent);
// No longer a tree, no longer any protection contract!
cityBuilding.setProtectionState(Enum.ProtectionState.NONE);
// Destroy all remaining city assets
if ((cityBuilding.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.BARRACK)
|| (cityBuilding.getBlueprint().isWallPiece())
|| (cityBuilding.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.SHRINE)
|| (cityBuilding.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.TOL)
|| (cityBuilding.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.SPIRE)
|| (cityBuilding.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.WAREHOUSE)) {
//destroy all buildings if we are destroying the city itself
if (cityBuilding.getRank() != -1)
cityBuilding.setRank(-1);
if(BuildingManager.getBuildingFromCache(cityBuilding.getObjectUUID()) != null){
cityBuilding.removeFromCache();
DbManager.BuildingQueries.DELETE_FROM_DATABASE(cityBuilding);
}
}
if (city.getRealm() != null)

81
src/engine/workthreads/MineThread.java

@ -13,52 +13,19 @@ import engine.objects.Guild; @@ -13,52 +13,19 @@ import engine.objects.Guild;
import engine.objects.Mine;
import engine.objects.PlayerCharacter;
import org.pmw.tinylog.Logger;
import java.time.LocalDateTime;
public class MineThread implements Runnable {
public static LocalDateTime nextPulse;
public MineThread(){
}
@Override
public void run() {
LocalDateTime nextPulse = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0);
nextPulse = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0);
while (true) {
if(LocalDateTime.now().isAfter(nextPulse)) {
for (Mine mine : Mine.getMines()) {
if(nextPulse.getHour() == 2 && nextPulse.getMinute() == 0){
mine.wasClaimed = false;
mine.hasProduced = false;
}
Building mineTower = BuildingManager.getBuilding(mine.getBuildingID());
if (mineTower == null)
continue;
int minute = 0;
if (mine.firstThirty == false)
minute = 30;
LocalDateTime openTime = LocalDateTime.now().withHour(mine.liveTime).withMinute(minute).withSecond(0);
LocalDateTime closeTime = openTime.plusMinutes(29);
//current time is after start time and before close time, open mine window
if (LocalDateTime.now().isAfter(openTime.minusMinutes(1)) && !mine.wasClaimed && !mine.wasOpened) {
mineWindowOpen(mine);
continue;
}
if (mine.isActive) {
if (LocalDateTime.now().isAfter(closeTime) && mineTower.getRank() > 0)
mineWindowClose(mine); //mine was never knocked down, close window
if (LocalDateTime.now().isAfter(closeTime) && mineTower.getRank() < 1 && mine.lastClaimer != null)
mineWindowClose(mine); //mine was knocked down and was claimed, close window
}
}
nextPulse = nextPulse.plusMinutes(30);
processMineWindows();
}
}
}
@ -66,7 +33,6 @@ public class MineThread implements Runnable { @@ -66,7 +33,6 @@ public class MineThread implements Runnable {
public static void mineWindowOpen(Mine mine) {
mine.setActive(true);
ChatManager.chatSystemChannel(mine.getParentZone().getName() + "'s Mine is now Active!");
Logger.info(mine.getParentZone().getName() + "'s Mine is now Active!");
}
@ -137,4 +103,45 @@ public class MineThread implements Runnable { @@ -137,4 +103,45 @@ public class MineThread implements Runnable {
mine.wasClaimed = true;
return true;
}
public static void processMineWindows(){
for (Mine mine : Mine.getMines()) {
Building tower = BuildingManager.getBuildingFromCache(mine.getBuildingID());
//if the tower comes back null, skip this mine
if(tower == null)
continue;
//log the current time right now
LocalDateTime currentTime = LocalDateTime.now().plusMinutes(1);
//check if this mine needs to open
LocalDateTime openTime = LocalDateTime.now().withHour(mine.liveHour).withMinute(mine.liveMinute).withSecond(0).withNano(0);
if(currentTime.isAfter(openTime) && currentTime.isBefore(openTime.plusMinutes(30)) && !mine.wasOpened){
mineWindowOpen(mine); //hour and minute match, time to open the window
ChatManager.chatSystemChannel(mine.getParentZone().getName() + " " + mine.getMineType() + "MINE is now vulnerable to attack!");
continue;
}
//check to see if the window shoul dbe closing now
if(currentTime.isAfter(openTime.plusMinutes(29)) && mine.isActive) {
//check to see if the tower was destoryed
boolean towerDestroyed = tower.getRank() < 1;
if(towerDestroyed){
//check if a valid claimer exists to close the window and claim the mine since the tower was destroyed
if(mine.lastClaimer != null) {
mineWindowClose(mine);
ChatManager.chatSystemChannel("The fight for " + mine.getParentZone().getName() + " " + mine.getMineType() + " MINE has concluded. " + mine.lastClaimer.getName() + " has seized it in the name of " + mine.lastClaimer.getGuild().getNation());
}else{
ChatManager.chatSystemChannel("The " + mine.getParentZone().getName() + " " + mine.getMineType() + " MINE is still unclaimed. The battle continues.");
}
}else{
//tower was not destroyed, mine window closes
mineWindowClose(mine);
ChatManager.chatSystemChannel(tower.getGuild().getNation().getName() + " has successfully defended the " + mine.getParentZone().getName() + " " + mine.getMineType() + " MINE, and retains their claim.");
}
}
}
nextPulse = nextPulse.plusMinutes(30);
}
}

132
src/engine/workthreads/ZergMechanicThread.java

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

Loading…
Cancel
Save