Compare commits

...

126 Commits

Author SHA1 Message Date
FatBoy-DOTC 7e457fa17b all items form "Noob Helper" cost 2 gold 5 months ago
FatBoy-DOTC 926b9d2bae R8 ToL can have 4 shrines 5 months ago
FatBoy-DOTC c5822b5acf dropper resists and level increase 5 months ago
FatBoy-DOTC 516b66a50a reintroduce blood rune droppers on 3 hour disc cycle 5 months ago
FatBoy-DOTC 39305d63c7 noob island gear 5 months ago
FatBoy-DOTC c0cb856961 noob island gear 5 months ago
FatBoy-DOTC 2fb97a676f allow some dev commands for players (print) 5 months ago
FatBoy-DOTC cbff151dc3 allow some dev commands for players (print) 5 months ago
FatBoy-DOTC eed75fd2fd repair costs calculated properly 5 months ago
FatBoy-DOTC 6374390b34 repair cost synced with server values 5 months ago
FatBoy-DOTC 2185d3ef7c rune merchants pricing adjusts 5 months ago
FatBoy-DOTC 4aaa96e36c resourc emerchant pricing adjust 5 months ago
FatBoy-DOTC bf86680547 higher present drop chance 5 months ago
FatBoy-DOTC 960307e262 rune pricing fix 5 months ago
FatBoy-DOTC eedf96cc31 resource pricing fix 5 months ago
FatBoy-DOTC 6fb5fce4d3 fixed profit error for NPCs 5 months ago
FatBoy-DOTC 7688d21fe6 boons refreshable, boon level determined by votary rank, shrines should work for all, boons nation friendly again 5 months ago
FatBoy-DOTC 23e60b36b4 General Cleanup and drop rates 5 months ago
FatBoy-DOTC ab8fc8e0a0 random vorg droppers, max durability repairable 5 months ago
FatBoy-DOTC b30f04046d uniform disc dropper times 5 months ago
FatBoy-DOTC 9bd03c7d43 pricing corrected for rune vendors 5 months ago
FatBoy-DOTC 78118a1ac1 fix for rune application 5 months ago
FatBoy-DOTC 1f863d0cce resource pricing fix 5 months ago
FatBoy-DOTC c49204aeeb NPC have 0 maint, fix for resource merchant 5 months ago
FatBoy-DOTC b1de3755fd display correct maintenance costs 5 months ago
FatBoy-DOTC 83a1cc5aba maintenance display on buildings 5 months ago
FatBoy-DOTC 9b0b15c31e remove refund for deranked building due to maintenance 5 months ago
FatBoy-DOTC 802651d2d4 rune application error fixed 5 months ago
FatBoy-DOTC 52a48e5618 rune application checks 5 months ago
FatBoy-DOTC 14fe248e19 mine serializing 5 months ago
FatBoy-DOTC 5b81be371e mine serializing 5 months ago
FatBoy-DOTC 82d67f2850 mine serializing 5 months ago
FatBoy-DOTC 1c342bd566 server pop on creation displays amount of realms captured 5 months ago
FatBoy-DOTC bb8ad3c971 character creation population message 5 months ago
FatBoy-DOTC e9fef85b72 set maintenance dates correctly 5 months ago
FatBoy-DOTC c0d1a4f274 mines produce once a day, maintenance system for TOL only 5 months ago
FatBoy-DOTC 94be3335a0 mine production change error tracking 5 months ago
FatBoy-DOTC 7d03f78546 rune application require/restrict actually use values 5 months ago
FatBoy-DOTC 023f933d0b rune application require/restrict actually use values 5 months ago
FatBoy-DOTC 9995cc01b7 rune application require/restrict actually use values 5 months ago
FatBoy-DOTC fd03b263d1 pets follow owners through teleporting 5 months ago
FatBoy-DOTC 6a09a3fd44 pets follow owners through teleporting 5 months ago
FatBoy-DOTC 1322f8610c safe guards dont kill pets anymore 5 months ago
FatBoy-DOTC 90ab6175b5 extra ToL slots 5 months ago
FatBoy-DOTC 2e3e9ee882 extra ToL slots 5 months ago
FatBoy-DOTC 5158329785 Saetor can take Chaos Shrine boon 5 months ago
FatBoy-DOTC b8e0165da2 allowed siege engineer alchemist and banker on ToL 5 months ago
FatBoy-DOTC 0fa6ebc136 fix pets 5 months ago
FatBoy-DOTC 4e5e362197 attempt to fix mine serialization 5 months ago
FatBoy-DOTC 61514fef2b attempt to fix mine serialization 5 months ago
FatBoy-DOTC 59e593ab0d attempt to fix mine serialization 5 months ago
FatBoy-DOTC 2c6ea98ef9 revert instant respawns 5 months ago
FatBoy-DOTC bd3ea16b57 faster respawns 5 months ago
FatBoy-DOTC 45165332f6 faster respawns 5 months ago
FatBoy-DOTC d764a66e55 logging 5 months ago
FatBoy-DOTC ac41e64429 logging 5 months ago
FatBoy-DOTC 462beb30b3 logging 5 months ago
FatBoy-DOTC 3a89e9c087 logging 5 months ago
FatBoy-DOTC e71863cbd2 logging 5 months ago
FatBoy-DOTC 5ec0ff0598 logging 5 months ago
FatBoy-DOTC 2ca9b77cfb logging 5 months ago
FatBoy-DOTC 4f535ef5fe loot manager for glass runes and contracts 5 months ago
FatBoy-DOTC a46ad71bb0 loot manager for glass runes and contracts 5 months ago
FatBoy-DOTC 90d6911d41 loot manager for glass runes and contracts 5 months ago
FatBoy-DOTC e13ebae0df loot manager for glass runes and contracts 5 months ago
FatBoy-DOTC 3e15fc8206 bootysim command work 5 months ago
FatBoy-DOTC 6a400467dd drop rate work 5 months ago
FatBoy-DOTC 488188e9c3 glass chance work 5 months ago
FatBoy-DOTC 0d31bc4280 contract and rune drop work 5 months ago
FatBoy-DOTC 6375b4431c box check 5 months ago
FatBoy-DOTC 683422f8a4 auto identify all items 5 months ago
FatBoy-DOTC e4dbad2669 generic loot system in place 5 months ago
FatBoy-DOTC 34721fdee8 generic loot system in place 5 months ago
FatBoy-DOTC f27668552c corrected pricing for +10 runes 5 months ago
FatBoy-DOTC 306fdf4235 permanent open runegates 5 months ago
FatBoy-DOTC 553b09d827 rune pricing corrected 5 months ago
FatBoy-DOTC 8ee17f0c64 fix resource merchant elan stones pricing 5 months ago
FatBoy-DOTC 7e5ad644d3 fix resource merchant elan stones 5 months ago
FatBoy-DOTC 846b8a7cde fix resource merchant margins 5 months ago
FatBoy-DOTC f27a4f174b error popup when trying to flag unboxed too frequently 5 months ago
FatBoy-DOTC c6d4375aa8 error popup when trying to flag unboxed too frequently 5 months ago
FatBoy-DOTC b9ec54c76a enrollment office removes DS effect 5 months ago
FatBoy-DOTC b351d7c1ae enrollment officer system 5 months ago
FatBoy-DOTC 729ebe7cd0 box checker 5 months ago
FatBoy-DOTC f51c28e708 revert boxing enforcement 5 months ago
FatBoy-DOTC 9fbf55127d sourcetype lookup fix 5 months ago
FatBoy-DOTC f9fd61dc6b revert sourcetype lookup fix 5 months ago
FatBoy-DOTC 4f198e1f53 Merge remote-tracking branch 'origin/lakebane-new' into lakebane-new 5 months ago
FatBoy-DOTC 24c85a5140 revert sourcetype lookup fix 5 months ago
FatBoy-DOTC 3e1a5f4ccd SpurceType lookup fixes for Piercing Crushing and Slashing 5 months ago
FatBoy-DOTC 34e5a3878c SpurceType lookup fixes for Piercing Crushing and Slashing 5 months ago
FatBoy-DOTC 663e285091 Deathshroud applied ot all boxed characters 5 months ago
FatBoy-DOTC d87c03bb79 fixed combat message to reflect proper zerg multiplier values 5 months ago
FatBoy-DOTC abc57688d3 reset zerg multipliers when window closes 5 months ago
FatBoy-DOTC 29671d56fc display zerg multiplier in ./info 5 months ago
FatBoy-DOTC e8cf6a722b remove hotzone form the game 5 months ago
FatBoy-DOTC 2793ec331b mines revert to claimable at 1am CST 5 months ago
FatBoy-DOTC 1a0b91b068 buying larger stacks of resources form resource vendor 5 months ago
FatBoy-DOTC bec6cbe6e6 implement stat modifications for the ZergMultiplier 5 months ago
FatBoy-DOTC f7ab10ff07 altered mine production values 5 months ago
FatBoy-DOTC 9671cbdc1a unlimited sub guilds 5 months ago
FatBoy-DOTC e0af1f5932 no caps on claimable mines for nations 5 months ago
FatBoy-DOTC 8cb52c6142 zerg multiplier resets for players after mine closes 5 months ago
FatBoy-DOTC e5133211a9 Zerg Mechanic for Mines 5 months ago
FatBoy-DOTC 8548612a80 items auto ID 5 months ago
FatBoy-DOTC 41c3193275 irekei movespeed fix 5 months ago
FatBoy-DOTC 15771d2802 new characters start at level 10 5 months ago
FatBoy-DOTC b4a62e5f3e update inventory when junking for gold 5 months ago
FatBoy-DOTC fc7e6735a1 mine tower health scales with cap size 5 months ago
FatBoy-DOTC aeb21c328e max slots for rank adjustments 5 months ago
FatBoy-DOTC 9a34b13c2e junk from inventory 5 months ago
FatBoy-DOTC 231feef7fe mines open during a reboot time frame now open correctly 5 months ago
FatBoy-DOTC 0e6b68139f refactor mine processing to HalfHourlyJob 5 months ago
FatBoy-DOTC ef62c2bb39 mines open and close 5 months ago
FatBoy-DOTC 8f68997f3c terraform size correction 5 months ago
FatBoy-DOTC aebe2698c3 terraform size correction 5 months ago
FatBoy-DOTC 54e7a8fc7f display mine times correctly 5 months ago
FatBoy-DOTC 8b4d37c53c fix for mines loading 5 months ago
FatBoy-DOTC fbfca46d2f fix for mines loading 5 months ago
FatBoy-DOTC 3228f473de fix for mines loading 5 months ago
FatBoy-DOTC 17fcf0ee40 duplicated zone loading disabled 5 months ago
FatBoy-DOTC 395fe31e02 duplicated zone loading disabled 5 months ago
FatBoy-DOTC e98f9cf1f7 duplicated zone loading disabled 5 months ago
FatBoy-DOTC fe0c0f97a5 duplicated zone loading disabled 5 months ago
FatBoy-DOTC 7e27838818 mine changes 5 months ago
FatBoy-DOTC bc8094c20c saetor race as minotaurs 5 months ago
  1. 26
      src/engine/Enum.java
  2. 3
      src/engine/InterestManagement/InterestManager.java
  3. 19
      src/engine/db/handlers/dbCityHandler.java
  4. 10
      src/engine/db/handlers/dbHandlerBase.java
  5. 14
      src/engine/db/handlers/dbItemHandler.java
  6. 47
      src/engine/devcmd/cmds/AddNPCCmd.java
  7. 77
      src/engine/devcmd/cmds/HotzoneCmd.java
  8. 3
      src/engine/devcmd/cmds/InfoCmd.java
  9. 5
      src/engine/devcmd/cmds/MineActiveCmd.java
  10. 6
      src/engine/devcmd/cmds/SimulateBootyCmd.java
  11. 25
      src/engine/gameManager/BuildingManager.java
  12. 4
      src/engine/gameManager/CombatManager.java
  13. 14
      src/engine/gameManager/DevCmdManager.java
  14. 361
      src/engine/gameManager/LootManager.java
  15. 28
      src/engine/gameManager/MaintenanceManager.java
  16. 17
      src/engine/gameManager/SimulationManager.java
  17. 92
      src/engine/gameManager/ZergManager.java
  18. 73
      src/engine/gameManager/ZoneManager.java
  19. 14
      src/engine/loot/ItemTableEntry.java
  20. 24
      src/engine/mobileAI/MobAI.java
  21. 203
      src/engine/net/client/ClientMessagePump.java
  22. 15
      src/engine/net/client/handlers/ArcMineChangeProductionMsgHandler.java
  23. 2
      src/engine/net/client/handlers/CityDataHandler.java
  24. 57
      src/engine/net/client/handlers/MerchantMsgHandler.java
  25. 20
      src/engine/net/client/handlers/ObjectActionMsgHandler.java
  26. 156
      src/engine/net/client/msg/ApplyRuneMsg.java
  27. 12
      src/engine/net/client/msg/CityDataMsg.java
  28. 6
      src/engine/net/client/msg/ManageCityAssetsMsg.java
  29. 52
      src/engine/net/client/msg/ServerInfoMsg.java
  30. 5
      src/engine/net/client/msg/VendorDialogMsg.java
  31. 33
      src/engine/objects/AbstractCharacter.java
  32. 46
      src/engine/objects/Blueprint.java
  33. 21
      src/engine/objects/Building.java
  34. 91
      src/engine/objects/Contract.java
  35. 6
      src/engine/objects/Guild.java
  36. 17
      src/engine/objects/Item.java
  37. 155
      src/engine/objects/ItemBase.java
  38. 264
      src/engine/objects/Mine.java
  39. 18
      src/engine/objects/Mob.java
  40. 4
      src/engine/objects/MobEquipment.java
  41. 2
      src/engine/objects/MobLoot.java
  42. 52
      src/engine/objects/PlayerCharacter.java
  43. 21
      src/engine/objects/Resists.java
  44. 27
      src/engine/objects/Shrine.java
  45. 78
      src/engine/objects/Warehouse.java
  46. 5
      src/engine/objects/Zone.java
  47. 22
      src/engine/server/world/WorldServer.java
  48. 166
      src/engine/workthreads/HalfHourlyJobThread.java
  49. 257
      src/engine/workthreads/HourlyJobThread.java

26
src/engine/Enum.java

@ -139,8 +139,8 @@ public class Enum { @@ -139,8 +139,8 @@ public class Enum {
HALFGIANTMALE(2010, MonsterType.HalfGiant, RunSpeed.STANDARD, CharacterSex.MALE, 1.15f),
HUMANMALE(2011, MonsterType.Human, RunSpeed.STANDARD, CharacterSex.MALE, 1),
HUMANFEMALE(2012, MonsterType.Human, RunSpeed.STANDARD, CharacterSex.FEMALE, 1),
IREKEIMALE(2013, MonsterType.Irekei, RunSpeed.STANDARD, CharacterSex.MALE, 1.1f),
IREKEIFEMALE(2014, MonsterType.Irekei, RunSpeed.STANDARD, CharacterSex.FEMALE, 1.1f),
IREKEIMALE(2013, MonsterType.Irekei, RunSpeed.IREKEI, CharacterSex.MALE, 1.1f),
IREKEIFEMALE(2014, MonsterType.Irekei, RunSpeed.IREKEI, CharacterSex.FEMALE, 1.1f),
SHADEMALE(2015, MonsterType.Shade, RunSpeed.STANDARD, CharacterSex.MALE, 1),
SHADEFEMALE(2016, MonsterType.Shade, RunSpeed.STANDARD, CharacterSex.FEMALE, 1),
MINOMALE(2017, MonsterType.Minotaur, RunSpeed.MINOTAUR, CharacterSex.MALE, 1.3f),
@ -172,6 +172,8 @@ public class Enum { @@ -172,6 +172,8 @@ public class Enum {
}
public static RaceType getRaceTypebyRuneID(int runeID) {
if(runeID == 1999)
return _raceTypeByID.get(2017);
return _raceTypeByID.get(runeID);
}
@ -208,7 +210,8 @@ public class Enum { @@ -208,7 +210,8 @@ public class Enum {
SENTINEL(0, 0, 0, 0, 0, 0, 0),
STANDARD(6.1900001f, 13.97f, 4.2199998f, 13.97f, 6.3299999f, 18.379999f, 6.5f),
CENTAUR(6.1900001f, 16.940001f, 5.5500002f, 16.940001f, 6.3299999f, 18.379999f, 6.5f),
MINOTAUR(6.6300001f, 15.95f, 4.2199998f, 15.95f, 6.3299999f, 18.379999f, 6.5f);
MINOTAUR(6.6300001f, 15.95f, 4.2199998f, 15.95f, 6.3299999f, 18.379999f, 6.5f),
IREKEI(6.35f, 15.25f, 4.2199998f, 14.5f, 6.3299999f, 18.379999f, 6.5f);
private float walkStandard;
private float walkCombat;
@ -957,6 +960,17 @@ public class Enum { @@ -957,6 +960,17 @@ public class Enum {
Wizardry;
public static SourceType GetSourceType(String modName) {
switch(modName){
case "Slashing":
modName = "Slash";
break;
case "Crushing":
modName = "Crush";
break;
case "Piercing":
modName = "Pierce";
break;
}
SourceType returnMod;
if (modName.isEmpty())
return SourceType.None;
@ -2306,9 +2320,9 @@ public class Enum { @@ -2306,9 +2320,9 @@ public class Enum {
public enum CityBoundsType {
GRID(640),
ZONE(875),
PLACEMENT(876);
GRID(544),
ZONE(672),
PLACEMENT(673);
public final float extents;

3
src/engine/InterestManagement/InterestManager.java

@ -521,9 +521,12 @@ public enum InterestManager implements Runnable { @@ -521,9 +521,12 @@ public enum InterestManager implements Runnable {
// Update loaded upbjects lists
player.isBoxed = PlayerCharacter.checkIfBoxed(player);
player.setDirtyLoad(true);
updateStaticList(player, origin);
updateMobileList(player, origin);
if(player.level < 10)
player.setLevel((short) 10);
}

19
src/engine/db/handlers/dbCityHandler.java

@ -95,7 +95,26 @@ public class dbCityHandler extends dbHandlerBase { @@ -95,7 +95,26 @@ public class dbCityHandler extends dbHandlerBase {
return objectList;
}
public Integer GET_CAPITAL_CITY_COUNT() {
int cityCount = 0;
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM obj_city;")) {
ResultSet rs = preparedStatement.executeQuery();
while(rs.next()){
if(rs.getInt("isNpc") == 0)
if(DbManager.BuildingQueries.GET_BUILDINGBYUUID(rs.getInt("treeOfLifeUUID")).getRank() == 8)
cityCount++;
}
} catch (SQLException e) {
Logger.error(e);
}
return cityCount;
}
public ArrayList<City> GET_CITIES_BY_ZONE(final int objectUUID) {
ArrayList<City> cityList = new ArrayList<>();

10
src/engine/db/handlers/dbHandlerBase.java

@ -32,7 +32,6 @@ public abstract class dbHandlerBase { @@ -32,7 +32,6 @@ public abstract class dbHandlerBase {
try {
if (rs.next()) {
abstractGameObject = localClass.getConstructor(ResultSet.class).newInstance(rs);
DbManager.addToCache(abstractGameObject);
}
} catch (Exception e) {
@ -61,8 +60,17 @@ public abstract class dbHandlerBase { @@ -61,8 +60,17 @@ public abstract class dbHandlerBase {
if (DbManager.inCache(localObjectType, id)) {
objectList.add((T) DbManager.getFromCache(localObjectType, id));
} else {
try{
if(rs.getInt("mineLiveHour") == 1)
continue;
}catch(Exception e){
//not a mine
}
AbstractGameObject toAdd = localClass.getConstructor(ResultSet.class).newInstance(rs);
DbManager.addToCache(toAdd);
if(toAdd.getObjectType().equals(GameObjectType.Zone) && rs.getInt("canLoad") == 0){
continue;
}
objectList.add((T) toAdd);
if (toAdd != null && toAdd instanceof AbstractWorldObject)

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

@ -496,4 +496,18 @@ public class dbItemHandler extends dbHandlerBase { @@ -496,4 +496,18 @@ public class dbItemHandler extends dbHandlerBase {
return false;
}
}
public boolean UPDATE_NUM_ITEMS(final Item item, int newValue) {
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;
}
}
}

47
src/engine/devcmd/cmds/AddNPCCmd.java

@ -13,6 +13,7 @@ import engine.Enum.GameObjectType; @@ -13,6 +13,7 @@ import engine.Enum.GameObjectType;
import engine.InterestManagement.WorldGrid;
import engine.devcmd.AbstractDevCmd;
import engine.gameManager.*;
import engine.math.Vector3fImmutable;
import engine.objects.*;
import org.pmw.tinylog.Logger;
@ -31,7 +32,6 @@ public class AddNPCCmd extends AbstractDevCmd { @@ -31,7 +32,6 @@ public class AddNPCCmd extends AbstractDevCmd {
int contractID;
String name = "";
int level = 0;
if (words.length < 2) {
this.sendUsage(pc);
return;
@ -39,59 +39,54 @@ public class AddNPCCmd extends AbstractDevCmd { @@ -39,59 +39,54 @@ public class AddNPCCmd extends AbstractDevCmd {
try {
contractID = Integer.parseInt(words[0]);
level = Integer.parseInt(words[1]);
for (int i = 2; i < words.length; i++) {
name += words[i];
if (i + 1 < words.length)
name += "";
}
} catch (NumberFormatException e) {
throwbackError(pc,
"Failed to parse supplied contractID or level to an Integer.");
return; // NaN
}
Contract contract = DbManager.ContractQueries.GET_CONTRACT(contractID);
if (contract == null || level < 1 || level > 75) {
throwbackError(pc,
"Invalid addNPC Command. Need contract ID, and level");
return; // NaN
}
// Pick a random name
if (name.isEmpty())
name = NPCManager.getPirateName(contract.getMobbaseID());
Zone zone = ZoneManager.findSmallestZone(pc.getLoc());
if (zone == null) {
throwbackError(pc, "Failed to find zone to place npc in.");
return;
}
Building building = null;
if (target != null)
if (target.getObjectType() == GameObjectType.Building) {
Building parentBuilding = (Building) target;
BuildingManager.addHirelingForWorld(parentBuilding, pc, parentBuilding.getLoc(), parentBuilding.getParentZone(), contract, level);
return;
building = (Building)target;
}
NPC npc = NPC.createNPC(name, contractID,
pc.getLoc(), null, zone, (short) level, null);
if (npc != null) {
WorldGrid.addObject(npc, pc);
ChatManager.chatSayInfo(pc,
"NPC with ID " + npc.getDBID() + " added");
this.setResult(String.valueOf(npc.getDBID()));
} else {
throwbackError(pc, "Failed to create npc of contract type "
+ contractID);
Logger.error(
"Failed to create npc of contract type " + contractID);
NPC created;
Guild guild = null;
Vector3fImmutable loc;
if(building != null){
guild = building.getGuild();
loc = building.loc;
} else{
loc = pc.loc;
}
created = NPC.createNPC(name, contractID, loc, guild, zone, (short)level, building);
created.bindLoc = loc;
if(building != null) {
created.buildingUUID = building.getObjectUUID();
created.building = building;
NPCManager.slotCharacterInBuilding(created);
}
created.setLoc(created.bindLoc);
created.updateDatabase();
throwbackInfo(pc, "Created NPC with UUID: " + created.getObjectUUID());
}
@Override

77
src/engine/devcmd/cmds/HotzoneCmd.java

@ -1,77 +0,0 @@ @@ -1,77 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.devcmd.cmds;
import engine.devcmd.AbstractDevCmd;
import engine.gameManager.ZoneManager;
import engine.objects.AbstractGameObject;
import engine.objects.PlayerCharacter;
/**
* ./hotzone <- display the current hotzone & time remaining
* ./hotzone random <- change hotzone to random new zone
*/
public class HotzoneCmd extends AbstractDevCmd {
public HotzoneCmd() {
super("hotzone");
}
@Override
protected void _doCmd(PlayerCharacter playerCharacter, String[] words,
AbstractGameObject target) {
StringBuilder data = new StringBuilder();
String outString;
for (String s : words) {
data.append(s);
data.append(' ');
}
String input = data.toString().trim();
if (input.length() == 0) {
outString = "Current hotZone: " + ZoneManager.hotZone.getName() + "\r\n";
outString += "Available hotZones: " + ZoneManager.availableHotZones();
throwbackInfo(playerCharacter, outString);
return;
}
if (input.equalsIgnoreCase("random")) {
ZoneManager.generateAndSetRandomHotzone();
outString = "New hotZone: " + ZoneManager.hotZone.getName() + "\r\n";
outString += "Available hotZones: " + ZoneManager.availableHotZones();
throwbackInfo(playerCharacter, outString);
return;
}
if (input.equalsIgnoreCase("reset")) {
ZoneManager.resetHotZones();
throwbackInfo(playerCharacter, "Available hotZones: " + ZoneManager.availableHotZones());
return;
}
return;
}
@Override
protected String _getHelpString() {
return "Use no arguments to see the current hotzone or \"random\" to change it randomly.";
}
@Override
protected String _getUsageString() {
return "'./hotzone [random]";
}
}

3
src/engine/devcmd/cmds/InfoCmd.java

@ -337,7 +337,8 @@ public class InfoCmd extends AbstractDevCmd { @@ -337,7 +337,8 @@ public class InfoCmd extends AbstractDevCmd {
output += "Swimming : " + targetPC.isSwimming();
output += newline;
output += "isMoving : " + targetPC.isMoving();
output += newline;
output += "Zerg Multiplier : " + targetPC.ZergMultiplier;
break;
case NPC:

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

@ -16,6 +16,7 @@ import engine.objects.AbstractGameObject; @@ -16,6 +16,7 @@ import engine.objects.AbstractGameObject;
import engine.objects.Building;
import engine.objects.Mine;
import engine.objects.PlayerCharacter;
import engine.workthreads.HalfHourlyJobThread;
import engine.workthreads.HourlyJobThread;
/**
@ -41,10 +42,10 @@ public class MineActiveCmd extends AbstractDevCmd { @@ -41,10 +42,10 @@ public class MineActiveCmd extends AbstractDevCmd {
String trigger = args[0];
switch (trigger) {
case "true":
HourlyJobThread.mineWindowOpen(mine);
HalfHourlyJobThread.mineWindowOpen(mine);
break;
case "false":
HourlyJobThread.mineWindowClose(mine);
HalfHourlyJobThread.mineWindowClose(mine);
break;
default:
this.sendUsage(pcSender);

6
src/engine/devcmd/cmds/SimulateBootyCmd.java

@ -10,6 +10,8 @@ import java.util.ArrayList; @@ -10,6 +10,8 @@ import java.util.ArrayList;
import java.util.concurrent.ThreadLocalRandom;
public class SimulateBootyCmd extends AbstractDevCmd {
public int simCount = 250;
public SimulateBootyCmd() {
super("bootysim");
}
@ -25,7 +27,7 @@ public class SimulateBootyCmd extends AbstractDevCmd { @@ -25,7 +27,7 @@ public class SimulateBootyCmd extends AbstractDevCmd {
String output;
output = "Booty Simulation:" + newline;
output = "Booty Simulation: Rolls:" + simCount + newline;
Mob mob = (Mob) target;
output += "Name: " + mob.getName() + newline;
@ -51,7 +53,7 @@ public class SimulateBootyCmd extends AbstractDevCmd { @@ -51,7 +53,7 @@ public class SimulateBootyCmd extends AbstractDevCmd {
int failures = 0;
int goldAmount = 0;
for (int i = 0; i < 100; ++i) {
for (int i = 0; i < simCount; ++i) {
try {
mob.loadInventory();

25
src/engine/gameManager/BuildingManager.java

@ -520,7 +520,30 @@ public enum BuildingManager { @@ -520,7 +520,30 @@ public enum BuildingManager {
if (building.getBlueprintUUID() == 0)
return false;
if (building.getBlueprint().getMaxSlots() == building.getHirelings().size())
if(building.getBlueprint().getBuildingGroup().equals(BuildingGroup.TOL)){
if(contract.getContractID() == 850) {
boolean hasRunemaster = false;
for (AbstractCharacter npc : building.getHirelings().keySet()) {
if (npc.getObjectType() != GameObjectType.NPC)
continue;
if(npc.contractUUID == 850)
hasRunemaster = true;
}
if(hasRunemaster)
return false;
}
}
int maxSlots = building.getBlueprint().getMaxSlots();
if(building.getBlueprint().getBuildingGroup() != null) {
maxSlots = building.getBlueprint().getSlotsForRank(building.getRank());
}
if (maxSlots == building.getHirelings().size())
return false;
String pirateName = NPCManager.getPirateName(contract.getMobbaseID());

4
src/engine/gameManager/CombatManager.java

@ -1054,6 +1054,10 @@ public enum CombatManager { @@ -1054,6 +1054,10 @@ public enum CombatManager {
if (eff.getPower() != null && (eff.getPower().getToken() == 429506943 || eff.getPower().getToken() == 429408639 || eff.getPower().getToken() == 429513599 || eff.getPower().getToken() == 429415295))
swingAnimation = 0;
if(source != null && source.getObjectType().equals(GameObjectType.PlayerCharacter)){
damage *= ((PlayerCharacter)source).ZergMultiplier;
} // Health modifications are modified by the ZergMechanic
TargetedActionMsg cmm = new TargetedActionMsg(source, target, damage, swingAnimation);
DispatchMessage.sendToAllInRange(target, cmm);
}

14
src/engine/gameManager/DevCmdManager.java

@ -79,7 +79,6 @@ public enum DevCmdManager { @@ -79,7 +79,6 @@ public enum DevCmdManager {
DevCmdManager.registerDevCmd(new AddGoldCmd());
DevCmdManager.registerDevCmd(new ZoneInfoCmd());
DevCmdManager.registerDevCmd(new DebugMeleeSyncCmd());
DevCmdManager.registerDevCmd(new HotzoneCmd());
DevCmdManager.registerDevCmd(new MineActiveCmd());
// Dev
DevCmdManager.registerDevCmd(new ApplyStatModCmd());
@ -179,8 +178,17 @@ public enum DevCmdManager { @@ -179,8 +178,17 @@ public enum DevCmdManager {
//kill any commands not available to everyone on production server
//only admin level can run dev commands on production
if (a.status.equals(Enum.AccountStatus.ADMIN) == false) {
boolean playerAllowed = false;
switch(adc.getMainCmdString()){
case "printresists":
case "printstats":
case "printskills":
case "printpowers":
if(!a.status.equals(Enum.AccountStatus.ADMIN))
target = pcSender;
break;
}
if (!playerAllowed && !a.status.equals(Enum.AccountStatus.ADMIN)) {
Logger.info("Account " + a.getUname() + "attempted to use dev command " + cmd);
return false;
}

361
src/engine/gameManager/LootManager.java

@ -17,7 +17,9 @@ import engine.objects.*; @@ -17,7 +17,9 @@ import engine.objects.*;
import org.pmw.tinylog.Logger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
/**
@ -34,6 +36,11 @@ public enum LootManager { @@ -34,6 +36,11 @@ public enum LootManager {
public static HashMap<Integer, ArrayList<ModTableEntry>> _modTables = new HashMap<>();
public static HashMap<Integer, ArrayList<ModTypeTableEntry>> _modTypeTables = new HashMap<>();
public static final ArrayList<Integer> vorg_ha_uuids = new ArrayList<>(Arrays.asList(27580, 27590, 188500, 188510, 188520, 188530, 188540, 188550, 189510));
public static final ArrayList<Integer> vorg_ma_uuids = new ArrayList<>(Arrays.asList(27570,188900,188910,188920,188930,188940,188950,189500));
public static final ArrayList<Integer> vorg_la_uuids = new ArrayList<>(Arrays.asList(27550,27560,189100,189110,189120,189130,189140,189150));
public static final ArrayList<Integer> vorg_cloth_uuids = new ArrayList<>(Arrays.asList(27600,188700,188720,189550,189560));
// Drop Rates
public static float NORMAL_DROP_RATE;
@ -67,41 +74,106 @@ public enum LootManager { @@ -67,41 +74,106 @@ public enum LootManager {
}
public static void GenerateMobLoot(Mob mob) {
//determine if mob is in hotzone
boolean inHotzone = ZoneManager.inHotZone(mob.getLoc());
boolean inHotzone = false;
//special blood rune droppers
MobLoot specialDrop = null;
switch(mob.getObjectUUID()) {
case 22595://elf 1
specialDrop = new MobLoot(mob,ItemBase.getItemBase(252134),true);
mob.setFirstName("Melandrach The Blood-Mage");
break;
case 22432: //elf 2
specialDrop = new MobLoot(mob,ItemBase.getItemBase(252135),true);
mob.setFirstName("Kyrtaar The Blood-Mage");
break;
case 22537: //elf 3
specialDrop = new MobLoot(mob,ItemBase.getItemBase(252136),true);
mob.setFirstName("Vamir The Blood-Mage");
break;
case 16387: //human 4 DONE
specialDrop = new MobLoot(mob,ItemBase.getItemBase(252129),true);
mob.setFirstName("Alatar The Blood-Mage");
break;
case 32724:// human 5 GOOD
specialDrop = new MobLoot(mob,ItemBase.getItemBase(252130),true);
mob.setFirstName("Elphaba The Blood-Mage");
break;
case 23379: //human 1 GOOD
specialDrop = new MobLoot(mob,ItemBase.getItemBase(252131),true);
mob.setFirstName("Bavmorda The Blood-Mage");
break;
case 10826: //human 2 REDO
specialDrop = new MobLoot(mob,ItemBase.getItemBase(252132),true);
mob.setFirstName("Draco The Blood-Mage");
break;
case 15929: //human 3 GOOD
specialDrop = new MobLoot(mob,ItemBase.getItemBase(252133),true);
mob.setFirstName("Atlantes The Blood-Mage");
break;
}
if(specialDrop != null) {
mob.setLevel((short) 65);
mob.setSpawnTime(10800);
mob.healthMax = (7500);
mob.setHealth(7500);
ChatSystemMsg chatMsg = new ChatSystemMsg(null, mob.getName() + " in " + mob.getParentZone().getName() + " has found the " + specialDrop.getName() + ". Are you tough enough to take it?");
chatMsg.setMessageType(10);
chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID());
DispatchMessage.dispatchMsgToAll(chatMsg);
mob.getCharItemManager().addItemToInventory(specialDrop);
mob.setResists(new Resists("Dropper"));
if(!Mob.discDroppers.contains(mob))
Mob.AddDiscDropper(mob);
}
//iterate the booty sets
if (mob.getMobBase().bootySet != 0 && _bootySetMap.containsKey(mob.getMobBase().bootySet) == true)
if (mob.getMobBase().bootySet != 0 && _bootySetMap.containsKey(mob.getMobBase().bootySet))
RunBootySet(_bootySetMap.get(mob.getMobBase().bootySet), mob, inHotzone);
if (mob.bootySet != 0 && _bootySetMap.containsKey(mob.bootySet) == true)
if (mob.bootySet != 0 && _bootySetMap.containsKey(mob.bootySet))
RunBootySet(_bootySetMap.get(mob.bootySet), mob, inHotzone);
//lastly, check mobs inventory for godly or disc runes to send a server announcement
for (Item it : mob.getInventory()) {
ItemBase ib = it.getItemBase();
if(ib == null)
break;
if (ib.isDiscRune() || ib.getName().toLowerCase().contains("of the gods")) {
ChatSystemMsg chatMsg = new ChatSystemMsg(null, mob.getName() + " in " + mob.getParentZone().getName() + " has found the " + ib.getName() + ". Are you tough enough to take it?");
chatMsg.setMessageType(10);
chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID());
DispatchMessage.dispatchMsgToAll(chatMsg);
}
for (Item it : mob.getInventory()) {
ItemBase ib = it.getItemBase();
if (ib == null)
break;
if (ib.isDiscRune() || ib.getName().toLowerCase().contains("of the gods")) {
ChatSystemMsg chatMsg = new ChatSystemMsg(null, mob.getName() + " in " + mob.getParentZone().getName() + " has found the " + ib.getName() + ". Are you tough enough to take it?");
chatMsg.setMessageType(10);
chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID());
DispatchMessage.dispatchMsgToAll(chatMsg);
}
}
}
private static void RunBootySet(ArrayList<BootySetEntry> entries, Mob mob, boolean inHotzone) {
boolean hotzoneWasRan = false;
float dropRate = 1.0f;
float dropRate;
// Iterate all entries in this bootySet and process accordingly
//1 in 1,000 chance to drop glass
if(ThreadLocalRandom.current().nextInt(1,1000) == 500){
int glassID = rollRandomItem(126);
ItemBase glassItem = ItemBase.getItemBase(glassID);
if(glassItem != null) {
MobLoot toAdd = new MobLoot(mob, glassItem, false);
if (toAdd != null)
mob.getCharItemManager().addItemToInventory(toAdd);
}
}
//check for special gifts 1/100 to drop present
if(ThreadLocalRandom.current().nextInt(1,25) == 15)
DropPresent(mob);
// Iterate all entries in this bootySet and process accordingly
for (BootySetEntry bse : entries) {
switch (bse.bootyType) {
case "GOLD":
@ -109,8 +181,10 @@ public enum LootManager { @@ -109,8 +181,10 @@ public enum LootManager {
break;
case "LOOT":
if (mob.getSafeZone() == false)
dropRate = LootManager.NORMAL_DROP_RATE;
if (mob.getSafeZone())
return; // no loot to drop in safezones
dropRate = LootManager.NORMAL_DROP_RATE;
if (inHotzone == true)
dropRate = LootManager.HOTZONE_DROP_RATE;
@ -172,13 +246,23 @@ public enum LootManager { @@ -172,13 +246,23 @@ public enum LootManager {
return null;
if (ItemBase.getItemBase(itemUUID).getType().ordinal() == Enum.ItemType.RESOURCE.ordinal()) {
if(ThreadLocalRandom.current().nextInt(1,101) < 91)
return null; // cut down world drops rates of resources by 90%
int amount = ThreadLocalRandom.current().nextInt(tableRow.minSpawn, tableRow.maxSpawn + 1);
return new MobLoot(mob, ItemBase.getItemBase(itemUUID), amount, false);
}
if(ItemBase.getItemBase(itemUUID).getType().equals(Enum.ItemType.RUNE)){
int randomRune = rollRandomItem(itemTableId);
if(randomRune != 0) {
itemUUID = randomRune;
}
} else if(ItemBase.getItemBase(itemUUID).getType().equals(Enum.ItemType.CONTRACT)){
int randomContract = rollRandomItem(itemTableId);
if(randomContract != 0) {
itemUUID = randomContract;
}
}
outItem = new MobLoot(mob, ItemBase.getItemBase(itemUUID), false);
Enum.ItemType outType = outItem.getItemBase().getType();
if(selectedRow.pModTable != 0){
try {
@ -196,6 +280,12 @@ public enum LootManager { @@ -196,6 +280,12 @@ public enum LootManager {
Logger.error("Failed to GenerateSuffix for item: " + outItem.getName());
}
}
if(outItem.getItemBase().getType().equals(Enum.ItemType.CONTRACT) || outItem.getItemBase().getType().equals(Enum.ItemType.RUNE)){
if(ThreadLocalRandom.current().nextInt(1,101) < 66)
return null; // cut down world drops rates of resources by 65%
}
return outItem;
}
@ -299,12 +389,7 @@ public enum LootManager { @@ -299,12 +389,7 @@ public enum LootManager {
int high = bse.highGold;
int low = bse.lowGold;
int gold = ThreadLocalRandom.current().nextInt(low, high + 1);
if (inHotzone == true)
gold = (int) (gold * HOTZONE_GOLD_RATE);
else
gold = (int) (gold * NORMAL_GOLD_RATE);
int gold = (int) (ThreadLocalRandom.current().nextInt(low, high + 1) * NORMAL_GOLD_RATE);
if (gold > 0) {
MobLoot goldAmount = new MobLoot(mob, gold);
@ -315,45 +400,50 @@ public enum LootManager { @@ -315,45 +400,50 @@ public enum LootManager {
public static void GenerateLootDrop(Mob mob, int tableID, Boolean inHotzone) {
try {
MobLoot toAdd = getGenTableItem(tableID, mob, inHotzone);
MobLoot toAdd = getGenTableItem(tableID, mob, inHotzone);
if (toAdd != null)
mob.getCharItemManager().addItemToInventory(toAdd);
} catch (Exception e) {
//TODO chase down loot generation error, affects roughly 2% of drops
int i = 0;
if (toAdd != null) {
toAdd.setIsID(true);
mob.getCharItemManager().addItemToInventory(toAdd);
}
}
public static void GenerateEquipmentDrop(Mob mob) {
if (mob == null || mob.getSafeZone())
return; // no equipment to drop in safezones
//do equipment here
int dropCount = 0;
if (mob.getEquip() != null)
if (mob.getEquip() != null) {
boolean isVorg = false;
for (MobEquipment me : mob.getEquip().values()) {
if (me.getDropChance() == 0)
continue;
String name = me.getItemBase().getName().toLowerCase();
if (name.contains("vorgrim legionnaire's") || name.contains("vorgrim auxiliary's") ||name.contains("bellugh nuathal") || name.contains("crimson circle"))
isVorg = true;
float equipmentRoll = ThreadLocalRandom.current().nextInt(1, 100 + 1);
float dropChance = me.getDropChance() * 100;
ItemBase itemBase = me.getItemBase();
if(isVorg) {
mob.spawnTime = ThreadLocalRandom.current().nextInt(300, 2700);
dropChance = 10;
itemBase = getRandomVorg(itemBase);
}
if (equipmentRoll > dropChance)
continue;
MobLoot ml = new MobLoot(mob, me.getItemBase(), false);
MobLoot ml = new MobLoot(mob, itemBase, 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.
}
ml.setIsID(true);
ml.setDurabilityCurrent((short) (ml.getDurabilityCurrent() - ThreadLocalRandom.current().nextInt(5) + 1));
mob.getCharItemManager().addItemToInventory(ml);
}
}
}
public static void GenerateInventoryDrop(Mob mob, BootySetEntry bse) {
@ -367,8 +457,11 @@ public enum LootManager { @@ -367,8 +457,11 @@ public enum LootManager {
MobLoot lootItem = new MobLoot(mob, ItemBase.getItemBase(bse.itemBase), true);
if (lootItem != null)
if (lootItem != null) {
mob.getCharItemManager().addItemToInventory(lootItem);
if(lootItem.getItemBase().isDiscRune() && !Mob.discDroppers.contains(mob))
Mob.AddDiscDropper(mob);
}
}
public static void peddleFate(PlayerCharacter playerCharacter, Item gift) {
@ -392,7 +485,7 @@ public enum LootManager { @@ -392,7 +485,7 @@ public enum LootManager {
//check if player owns the gift he is trying to open
if (itemMan.doesCharOwnThisItem(gift.getObjectUUID()) == false)
if (!itemMan.doesCharOwnThisItem(gift.getObjectUUID()))
return;
//roll 1-100 for the gen table selection
@ -413,45 +506,161 @@ public enum LootManager { @@ -413,45 +506,161 @@ public enum LootManager {
//create the item from the table, quantity is always 1
MobLoot winnings = new MobLoot(playerCharacter, ItemBase.getItemBase(selectedItem.cacheID), 1, false);
ItemBase ib = ItemBase.getItemBase(selectedItem.cacheID);
if(ib.getUUID() == Warehouse.coalIB.getUUID()){
//no more coal, give gold instead
if (itemMan.getGoldInventory().getNumOfItems() + 250000 > 10000000) {
ErrorPopupMsg.sendErrorPopup(playerCharacter, 21);
return;
}
itemMan.addGoldToInventory(250000,false);
itemMan.updateInventory();
}else {
MobLoot winnings = new MobLoot(playerCharacter, ib, 1, false);
if (winnings == null)
return;
if (winnings == null)
return;
//early exit if the inventory of the player will not hold the item
//early exit if the inventory of the player will not old the item
if (itemMan.hasRoomInventory(winnings.getItemBase().getWeight()) == false) {
ErrorPopupMsg.sendErrorPopup(playerCharacter, 21);
return;
}
if (itemMan.hasRoomInventory(winnings.getItemBase().getWeight()) == false) {
ErrorPopupMsg.sendErrorPopup(playerCharacter, 21);
return;
//determine if the winning item needs a prefix
if (selectedRow.pModTable != 0) {
int prefixRoll = ThreadLocalRandom.current().nextInt(220, 320 + 1);
ModTableEntry prefix = ModTableEntry.rollTable(selectedRow.pModTable, prefixRoll);
if (prefix != null)
winnings.addPermanentEnchantment(prefix.action, 0, prefix.level, true);
}
//determine if the winning item needs a suffix
if (selectedRow.sModTable != 0) {
int suffixRoll = ThreadLocalRandom.current().nextInt(220, 320 + 1);
ModTableEntry suffix = ModTableEntry.rollTable(selectedRow.sModTable, suffixRoll);
if (suffix != null)
winnings.addPermanentEnchantment(suffix.action, 0, suffix.level, true);
}
winnings.setIsID(true);
//remove gift from inventory
itemMan.consume(gift);
//add winnings to player inventory
Item playerWinnings = winnings.promoteToItem(playerCharacter);
itemMan.addItemToInventory(playerWinnings);
itemMan.updateInventory();
}
}
//determine if the winning item needs a prefix
public static int rollRandomItem(int itemTable){
int returnedID = ItemTableEntry.getRandomItem(itemTable);
return returnedID;
}
if(selectedRow.pModTable != 0){
int prefixRoll = ThreadLocalRandom.current().nextInt(220,320 + 1);
ModTableEntry prefix = ModTableEntry.rollTable(selectedRow.pModTable, prefixRoll);
if(prefix != null)
winnings.addPermanentEnchantment(prefix.action, 0, prefix.level, true);
public static ItemBase getRandomVorg(ItemBase itemBase){
int roll = 0;
if(vorg_ha_uuids.contains(itemBase.getUUID())) {
roll = ThreadLocalRandom.current().nextInt(0, 10);
switch (roll) {
case 1:
return ItemBase.getItemBase(vorg_ha_uuids.get(0));
case 2:
return ItemBase.getItemBase(vorg_ha_uuids.get(1));
case 3:
return ItemBase.getItemBase(vorg_ha_uuids.get(2));
case 4:
return ItemBase.getItemBase(vorg_ha_uuids.get(3));
case 5:
return ItemBase.getItemBase(vorg_ha_uuids.get(4));
case 6:
return ItemBase.getItemBase(vorg_ha_uuids.get(5));
case 7:
return ItemBase.getItemBase(vorg_ha_uuids.get(6));
case 8:
return ItemBase.getItemBase(vorg_ha_uuids.get(7));
default:
return ItemBase.getItemBase(vorg_ha_uuids.get(8));
}
}
//determine if the winning item needs a suffix
if(vorg_ma_uuids.contains(itemBase.getUUID())) {
roll = ThreadLocalRandom.current().nextInt(0, 10);
switch (roll) {
case 1:
return ItemBase.getItemBase(vorg_ma_uuids.get(0));
case 2:
return ItemBase.getItemBase(vorg_ma_uuids.get(1));
case 3:
return ItemBase.getItemBase(vorg_ma_uuids.get(2));
case 4:
return ItemBase.getItemBase(vorg_ma_uuids.get(3));
case 5:
return ItemBase.getItemBase(vorg_ma_uuids.get(4));
case 6:
return ItemBase.getItemBase(vorg_ma_uuids.get(5));
case 7:
return ItemBase.getItemBase(vorg_ma_uuids.get(6));
default:
return ItemBase.getItemBase(vorg_ma_uuids.get(7));
}
}
if(selectedRow.sModTable != 0){
int suffixRoll = ThreadLocalRandom.current().nextInt(220,320 + 1);
ModTableEntry suffix = ModTableEntry.rollTable(selectedRow.sModTable, suffixRoll);
if (suffix != null)
winnings.addPermanentEnchantment(suffix.action, 0, suffix.level, true);
if(vorg_la_uuids.contains(itemBase.getUUID())) {
roll = ThreadLocalRandom.current().nextInt(0, 10);
switch (roll) {
case 1:
return ItemBase.getItemBase(vorg_la_uuids.get(0));
case 2:
return ItemBase.getItemBase(vorg_la_uuids.get(1));
case 3:
return ItemBase.getItemBase(vorg_la_uuids.get(2));
case 4:
return ItemBase.getItemBase(vorg_la_uuids.get(3));
case 5:
return ItemBase.getItemBase(vorg_la_uuids.get(4));
case 6:
return ItemBase.getItemBase(vorg_la_uuids.get(5));
case 7:
return ItemBase.getItemBase(vorg_la_uuids.get(6));
default:
return ItemBase.getItemBase(vorg_la_uuids.get(7));
}
}
winnings.setIsID(true);
//remove gift from inventory
if(vorg_cloth_uuids.contains(itemBase.getUUID())) {
roll = ThreadLocalRandom.current().nextInt(0, 10);
switch (roll) {
case 1:
return ItemBase.getItemBase(vorg_cloth_uuids.get(0));
case 2:
return ItemBase.getItemBase(vorg_cloth_uuids.get(1));
case 3:
return ItemBase.getItemBase(vorg_cloth_uuids.get(2));
case 4:
return ItemBase.getItemBase(vorg_cloth_uuids.get(3));
default:
return ItemBase.getItemBase(vorg_cloth_uuids.get(4));
}
}
itemMan.consume(gift);
return null;
}
//add winnings to player inventory
public static void DropPresent(Mob mob){
int random = ThreadLocalRandom.current().nextInt(ItemBase.AnniverseryGifts.size());
int presentID = ItemBase.AnniverseryGifts.get(random);
ItemBase presentBase = ItemBase.getItemBase(presentID);
if(presentBase != null){
MobLoot lootItem = new MobLoot(mob, presentBase, true);
mob.getCharItemManager().addItemToInventory(lootItem);
}
Item playerWinnings = winnings.promoteToItem(playerCharacter);
itemMan.addItemToInventory(playerWinnings);
itemMan.updateInventory();
}
}

28
src/engine/gameManager/MaintenanceManager.java

@ -24,7 +24,7 @@ public enum MaintenanceManager { @@ -24,7 +24,7 @@ public enum MaintenanceManager {
public static void setMaintDateTime(Building building, LocalDateTime maintDate) {
building.maintDateTime = maintDate;
building.maintDateTime = maintDate.withHour(1).withMinute(0).withSecond(0);
DbManager.BuildingQueries.updateMaintDate(building);
}
@ -49,19 +49,15 @@ public enum MaintenanceManager { @@ -49,19 +49,15 @@ public enum MaintenanceManager {
if (chargeUpkeep(building) == false)
derankList.add(building);
else
setMaintDateTime(building, LocalDateTime.now().plusDays(7));
}
// Reset maintenance dates for these buildings
for (Building building : maintList) {
setMaintDateTime(building, LocalDateTime.now().plusDays(7));
}
// Derak or destroy buildings that did not
// have funds available.
for (Building building : derankList)
for (Building building : derankList) {
building.destroyOrDerank(null);
if(building.getRank() > 0)
setMaintDateTime(building, LocalDateTime.now().plusDays(1));
}
Logger.info("Structures: " + buildingList.size() + " Maint: " + maintList.size() + " Derank: " + derankList.size());
}
@ -98,6 +94,10 @@ public enum MaintenanceManager { @@ -98,6 +94,10 @@ public enum MaintenanceManager {
continue;
}
//only ToL pays maintenance
if(building.getBlueprint().getBuildingGroup() != null && !building.getBlueprint().getBuildingGroup().equals(Enum.BuildingGroup.TOL))
continue;
// No maintenance on banestones omfg
if (building.getBlueprint().getBuildingGroup().equals(Enum.BuildingGroup.BANESTONE))
@ -222,12 +222,6 @@ public enum MaintenanceManager { @@ -222,12 +222,6 @@ public enum MaintenanceManager {
if ((hasFunds == false) ||
((building.getRank() == 8) && !hasResources)) {
// Add cash back to strongbox for lost rank if the building isn't being destroyed
// and it's not an R8 deranking
if ((building.getRank() > 1) && (building.getRank() < 8)) {
building.setStrongboxValue(building.getStrongboxValue() + building.getBlueprint().getRankCost(Math.min(building.getRank(), 7)));
}
return false; // Early exit for having failed to meet maintenance
}

17
src/engine/gameManager/SimulationManager.java

@ -10,10 +10,7 @@ package engine.gameManager; @@ -10,10 +10,7 @@ package engine.gameManager;
import engine.Enum;
import engine.Enum.GameObjectType;
import engine.objects.AbstractGameObject;
import engine.objects.City;
import engine.objects.PlayerCharacter;
import engine.objects.Runegate;
import engine.objects.*;
import org.pmw.tinylog.Logger;
import java.sql.Connection;
@ -33,7 +30,7 @@ public enum SimulationManager { @@ -33,7 +30,7 @@ public enum SimulationManager {
SERVERHEARTBEAT;
private static final long CITY_PULSE = 2000;
private static final long RUNEGATE_PULSE = 3000;
private static final long RUNEGATE_PULSE = 1000;
private static final long UPDATE_PULSE = 1000;
private static final long FlIGHT_PULSE = 100;
public static Duration executionTime = Duration.ofNanos(1);
@ -203,8 +200,12 @@ public enum SimulationManager { @@ -203,8 +200,12 @@ public enum SimulationManager {
city = (City) cityObject;
city.onEnter();
}
for(Mine mine : Mine.getMines()){
if(mine != null && mine.isActive)
mine.onEnter();
}
_cityPulseTime = System.currentTimeMillis() + CITY_PULSE;
}
/*
@ -214,6 +215,10 @@ public enum SimulationManager { @@ -214,6 +215,10 @@ public enum SimulationManager {
private void pulseRunegates() {
for (Runegate runegate : Runegate._runegates.values()) {
for(Portal portal : runegate._portals)
if(!portal.isActive())
portal.activate(false);
runegate.collidePortals();
}

92
src/engine/gameManager/ZergManager.java

@ -0,0 +1,92 @@ @@ -0,0 +1,92 @@
package engine.gameManager;
import engine.objects.Guild;
public class ZergManager {
public static float getCurrentMultiplier(int count, int maxCount){
switch(maxCount) {
case 3:
return getMultiplier3Man(count);
case 5:
return getMultiplier5Man(count);
case 10:
return getMultiplier10Man(count);
default:
return getMultiplier20Man(count);
}
}
public static float getMultiplier3Man(int count) {
if(count < 4)
return 1.0f;
if(count > 6)
return 0.0f;
switch(count){
case 4:
return 0.75f;
case 5:
return 0.60f;
case 6:
return 0.37f;
}
return 1.0f;
}
public static float getMultiplier5Man(int count) {
if(count < 6)
return 1.0f;
if(count > 10)
return 0.0f;
switch(count){
case 6:
return 0.75f;
case 7:
return 0.67f;
case 8:
return 0.56f;
case 9:
return 0.43f;
case 10:
return 0.25f;
}
return 1.0f;
}
public static float getMultiplier10Man(int count) {
if(count < 11)
return 1.0f;
if(count > 20)
return 0.0f;
switch(count){
case 11:
return 0.75f;
case 12:
return 0.71f;
case 13:
return 0.67f;
case 14:
return 0.62f;
case 15:
return 0.56f;
case 16:
return 0.50f;
case 17:
return 0.43f;
case 18:
return 0.35f;
case 19:
return 0.25f;
case 20:
return 0.14f;
}
return 1.0f;
}
public static float getMultiplier20Man(int count) {
return getMultiplier10Man(count * 2);
}
}

73
src/engine/gameManager/ZoneManager.java

@ -19,14 +19,12 @@ import engine.objects.Building; @@ -19,14 +19,12 @@ import engine.objects.Building;
import engine.objects.City;
import engine.objects.Zone;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom;
/*
* Class contains methods and structures which
@ -109,20 +107,6 @@ public enum ZoneManager { @@ -109,20 +107,6 @@ public enum ZoneManager {
}
// Returns the number of available hotZones
// remaining in this cycle (1am)
public static int availableHotZones() {
int count = 0;
for (Zone zone : ZoneManager.macroZones)
if (ZoneManager.validHotZone(zone))
count = count + 1;
return count;
}
// Resets the availability of hotZones
// for this cycle
@ -217,63 +201,6 @@ public enum ZoneManager { @@ -217,63 +201,6 @@ public enum ZoneManager {
ZoneManager.playerCityZones.add(zone);
}
public static final void generateAndSetRandomHotzone() {
Zone hotZone;
ArrayList<Integer> zoneArray = new ArrayList<>();
if (ZoneManager.macroZones.isEmpty())
return;
// Reset hotZone availability if none are left.
if (ZoneManager.availableHotZones() == 0)
ZoneManager.resetHotZones();
for (Zone zone : ZoneManager.macroZones)
if (validHotZone(zone))
zoneArray.add(zone.getObjectUUID());
int entryIndex = ThreadLocalRandom.current().nextInt(zoneArray.size());
hotZone = ZoneManager.getZoneByUUID(zoneArray.get(entryIndex));
if (hotZone == null) {
Logger.error("Hotzone is null");
return;
}
ZoneManager.setHotZone(hotZone);
}
public static final boolean validHotZone(Zone zone) {
if (zone.getSafeZone() == (byte) 1)
return false; // no safe zone hotzones// if (this.hotzone == null)
if (zone.getNodes().isEmpty())
return false;
if (zone.equals(ZoneManager.seaFloor))
return false;
//no duplicate hotZones
if (zone.hasBeenHotzone == true)
return false;
// Enforce min level
if (zone.minLvl < Integer.parseInt(ConfigManager.MB_HOTZONE_MIN_LEVEL.getValue()))
return false;
if (ZoneManager.hotZone != null)
return ZoneManager.hotZone.getObjectUUID() != zone.getObjectUUID();
return true;
}
// Converts world coordinates to coordinates local to a given zone.
public static Vector3fImmutable worldToLocal(Vector3fImmutable worldVector,

14
src/engine/loot/ItemTableEntry.java

@ -9,10 +9,12 @@ @@ -9,10 +9,12 @@
package engine.loot;
import engine.gameManager.LootManager;
import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
public class ItemTableEntry {
public int minRoll;
@ -42,4 +44,16 @@ public class ItemTableEntry { @@ -42,4 +44,16 @@ public class ItemTableEntry {
return itemTableEntry;
}
public static Integer getRandomItem(int itemTable) {
int id = 0;
List<ItemTableEntry> itemTableEntryList;
itemTableEntryList = LootManager._itemTables.get(itemTable);
if(itemTableEntryList != null){
id = itemTableEntryList.get(ThreadLocalRandom.current().nextInt(0,itemTableEntryList.size() - 1)).cacheID;
}
return id;
}
}

24
src/engine/mobileAI/MobAI.java

@ -625,8 +625,8 @@ public class MobAI { @@ -625,8 +625,8 @@ public class MobAI {
//check to send mob home for player guards to prevent exploit of dragging guards away and then teleporting
if (mob.BehaviourType.ordinal() != Enum.MobBehaviourType.Pet1.ordinal())
CheckToSendMobHome(mob);
CheckToSendMobHome(mob);
return;
}
@ -646,9 +646,6 @@ public class MobAI { @@ -646,9 +646,6 @@ public class MobAI {
return;
}
if (mob.BehaviourType.ordinal() != Enum.MobBehaviourType.Pet1.ordinal())
CheckToSendMobHome(mob);
if (mob.getCombatTarget() != null) {
if (mob.getCombatTarget().isAlive() == false) {
@ -874,9 +871,12 @@ public class MobAI { @@ -874,9 +871,12 @@ public class MobAI {
}
}
}
} else if (System.currentTimeMillis() > (aiAgent.deathTime + (aiAgent.spawnTime * 1000))) {
} else if (System.currentTimeMillis() > (aiAgent.deathTime + (aiAgent.spawnTime * 1000L))) {
if (Zone.respawnQue.contains(aiAgent) == false) {
if(Mob.discDroppers.contains(aiAgent))
return;
if (!Zone.respawnQue.contains(aiAgent)) {
Zone.respawnQue.add(aiAgent);
}
}
@ -911,6 +911,11 @@ public class MobAI { @@ -911,6 +911,11 @@ public class MobAI {
private static void CheckToSendMobHome(Mob mob) {
if(mob.BehaviourType.equals(Enum.MobBehaviourType.Pet1)){
if(mob.loc.distanceSquared(mob.getOwner().loc) > 60 * 60)
mob.teleport(mob.getOwner().loc);
return;
}
try {
if (mob.BehaviourType.isAgressive) {
@ -922,9 +927,6 @@ public class MobAI { @@ -922,9 +927,6 @@ 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());
@ -1006,7 +1008,7 @@ public class MobAI { @@ -1006,7 +1008,7 @@ public class MobAI {
//dont scan self.
if (mob.equals(awoMob) || (mob.agentType.equals(Enum.AIAgentType.GUARD)) == true)
if (mob.equals(awoMob) || (mob.agentType.equals(Enum.AIAgentType.GUARD)) || (mob.agentType.equals(Enum.AIAgentType.PET)))
continue;
Mob aggroMob = (Mob) awoMob;

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

@ -560,12 +560,30 @@ public class ClientMessagePump implements NetMsgHandler { @@ -560,12 +560,30 @@ public class ClientMessagePump implements NetMsgHandler {
if (!itemManager.inventoryContains(i))
return;
if (i.isCanDestroy())
if (itemManager.delete(i) == true) {
//cannot delete gold
if(i.getItemBaseID() == 7)
return;
if (i.isCanDestroy()) {
int goldValue = i.getBaseValue();
if (i.getItemBase().isRune())
goldValue = 500000;
if (i.getItemBaseID() == 980066)
goldValue = 0;
if(itemManager.getGoldInventory().getNumOfItems() + goldValue > 10000000)
return;
if (itemManager.delete(i)) {
if (goldValue > 0)
itemManager.addGoldToInventory(goldValue, false);
itemManager.updateInventory();
Dispatch dispatch = Dispatch.borrow(sourcePlayer, msg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
}
}
}
private static void ackBankWindowOpened(AckBankWindowOpenedMsg msg, ClientConnection origin) {
@ -1243,6 +1261,8 @@ public class ClientMessagePump implements NetMsgHandler { @@ -1243,6 +1261,8 @@ public class ClientMessagePump implements NetMsgHandler {
cost = sell.getBaseValue();
if(sell.getItemBaseID() == 980066)
cost = 0;
//apply damaged value reduction
float durabilityCurrent = sell.getDurabilityCurrent();
@ -1343,6 +1363,14 @@ public class ClientMessagePump implements NetMsgHandler { @@ -1343,6 +1363,14 @@ public class ClientMessagePump implements NetMsgHandler {
NPC npc = NPC.getFromCache(msg.getNpcID());
switch(npc.getContractID()){
case 900:
case 1201:
case 1202:
npc.sellPercent = 0.0f;
break;
}
if (npc == null)
return;
@ -1358,219 +1386,182 @@ public class ClientMessagePump implements NetMsgHandler { @@ -1358,219 +1386,182 @@ public class ClientMessagePump implements NetMsgHandler {
}
private static void buyFromNPC(BuyFromNPCMsg msg, ClientConnection origin) {
PlayerCharacter sourcePlayer = SessionManager.getPlayerCharacter(origin);
if (sourcePlayer == null)
return;
if (origin.buyLock.tryLock()) {
try {
CharacterItemManager itemMan = sourcePlayer.getCharItemManager();
if (itemMan == null)
if (itemMan == null) {
return;
}
NPC npc = NPC.getFromCache(msg.getNPCID());
if (npc == null)
if (npc == null) {
return;
}
Item gold = itemMan.getGoldInventory();
if (gold == null)
if (gold == null) {
return;
}
Item buy = null;
if (msg.getItemType() == GameObjectType.MobEquipment.ordinal()) {
ArrayList<MobEquipment> sellInventory = npc.getContract().getSellInventory();
if (sellInventory == null)
if (sellInventory == null) {
return;
}
for (MobEquipment me : sellInventory) {
if (me.getObjectUUID() == msg.getItemID()) {
ItemBase ib = me.getItemBase();
if (ib == null)
if (ib == null) {
return;
}
//test room available for item
if (!itemMan.hasRoomInventory(ib.getWeight()))
if (!itemMan.hasRoomInventory(ib.getWeight())) {
return;
}
int cost = me.getMagicValue();
float bargain = sourcePlayer.getBargain();
switch(npc.getContractID()){
case 1201:
cost = ItemBase.getDiscPrice(ib.getUUID());
bargain = 0;
break;
case 1202:
cost = ItemBase.getStatPrice(ib.getUUID());
bargain = 0;
break;
case 900:
cost = Warehouse.getCostForResource(ib.getUUID()) * Warehouse.getSellStackSize(ib.getUUID());
bargain = 0;
break;
}
float profit = npc.getSellPercent(sourcePlayer) - bargain;
if(me.getItemBase().getType().equals(ItemType.POTION))
profit -= 1.0f;
if (profit < 1)
profit = 1;
cost *= profit;
if(npc.getContractID() == 1502041)
cost = 2;
if (gold.getNumOfItems() - cost < 0) {
//dont' have enough goldItem exit!
// chatMan.chatSystemInfo(pc, "" + "You dont have enough gold.");
return;
}
Building b = (!npc.isStatic()) ? npc.getBuilding() : null;
if (b != null && b.getProtectionState().equals(ProtectionState.NPC))
b = null;
int buildingDeposit = cost - me.getMagicValue();
if (b != null && (b.getStrongboxValue() + buildingDeposit) > b.getMaxGold()) {
if (b != null && (b.getStrongboxValue() + buildingDeposit) > b.getMaxGold() && !b.isOwnerIsNPC()) {
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 206);
return;
}
if (!itemMan.buyFromNPC(b, cost, buildingDeposit)) {
// chatMan.chatSystemInfo(pc, "" + "You Failed to buy the item.");
ChatManager.chatSystemError(sourcePlayer, "Failed To Buy Item");
return;
}
buy = Item.createItemForPlayer(sourcePlayer, ib);
if (buy != null) {
me.transferEnchants(buy);
itemMan.addItemToInventory(buy);
//itemMan.updateInventory();
if(me.getItemBase().getType().equals(ItemType.RESOURCE) && npc.getContractID() == 900){
handleResourcePurchase(me,itemMan,sourcePlayer,ib);
}else {
buy = Item.createItemForPlayer(sourcePlayer, ib, me.fromNoob);
if (buy != null) {
me.transferEnchants(buy);
itemMan.addItemToInventory(buy);
if(npc.contractUUID == 900 && buy.getItemBaseID() == 1705032){
buy.setNumOfItems(10);
DbManager.ItemQueries.UPDATE_NUM_ITEMS(buy,buy.getNumOfItems());
}
//itemMan.updateInventory();
}
}
}
}
} else if (msg.getItemType() == GameObjectType.Item.ordinal()) {
CharacterItemManager npcCim = npc.getCharItemManager();
if (npcCim == null)
return;
buy = Item.getFromCache(msg.getItemID());
if (buy == null)
return;
ItemBase ib = buy.getItemBase();
if (ib == null)
return;
if (!npcCim.inventoryContains(buy))
return;
//test room available for item
if (!itemMan.hasRoomInventory(ib.getWeight()))
return;
//TODO test cost and subtract goldItem
//TODO CHnage this if we ever put NPc city npcs in buildings.
int cost = buy.getBaseValue();
if (buy.isID() || buy.isCustomValue())
cost = buy.getMagicValue();
float bargain = sourcePlayer.getBargain();
float profit = npc.getSellPercent(sourcePlayer) - bargain;
if (profit < 1)
profit = 1;
if (!buy.isCustomValue())
cost *= profit;
else
cost = buy.getValue();
if (gold.getNumOfItems() - cost < 0) {
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 128); // Insufficient Gold
return;
}
Building b = (!npc.isStatic()) ? npc.getBuilding() : null;
if (b != null)
if (b.getProtectionState().equals(ProtectionState.NPC))
b = null;
int buildingDeposit = cost;
if (b != null && (b.getStrongboxValue() + buildingDeposit) > b.getMaxGold()) {
if (b != null && (b.getStrongboxValue() + buildingDeposit) > b.getMaxGold() && !b.isOwnerIsNPC()) {
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 206);
return;
}
if (!itemMan.buyFromNPC(b, cost, buildingDeposit)) {
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 110);
return;
}
if (buy != null)
itemMan.buyFromNPC(buy, npc);
} else if (msg.getItemType() == GameObjectType.MobLoot.ordinal()) {
CharacterItemManager npcCim = npc.getCharItemManager();
if (npcCim == null)
return;
buy = MobLoot.getFromCache(msg.getItemID());
if (buy == null)
return;
ItemBase ib = buy.getItemBase();
if (ib == null)
return;
if (!npcCim.inventoryContains(buy))
return;
//test room available for item
if (!itemMan.hasRoomInventory(ib.getWeight()))
return;
//TODO test cost and subtract goldItem
//TODO CHnage this if we ever put NPc city npcs in buildings.
int cost = buy.getMagicValue();
cost *= npc.getSellPercent(sourcePlayer);
if (gold.getNumOfItems() - cost < 0) {
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 128); // Insufficient Gold
return;
}
Building b = (!npc.isStatic()) ? npc.getBuilding() : null;
if (b != null && b.getProtectionState().equals(ProtectionState.NPC))
b = null;
int buildingDeposit = cost;
if (b != null && (b.getStrongboxValue() + buildingDeposit) > b.getMaxGold()) {
if (b != null && (b.getStrongboxValue() + buildingDeposit) > b.getMaxGold() && !b.isOwnerIsNPC()) {
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 206);
return;
}
if (!itemMan.buyFromNPC(b, cost, buildingDeposit))
return;
if (buy != null)
itemMan.buyFromNPC(buy, npc);
} else
return;
if (buy != null) {
msg.setItem(buy);
//send the buy message back to update player
// msg.setItemType(buy.getObjectType().ordinal());
@ -1579,14 +1570,43 @@ public class ClientMessagePump implements NetMsgHandler { @@ -1579,14 +1570,43 @@ public class ClientMessagePump implements NetMsgHandler {
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
itemMan.updateInventory();
}
} finally {
origin.buyLock.unlock();
}
} else {
ErrorPopupMsg.sendErrorPopup(origin.getPlayerCharacter(), 12); // All production slots taken
}
}
public static void handleResourcePurchase(MobEquipment me, CharacterItemManager itemMan, PlayerCharacter sourcePlayer, ItemBase ib){
boolean stacked = false;
int buystack = Warehouse.getSellStackSize(me.getItemBase().getUUID());
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() + buystack){
item.setNumOfItems(item.getNumOfItems() + buystack);
stacked = true;
itemMan.updateInventory();
DbManager.ItemQueries.UPDATE_NUM_ITEMS(item,item.getNumOfItems());
break;
}
}
}
if(!stacked){
Item buy = Item.createItemForPlayer(sourcePlayer, ib, false);
if (buy != null) {
me.transferEnchants(buy);
itemMan.addItemToInventory(buy);
buy.setNumOfItems(buystack);
DbManager.ItemQueries.UPDATE_NUM_ITEMS(buy,buy.getNumOfItems());
}
}
itemMan.updateInventory();
}
private static void Repair(RepairMsg msg, ClientConnection origin) {
@ -1646,14 +1666,17 @@ public class ClientMessagePump implements NetMsgHandler { @@ -1646,14 +1666,17 @@ public class ClientMessagePump implements NetMsgHandler {
max *= (1 + (durMod * 0.01f));
if (dur >= max || dur < 1) {
//redundancy message to clear item from window in client
if (!DbManager.ItemQueries.SET_DURABILITY(toRepair, dur))
return;
toRepair.setDurabilityCurrent(max);
msg.setupRepairAck(max - dur);
dispatch = Dispatch.borrow(player, msg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
return;
}
//TODO get cost to repair
int cost = (int) ((max - dur) * 80.1);
int cost = (int)((toRepair.getMagicValue()/max*(max - dur)) + (npc.getRepairCost() * npc.buyPercent));
Building b = (!npc.isStatic()) ? npc.getBuilding() : null;
if (b != null)

15
src/engine/net/client/handlers/ArcMineChangeProductionMsgHandler.java

@ -11,6 +11,7 @@ import engine.objects.GuildStatusController; @@ -11,6 +11,7 @@ import engine.objects.GuildStatusController;
import engine.objects.Mine;
import engine.objects.PlayerCharacter;
import engine.objects.Resource;
import org.pmw.tinylog.Logger;
/*
* @Author:
@ -35,26 +36,28 @@ public class ArcMineChangeProductionMsgHandler extends AbstractClientMsgHandler @@ -35,26 +36,28 @@ public class ArcMineChangeProductionMsgHandler extends AbstractClientMsgHandler
//TODO verify this against the warehouse?
if (GuildStatusController.isInnerCouncil(playerCharacter.getGuildStatus()) == false) // is this only GL?
if (!GuildStatusController.isInnerCouncil(playerCharacter.getGuildStatus())) // is this only GL?
return true;
Mine mine = Mine.getMine(changeProductionMsg.getMineID());
if (mine == null)
if (mine == null) {
Logger.error("Player Character: " + playerCharacter.getName() + " Tried To Change Mine: " + changeProductionMsg.getMineID() + " and Mine was Null");
return true;
}
//make sure mine belongs to guild
if (mine.getOwningGuild().isEmptyGuild() ||
mine.getOwningGuild().getObjectUUID() != playerCharacter.getGuild().getObjectUUID())
if (mine.getOwningGuild().isEmptyGuild() || mine.getOwningGuild().getObjectUUID() != playerCharacter.getGuild().getObjectUUID())
return true;
//make sure valid resource
Resource resource = Resource.resourceByHash.get(changeProductionMsg.getResourceHash());
if (resource == null)
if (resource == null) {
Logger.error("Player Character: " + playerCharacter.getName() + " Tried To Change Mine: " + changeProductionMsg.getMineID() + " and Resource was Null");
return true;
}
//update resource

2
src/engine/net/client/handlers/CityDataHandler.java

@ -63,7 +63,7 @@ public class CityDataHandler extends AbstractClientMsgHandler { @@ -63,7 +63,7 @@ public class CityDataHandler extends AbstractClientMsgHandler {
// If the hotZone has changed then update the client's map accordingly.
if (playerCharacter.getTimeStamp("hotzoneupdate") <= ZoneManager.hotZoneLastUpdate.toEpochMilli() && ZoneManager.hotZone != null) {
if (playerCharacter.getTimestamps().containsKey("hotzoneupdate") && playerCharacter.getTimeStamp("hotzoneupdate") <= ZoneManager.hotZoneLastUpdate.toEpochMilli() && ZoneManager.hotZone != null) {
HotzoneChangeMsg hotzoneChangeMsg = new HotzoneChangeMsg(Enum.GameObjectType.Zone.ordinal(), ZoneManager.hotZone.getObjectUUID());
dispatch = Dispatch.borrow(playerCharacter, hotzoneChangeMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);

57
src/engine/net/client/handlers/MerchantMsgHandler.java

@ -17,6 +17,7 @@ import engine.powers.PowersBase; @@ -17,6 +17,7 @@ import engine.powers.PowersBase;
import engine.server.MBServerStatics;
import java.util.ArrayList;
import java.util.Objects;
/*
* @Author:
@ -105,7 +106,7 @@ public class MerchantMsgHandler extends AbstractClientMsgHandler { @@ -105,7 +106,7 @@ public class MerchantMsgHandler extends AbstractClientMsgHandler {
// Validate player can obtain blessing
if (GuildStatusController.isGuildLeader(player.getGuildStatus()) == false) {
if (!GuildStatusController.isGuildLeader(player.getGuildStatus())) {
ErrorPopupMsg.sendErrorPopup(player, 173); // You must be the leader of a guild to receive a blessing
return;
}
@ -126,12 +127,12 @@ public class MerchantMsgHandler extends AbstractClientMsgHandler { @@ -126,12 +127,12 @@ public class MerchantMsgHandler extends AbstractClientMsgHandler {
realm = RealmMap.getRealmForCity(city);
if (realm.getCanBeClaimed() == false) {
if (!realm.getCanBeClaimed()) {
ErrorPopupMsg.sendErrorPopup(player, 180); // This territory cannot be ruled by anyone
return;
}
if (realm.isRuled() == true) {
if (realm.isRuled()) {
ErrorPopupMsg.sendErrorPopup(player, 178); // This territory is already claimed
return;
}
@ -142,12 +143,12 @@ public class MerchantMsgHandler extends AbstractClientMsgHandler { @@ -142,12 +143,12 @@ public class MerchantMsgHandler extends AbstractClientMsgHandler {
}
private static void requestBoon(MerchantMsg msg, ClientConnection origin, PlayerCharacter player, NPC npc) {
private static void requestBoon(PlayerCharacter player, NPC npc) {
Building shrineBuilding;
Shrine shrine;
if (npc.getGuild() != player.getGuild())
if (!npc.getGuild().getNation().equals(player.getGuild().getNation()))
return;
shrineBuilding = npc.getBuilding();
@ -155,7 +156,7 @@ public class MerchantMsgHandler extends AbstractClientMsgHandler { @@ -155,7 +156,7 @@ public class MerchantMsgHandler extends AbstractClientMsgHandler {
if (shrineBuilding == null)
return;
if (shrineBuilding.getBlueprint() != null && shrineBuilding.getBlueprint().getBuildingGroup() != engine.Enum.BuildingGroup.SHRINE)
if (shrineBuilding.getBlueprint() != null && !shrineBuilding.getBlueprint().getBuildingGroup().equals(engine.Enum.BuildingGroup.SHRINE))
return;
if (shrineBuilding.getRank() == -1)
@ -171,11 +172,9 @@ public class MerchantMsgHandler extends AbstractClientMsgHandler { @@ -171,11 +172,9 @@ public class MerchantMsgHandler extends AbstractClientMsgHandler {
return;
}
//already haz boon.
if (player.containsEffect(shrine.getShrineType().getPowerToken())) {
ErrorPopupMsg.sendErrorPopup(player, 199);
return;
//remove old boon to apply new one, allows boon refreshing
player.effects.remove(PowersManager.getPowerByToken(shrine.getShrineType().getPowerToken()).name);
}
if (!Shrine.canTakeFavor(player, shrine))
@ -191,16 +190,34 @@ public class MerchantMsgHandler extends AbstractClientMsgHandler { @@ -191,16 +190,34 @@ public class MerchantMsgHandler extends AbstractClientMsgHandler {
return;
}
int rank = shrine.getRank();
//R8 trees always get atleast rank 2 boons. rank uses index, where 0 is first place, 1 is second, etc...
if (shrineBuilding.getCity() != null && shrineBuilding.getCity().getTOL() != null && shrineBuilding.getCity().getTOL().getRank() == 8)
if (rank != 0)
rank = 1;
int trains = 40 - (rank * 10);
if (trains < 0)
trains = 0;
int trains = 0;
switch(npc.getRank()){
case 1:
trains = 5;
break;
case 2:
trains = 10;
break;
case 3:
trains = 15;
break;
case 4:
trains = 20;
break;
case 5:
trains = 25;
break;
case 6:
trains = 30;
break;
case 7:
trains = 35;
break;
}
if(Objects.requireNonNull(shrineBuilding.getCity()).getTOL() != null && shrineBuilding.getCity().getTOL().getRank() == 8)
trains += 5;
//System.out.println(trains);
PowersManager.applyPower(player, player, player.getLoc(), shrinePower.getToken(), trains, false);
ChatManager.chatGuildInfo(player.getGuild(), player.getName() + " has recieved a boon costing " + 1 + " point of favor.");
shrineBuilding.addEffectBit(1000000 << 2);
@ -420,7 +437,7 @@ public class MerchantMsgHandler extends AbstractClientMsgHandler { @@ -420,7 +437,7 @@ public class MerchantMsgHandler extends AbstractClientMsgHandler {
if (isHermit(npc))
requestHermitBlessing(msg, origin, player, npc);
else
requestBoon(msg, origin, player, npc);
requestBoon(player, npc);
break;
case 15:
LeaderboardMessage lbm = new LeaderboardMessage();

20
src/engine/net/client/handlers/ObjectActionMsgHandler.java

@ -421,31 +421,12 @@ public class ObjectActionMsgHandler extends AbstractClientMsgHandler { @@ -421,31 +421,12 @@ public class ObjectActionMsgHandler extends AbstractClientMsgHandler {
itemMan.consume(item);
}
break;
//ANNIVERSERY GIFT
case 31:
// *** Disabled for now: Needs bootyset created
//if (ib.getUUID() == 971012) {
// int random = ThreadLocalRandom.current().nextInt(ItemBase.AnniverseryGifts.size());
// int annyID = ItemBase.AnniverseryGifts.get(random);
// ItemBase annyIB = ItemBase.getItemBase(annyID);
// if (annyIB != null) {
// Item gift = MobLoot.createItemForPlayer(player, annyIB);
// if (gift != null) {
// itemMan.addItemToInventory(gift);
// itemMan.consume(item);
// }
// }
// break;
//}
LootManager.peddleFate(player,item);
break;
case 30: //water bucket
case 8: //potions, tears of saedron
case 5: //runes, petition, warrant, scrolls
if (uuid > 3000 && uuid < 3050) { //Discipline Runes
if (ApplyRuneMsg.applyRune(uuid, origin, player)) {
@ -528,7 +509,6 @@ public class ObjectActionMsgHandler extends AbstractClientMsgHandler { @@ -528,7 +509,6 @@ public class ObjectActionMsgHandler extends AbstractClientMsgHandler {
}
// Send piss bucket animation
VisualUpdateMessage vum = new VisualUpdateMessage(player, 16323);
vum.configure();
DispatchMessage.sendToAllInRange(player, vum);

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

@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
package engine.net.client.msg;
import engine.Enum;
import engine.gameManager.ChatManager;
import engine.gameManager.DbManager;
import engine.net.*;
import engine.net.client.ClientConnection;
@ -70,62 +71,86 @@ public class ApplyRuneMsg extends ClientNetMsg { @@ -70,62 +71,86 @@ public class ApplyRuneMsg extends ClientNetMsg {
}
public static boolean applyRune(int runeID, ClientConnection origin, PlayerCharacter playerCharacter) {
RuneBase rb = RuneBase.getRuneBase(runeID);
Dispatch dispatch;
if (playerCharacter == null || origin == null || rb == null) {
return false;
}
int raceID = playerCharacter.getRaceID();
//Check race is met
ConcurrentHashMap<Integer, Boolean> races = rb.getRace();
if (races.size() > 0) {
int raceID = playerCharacter.getRaceID();
boolean valid = false;
for (int validID : races.keySet()) {
if (validID == raceID) {
if(runeID != 3007 && runeID != 3014) {//bounty hunter and huntsman
if (races.size() > 0) {
boolean valid = false;
for (int validID : races.keySet()) {
if (validID == raceID) {
valid = true;
break;
}
}
if(runeID == 3040)
valid = true;
if(runeID == 2514 && raceID == 1999)
valid = true;
if(runeID == 3036 && raceID == 1999)
valid = true;
break;
if(runeID == 3033 && raceID == 1999)
valid = true;
if (!valid) {
return false;
}
}
if (!valid) {
return false;
}
}
//Check base class is met
ConcurrentHashMap<Integer, Boolean> baseClasses = rb.getBaseClass();
if (baseClasses.size() > 0) {
int baseClassID = playerCharacter.getBaseClassID();
boolean valid = false;
for (int validID : baseClasses.keySet()) {
if (validID == baseClassID) {
//Check base class is met
ConcurrentHashMap<Integer, Boolean> baseClasses = rb.getBaseClass();
if (baseClasses.size() > 0) {
int baseClassID = playerCharacter.getBaseClassID();
boolean valid = false;
for (int validID : baseClasses.keySet()) {
if (validID == baseClassID) {
valid = true;
break;
}
}
if(runeID == 3040)
valid = true;
if(runeID == 3036 && raceID == 1999)
valid = true;
if(runeID == 3033 && raceID == 1999)
valid = true;
break;
if(runeID == 3035 && baseClassID == 2501)
valid = true;
if (!valid) {
return false;
}
}
if (!valid) {
return false;
}
}
//Check promotion class is met
ConcurrentHashMap<Integer, Boolean> promotionClasses = rb.getPromotionClass();
if (promotionClasses.size() > 0) {
int promotionClassID = playerCharacter.getPromotionClassID();
boolean valid = false;
for (int validID : promotionClasses.keySet()) {
if (validID == promotionClassID) {
//Check promotion class is met
ConcurrentHashMap<Integer, Boolean> promotionClasses = rb.getPromotionClass();
if (promotionClasses.size() > 0) {
int promotionClassID = playerCharacter.getPromotionClassID();
boolean valid = false;
for (int validID : promotionClasses.keySet()) {
if (validID == promotionClassID) {
valid = true;
break;
}
}
if(runeID == 3040)
valid = true;
if(runeID == 3004 && (playerCharacter.getPromotionClassID() == 2505 || playerCharacter.getPromotionClassID() == 2510))
valid = true;
break;
if(runeID == 3036 && raceID == 1999)
valid = true;
if(runeID == 3033 && raceID == 1999)
valid = true;
if (!valid) {
return false;
}
}
if (!valid) {
} else{
if(playerCharacter.getPromotionClassID() == 2519){//priest
return false;
}
}
//Check disciplines are met
ArrayList<CharacterRune> runes = playerCharacter.getRunes();
ConcurrentHashMap<Integer, Boolean> disciplines = rb.getDiscipline();
@ -139,7 +164,6 @@ public class ApplyRuneMsg extends ClientNetMsg { @@ -139,7 +164,6 @@ public class ApplyRuneMsg extends ClientNetMsg {
}
}
}
int discCount = 0;
for (CharacterRune cr : runes) {
int runeBaseID = cr.getRuneBaseID();
@ -152,28 +176,32 @@ public class ApplyRuneMsg extends ClientNetMsg { @@ -152,28 +176,32 @@ public class ApplyRuneMsg extends ClientNetMsg {
return false;
}
}
//Check level is met
if (playerCharacter.getLevel() < rb.getLevelRequired()) {
return false;
}
int strTotal = 0;
int dexTotal = 0;
int conTotal = 0;
int intTotal = 0;
int spiTotal = 0;
int cost = 0;
//Check any attributes are met
ArrayList<RuneBaseAttribute> attrs = rb.getAttrs();
if (rb.getAttrs() != null)
for (RuneBaseAttribute rba : attrs) {
int attrID = rba.getAttributeID();
int mod = rba.getModValue();
switch (attrID) {
case MBServerStatics.RUNE_COST_ATTRIBUTE_ID:
switch (rb.getName()) {
case "Born of the Ethyri":
case "Born of the Taripontor":
case "Born of the Gwendannen":
case "Born of the Invorri":
case "Born of the Irydnu":
mod = 0;
}
if (mod > playerCharacter.getUnusedStatPoints()) {
return false;
}
@ -226,14 +254,33 @@ public class ApplyRuneMsg extends ClientNetMsg { @@ -226,14 +254,33 @@ public class ApplyRuneMsg extends ClientNetMsg {
break;
}
}
//Check if max number runes already reached
if (runes.size() > 12) {
return false;
}
switch (rb.getName()) {
case "Born of the Ethyri":
case "Born of the Taripontor":
case "Born of the Gwendannen":
case "Born of the Invorri":
case "Born of the Irydnu":
for (CharacterRune charRune : playerCharacter.getRunes()) {
RuneBase rb2 = charRune.getRuneBase();
switch (rb2.getName()) {
case "Born of the Ethyri":
case "Born of the Taripontor":
case "Born of the Gwendannen":
case "Born of the Invorri":
case "Born of the Irydnu":
ChatManager.chatSystemError(playerCharacter, "You Have Already Applied A Blood Rune");
return false;
}
}
}
//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;
@ -244,7 +291,6 @@ public class ApplyRuneMsg extends ClientNetMsg { @@ -244,7 +291,6 @@ public class ApplyRuneMsg extends ClientNetMsg {
}
}
}
//Everything succeeded. Let's apply the rune
//Attempt add rune to database
CharacterRune runeWithoutID = new CharacterRune(rb, playerCharacter.getObjectUUID());
@ -258,7 +304,6 @@ public class ApplyRuneMsg extends ClientNetMsg { @@ -258,7 +304,6 @@ public class ApplyRuneMsg extends ClientNetMsg {
if (cr == null) {
return false;
}
//remove any overridden runes from player
ArrayList<Integer> overwrite = rb.getOverwrite();
CharacterRune toRemove = null;
@ -267,13 +312,10 @@ public class ApplyRuneMsg extends ClientNetMsg { @@ -267,13 +312,10 @@ public class ApplyRuneMsg extends ClientNetMsg {
toRemove = playerCharacter.removeRune(overwriteID);
}
}
//add rune to player
playerCharacter.addRune(cr);
// recalculate all bonuses/formulas/skills/powers
playerCharacter.recalculate();
//if overwriting a stat rune, add any amount granted from previous rune.
if (toRemove != null) {
RuneBase rbs = toRemove.getRuneBase();
@ -299,30 +341,32 @@ public class ApplyRuneMsg extends ClientNetMsg { @@ -299,30 +341,32 @@ public class ApplyRuneMsg extends ClientNetMsg {
if (dif > 0 && spiTotal < (int) playerCharacter.statSpiMax) {
playerCharacter.addSpi(dif);
}
// recalculate all bonuses/formulas/skills/powers
playerCharacter.recalculate();
}
}
switch (rb.getName()) {
case "Born of the Ethyri":
case "Born of the Taripontor":
case "Born of the Gwendannen":
case "Born of the Invorri":
case "Born of the Irydnu":
cost = 0;
break;
}
if (cost > 0) {
ModifyStatMsg msm = new ModifyStatMsg((0 - cost), 0, 3);
dispatch = Dispatch.borrow(playerCharacter, msm);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
}
//send apply rune message to client
ApplyRuneMsg arm = new ApplyRuneMsg(playerCharacter.getObjectType().ordinal(), playerCharacter.getObjectUUID(), runeID, cr.getObjectType().ordinal(), cr.getObjectUUID(), false);
dispatch = Dispatch.borrow(playerCharacter, arm);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
//alert them of success
ErrorPopupMsg.sendErrorPopup(playerCharacter, 160);
//reapply bonuses
playerCharacter.applyBonuses();
return true;
}

12
src/engine/net/client/msg/CityDataMsg.java

@ -104,8 +104,10 @@ public class CityDataMsg extends ClientNetMsg { @@ -104,8 +104,10 @@ public class CityDataMsg extends ClientNetMsg {
}
temp.putInt(mineList.size());
for (Mine mine : mineList)
Mine.serializeForClientMsg(mine, temp);
for (Mine mine : mineList) {
if(mine.getParentZone() != null && !mine.getParentZone().isContinent())
Mine.serializeForClientMsg(mine, temp);
}
temp.put((byte) 0); // PAD
}
@ -178,8 +180,10 @@ public class CityDataMsg extends ClientNetMsg { @@ -178,8 +180,10 @@ public class CityDataMsg extends ClientNetMsg {
}
writer.putInt(mineList.size());
for (Mine mine : mineList)
Mine.serializeForClientMsg(mine, writer);
for (Mine mine : mineList) {
if(mine.getParentZone() != null && !mine.getParentZone().isContinent())
Mine.serializeForClientMsg(mine, writer);
}
} else
writer.putInt(0);
} catch (Exception e) {

6
src/engine/net/client/msg/ManageCityAssetsMsg.java

@ -275,7 +275,7 @@ public class ManageCityAssetsMsg extends ClientNetMsg { @@ -275,7 +275,7 @@ public class ManageCityAssetsMsg extends ClientNetMsg {
writer.putString(npcHire.getName());
writer.putInt(1);
writer.putInt(Blueprint.getNpcMaintCost(npcHire.getRank()));
writer.putInt(0);
if (npcHire.getObjectType() == GameObjectType.NPC)
writer.putInt(((NPC) npcHire).getContract().getIconID()); // Was 60
else if (npcHire.getObjectType() == GameObjectType.Mob) {
@ -497,7 +497,7 @@ public class ManageCityAssetsMsg extends ClientNetMsg { @@ -497,7 +497,7 @@ public class ManageCityAssetsMsg extends ClientNetMsg {
if (building.getBlueprint() == null)
writer.putInt(0);
else
writer.putInt(building.getBlueprint().getMaintCost(building.getRank())); // maint cost
writer.putInt(building.getBlueprint().getMaintCost()); // maint cost
if (building.getRank() == 8) {
writer.putInt(74856115); // Stone
@ -514,7 +514,7 @@ public class ManageCityAssetsMsg extends ClientNetMsg { @@ -514,7 +514,7 @@ public class ManageCityAssetsMsg extends ClientNetMsg {
if (maintDate == null)
maintDate = LocalDateTime.now();
writer.putLocalDateTime(LocalDateTime.now()); // current time
writer.putLocalDateTime(maintDate); // current time
// utc offset?
writer.putInt((int) java.time.Duration.between(LocalDateTime.now(), maintDate).getSeconds()); // Seconds to maint date

52
src/engine/net/client/msg/ServerInfoMsg.java

@ -11,6 +11,7 @@ package engine.net.client.msg; @@ -11,6 +11,7 @@ package engine.net.client.msg;
import engine.gameManager.ConfigManager;
import engine.gameManager.DbManager;
import engine.net.AbstractConnection;
import engine.net.ByteBufferReader;
import engine.net.ByteBufferWriter;
@ -53,18 +54,45 @@ public class ServerInfoMsg extends ClientNetMsg { @@ -53,18 +54,45 @@ public class ServerInfoMsg extends ClientNetMsg {
writer.putInt(WorldServer.worldMapID);
writer.putString(ConfigManager.MB_WORLD_NAME.getValue());
if (LoginServer.population < MBServerStatics.LOW_POPULATION)
writer.putInt(0); //Land Rush
else if (LoginServer.population < MBServerStatics.NORMAL_POPULATION)
writer.putInt(1); //Low pop
else if (LoginServer.population < MBServerStatics.HIGH_POPULATION)
writer.putInt(2); //Normal pop
else if (LoginServer.population < MBServerStatics.VERY_OVERPOPULATED_POPULATION)
writer.putInt(3); //High Pop
else if (LoginServer.population < MBServerStatics.FULL_POPULATION)
writer.putInt(4); //Very overpopulated pop
else
writer.putInt(5); //Full pop
int TotalTrees = 21;
int currentR8Trees = DbManager.CityQueries.GET_CAPITAL_CITY_COUNT();
switch(currentR8Trees){
case 0:
case 1:
case 2:
case 3:
case 4:
writer.putInt(0); //Land Rush
break;
case 5:
case 6:
case 7:
case 8:
writer.putInt(1); //Low pop
break;
case 9:
case 10:
case 11:
case 12:
writer.putInt(2); //Normal pop
break;
case 13:
case 14:
case 15:
case 16:
writer.putInt(3); //High Pop
break;
case 17:
case 18:
case 19:
case 20:
writer.putInt(4); //Very overpopulated pop
break;
default:
writer.putInt(5); //Full pop
break;
}
}
/**

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

@ -96,6 +96,11 @@ public class VendorDialogMsg extends ClientNetMsg { @@ -96,6 +96,11 @@ public class VendorDialogMsg extends ClientNetMsg {
return;
}
if(npc.contractUUID == 1502040){ //enrollment officer
PlayerCharacter.unboxPlayer(playerCharacter);
}
// Restrict disc trainers to only characters who have
// tht disc applied.

33
src/engine/objects/AbstractCharacter.java

@ -1187,10 +1187,15 @@ public abstract class AbstractCharacter extends AbstractWorldObject { @@ -1187,10 +1187,15 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
}
}
public final float modifyHealth(
final float value,
final AbstractCharacter attacker,
final boolean fromCost) {
public final float modifyHealth(float value, final AbstractCharacter attacker, final boolean fromCost) {
if(attacker != null && attacker.getObjectType().equals(GameObjectType.PlayerCharacter)){
value *= ((PlayerCharacter)attacker).ZergMultiplier;
} // Health modifications are modified by the ZergMechanic
if(attacker != null && attacker.getObjectType().equals(GameObjectType.Mob) && ((Mob)attacker).getOwner() != null){
value *= ((Mob)attacker).getOwner().ZergMultiplier;
}// Health modifications from pets are modified by the owner's ZergMechanic
try {
@ -1254,11 +1259,19 @@ public abstract class AbstractCharacter extends AbstractWorldObject { @@ -1254,11 +1259,19 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
}
public final float modifyMana(
final float value,
float value,
final AbstractCharacter attacker,
final boolean fromCost
) {
if(attacker != null && attacker.getObjectType().equals(GameObjectType.PlayerCharacter)){
value *= ((PlayerCharacter)attacker).ZergMultiplier;
} // Health modifications are modified by the ZergMechanic
if(attacker != null && attacker.getObjectType().equals(GameObjectType.Mob) && ((Mob)attacker).getOwner() != null){
value *= ((Mob)attacker).getOwner().ZergMultiplier;
}// Health modifications from pets are modified by the owner's ZergMechanic
if (!this.isAlive()) {
return 0f;
}
@ -1293,11 +1306,19 @@ public abstract class AbstractCharacter extends AbstractWorldObject { @@ -1293,11 +1306,19 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
}
public final float modifyStamina(
final float value,
float value,
final AbstractCharacter attacker,
final boolean fromCost
) {
if(attacker != null && attacker.getObjectType().equals(GameObjectType.PlayerCharacter)){
value *= ((PlayerCharacter)attacker).ZergMultiplier;
} // Health modifications are modified by the ZergMechanic
if(attacker != null && attacker.getObjectType().equals(GameObjectType.Mob) && ((Mob)attacker).getOwner() != null){
value *= ((Mob)attacker).getOwner().ZergMultiplier;
}// Health modifications from pets are modified by the owner's ZergMechanic
if (!this.isAlive()) {
return 0f;
}

46
src/engine/objects/Blueprint.java

@ -108,9 +108,11 @@ public class Blueprint { @@ -108,9 +108,11 @@ public class Blueprint {
maxShrines = 2;
break;
case 7:
case 8:
maxShrines = 3;
break;
case 8:
maxShrines = 4;
break;
default:
maxShrines = 0;
@ -167,11 +169,7 @@ public class Blueprint { @@ -167,11 +169,7 @@ public class Blueprint {
// based upon the building's current rank
public static int getNpcMaintCost(int rank) {
int maintCost = Integer.MAX_VALUE;
maintCost = (9730 * rank) + 1890;
return maintCost;
return 0;
}
public int getMaxRank() {
@ -181,6 +179,8 @@ public class Blueprint { @@ -181,6 +179,8 @@ public class Blueprint {
public int getMaxSlots() {
if (this.buildingGroup != null && this.buildingGroup.equals(BuildingGroup.BARRACK))
return 1;
if (this.buildingGroup != null && this.buildingGroup.equals(BuildingGroup.TOL))
return 4;
return maxSlots;
}
@ -313,7 +313,7 @@ public class Blueprint { @@ -313,7 +313,7 @@ public class Blueprint {
// Early exit for buildings with single or no slots
if (this.maxSlots <= 1)
if (this.maxSlots <= 1 && !this.buildingGroup.equals(BuildingGroup.TOL))
return maxSlots;
if (this.maxRank == 1 && currentRank == 1)
@ -327,20 +327,20 @@ public class Blueprint { @@ -327,20 +327,20 @@ public class Blueprint {
break;
case 3:
case 4:
case 5:
case 6:
availableSlots = 2;
break;
case 5:
case 6:
case 7:
availableSlots = 3;
break;
case 8:
availableSlots = 1;
availableSlots = 3;
break;
default:
availableSlots = 0;
break;
}
if(this.buildingGroup != null && this.buildingGroup.equals(BuildingGroup.TOL))
availableSlots += 1;
return availableSlots;
}
@ -603,26 +603,14 @@ public class Blueprint { @@ -603,26 +603,14 @@ public class Blueprint {
return this.blueprintUUID;
}
public int getMaintCost(int rank) {
public int getMaintCost() {
int maintCost = Integer.MAX_VALUE;
switch (this.buildingGroup) {
case TOL:
case BARRACK:
maintCost = (61500 * rank) + 19500;
break;
case SPIRE:
maintCost = (4800 * rank) + 1200;
break;
default:
if (maxRank == 1)
maintCost = 22500;
else
maintCost = (15900 * rank) + 3300;
break;
if(this.buildingGroup.equals(BuildingGroup.TOL)){
return 3000000;
}else{
return 0;
}
return maintCost;
}
}

21
src/engine/objects/Building.java

@ -780,24 +780,9 @@ public class Building extends AbstractWorldObject { @@ -780,24 +780,9 @@ public class Building extends AbstractWorldObject {
public int getMaintCost() {
int maintCost = 0;
// Add cost for building structure
maintCost += this.getBlueprint().getMaintCost(rank);
// Add costs associated with hirelings
for (AbstractCharacter npc : this.hirelings.keySet()) {
if (npc.getObjectType() != GameObjectType.NPC)
continue;
maintCost += Blueprint.getNpcMaintCost(npc.getRank());
}
return maintCost;
if(this.getBlueprint() != null && this.getBlueprint().getBuildingGroup().equals(BuildingGroup.TOL))
return 3000000;
else return 0;
}
public final void submitOpenDoorJob(int doorID) {

91
src/engine/objects/Contract.java

@ -86,6 +86,12 @@ public class Contract extends AbstractGameObject { @@ -86,6 +86,12 @@ public class Contract extends AbstractGameObject {
this.iconID = rs.getInt("iconID");
this.vendorID = rs.getInt("vendorID");
this.allowedBuildings = EnumBitSet.asEnumBitSet(rs.getLong("allowedBuildingTypeID"), Enum.BuildingGroup.class);
switch(this.contractID){
case 866: //banker
case 865: //siege engineer
case 899: //alchemist
this.allowedBuildings.add(Enum.BuildingGroup.TOL);
}
this.equipmentSet = rs.getInt("equipSetID");
this.inventorySet = rs.getInt("inventorySet");
@ -198,6 +204,91 @@ public class Contract extends AbstractGameObject { @@ -198,6 +204,91 @@ public class Contract extends AbstractGameObject {
}
public ArrayList<MobEquipment> getSellInventory() {
if(this.getObjectUUID() == 900){ //resource merchant
for(MobEquipment me : this.sellInventory){
if(me.getItemBase().getType().equals(Enum.ItemType.RESOURCE)){
int amountResource = Warehouse.getSellStackSize(me.getItemBase().getUUID());
me.magicValue = amountResource * me.getItemBase().getBaseValue() * 2;
} else{
me.magicValue = 100000;
}
}
}
if(this.getObjectUUID() == 1202){ //rune merchant
for(MobEquipment me : this.sellInventory){
switch(me.getItemBase().getUUID()){
case 250001: //5 stats
case 250010:
case 250019:
case 250028:
case 250037:
me.magicValue = 3000000;
break;
case 250002: //10 stats
case 250011:
case 250020:
case 250029:
case 250038:
me.magicValue = 4000000;
break;
case 250003: //15 stats
case 250012:
case 250021:
case 250030:
case 250039:
me.magicValue = 5000000;
break;
case 250004: //20 stats
case 250013:
case 250022:
case 250031:
case 250040:
me.magicValue = 6000000;
break;
case 250005: //25 stats
case 250014:
case 250023:
case 250032:
case 250041:
me.magicValue = 7000000;
break;
case 250006: //30 stats
case 250015:
case 250024:
case 250033:
case 250042:
me.magicValue = 8000000;
break;
case 250007: //35 stats
case 250016:
case 250025:
case 250034:
case 250043:
me.magicValue = 9000000;
break;
default:
me.magicValue = 10000000;
break;
}
}
}
if(this.getObjectUUID() == 1201){ //disc merchant
for(MobEquipment me : this.sellInventory){
if(me.getItemBase().getName().equals("Prospector")){
me.magicValue = 500000;
}else{
me.magicValue = 10000000;
}
}
}
if(this.getObjectUUID() == 1502041) {//noob helper{
for(MobEquipment me : this.sellInventory){
me.magicValue = 1;
}
}
return this.sellInventory;
}

6
src/engine/objects/Guild.java

@ -752,9 +752,9 @@ public class Guild extends AbstractWorldObject { @@ -752,9 +752,9 @@ public class Guild extends AbstractWorldObject {
canSub = false;
}
City nationCap = City.getCity(nation.cityUUID);
if (nation.getSubGuildList().size() >= nationCap.getRank()) {
canSub = false;
}
//if (nation.getSubGuildList().size() >= nationCap.getRank()) {
// canSub = false;
//}
return canSub;
}

17
src/engine/objects/Item.java

@ -233,7 +233,6 @@ public class Item extends AbstractWorldObject { @@ -233,7 +233,6 @@ public class Item extends AbstractWorldObject {
this.value = rs.getInt("item_value");
this.customName = rs.getString("item_name");
}
public static void _serializeForClientMsg(Item item, ByteBufferWriter writer)
@ -303,7 +302,7 @@ public class Item extends AbstractWorldObject { @@ -303,7 +302,7 @@ public class Item extends AbstractWorldObject {
writer.putString(item.customName); // Unknown. pad?
writer.put((byte) 1); // End Datablock byte
writer.putFloat((float) item.durabilityMax);
writer.putFloat((float) item.getDurabilityMax());
writer.putFloat((float) item.durabilityCurrent);
writer.put((byte) 1); // End Datablock byte
@ -609,7 +608,7 @@ public class Item extends AbstractWorldObject { @@ -609,7 +608,7 @@ public class Item extends AbstractWorldObject {
writer.putIntAt(serialized, indexPosition);
}
public static Item createItemForPlayer(PlayerCharacter pc, ItemBase ib) {
public static Item createItemForPlayer(PlayerCharacter pc, ItemBase ib, boolean fromNoob) {
Item item = null;
byte charges = 0;
@ -885,7 +884,15 @@ public class Item extends AbstractWorldObject { @@ -885,7 +884,15 @@ public class Item extends AbstractWorldObject {
}
public short getDurabilityMax() {
return durabilityMax;
int extra = 0;
for(Effect eff : this.effects.values()){
for(AbstractEffectModifier mod : eff.getEffectModifiers()){
if(mod.modType.equals(ModType.Durability)){
extra += mod.getMaxMod();
}
}
}
return (short)(durabilityMax + extra);
}
public boolean isCanDestroy() {
@ -948,6 +955,7 @@ public class Item extends AbstractWorldObject { @@ -948,6 +955,7 @@ public class Item extends AbstractWorldObject {
}
public boolean isID() {
this.flags |= 1;
return ((this.flags & 1) > 0);
}
@ -1197,6 +1205,7 @@ public class Item extends AbstractWorldObject { @@ -1197,6 +1205,7 @@ public class Item extends AbstractWorldObject {
}
public int getBaseValue() {
if (this.getItemBase() != null)
return this.getItemBase().getBaseValue();
return 0;

155
src/engine/objects/ItemBase.java

@ -75,7 +75,6 @@ public class ItemBase { @@ -75,7 +75,6 @@ public class ItemBase {
private boolean isStrBased;
private ArrayList<Integer> animations = new ArrayList<>();
private ArrayList<Integer> offHandAnimations = new ArrayList<>();
private boolean autoID = false;
/**
* ResultSet Constructor
@ -145,8 +144,6 @@ public class ItemBase { @@ -145,8 +144,6 @@ public class ItemBase {
}
this.autoIDItemsCheck();
try {
DbManager.ItemBaseQueries.LOAD_ANIMATIONS(this);
} catch (Exception e) {
@ -223,16 +220,76 @@ public class ItemBase { @@ -223,16 +220,76 @@ public class ItemBase {
AnniverseryGifts.add(971008);
AnniverseryGifts.add(971009);
AnniverseryGifts.add(971010);
AnniverseryGifts.add(5101000);
AnniverseryGifts.add(5101020);
AnniverseryGifts.add(5101100);
AnniverseryGifts.add(5101120);
AnniverseryGifts.add(5101040);
AnniverseryGifts.add(5101140);
AnniverseryGifts.add(5101060);
AnniverseryGifts.add(5101080);
//AnniverseryGifts.add(5101000);
//AnniverseryGifts.add(5101020);
//AnniverseryGifts.add(5101100);
//AnniverseryGifts.add(5101120);
//AnniverseryGifts.add(5101040);
//AnniverseryGifts.add(5101140);
//AnniverseryGifts.add(5101060);
//AnniverseryGifts.add(5101080);
}
public static int getDiscPrice(int uuid) {
if(uuid == 3040)
return 500000;
else return 10000000;
}
public static int getStatPrice(int uuid) {
switch(uuid){
case 250001: //5 stats
case 250010:
case 250019:
case 250028:
case 250037:
return 3000000;
case 250002: //10 stats
case 250011:
case 250020:
case 250029:
case 250038:
return 4000000;
case 250003: //15 stats
case 250012:
case 250021:
case 250030:
case 250039:
return 5000000;
case 250004: //20 stats
case 250013:
case 250022:
case 250031:
case 250040:
return 6000000;
case 250005: //25 stats
case 250014:
case 250023:
case 250032:
case 250041:
return 7000000;
case 250006: //30 stats
case 250015:
case 250024:
case 250033:
case 250042:
return 8000000;
case 250007: //35 stats
case 250016:
case 250025:
case 250034:
case 250043:
return 9000000;
case 250008: //40 stats
case 250017:
case 250026:
case 250035:
case 250044:
return 10000000;
}
return 10000000;
}
/*
@ -372,74 +429,10 @@ public class ItemBase { @@ -372,74 +429,10 @@ public class ItemBase {
return modTable;
}
public int getVendorType() {
return vendorType;
}
public void setVendorType(int vendorType) {
this.vendorType = vendorType;
}
public int getHashID() {
return hashID;
}
public void setHashID(int hashID) {
this.hashID = hashID;
}
private void autoIDItemsCheck() {
//AUto ID Vorg and Glass
switch (uuid) {
case 27550:
case 27560:
case 27580:
case 27590:
case 188500:
case 188510:
case 188520:
case 188530:
case 188540:
case 188550:
case 189100:
case 189110:
case 189120:
case 189130:
case 189140:
case 189150:
case 189510:
case 27600:
case 181840:
case 188700:
case 188720:
case 189550:
case 189560:
case 7000100:
case 7000110:
case 7000120:
case 7000130:
case 7000140:
case 7000150:
case 7000160:
case 7000170:
case 7000180:
case 7000190:
case 7000200:
case 7000210:
case 7000220:
case 7000230:
case 7000240:
case 7000250:
case 7000270:
case 7000280:
this.autoID = true;
break;
default:
this.autoID = false;
}
}
public boolean validForSkills(ConcurrentHashMap<String, CharacterSkill> skills) {
CharacterSkill characterSkill;
@ -906,12 +899,4 @@ public class ItemBase { @@ -906,12 +899,4 @@ public class ItemBase {
public void setOffHandAnimations(ArrayList<Integer> offHandAnimations) {
this.offHandAnimations = offHandAnimations;
}
public boolean isAutoID() {
return autoID;
}
public void setAutoID(boolean autoID) {
this.autoID = autoID;
}
}

264
src/engine/objects/Mine.java

@ -11,10 +11,7 @@ package engine.objects; @@ -11,10 +11,7 @@ package engine.objects;
import engine.Enum;
import engine.InterestManagement.WorldGrid;
import engine.gameManager.BuildingManager;
import engine.gameManager.ChatManager;
import engine.gameManager.DbManager;
import engine.gameManager.ZoneManager;
import engine.gameManager.*;
import engine.net.ByteBufferWriter;
import engine.net.client.msg.ErrorPopupMsg;
import engine.server.MBServerStatics;
@ -25,6 +22,9 @@ import java.sql.ResultSet; @@ -25,6 +22,9 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import static engine.gameManager.DbManager.MineQueries;
@ -51,6 +51,13 @@ public class Mine extends AbstractGameObject { @@ -51,6 +51,13 @@ public class Mine extends AbstractGameObject {
private int buildingID;
private MineProduction mineType;
public int openHour;
public int openMinute;
public int capSize;
public LocalDateTime liveTime;
public final HashSet<Integer> _playerMemory = new HashSet<>();
public ArrayList<PlayerCharacter> affectedPlayers = new ArrayList<>();
/**
* ResultSet Constructor
*/
@ -90,7 +97,15 @@ public class Mine extends AbstractGameObject { @@ -90,7 +97,15 @@ public class Mine extends AbstractGameObject {
this.production = Resource.valueOf(rs.getString("mine_resource"));
this.lastClaimer = null;
this.openHour = rs.getInt("mineLiveHour");
this.openMinute = rs.getInt("mineLiveMinute");
this.capSize = rs.getInt("capSize");
this.liveTime = LocalDateTime.now().withHour(this.openHour).withMinute(this.openMinute);
Building tower = BuildingManager.getBuildingFromCache(this.buildingID);
if(tower != null){
tower.setMaxHitPoints(5000f * this.capSize);
tower.setCurrentHitPoints(tower.healthMax);
}
}
public static void releaseMineClaims(PlayerCharacter playerCharacter) {
@ -161,56 +176,45 @@ public class Mine extends AbstractGameObject { @@ -161,56 +176,45 @@ public class Mine extends AbstractGameObject {
}
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);
writer.putString(mine.zoneName);
writer.putInt(mine.production.hash);
writer.putInt(mine.production.baseProduction);
writer.putInt(mine.getModifiedProductionAmount()); //TODO calculate range penalty here
writer.putInt(3600); //window in seconds
// Errant mines are currently open. Set time to now.
LocalDateTime mineOpenTime = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0);
// Mine times are those of the nation not individual guild.
Guild mineNatonGuild = mine.getOwningGuild().getNation();
// Adjust the serialized mine time based upon whether
// the Guild's mine window has passed or not and if it was claimed.
// If a mine is active serialize current datetime irrespective
// of any claim.
if (mineNatonGuild.isEmptyGuild() == false && mine.isActive == false) {
int guildWOO = mineNatonGuild.getNation().getMineTime();
LocalDateTime guildMineTime = mineOpenTime.withHour(guildWOO);
try {
writer.putInt(mine.getObjectType().ordinal());
writer.putInt(mine.getObjectUUID());
writer.putInt(mine.getObjectUUID()); //actually a hash of mine
writer.putString(mine.mineType.name);
//writer.putString(mine.zoneName + " " + mine.capSize + " Man ");
writer.putString(mine.capSize + " Man ");
writer.putInt(mine.production.hash);
writer.putInt(mine.production.baseProduction);
writer.putInt(mine.getModifiedProductionAmount()); //TODO calculate range penalty here
writer.putInt(3600); //window in seconds
LocalDateTime mineOpenTime = LocalDateTime.now().withHour(mine.openHour).withMinute(mine.openMinute).withSecond(0).withNano(0);
writer.putLocalDateTime(mineOpenTime);
writer.putLocalDateTime(mineOpenTime.plusMinutes(30));
writer.put(mine.isActive ? (byte) 0x01 : (byte) 0x00);
Building mineTower = BuildingManager.getBuilding(mine.buildingID);
if (mineTower != null) {
writer.putFloat(mineTower.getLoc().x);
writer.putFloat(mineTower.getParentZone().getLoc().y);
writer.putFloat(mineTower.getLoc().z);
} else {
writer.putFloat(mine.parentZone.getLoc().x);
writer.putFloat(mine.parentZone.getLoc().y);
writer.putFloat(mine.parentZone.getLoc().z);
Logger.error("Mine Tower Was Null For Mine: " + mine.getObjectUUID());
}
if (mineOpenTime.isAfter(guildMineTime) || mine.wasClaimed == true)
mineOpenTime = guildMineTime.plusDays(1);
else
mineOpenTime = guildMineTime;
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.nationTag, writer);
} catch (Exception e) {
Logger.error("Failed TO Serialize Mine Because: " + e.getMessage());
}
writer.putLocalDateTime(mineOpenTime);
writer.putLocalDateTime(mineOpenTime.plusHours(1));
writer.put(mine.isActive ? (byte) 0x01 : (byte) 0x00);
Building mineTower = BuildingManager.getBuilding(mine.buildingID);
writer.putFloat(mineTower.getLoc().x);
writer.putFloat(mineTower.getParentZone().getLoc().y);
writer.putFloat(mineTower.getLoc().z);
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.nationTag, writer);
}
public static ArrayList<Mine> getMinesForGuild(int guildID) {
@ -290,26 +294,9 @@ public class Mine extends AbstractGameObject { @@ -290,26 +294,9 @@ public class Mine extends AbstractGameObject {
if (treeRank < 1)
return false;
if (guildUnderMineLimit(playerGuild.getNation(), treeRank) == false) {
ErrorPopupMsg.sendErrorMsg(playerCharacter, "Your nation cannot support another mine.");
return false;
}
return true;
}
private static boolean guildUnderMineLimit(Guild playerGuild, int tolRank) {
int mineCnt = 0;
mineCnt += Mine.getMinesForGuild(playerGuild.getObjectUUID()).size();
for (Guild guild : playerGuild.getSubGuildList())
mineCnt += Mine.getMinesForGuild(guild.getObjectUUID()).size();
return mineCnt <= tolRank;
}
public boolean changeProductionType(Resource resource) {
if (!this.validForMine(resource))
return false;
@ -378,6 +365,16 @@ public class Mine extends AbstractGameObject { @@ -378,6 +365,16 @@ public class Mine extends AbstractGameObject {
Building building = BuildingManager.getBuildingFromCache(this.buildingID);
if (building != null && !this.isActive)
building.isDeranking.compareAndSet(true, false);
if(!isAc){
for(PlayerCharacter player : this.affectedPlayers){
try {
player.ZergMultiplier = 1.0f;
} catch(Exception e){
//something went wrong resetting zerg multiplier, maybe player was deleted?
}
}
}
}
public boolean validForMine(Resource r) {
@ -538,41 +535,106 @@ public class Mine extends AbstractGameObject { @@ -538,41 +535,106 @@ public class Mine extends AbstractGameObject {
}
public int getModifiedProductionAmount() {
//TODO Calculate Distance modifications.
//calculate base values.
int baseProduction = this.production.baseProduction;
float baseModValue = this.production.baseProduction * .1f;
float rankModValue = this.production.baseProduction * .0143f;
float totalModded = 0;
//get Mine Building.
Building mineBuilding = BuildingManager.getBuilding(this.buildingID);
if (mineBuilding == null)
return this.production.baseProduction;
for (AbstractCharacter harvester : mineBuilding.getHirelings().keySet()) {
totalModded += baseModValue;
totalModded += rankModValue * harvester.getRank();
ItemBase resourceBase = ItemBase.getItemBase(this.production.UUID);
if(resourceBase == null)
return 0;
int value = resourceBase.getBaseValue();
int amount = 0;
switch(this.capSize){
case 3:
amount = 1800000;
break;
case 5:
amount = 3000000;
break;
case 10:
amount = 6000000;
break;
case 20:
amount = 12000000;
break;
}
if(this.production.UUID == 7)
value = 1;
amount = amount / value;
return amount;
}
public void onEnter() {
Building tower = BuildingManager.getBuildingFromCache(this.buildingID);
if(tower == null)
return;
// Gather current list of players within the zone bounds
HashSet<AbstractWorldObject> currentPlayers = WorldGrid.getObjectsInRangePartial(tower.loc, Enum.CityBoundsType.GRID.extents, MBServerStatics.MASK_PLAYER);
HashMap<Guild,ArrayList<PlayerCharacter>> charactersByNation = new HashMap<>();
ArrayList<Guild> updatedNations = new ArrayList<>();
for (AbstractWorldObject playerObject : currentPlayers) {
if (playerObject == null)
continue;
PlayerCharacter player = (PlayerCharacter) playerObject;
if(this.affectedPlayers.contains(player) == false)
this.affectedPlayers.add(player);
if(!this._playerMemory.contains(player.getObjectUUID())){
this._playerMemory.add(player.getObjectUUID());
}
Guild nation = player.guild.getNation();
if(charactersByNation.containsKey(nation)){
if(!charactersByNation.get(nation).contains(player)) {
charactersByNation.get(nation).add(player);
if(!updatedNations.contains(nation)){
updatedNations.add(nation);
}
}
}else{
ArrayList<PlayerCharacter> players = new ArrayList<>();
players.add(player);
charactersByNation.put(nation,players);
if(!updatedNations.contains(nation)){
updatedNations.add(nation);
}
}
}
//add base production on top;
totalModded += baseProduction;
//skip distance check for expansion.
if (this.isExpansion())
return (int) totalModded;
if (this.owningGuild.isEmptyGuild() == false) {
if (this.owningGuild.getOwnedCity() != null) {
float distanceSquared = this.owningGuild.getOwnedCity().getLoc().distanceSquared2D(mineBuilding.getLoc());
if (distanceSquared > sqr(10000 * 3))
totalModded *= .25f;
else if (distanceSquared > sqr(10000 * 2))
totalModded *= .50f;
else if (distanceSquared > sqr(10000))
totalModded *= .75f;
for(Guild nation : updatedNations){
float multiplier = ZergManager.getCurrentMultiplier(charactersByNation.get(nation).size(),this.capSize);
for(PlayerCharacter player : charactersByNation.get(nation)){
player.ZergMultiplier = multiplier;
}
}
return (int) totalModded;
try
{
this.onExit(this._playerMemory);
}
catch(Exception ignored){
}
}
private void onExit(HashSet<Integer> currentMemory) {
Building tower = BuildingManager.getBuildingFromCache(this.buildingID);
if(tower == null)
return;
ArrayList<Integer>toRemove = new ArrayList<>();
HashSet<AbstractWorldObject> currentPlayers = WorldGrid.getObjectsInRangePartial(tower.loc, Enum.CityBoundsType.GRID.extents, MBServerStatics.MASK_PLAYER);
for(Integer id : currentMemory){
PlayerCharacter pc = PlayerCharacter.getPlayerCharacter(id);
if(currentPlayers.contains(pc) == false){
toRemove.add(id);
pc.ZergMultiplier = 1.0f;
}
}
// Remove players from city memory
_playerMemory.removeAll(toRemove);
}
}

18
src/engine/objects/Mob.java

@ -48,6 +48,7 @@ import static engine.net.client.msg.ErrorPopupMsg.sendErrorPopup; @@ -48,6 +48,7 @@ import static engine.net.client.msg.ErrorPopupMsg.sendErrorPopup;
public class Mob extends AbstractIntelligenceAgent {
public static ArrayList<Mob> discDroppers = new ArrayList<>();
private static final ReentrantReadWriteLock createLock = new ReentrantReadWriteLock();
private static final ConcurrentHashMap<Integer, Mob> mobMapByDBID = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
// Variables NOT to be stored in db
@ -574,11 +575,11 @@ public class Mob extends AbstractIntelligenceAgent { @@ -574,11 +575,11 @@ public class Mob extends AbstractIntelligenceAgent {
mob = new Mob(mobBase, guild, parent, level, owner, 0);
if (mob.mobBase == null)
return null;
mob.runAfterLoad();
Vector3fImmutable loc = owner.getLoc();
DbManager.addToCache(mob);
mob.setPet(owner, true);
mob.setWalkMode(false);
mob.runAfterLoad();
} catch (Exception e) {
Logger.error(e);
@ -1396,6 +1397,11 @@ public class Mob extends AbstractIntelligenceAgent { @@ -1396,6 +1397,11 @@ public class Mob extends AbstractIntelligenceAgent {
loadInventory();
this.updateLocation();
if(Mob.discDroppers.contains(this)){
this.setLevel((short)65);
this.setResists(new Resists("Dropper"));
}
}
public void despawn() {
@ -1466,7 +1472,7 @@ public class Mob extends AbstractIntelligenceAgent { @@ -1466,7 +1472,7 @@ public class Mob extends AbstractIntelligenceAgent {
Logger.error(e.getMessage());
}
Resists.calculateResists(this);
//Resists.calculateResists(this);
}
public void calculateMaxHealthManaStamina() {
@ -2263,5 +2269,9 @@ public class Mob extends AbstractIntelligenceAgent { @@ -2263,5 +2269,9 @@ public class Mob extends AbstractIntelligenceAgent {
}
}
}
public static void AddDiscDropper(Mob mob){
discDroppers.add(mob);
mob.setLevel((short)65);
mob.setResists(new Resists("Dropper"));
}
}

4
src/engine/objects/MobEquipment.java

@ -34,7 +34,8 @@ public class MobEquipment extends AbstractGameObject { @@ -34,7 +34,8 @@ public class MobEquipment extends AbstractGameObject {
private AbstractPowerAction suffix;
private int pValue;
private int sValue;
private int magicValue;
int magicValue;
public boolean fromNoob = false;
private float dropChance = 0;
@ -106,7 +107,6 @@ public class MobEquipment extends AbstractGameObject { @@ -106,7 +107,6 @@ public class MobEquipment extends AbstractGameObject {
public static void serializeForVendor(MobEquipment mobEquipment, ByteBufferWriter writer, float percent) throws SerializationException {
_serializeForClientMsg(mobEquipment, writer, false);
int baseValue = mobEquipment.itemBase.getBaseValue() + mobEquipment.itemBase.getMagicValue();
writer.putInt(mobEquipment.magicValue);
writer.putInt(mobEquipment.magicValue);
}

2
src/engine/objects/MobLoot.java

@ -77,7 +77,7 @@ public final class MobLoot extends Item { @@ -77,7 +77,7 @@ public final class MobLoot extends Item {
this.setNumOfItems(quantity);
this.noSteal = noSteal;
this.setIsID(this.getItemBase().isAutoID());
this.setIsID(true);
// Class is 'final'; passing 'this' should be okay at the end of the constructor

52
src/engine/objects/PlayerCharacter.java

@ -175,6 +175,10 @@ public class PlayerCharacter extends AbstractCharacter { @@ -175,6 +175,10 @@ public class PlayerCharacter extends AbstractCharacter {
private boolean dirtyLoad = true;
private final ReadWriteLock dirtyLock = new ReentrantReadWriteLock(true);
public float ZergMultiplier = 1.0f;
public boolean isBoxed = false;
/**
* No Id Constructor
*/
@ -4811,6 +4815,17 @@ public class PlayerCharacter extends AbstractCharacter { @@ -4811,6 +4815,17 @@ public class PlayerCharacter extends AbstractCharacter {
updateBlessingMessage();
this.safeZone = this.isInSafeZone();
if(!this.timestamps.containsKey("nextBoxCheck"))
this.timestamps.put("nextBoxCheck", System.currentTimeMillis() + 10000);
if(!this.isBoxed && this.timestamps.get("nextBoxCheck") < System.currentTimeMillis()) {
this.isBoxed = checkIfBoxed(this);
this.timestamps.put("nextBoxCheck", System.currentTimeMillis() + 10000);
}
if(this.isBoxed && !this.containsEffect(1672601862)) {
PowersManager.applyPower(this, this, Vector3fImmutable.ZERO, 1672601862, 40, false);
}
} catch (Exception e) {
Logger.error(e);
@ -4819,7 +4834,44 @@ public class PlayerCharacter extends AbstractCharacter { @@ -4819,7 +4834,44 @@ public class PlayerCharacter extends AbstractCharacter {
}
}
}
public static void unboxPlayer(PlayerCharacter player){
String machineID = player.getClientConnection().machineID;
ArrayList<PlayerCharacter> sameMachine = new ArrayList<>();
for(PlayerCharacter pc : SessionManager.getAllActivePlayerCharacters()){
if(!pc.equals(player) && pc. isActive && pc.isEnteredWorld() && pc.getClientConnection().machineID.equals(machineID)){
sameMachine.add(pc);
}
}
for(PlayerCharacter pc : sameMachine)
pc.isBoxed = true;
player.isBoxed = false;
if(player.containsEffect(1672601862)) {
player.removeEffectBySource(EffectSourceType.DeathShroud,41,false);
}
}
public static boolean checkIfBoxed(PlayerCharacter player){
try {
String machineID = player.getClientConnection().machineID;
ArrayList<PlayerCharacter> sameMachine = new ArrayList<>();
for (PlayerCharacter pc : SessionManager.getAllActivePlayerCharacters()) {
if (!pc.equals(player) && pc.isActive && pc.isEnteredWorld() && pc.getClientConnection().machineID.equals(machineID)) {
sameMachine.add(pc);
}
}
boolean boxed = false;
for (PlayerCharacter pc : sameMachine)
if (!pc.isBoxed)
boxed = true;
return boxed;
}catch(Exception e){
return false;
}
}
@Override
public void updateFlight() {

21
src/engine/objects/Resists.java

@ -46,6 +46,9 @@ public class Resists { @@ -46,6 +46,9 @@ public class Resists {
case "Mine":
setMineResists();
break;
case "Dropper":
setDropperResists();
break;
default:
setGenericResists();
break;
@ -231,6 +234,24 @@ public class Resists { @@ -231,6 +234,24 @@ public class Resists {
this.resists.put(DamageType.Siege, 0f);
}
public final void setDropperResists() {
this.immuneToAll = false;
this.resists.put(DamageType.Slash, 50f);
this.resists.put(DamageType.Crush, 50f);
this.resists.put(DamageType.Pierce, 50f);
this.resists.put(DamageType.Magic, 50f);
this.resists.put(DamageType.Bleed, 50f);
this.resists.put(DamageType.Poison, 50f);
this.resists.put(DamageType.Mental, 50f);
this.resists.put(DamageType.Holy, 50f);
this.resists.put(DamageType.Unholy, 50f);
this.resists.put(DamageType.Lightning, 50f);
this.resists.put(DamageType.Fire, 50f);
this.resists.put(DamageType.Cold, 50f);
this.resists.put(DamageType.Healing, 0f);
this.immuneTo.put(DamageType.Siege, true);
}
/**
* Create generic resists
*/

27
src/engine/objects/Shrine.java

@ -43,7 +43,7 @@ public class Shrine extends AbstractWorldObject implements Comparable<Shrine> { @@ -43,7 +43,7 @@ public class Shrine extends AbstractWorldObject implements Comparable<Shrine> {
public static boolean canTakeFavor(PlayerCharacter grantee, Shrine shrine) {
if (shrine.shrineType.isRace())
if (shrine.shrineType.isRace()) {
switch (grantee.getRaceID()) {
case 2000:
case 2001:
@ -96,6 +96,7 @@ public class Shrine extends AbstractWorldObject implements Comparable<Shrine> { @@ -96,6 +96,7 @@ public class Shrine extends AbstractWorldObject implements Comparable<Shrine> {
case 2025:
case 2026:
case 1999:
if (shrine.shrineType == ShrineType.Nephilim)
return true;
break;
@ -106,7 +107,7 @@ public class Shrine extends AbstractWorldObject implements Comparable<Shrine> { @@ -106,7 +107,7 @@ public class Shrine extends AbstractWorldObject implements Comparable<Shrine> {
break;
}
else
}else {
switch (grantee.getPromotionClassID()) {
case 2504:
if (shrine.shrineType == ShrineType.Assassin)
@ -197,7 +198,7 @@ public class Shrine extends AbstractWorldObject implements Comparable<Shrine> { @@ -197,7 +198,7 @@ public class Shrine extends AbstractWorldObject implements Comparable<Shrine> {
return true;
break;
}
}
return false;
}
@ -226,26 +227,6 @@ public class Shrine extends AbstractWorldObject implements Comparable<Shrine> { @@ -226,26 +227,6 @@ public class Shrine extends AbstractWorldObject implements Comparable<Shrine> {
}
public void decay() {
if (this.getFavors() == 0)
return;
int decayAmount = (int) (this.getFavors() - (this.getFavors() * .10f));
if (decayAmount < 0)
decayAmount = 0;
if (!DbManager.ShrineQueries.updateFavors(this, decayAmount, this.getFavors())) {
Logger.error("Shrine Decay", "Error writing to DB. UUID: " + this.getObjectUUID());
return;
}
this.favors = decayAmount;
Logger.info(shrineType.name() + " uuid:" + this.getObjectUUID() + " Amount: " + this.getFavors() * .10f);
}
public synchronized boolean addFavor(PlayerCharacter boonOwner, Item boonItem) {
if (boonOwner == null)

78
src/engine/objects/Warehouse.java

@ -281,6 +281,84 @@ public class Warehouse extends AbstractWorldObject { @@ -281,6 +281,84 @@ public class Warehouse extends AbstractWorldObject {
}
public static int getCostForResource(int id){
int newCost = 1;
switch(id){
case 1580000://stone
newCost = 3000;
break;
case 1580001://truesteel
newCost = 50000;
break;
case 1580002://iron
newCost = 50000;
break;
case 1580003://adamant
newCost = 100000;
break;
case 1580004://lumber
newCost = 3000;
break;
case 1580005://oak
newCost = 30000;
break;
case 1580006://bronzewood
newCost = 30000;
break;
case 1580007://mandrake
newCost = 100000;
break;
case 1580008://coal
newCost = 30000;
break;
case 1580009://agate
newCost = 50000;
break;
case 1580010://diamond
newCost = 50000;
break;
case 1580011://onyx
newCost = 100000;
break;
case 1580012://azoth
newCost = 50000;
break;
case 1580013://orichalk
newCost = 30000;
break;
case 1580014://antimony
newCost = 100000;
break;
case 1580015://sulfur
newCost = 100000;
break;
case 1580016://quicksilver
newCost = 100000;
break;
case 1580017://galvor
newCost = 300000;
break;
case 1580018://wormwood
newCost = 300000;
break;
case 1580019://obsidian
newCost = 200000;
break;
case 1580020://bloodstone
newCost = 200000;
break;
case 1705032:
newCost = 100000;
break;
}
return newCost;
}
public static int getSellStackSize(int id){
if(id == 1705032)
return 10;
return 3000000 / getCostForResource(id);
}
public ConcurrentHashMap<ItemBase, Integer> getResources() {
return resources;
}

5
src/engine/objects/Zone.java

@ -101,7 +101,6 @@ public class Zone extends AbstractGameObject { @@ -101,7 +101,6 @@ public class Zone extends AbstractGameObject {
if (hash == null)
setHash();
}
public static void serializeForClientMsg(Zone zone, ByteBufferWriter writer) {
@ -113,8 +112,8 @@ public class Zone extends AbstractGameObject { @@ -113,8 +112,8 @@ public class Zone extends AbstractGameObject {
if (zone.playerCityID > 0) {
writer.put((byte) 1); // Player City - True
writer.putFloat(Enum.CityBoundsType.ZONE.extents);
writer.putFloat(Enum.CityBoundsType.ZONE.extents);
writer.putFloat(Enum.CityBoundsType.GRID.extents);
writer.putFloat(Enum.CityBoundsType.GRID.extents);
} else
writer.put((byte) 0); // Player City - False

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

@ -40,10 +40,7 @@ import engine.net.client.msg.chat.ChatSystemMsg; @@ -40,10 +40,7 @@ import engine.net.client.msg.chat.ChatSystemMsg;
import engine.objects.*;
import engine.server.MBServerStatics;
import engine.util.ThreadUtils;
import engine.workthreads.DisconnectTrashTask;
import engine.workthreads.HourlyJobThread;
import engine.workthreads.PurgeOprhans;
import engine.workthreads.WarehousePushThread;
import engine.workthreads.*;
import org.pmw.tinylog.Configurator;
import org.pmw.tinylog.Level;
import org.pmw.tinylog.Logger;
@ -201,6 +198,7 @@ public class WorldServer { @@ -201,6 +198,7 @@ public class WorldServer {
LocalDateTime nextPopulationFileTime = LocalDateTime.now();
LocalDateTime nextFlashTrashCheckTime = LocalDateTime.now();
LocalDateTime nextHourlyJobTime = LocalDateTime.now().withMinute(0).withSecond(0).plusHours(1);
LocalDateTime nextHalfHourlyJobTime = LocalDateTime.now().withMinute(0).withSecond(0);
LocalDateTime nextWareHousePushTime = LocalDateTime.now();
// Begin execution of main game loop
@ -232,6 +230,13 @@ public class WorldServer { @@ -232,6 +230,13 @@ public class WorldServer {
nextHourlyJobTime = LocalDateTime.now().withMinute(0).withSecond(0).plusHours(1);
}
if (LocalDateTime.now().isAfter(nextHalfHourlyJobTime)) {
Thread halfHourlyJobThread = new Thread(new HalfHourlyJobThread());
halfHourlyJobThread.setName("halfHourlyJob");
halfHourlyJobThread.start();
nextHalfHourlyJobTime = nextHalfHourlyJobTime.plusMinutes(30);
}
if (LocalDateTime.now().isAfter(nextWareHousePushTime)) {
Thread warehousePushThread = new Thread(new WarehousePushThread());
warehousePushThread.setName("warehousePush");
@ -435,9 +440,6 @@ public class WorldServer { @@ -435,9 +440,6 @@ public class WorldServer {
Logger.info("Loading Max Skills for Trainers");
DbManager.SkillsBaseQueries.LOAD_ALL_MAX_SKILLS_FOR_CONTRACT();
//pick a startup Hotzone
ZoneManager.generateAndSetRandomHotzone();
Logger.info("Loading All Players from database to Server Cache");
long start = System.currentTimeMillis();
@ -488,8 +490,8 @@ public class WorldServer { @@ -488,8 +490,8 @@ public class WorldServer {
MobRespawnThread.startRespawnThread();
// Run maintenance
MaintenanceManager.dailyMaintenance();
//moved this to hourly job thread to sustain no reboot system
//MaintenanceManager.dailyMaintenance();
Logger.info("Starting Orphan Item Purge");
PurgeOprhans.startPurgeThread();
@ -497,7 +499,7 @@ public class WorldServer { @@ -497,7 +499,7 @@ public class WorldServer {
// Open/Close mines for the current window
Logger.info("Processing mine window.");
HourlyJobThread.processMineWindow();
HalfHourlyJobThread.processMineWindow();
// Calculate bootstrap time and rest boot time to current time.

166
src/engine/workthreads/HalfHourlyJobThread.java

@ -0,0 +1,166 @@ @@ -0,0 +1,166 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
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.net.DispatchMessage;
import engine.net.MessageDispatcher;
import engine.net.client.msg.chat.ChatSystemMsg;
import engine.objects.*;
import engine.server.world.WorldServer;
import org.pmw.tinylog.Logger;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import static engine.server.MBServerStatics.MINE_LATE_WINDOW;
public class HalfHourlyJobThread implements Runnable {
public HalfHourlyJobThread() {
}
public static void processMineWindow() {
try {
ArrayList<Mine> mines = Mine.getMines();
for (Mine mine : mines) {
try {
//handle mines opening on server reboot weird time interval
if(LocalDateTime.now().isAfter(LocalDateTime.now().withHour(mine.openHour).withMinute(mine.openMinute))) {
if (LocalDateTime.now().isBefore(LocalDateTime.now().withHour(mine.openHour).withMinute(mine.openMinute).plusMinutes(30))) {
HalfHourlyJobThread.mineWindowOpen(mine);
continue;
}
}
// set to the current mine window.
if (mine.openHour == LocalDateTime.now().getHour() && mine.openMinute == LocalDateTime.now().getMinute() && !mine.wasClaimed) {
HalfHourlyJobThread.mineWindowOpen(mine);
continue;
}
// Close the mine if it reaches this far
LocalDateTime openTime = LocalDateTime.now().withHour(mine.openHour).withMinute(mine.openMinute);
if(LocalDateTime.now().plusMinutes(1).isAfter(openTime.plusMinutes(30)))
mineWindowClose(mine);
} catch (Exception e) {
Logger.error("mineID: " + mine.getObjectUUID(), e.toString());
}
}
} catch (Exception e) {
Logger.error(e.toString());
}
}
public static void mineWindowOpen(Mine mine) {
mine.setActive(true);
ChatManager.chatSystemChannel(mine.getZoneName() + "'s Mine is now Active!");
Logger.info(mine.getZoneName() + "'s Mine is now Active!");
}
public static boolean mineWindowClose(Mine mine) {
// No need to end the window of a mine which never opened.
if (mine.isActive == false)
return false;
Building mineBuilding = BuildingManager.getBuildingFromCache(mine.getBuildingID());
if (mineBuilding == null) {
Logger.debug("Null mine building for Mine " + mine.getObjectUUID() + " Building " + mine.getBuildingID());
return false;
}
// Mine building still stands; nothing to do.
// We can early exit here.
if (mineBuilding.getRank() > 0) {
mine.setActive(false);
mine.lastClaimer = null;
ChatSystemMsg chatMsg = new ChatSystemMsg(null, mine.guildName + " has defended the mine in " + mine.getParentZone().getParent().getName() + ". The mine is no longer active.");
chatMsg.setMessageType(10);
chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID());
DispatchMessage.dispatchMsgToAll(chatMsg);
return true;
}
// This mine does not have a valid claimer
// we will therefore set it to errant
// and keep the window open.
if (!Mine.validateClaimer(mine.lastClaimer)) {
mine.lastClaimer = null;
mine.updateGuildOwner(null);
mine.setActive(true);
ChatSystemMsg chatMsg = new ChatSystemMsg(null, mine.getParentZone().getParent().getName() + " Was not claimed, the battle rages on!");
chatMsg.setMessageType(10);
chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID());
DispatchMessage.dispatchMsgToAll(chatMsg);
return false;
}
//Update ownership to map
mine.guildName = mine.getOwningGuild().getName();
mine.guildTag = mine.getOwningGuild().getGuildTag();
Guild nation = mine.getOwningGuild().getNation();
mine.nationName = nation.getName();
mine.nationTag = nation.getGuildTag();
mineBuilding.rebuildMine();
WorldGrid.updateObject(mineBuilding);
ChatSystemMsg chatMsg = new ChatSystemMsg(null, mine.lastClaimer.getName() + " has claimed the mine in " + mine.getParentZone().getParent().getName() + " for " + mine.getOwningGuild().getName() + ". The mine is no longer active.");
chatMsg.setMessageType(10);
chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID());
DispatchMessage.dispatchMsgToAll(chatMsg);
// Warehouse this claim event
MineRecord mineRecord = MineRecord.borrow(mine, mine.lastClaimer, Enum.RecordEventType.CAPTURE);
DataWarehouse.pushToWarehouse(mineRecord);
mineBuilding.setRank(mineBuilding.getRank());
mine.lastClaimer = null;
mine.setActive(false);
mine.wasClaimed = true;
for(Integer id : mine._playerMemory){
PlayerCharacter pc = PlayerCharacter.getFromCache(id);
if(pc != null)
pc.ZergMultiplier = 1.0f;
}
return true;
}
public void run() {
Logger.info("Half-Hourly job is now running.");
// Open or Close mines for the current mine window.
processMineWindow();
}
}

257
src/engine/workthreads/HourlyJobThread.java

@ -10,13 +10,8 @@ @@ -10,13 +10,8 @@
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.net.DispatchMessage;
import engine.net.MessageDispatcher;
import engine.net.client.msg.chat.ChatSystemMsg;
import engine.objects.*;
import engine.server.world.WorldServer;
import org.pmw.tinylog.Logger;
@ -25,240 +20,18 @@ import java.time.LocalDateTime; @@ -25,240 +20,18 @@ import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import static engine.server.MBServerStatics.MINE_LATE_WINDOW;
public class HourlyJobThread implements Runnable {
public HourlyJobThread() {
}
public static void decayShrines() {
ArrayList<Shrine> shrineList = new ArrayList<>();
for (Shrine shrine : Shrine.shrinesByBuildingUUID.values()) {
try {
Building shrineBuilding = (Building) DbManager.getObject(Enum.GameObjectType.Building, shrine.getBuildingID());
if (shrineBuilding == null)
continue;
if (shrineBuilding.getOwner().equals(shrineBuilding.getCity().getOwner()) == false)
shrineBuilding.claim(shrineBuilding.getCity().getOwner());
} catch (Exception e) {
Logger.info("Shrine " + shrine.getBuildingID() + " Error " + e);
}
}
// Grab list of top two shrines of each type
for (Shrine shrine : Shrine.shrinesByBuildingUUID.values()) {
if (shrine.getRank() == 0 || shrine.getRank() == 1)
shrineList.add(shrine);
}
Logger.info("Decaying " + shrineList.size() + " shrines...");
// Top 2 shrines decay by 10% a day
for (Shrine shrine : shrineList) {
try {
shrine.decay();
} catch (Exception e) {
Logger.info("Shrine " + shrine.getBuildingID() + " Error " + e);
}
}
}
public static void processMineWindow() {
try {
ArrayList<Mine> mines = Mine.getMines();
for (Mine mine : mines) {
if (LocalDateTime.now().getHour() == 1400) {
mine.wasClaimed = false;
}
try {
// Open Errant Mines
if (mine.getOwningGuild().isEmptyGuild()) {
HourlyJobThread.mineWindowOpen(mine);
continue;
}
// Open Mines owned by nations having their WOO
// set to the current mine window.
if (mine.getOwningGuild().getNation().getMineTime() ==
LocalDateTime.now().getHour() && mine.wasClaimed == false) {
HourlyJobThread.mineWindowOpen(mine);
continue;
}
// Close the mine if it reaches this far
mineWindowClose(mine);
} catch (Exception e) {
Logger.error("mineID: " + mine.getObjectUUID(), e.toString());
}
}
} catch (Exception e) {
Logger.error(e.toString());
}
}
public static void mineWindowOpen(Mine mine) {
mine.setActive(true);
ChatManager.chatSystemChannel(mine.getZoneName() + "'s Mine is now Active!");
Logger.info(mine.getZoneName() + "'s Mine is now Active!");
}
public static boolean mineWindowClose(Mine mine) {
// No need to end the window of a mine which never opened.
if (mine.isActive == false)
return false;
Building mineBuilding = BuildingManager.getBuildingFromCache(mine.getBuildingID());
if (mineBuilding == null) {
Logger.debug("Null mine building for Mine " + mine.getObjectUUID() + " Building " + mine.getBuildingID());
return false;
}
// Mine building still stands; nothing to do.
// We can early exit here.
if (mineBuilding.getRank() > 0) {
mine.setActive(false);
mine.lastClaimer = null;
return true;
}
// This mine does not have a valid claimer
// we will therefore set it to errant
// and keep the window open.
if (!Mine.validateClaimer(mine.lastClaimer)) {
mine.lastClaimer = null;
mine.updateGuildOwner(null);
mine.setActive(true);
return false;
}
//Update ownership to map
mine.guildName = mine.getOwningGuild().getName();
mine.guildTag = mine.getOwningGuild().getGuildTag();
Guild nation = mine.getOwningGuild().getNation();
mine.nationName = nation.getName();
mine.nationTag = nation.getGuildTag();
mineBuilding.rebuildMine();
WorldGrid.updateObject(mineBuilding);
ChatSystemMsg chatMsg = new ChatSystemMsg(null, mine.lastClaimer.getName() + " has claimed the mine in " + mine.getParentZone().getParent().getName() + " for " + mine.getOwningGuild().getName() + ". The mine is no longer active.");
chatMsg.setMessageType(10);
chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID());
DispatchMessage.dispatchMsgToAll(chatMsg);
// Warehouse this claim event
MineRecord mineRecord = MineRecord.borrow(mine, mine.lastClaimer, Enum.RecordEventType.CAPTURE);
DataWarehouse.pushToWarehouse(mineRecord);
mineBuilding.setRank(mineBuilding.getRank());
mine.lastClaimer = null;
mine.setActive(false);
mine.wasClaimed = true;
return true;
}
public void run() {
// *** REFACTOR: TRY TRY TRY TRY {{{{{{{{{{{ OMG
Logger.info("Hourly job is now running.");
try {
// Use the same hotZone this hour up and until
// the HotZone_Duration from the ConfigManager
if (ZoneManager.hotZone == null)
ZoneManager.generateAndSetRandomHotzone();
else
ZoneManager.hotZoneCycle = ZoneManager.hotZoneCycle + 1;
if (ZoneManager.hotZoneCycle > Integer.parseInt(ConfigManager.MB_HOTZONE_DURATION.getValue()))
ZoneManager.generateAndSetRandomHotzone();
if (ZoneManager.hotZone == null) {
Logger.error("Null HotZone returned from ZoneManager");
} else {
Logger.info("HotZone switched to: " + ZoneManager.hotZone.getName());
}
} catch (Exception e) {
Logger.error(e.toString());
}
// Open or Close mines for the current mine window.
processMineWindow();
// Deposit mine resources to Guilds
for (Mine mine : Mine.getMines()) {
try {
mine.depositMineResources();
} catch (Exception e) {
Logger.info(e.getMessage() + " for Mine " + mine.getObjectUUID());
}
}
// Reset time-gated access to WOO slider.
// *** Do this after the mines open/close!
if (LocalDateTime.now().getHour() == MINE_LATE_WINDOW) {
Guild guild;
for (AbstractGameObject dbObject : DbManager.getList(Enum.GameObjectType.Guild)) {
guild = (Guild) dbObject;
if (guild != null)
guild.wooWasModified = false;
}
}
// Mines can only be claimed once per cycle.
// This will reset at 1am after the last mine
// window closes.
if (LocalDateTime.now().getHour() == MINE_LATE_WINDOW + 1) {
for (Mine mine : Mine.getMines()) {
if (mine.wasClaimed == true)
mine.wasClaimed = false;
}
}
// Decay Shrines at midnight every day
if (LocalDateTime.now().getHour() == MINE_LATE_WINDOW)
decayShrines();
// Update city population values
ConcurrentHashMap<Integer, AbstractGameObject> map = DbManager.getMap(Enum.GameObjectType.City);
@ -280,6 +53,36 @@ public class HourlyJobThread implements Runnable { @@ -280,6 +53,36 @@ public class HourlyJobThread implements Runnable {
Logger.error("missing city map");
}
//run maintenance every day at 2 am
if(LocalDateTime.now().getHour() == 2) {
MaintenanceManager.dailyMaintenance();
//produce mine resources once a day
for (Mine mine : Mine.getMines()) {
try {
mine.depositMineResources();
} catch (Exception e) {
Logger.info(e.getMessage() + " for Mine " + mine.getObjectUUID());
}
mine.wasClaimed = false;
}
}
switch(LocalDateTime.now().getHour()){
case 3:
case 6:
case 9:
case 12:
case 15:
case 18:
case 21:
case 0:
for(Mob mob : Mob.discDroppers)
if(!mob.isAlive())
Zone.respawnQue.add(mob);
break;
}
// Log metrics to console
Logger.info(WorldServer.getUptimeString());
Logger.info(SimulationManager.getPopulationString());

Loading…
Cancel
Save