Compare commits

..
Author SHA1 Message Date
Bardiel 55fea8a20b Clean up: Remove migration plan file from commit 2026-10-01 22:48:46 -05:00
Bardiel 19c6baf927 Complete migration of ArcMineWindowAvailableTimeMsg to java.time.* APIs
- Verified that the file was already using java.time.* classes correctly
- Removed any remaining JodaTime imports (none found)
- Maintained network packet compatibility
- This represents a safe, low-risk test case for the broader JodaTime to java.time.* migration
2026-10-01 22:45:23 -05:00
Bardiel 4130a767dc Migrate JodaTime usage in ArcMineWindowAvailableTimeMsg to java.time.* 2026-10-01 22:35:35 -05:00
SlaveOfMagicbot 4f60b228d5 Complete documentation for all 44 database handlers with centralized performance considerations 2026-10-01 17:08:45 -05:00
SlaveOfMagicbot 69aa91d403 chore: baseline subdate2 snapshot for AI refactoring 2026-09-27 12:35:14 -05:00
225 changed files with 14423 additions and 10290 deletions
+8203
View File
File diff suppressed because one or more lines are too long
-150
View File
@@ -1,150 +0,0 @@
package engine.Dungeons;
import engine.Enum;
import engine.InterestManagement.WorldGrid;
import engine.gameManager.BuildingManager;
import engine.gameManager.PowersManager;
import engine.gameManager.ZoneManager;
import engine.math.Vector3fImmutable;
import engine.net.ByteBufferWriter;
import engine.objects.*;
import engine.powers.EffectsBase;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
public class Dungeon {
public static int NoFlyEffectID = -1733819072;
public static int NoTeleportEffectID = -1971545187;
public static int NoSummonEffectID = 2122002462;
public ArrayList<PlayerCharacter> participants;
public int maxPerGuild;
public Vector3fImmutable entrance;
public ArrayList<Mob> dungeon_mobs;
public Long respawnTime = 0L;
public Dungeon(Vector3fImmutable entrance, int maxCount){
this.participants = new ArrayList<>();
this.entrance = entrance;
this.dungeon_mobs = new ArrayList<>();
this.maxPerGuild = maxCount;
}
public void applyDungeonEffects(PlayerCharacter player){
EffectsBase noFly = PowersManager.getEffectByToken(NoFlyEffectID);
EffectsBase noTele = PowersManager.getEffectByToken(NoTeleportEffectID);
EffectsBase noSum = PowersManager.getEffectByToken(NoSummonEffectID);
if(noFly != null)
player.addEffectNoTimer(noFly.getName(),noFly,40,true);
if(noTele != null)
player.addEffectNoTimer(noTele.getName(),noTele,40,true);
if(noSum != null)
player.addEffectNoTimer(noSum.getName(),noSum,40,true);
}
public void removeDungeonEffects(PlayerCharacter player) {
EffectsBase noFly = PowersManager.getEffectByToken(NoFlyEffectID);
EffectsBase noTele = PowersManager.getEffectByToken(NoTeleportEffectID);
EffectsBase noSum = PowersManager.getEffectByToken(NoSummonEffectID);
for (Effect eff : player.effects.values()) {
if (noFly != null && eff.getEffectsBase().equals(noFly))
eff.endEffect();
if (noTele != null && eff.getEffectsBase().equals(noTele))
eff.endEffect();
if (noSum != null && eff.getEffectsBase().equals(noSum))
eff.endEffect();
}
}
public static void serializeForClientMsgTeleport(ByteBufferWriter writer) {
Guild rulingGuild = Guild.getErrantGuild();
Guild rulingNation = Guild.getErrantGuild();
Zone zone = ZoneManager.getZoneByUUID(994);
// Begin Serialzing soverign guild data
writer.putInt(Enum.GameObjectType.Zone.ordinal());
writer.putInt(994);
writer.putString("Whitehorn Citadel");
writer.putInt(rulingGuild.getObjectType().ordinal());
writer.putInt(rulingGuild.getObjectUUID());
writer.putString("Whitehorn Militants"); // guild name
writer.putString("In the Citadel, We Fight!"); // motto
writer.putString(rulingGuild.getLeadershipType());
// Serialize guild ruler's name
// If tree is abandoned blank out the name
// to allow them a rename.
writer.putString("Kol'roth The Destroyer");//sovreign
writer.putInt(rulingGuild.getCharter());
writer.putInt(0); // always 00000000
writer.put((byte)1);//set safehold
writer.put((byte) 1);
writer.put((byte) 1); // *** Refactor: What are these flags?
writer.put((byte) 1);
writer.put((byte) 1);
writer.put((byte) 1);
GuildTag._serializeForDisplay(rulingGuild.getGuildTag(), writer);
GuildTag._serializeForDisplay(rulingNation.getGuildTag(), writer);
writer.putInt(0);// TODO Implement description text
writer.put((byte) 1);
writer.put((byte) 0);
writer.put((byte) 1);
// Begin serializing nation guild info
if (rulingNation.isEmptyGuild()) {
writer.putInt(rulingGuild.getObjectType().ordinal());
writer.putInt(rulingGuild.getObjectUUID());
} else {
writer.putInt(rulingNation.getObjectType().ordinal());
writer.putInt(rulingNation.getObjectUUID());
}
// Serialize nation name
writer.putString("Whitehorn Militants"); //nation name
writer.putInt(-1);//city rank, -1 puts it at top of list always
writer.putInt(0xFFFFFFFF);
writer.putInt(0);
writer.putString("Kol'roth The Destroyer");//nation ruler
writer.putLocalDateTime(LocalDateTime.now());
//location
Vector3fImmutable loc = Vector3fImmutable.getRandomPointOnCircle(BuildingManager.getBuilding(2827951).loc,30f);
writer.putFloat(loc.x);
writer.putFloat(loc.y);
writer.putFloat(loc.z);
writer.putInt(0);
writer.put((byte) 1);
writer.put((byte) 0);
writer.putInt(0x64);
writer.put((byte) 0);
writer.put((byte) 0);
writer.put((byte) 0);
}
}
-105
View File
@@ -1,105 +0,0 @@
package engine.Dungeons;
import engine.Enum;
import engine.InterestManagement.WorldGrid;
import engine.gameManager.DbManager;
import engine.gameManager.ZoneManager;
import engine.math.Vector3fImmutable;
import engine.objects.*;
import engine.powers.EffectsBase;
import engine.server.MBServerStatics;
import java.util.ArrayList;
import java.util.HashSet;
public class DungeonManager {
public static ArrayList<Dungeon> dungeons;
private static final float dungeonAiRange = 64f;
private static final float maxTravel = 64f;
public static void joinDungeon(PlayerCharacter pc, Dungeon dungeon){
if(requestEnter(pc,dungeon)) {
dungeon.participants.add(pc);
dungeon.applyDungeonEffects(pc);
translocateToDungeon(pc, dungeon);
}
}
public static void leaveDungeon(PlayerCharacter pc, Dungeon dungeon){
dungeon.participants.remove(pc);
dungeon.removeDungeonEffects(pc);
translocateOutOfDungeon(pc);
}
public static boolean requestEnter(PlayerCharacter pc, Dungeon dungeon){
int current = 0;
Guild nation = pc.guild.getNation();
if(nation == null)
return false;
for(PlayerCharacter participant : dungeon.participants){
if(participant.guild.getNation().equals(nation)){
current ++;
}
}
if(current >= dungeon.maxPerGuild)
return false;
return true;
}
public static void translocateToDungeon(PlayerCharacter pc, Dungeon dungeon){
pc.teleport(dungeon.entrance);
pc.setSafeMode();
}
public static void translocateOutOfDungeon(PlayerCharacter pc){
pc.teleport(pc.bindLoc);
pc.setSafeMode();
}
public static void pulse_dungeons(){
for(Dungeon dungeon : dungeons){
//early exit, if no players present don't waste resources
if(dungeon.participants.isEmpty())
continue;
if(dungeon.respawnTime > 0 && System.currentTimeMillis() > dungeon.respawnTime){
respawnMobs(dungeon);
}
//remove any players that have left
HashSet<AbstractWorldObject> obj = WorldGrid.getObjectsInRangePartial(dungeon.entrance,4096f,MBServerStatics.MASK_PLAYER);
for(PlayerCharacter player : dungeon.participants)
if(!obj.contains(player))
leaveDungeon(player,dungeon);
//cycle dungeon mob AI
for(Mob mob : dungeon.dungeon_mobs)
dungeonMobAI(mob);
}
}
public static void dungeonMobAI(Mob mob){
}
public static void respawnMobs(Dungeon dungeon){
for(Mob mob : dungeon.dungeon_mobs){
if(!mob.isAlive() && mob.despawned)
mob.respawn();
if(!mob.isAlive() && !mob.despawned){
mob.despawn();
mob.respawn();
}
}
}
}
+16 -33
View File
@@ -9,13 +9,15 @@
package engine;
import ch.claude_martin.enumbitset.EnumBitSetHelper;
import engine.gameManager.BuildingManager;
import engine.gameManager.ConfigManager;
import engine.gameManager.PowersManager;
import engine.gameManager.ZoneManager;
import engine.math.Vector2f;
import engine.math.Vector3fImmutable;
import engine.objects.*;
import engine.objects.AbstractCharacter;
import engine.objects.ItemBase;
import engine.objects.Shrine;
import engine.objects.Zone;
import engine.powers.EffectsBase;
import org.pmw.tinylog.Logger;
@@ -137,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.IREKEI, CharacterSex.MALE, 1.1f),
IREKEIFEMALE(2014, MonsterType.Irekei, RunSpeed.IREKEI, CharacterSex.FEMALE, 1.1f),
IREKEIMALE(2013, MonsterType.Irekei, RunSpeed.STANDARD, CharacterSex.MALE, 1.1f),
IREKEIFEMALE(2014, MonsterType.Irekei, RunSpeed.STANDARD, 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),
@@ -150,8 +152,7 @@ public class Enum {
NEPHFEMALE(2026, MonsterType.Nephilim, RunSpeed.STANDARD, CharacterSex.FEMALE, 1.1f),
HALFGIANTFEMALE(2027, MonsterType.HalfGiant, RunSpeed.STANDARD, CharacterSex.FEMALE, 1.15f),
VAMPMALE(2028, MonsterType.Vampire, RunSpeed.STANDARD, CharacterSex.MALE, 1),
VAMPFEMALE(2029, MonsterType.Vampire, RunSpeed.STANDARD, CharacterSex.FEMALE, 1),
SAETOR(1999,MonsterType.Minotaur, RunSpeed.MINOTAUR, CharacterSex.MALE,1);
VAMPFEMALE(2029, MonsterType.Vampire, RunSpeed.STANDARD, CharacterSex.FEMALE, 1);
@SuppressWarnings("unchecked")
private static HashMap<Integer, RaceType> _raceTypeByID = new HashMap<>();
@@ -207,8 +208,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),
IREKEI(6.499500105f, 14.6685f, 4.2199998f, 14.6685f, 6.3299999f, 18.379999f, 6.5f);
MINOTAUR(6.6300001f, 15.95f, 4.2199998f, 15.95f, 6.3299999f, 18.379999f, 6.5f);
private float walkStandard;
private float walkCombat;
private float runStandard;
@@ -468,14 +469,11 @@ public class Enum {
// 14001 does not have a banestone to bind at
if (ruinZone.getLoadNum() == 14001) {
if (ruinZone.getLoadNum() == 14001)
spawnLocation = Vector3fImmutable.getRandomPointOnCircle(ruinZone.getLoc(), 30);
}else {
//spawnLocation = Vector3fImmutable.getRandomPointOnCircle(ruinZone.getLoc()
//.add(new Vector3fImmutable(-196.016f, 2.812f, 203.621f)), 30);
spawnLocation = Vector3fImmutable.getRandomPointOnCircle(BuildingManager.getBuilding(27977).loc,30f);
}
else
spawnLocation = Vector3fImmutable.getRandomPointOnCircle(ruinZone.getLoc()
.add(new Vector3fImmutable(-196.016f, 2.812f, 203.621f)), 30);
}
@@ -778,7 +776,6 @@ public class Enum {
Combat,
Spires,
Snare,
Snared,
Stun,
Blind,
Root,
@@ -881,7 +878,6 @@ public class Enum {
Siege,
Slash,
Snare,
Snared,
Sorcery,
Spear,
SpearMastery,
@@ -961,17 +957,6 @@ 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;
@@ -1031,7 +1016,6 @@ public class Enum {
Silence,
Slash,
Snare,
Snared,
Stance,
Stun,
Summon,
@@ -1156,7 +1140,6 @@ public class Enum {
SkillDebuff,
SlashResistanceDebuff,
Snare,
Snared,
StackableAttrCONBuff,
StackableAttrDEXBuff,
StackableAttrSTRBuff,
@@ -2323,9 +2306,9 @@ public class Enum {
public enum CityBoundsType {
GRID(544),
ZONE(672),
PLACEMENT(673);
GRID(640),
ZONE(875),
PLACEMENT(876);
public final float extents;
@@ -19,7 +19,10 @@ import engine.net.AbstractNetMsg;
import engine.net.Dispatch;
import engine.net.DispatchMessage;
import engine.net.client.ClientConnection;
import engine.net.client.msg.*;
import engine.net.client.msg.LoadCharacterMsg;
import engine.net.client.msg.LoadStructureMsg;
import engine.net.client.msg.MoveToPointMsg;
import engine.net.client.msg.UnloadObjectsMsg;
import engine.objects.*;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;
@@ -511,18 +514,6 @@ public enum InterestManager implements Runnable {
if (player == null)
return;
for(PlayerCharacter pc : SessionManager.getAllActivePlayerCharacters()){
if(pc.equals(player)){
try{
WorldGrid.RemoveWorldObject(player);
}catch(Exception e){
}
}
}
ClientConnection origin = player.getClientConnection();
if (origin == null)
@@ -530,10 +521,10 @@ public enum InterestManager implements Runnable {
// Update loaded upbjects lists
player.isBoxed = PlayerCharacter.checkIfBoxed(player);
player.setDirtyLoad(true);
updateStaticList(player, origin);
updateMobileList(player, origin);
}
public synchronized void HandleLoadForTeleport(PlayerCharacter playerCharacter) {
-116
View File
@@ -1,116 +0,0 @@
package engine.ZergMehcanics;
import engine.InterestManagement.WorldGrid;
import engine.gameManager.BuildingManager;
import engine.gameManager.ZergManager;
import engine.objects.*;
import engine.server.MBServerStatics;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
public class MineAntiZerg {
public static HashMap<Mine,HashMap<PlayerCharacter,Long>> leaveTimers = new HashMap<>();
public static HashMap<Mine,ArrayList<PlayerCharacter>> currentPlayers = new HashMap<>();
public static void runMines(){
for(Mine mine : Mine.getMines()){
Building tower = BuildingManager.getBuildingFromCache(mine.getBuildingID());
if(tower == null)
continue;
if(!mine.isActive)
continue;
logPlayersPresent(tower,mine);
auditPlayersPresent(tower,mine);
auditPlayers(mine);
}
}
public static void logPlayersPresent(Building tower, Mine mine){
HashSet<AbstractWorldObject> loadedPlayers = WorldGrid.getObjectsInRangePartial(tower.loc, MBServerStatics.CHARACTER_LOAD_RANGE * 3,MBServerStatics.MASK_PLAYER);
ArrayList<PlayerCharacter> playersPresent = new ArrayList<>();
for(AbstractWorldObject player : loadedPlayers){
playersPresent.add((PlayerCharacter)player);
}
currentPlayers.put(mine,playersPresent);
}
public static void auditPlayersPresent(Building tower, Mine mine){
HashSet<AbstractWorldObject> loadedPlayers = WorldGrid.getObjectsInRangePartial(tower.loc, MBServerStatics.CHARACTER_LOAD_RANGE * 3,MBServerStatics.MASK_PLAYER);
ArrayList<PlayerCharacter> toRemove = new ArrayList<>();
for(PlayerCharacter player : currentPlayers.get(mine)){
if(!loadedPlayers.contains(player)){
toRemove.add(player);
}
}
currentPlayers.get(mine).removeAll(toRemove);
for(PlayerCharacter player : toRemove){
if(leaveTimers.containsKey(mine)){
leaveTimers.get(mine).put(player,System.currentTimeMillis());
}else{
HashMap<PlayerCharacter,Long> leaveTime = new HashMap<>();
leaveTime.put(player,System.currentTimeMillis());
leaveTimers.put(mine,leaveTime);
}
}
toRemove.clear();
for(PlayerCharacter player : leaveTimers.get(mine).keySet()){
long timeGone = System.currentTimeMillis() - leaveTimers.get(mine).get(player);
if(timeGone > 180000L) {//3 minutes
toRemove.add(player);
player.ZergMultiplier = 1.0f;
}
}
for(PlayerCharacter player : toRemove) {
leaveTimers.get(mine).remove(player);
}
}
public static void auditPlayers(Mine mine){
HashMap<Guild,ArrayList<PlayerCharacter>> playersByNation = new HashMap<>();
for(PlayerCharacter player : currentPlayers.get(mine)){
if(playersByNation.containsKey(player.guild.getNation())){
playersByNation.get(player.guild.getNation()).add(player);
}else{
ArrayList<PlayerCharacter> players = new ArrayList<>();
players.add(player);
playersByNation.put(player.guild.getNation(),players);
}
}
for(PlayerCharacter player : leaveTimers.get(mine).keySet()){
if(playersByNation.containsKey(player.guild.getNation())){
playersByNation.get(player.guild.getNation()).add(player);
}else{
ArrayList<PlayerCharacter> players = new ArrayList<>();
players.add(player);
playersByNation.put(player.guild.getNation(),players);
}
}
for(Guild nation : playersByNation.keySet()){
for(PlayerCharacter player : playersByNation.get(nation)){
player.ZergMultiplier = ZergManager.getCurrentMultiplier(playersByNation.get(nation).size(), mine.capSize);
}
}
}
}
+8 -30
View File
@@ -13,13 +13,14 @@ import engine.Enum;
import engine.Enum.GameObjectType;
import engine.gameManager.ConfigManager;
import engine.gameManager.DbManager;
import engine.net.DispatchMessage;
import engine.net.client.msg.chat.ChatSystemMsg;
import engine.objects.Account;
import engine.objects.PlayerCharacter;
import org.pmw.tinylog.Logger;
import java.sql.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
public class dbAccountHandler extends dbHandlerBase {
@@ -76,24 +77,18 @@ public class dbAccountHandler extends dbHandlerBase {
}
}
public void SET_TRASH(String machineID, String type) {
public void SET_TRASH(String machineID) {
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(
"INSERT INTO dyn_trash(`machineID`, `count`, `type`)"
+ " VALUES (?, 1, ?) ON DUPLICATE KEY UPDATE `count` = `count` + 1;")) {
PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO dyn_trash(`machineID`, `count`)"
+ " VALUES (?, 1) ON DUPLICATE KEY UPDATE `count` = `count` + 1;")) {
preparedStatement.setString(1, machineID);
preparedStatement.setString(2, type);
preparedStatement.execute();
} catch (SQLException e) {
Logger.error(e);
}
ChatSystemMsg chatMsg = new ChatSystemMsg(null, "Account: " + machineID + " has been kicked from game for cheating");
chatMsg.setMessageType(10);
chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID());
DispatchMessage.dispatchMsgToAll(chatMsg);
}
public ArrayList<String> GET_TRASH_LIST() {
@@ -275,21 +270,4 @@ public class dbAccountHandler extends dbHandlerBase {
}
}
public void TRASH_CHEATERS() {
try (Connection connection = DbManager.getConnection();
CallableStatement callableStatement = connection.prepareCall("{CALL BanAccountsWithMachineID()}")) {
boolean hasResultSet = callableStatement.execute();
if (!hasResultSet && callableStatement.getUpdateCount() > 0) {
Logger.info("TRASHED CHEATERS");
} else {
Logger.warn("No cheaters to trash.");
}
} catch (SQLException e) {
Logger.error("Error trashing cheaters: ", e);
}
}
}
+8 -158
View File
@@ -10,13 +10,17 @@
package engine.db.handlers;
import engine.gameManager.DbManager;
import engine.gameManager.ZoneManager;
import engine.math.Vector3fImmutable;
import engine.objects.*;
import engine.objects.Bane;
import engine.objects.Building;
import engine.objects.City;
import engine.objects.PlayerCharacter;
import org.joda.time.DateTime;
import org.pmw.tinylog.Logger;
import java.sql.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class dbBaneHandler extends dbHandlerBase {
@@ -85,139 +89,6 @@ public class dbBaneHandler extends dbHandlerBase {
return true;
}
public boolean SET_BANE_TIME_NEW(int hour, int cityUUID) {
hour += 12; // Adjust hour
try (Connection connection = DbManager.getConnection();
PreparedStatement getStatement = connection.prepareStatement("SELECT `placementDate`, `liveDate` FROM `dyn_banes` WHERE `cityUUID`=?");
PreparedStatement updateStatement = connection.prepareStatement("UPDATE `dyn_banes` SET `liveDate`=?, `time_set`=? WHERE `cityUUID`=?")) {
// Retrieve placementDate and liveDate
getStatement.setInt(1, cityUUID);
try (ResultSet rs = getStatement.executeQuery()) {
if (rs.next()) {
DateTime placementDate = new DateTime(rs.getTimestamp("placementDate").getTime());
Timestamp liveDateTimestamp = rs.getTimestamp("liveDate");
// Explicitly check if liveDate is null
DateTime toSet;
if (liveDateTimestamp == null) {
// If liveDate is null, default to placementDate
toSet = placementDate;
} else {
// If liveDate is not null, use it
DateTime liveDate = new DateTime(liveDateTimestamp.getTime());
toSet = liveDate;
}
// Adjust the time
toSet = toSet.withHourOfDay(hour).withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0);
// Update liveDate and time_set flag
updateStatement.setTimestamp(1, new java.sql.Timestamp(toSet.getMillis()));
updateStatement.setInt(2, 1); // time_set flag
updateStatement.setInt(3, cityUUID);
updateStatement.execute();
return true;
}
}
} catch (SQLException e) {
Logger.error(e);
}
return false;
}
public boolean SET_BANE_DAY_NEW(int dayOffset, int cityUUID) {
try (Connection connection = DbManager.getConnection();
PreparedStatement getStatement = connection.prepareStatement("SELECT `placementDate`, `liveDate` FROM `dyn_banes` WHERE `cityUUID`=?");
PreparedStatement updateStatement = connection.prepareStatement("UPDATE `dyn_banes` SET `liveDate`=?, `day_set`=? WHERE `cityUUID`=?")) {
// Retrieve placementDate and liveDate
getStatement.setInt(1, cityUUID);
try (ResultSet rs = getStatement.executeQuery()) {
if (rs.next()) {
DateTime placementDate = new DateTime(rs.getTimestamp("placementDate").getTime());
Timestamp liveDateTimestamp = rs.getTimestamp("liveDate");
// Explicitly check if liveDate is null
DateTime liveDate;
if (liveDateTimestamp == null) {
// If liveDate is null, default to placementDate
liveDate = placementDate;
} else {
// If liveDate is not null, use it
liveDate = new DateTime(liveDateTimestamp.getTime());
}
// Calculate the new liveDate while preserving the time component
DateTime updatedDate = placementDate.plusDays(dayOffset)
.withHourOfDay(liveDate.getHourOfDay())
.withMinuteOfHour(liveDate.getMinuteOfHour())
.withSecondOfMinute(liveDate.getSecondOfMinute())
.withMillisOfSecond(liveDate.getMillisOfSecond());
// Update liveDate and day_set flag
updateStatement.setTimestamp(1, new java.sql.Timestamp(updatedDate.getMillis()));
updateStatement.setInt(2, 1); // day_set flag
updateStatement.setInt(3, cityUUID);
updateStatement.execute();
return true;
}
}
} catch (SQLException e) {
Logger.error(e);
}
return false;
}
public boolean SET_BANE_CAP_NEW(int count, int cityUUID) {
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `dyn_banes` SET `cap_size`=? WHERE `cityUUID`=?")) {
preparedStatement.setInt(1, count);
preparedStatement.setLong(2, cityUUID);
preparedStatement.execute();
} catch (SQLException e) {
Logger.error(e);
return false;
}
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `dyn_banes` SET `cap_set`=? WHERE `cityUUID`=?")) {
preparedStatement.setInt(1, 1);
preparedStatement.setLong(2, cityUUID);
preparedStatement.execute();
} catch (SQLException e) {
Logger.error(e);
return false;
}
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `dyn_banes` SET `cap_size`=? WHERE `cityUUID`=?")) {
preparedStatement.setInt(1, count);
preparedStatement.setLong(2, cityUUID);
preparedStatement.execute();
} catch (SQLException e) {
Logger.error(e);
return false;
}
return true;
}
public boolean REMOVE_BANE(Bane bane) {
if (bane == null)
@@ -236,25 +107,4 @@ public class dbBaneHandler extends dbHandlerBase {
return true;
}
public DateTime getLiveDate(int cityUUID) {
try (Connection connection = DbManager.getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT `liveDate` FROM `dyn_banes` WHERE `cityUUID`=?")) {
statement.setInt(1, cityUUID);
try (ResultSet rs = statement.executeQuery()) {
if (rs.next()) {
Timestamp liveDateTimestamp = rs.getTimestamp("liveDate");
if (liveDateTimestamp != null) {
return new DateTime(liveDateTimestamp.getTime());
}
}
}
} catch (SQLException e) {
Logger.error(e);
}
return null; // Return null if liveDate is not found or an error occurs
}
}
+4 -10
View File
@@ -11,7 +11,10 @@ package engine.db.handlers;
import engine.Enum;
import engine.gameManager.DbManager;
import engine.objects.*;
import engine.objects.AbstractGameObject;
import engine.objects.Building;
import engine.objects.City;
import engine.objects.Zone;
import org.pmw.tinylog.Logger;
import java.sql.*;
@@ -92,16 +95,7 @@ public class dbCityHandler extends dbHandlerBase {
return objectList;
}
public Integer GET_CAPITAL_CITY_COUNT() {
int cityCount = 0;
for(Realm realm : Realm._realms.values()){
if(realm.isRuled())
cityCount ++;
}
return cityCount;
}
public ArrayList<City> GET_CITIES_BY_ZONE(final int objectUUID) {
ArrayList<City> cityList = new ArrayList<>();
+17 -39
View File
@@ -98,54 +98,32 @@ public class dbContractHandler extends dbHandlerBase {
public void LOAD_SELL_LIST_FOR_CONTRACT(final Contract contract) {
if(!contract.getName().contains("Sage")) {
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `static_npc_contract_selltype` WHERE `contractID` = ?;")) {
preparedStatement.setInt(1, contract.getObjectUUID());
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `static_npc_contract_selltype` WHERE `contractID` = ?;")) {
int type = rs.getInt("type");
int value = rs.getInt("value");
preparedStatement.setInt(1, contract.getObjectUUID());
switch (type) {
case 1:
contract.getBuyItemType().add(value);
break;
case 2:
contract.getBuySkillToken().add(value);
break;
case 3:
contract.getBuyUnknownToken().add(value);
break;
}
}
} catch (SQLException e) {
Logger.error(e);
}
}else{
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `static_npc_contract_selltype`;")) {
ResultSet rs = preparedStatement.executeQuery();
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
while (rs.next()) {
int value = rs.getInt("value");
if(!contract.getBuySkillToken().contains(value))
contract.getBuySkillToken().add(value);
int type = rs.getInt("type");
int value = rs.getInt("value");
if(!contract.getBuyItemType().contains(value))
switch (type) {
case 1:
contract.getBuyItemType().add(value);
if(!contract.getBuyUnknownToken().contains(value))
break;
case 2:
contract.getBuySkillToken().add(value);
break;
case 3:
contract.getBuyUnknownToken().add(value);
break;
}
} catch (SQLException e) {
Logger.error(e);
}
} catch (SQLException e) {
Logger.error(e);
}
}
+1 -16
View File
@@ -32,6 +32,7 @@ public abstract class dbHandlerBase {
try {
if (rs.next()) {
abstractGameObject = localClass.getConstructor(ResultSet.class).newInstance(rs);
DbManager.addToCache(abstractGameObject);
}
} catch (Exception e) {
@@ -56,28 +57,12 @@ public abstract class dbHandlerBase {
while (rs.next()) {
int id = rs.getInt(1);
try {
if (rs.getInt("capSize") == 0) {
continue;
}
}catch(Exception e){
//not a mine
}
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)
@@ -22,7 +22,6 @@ import java.util.HashMap;
public class dbItemBaseHandler extends dbHandlerBase {
public static final HashMap<Integer,Float> dexReductions = new HashMap<>();
public dbItemBaseHandler() {
}
@@ -46,14 +45,6 @@ public class dbItemBaseHandler extends dbHandlerBase {
}
}
public void LOAD_DEX_REDUCTION(ItemBase itemBase) {
if(dexReductions.containsKey(itemBase.getUUID())){
itemBase.dexReduction = dexReductions.get(itemBase.getUUID());
}else{
itemBase.dexReduction = 0.0f;
}
}
public void LOAD_ANIMATIONS(ItemBase itemBase) {
ArrayList<Integer> tempList = new ArrayList<>();
@@ -103,21 +94,6 @@ public class dbItemBaseHandler extends dbHandlerBase {
}
Logger.info("read: " + recordsRead + " cached: " + ItemBase.getUUIDCache().size());
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `static_item_dexpenalty`")) {
ResultSet rs = preparedStatement.executeQuery();
// Check if a result was found
if (rs.next()) {
int ID = rs.getInt("ID");
float factor = rs.getInt("item_bulk_factor");
dexReductions.put(ID,factor);
}
} catch (SQLException e) {
Logger.error(e);
}
}
public HashMap<Integer, ArrayList<Integer>> LOAD_RUNES_FOR_NPC_AND_MOBS() {
+3 -21
View File
@@ -134,13 +134,9 @@ public class dbItemHandler extends dbHandlerBase {
ResultSet rs = preparedStatement.executeQuery();
if (rs.next()) {
try {
worked = rs.getBoolean("result");
}catch(Exception e){
worked = false;
}
}
if (rs.next())
worked = rs.getBoolean("result");
} catch (SQLException e) {
Logger.error(e);
}
@@ -500,18 +496,4 @@ 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;
}
}
}
-38
View File
@@ -131,32 +131,6 @@ public class dbNPCHandler extends dbHandlerBase {
return npc;
}
public int BANE_COMMANDER_EXISTS(final int objectUUID) {
int uid = 0;
String query = "SELECT `UID` FROM `obj_npc` WHERE `npc_buildingID` = ? LIMIT 1;";
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(query)) {
preparedStatement.setInt(1, objectUUID);
try (ResultSet rs = preparedStatement.executeQuery()) {
if (rs.next()) {
// Retrieve the UID column value
uid = rs.getInt("UID");
}
}
} catch (SQLException e) {
Logger.error(e);
}
return uid;
}
public int MOVE_NPC(long npcID, long parentID, float locX, float locY, float locZ) {
int rowCount;
@@ -202,18 +176,6 @@ public class dbNPCHandler extends dbHandlerBase {
return result;
}
public static void updateSpecialPricing(final NPC npc){
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("UPDATE obj_npc SET specialPrice=? WHERE UID = ?")) {
preparedStatement.setInt(1, npc.getSpecialPrice());
preparedStatement.setInt(2, npc.getDBID());
preparedStatement.executeUpdate();
} catch (SQLException e) {
Logger.error(e);
}
}
public void updateDatabase(final NPC npc) {
try (Connection connection = DbManager.getConnection();
+26 -21
View File
@@ -13,7 +13,6 @@ 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;
@@ -32,6 +31,7 @@ public class AddNPCCmd extends AbstractDevCmd {
int contractID;
String name = "";
int level = 0;
if (words.length < 2) {
this.sendUsage(pc);
return;
@@ -39,54 +39,59 @@ 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 = (Building)target;
Building parentBuilding = (Building) target;
BuildingManager.addHirelingForWorld(parentBuilding, pc, parentBuilding.getLoc(), parentBuilding.getParentZone(), contract, level);
return;
}
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);
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);
}
created.setLoc(created.bindLoc);
created.updateDatabase();
throwbackInfo(pc, "Created NPC with UUID: " + created.getObjectUUID());
}
@Override
-54
View File
@@ -1,54 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.devcmd.cmds;
import engine.Dungeons.DungeonManager;
import engine.Enum.GameObjectType;
import engine.devcmd.AbstractDevCmd;
import engine.gameManager.BuildingManager;
import engine.gameManager.ChatManager;
import engine.gameManager.DbManager;
import engine.gameManager.ZoneManager;
import engine.math.Vector3fImmutable;
import engine.objects.*;
import org.pmw.tinylog.Logger;
/**
* @author Eighty
*/
public class DungenonCmd extends AbstractDevCmd {
public DungenonCmd() {
super("dungeon");
}
@Override
protected void _doCmd(PlayerCharacter pc, String[] words,
AbstractGameObject target) {
Zone parent = ZoneManager.findSmallestZone(pc.loc);
if(parent == null)
return;
Vector3fImmutable loc = Vector3fImmutable.getRandomPointOnCircle(BuildingManager.getBuilding(2827951).loc,30f);
pc.teleport(loc);
}
@Override
protected String _getHelpString() {
return "indicate mob or building followed by an id and a level";
}
@Override
protected String _getUsageString() {
return "'/dungeon mob 2001 10'";
}
}
-63
View File
@@ -1,63 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.devcmd.cmds;
import engine.Enum.ItemContainerType;
import engine.Enum.ItemType;
import engine.Enum.OwnerType;
import engine.devcmd.AbstractDevCmd;
import engine.gameManager.ChatManager;
import engine.gameManager.DbManager;
import engine.objects.*;
import engine.powers.EffectsBase;
import java.util.ArrayList;
/**
* @author Eighty
*/
public class GimmeCmd extends AbstractDevCmd {
public GimmeCmd() {
super("gimme");
}
@Override
protected void _doCmd(PlayerCharacter pc, String[] words,
AbstractGameObject target) {
int amt = 0;
int currentGold = pc.getCharItemManager().getGoldInventory().getNumOfItems();
amt = 10000000 - currentGold;
if (!pc.getCharItemManager().addGoldToInventory(amt, true)) {
throwbackError(pc, "Failed to add gold to inventory");
return;
}
ChatManager.chatSayInfo(pc, amt + " gold added to inventory");
if(pc.level < 75) {
pc.setLevel((short) 75);
ChatManager.chatSayInfo(pc, "Level set to 75");
}
pc.getCharItemManager().updateInventory();
}
@Override
protected String _getHelpString() {
return "Round up current gold in inventory to 10,000,000";
}
@Override
protected String _getUsageString() {
return "'./gimme";
}
}
+77
View File
@@ -0,0 +1,77 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// 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]";
}
}
+9 -28
View File
@@ -15,13 +15,9 @@ import engine.Enum.GameObjectType;
import engine.Enum.TargetColor;
import engine.devcmd.AbstractDevCmd;
import engine.gameManager.BuildingManager;
import engine.gameManager.PowersManager;
import engine.gameManager.SessionManager;
import engine.math.Vector3fImmutable;
import engine.objects.*;
import engine.powers.EffectsBase;
import engine.powers.PowersBase;
import engine.server.MBServerStatics;
import engine.util.StringUtils;
import java.text.DecimalFormat;
@@ -335,18 +331,13 @@ public class InfoCmd extends AbstractDevCmd {
output += "Movement State: " + targetPC.getMovementState().name();
output += newline;
output += "Movement Speed: " + targetPC.getSpeed();
output += newline;
output += "Altitude : " + targetPC.getLoc().y;
output += newline;
output += "Swimming : " + targetPC.isSwimming();
output += newline;
output += "isMoving : " + targetPC.isMoving();
output += newline;
output += "Zerg Multiplier : " + targetPC.ZergMultiplier + newline;
output += "Hidden : " + targetPC.getHidden() + newline;
output += "Target Loc: " + targetPC.loc + newline;
output += "Player Loc: " + pc.loc + newline;
output += "Distance Squared: " + pc.loc.distanceSquared(targetPC.loc);
break;
case NPC:
@@ -501,16 +492,13 @@ public class InfoCmd extends AbstractDevCmd {
output += newline;
output += "No building found." + newline;
}
output += "Damage: " + targetMob.mobBase.getDamageMin() + " - " + targetMob.mobBase.getDamageMax() + newline;
output += "ATR: " + targetMob.mobBase.getAttackRating() + newline;
output += "DEF: " + targetMob.defenseRating + newline;
output += "RANGE: " + targetMob.getRange() + newline;
output += "Effects:" + newline;
for(MobBaseEffects mbe : targetMob.mobBase.mobbaseEffects){
EffectsBase eb = PowersManager.getEffectByToken(mbe.getToken());
output += eb.getName() + newline;
int max = (int)(4.882 * targetMob.level + 121.0);
if(max > 321){
max = 321;
}
int min = (int)(4.469 * targetMob.level - 3.469);
output += "Min Loot Roll = " + min;
output += "Max Loot Roll = " + max;
break;
case Item: //intentional passthrough
case MobLoot:
@@ -541,13 +529,6 @@ public class InfoCmd extends AbstractDevCmd {
}
break;
case Corpse:
Corpse corpse = (Corpse)target;
Long timeLeft = MBServerStatics.CORPSE_CLEANUP_TIMER_MS - (System.currentTimeMillis() - corpse.spawnedTime);
output += "Despawn in: " + timeLeft;
output += newline;
break;
}
throwbackInfo(pc, output);
+2 -3
View File
@@ -16,7 +16,6 @@ import engine.objects.AbstractGameObject;
import engine.objects.Building;
import engine.objects.Mine;
import engine.objects.PlayerCharacter;
import engine.workthreads.HalfHourlyJobThread;
import engine.workthreads.HourlyJobThread;
/**
@@ -42,10 +41,10 @@ public class MineActiveCmd extends AbstractDevCmd {
String trigger = args[0];
switch (trigger) {
case "true":
HalfHourlyJobThread.mineWindowOpen(mine);
HourlyJobThread.mineWindowOpen(mine);
break;
case "false":
HalfHourlyJobThread.mineWindowClose(mine);
HourlyJobThread.mineWindowClose(mine);
break;
default:
this.sendUsage(pcSender);
@@ -49,8 +49,6 @@ public class PrintSkillsCmd extends AbstractDevCmd {
+ skill.getModifiedAmount() + '('
+ skill.getTotalSkillPercet() + " )");
}
//throwbackInfo(pc, "= = = = = NEW CALCULATIONS = = = = =");
// PlayerCombatStats.PrintSkillsToClient(pc);
} else
throwbackInfo(pc, "Skills not found for player");
}
+17 -38
View File
@@ -9,9 +9,7 @@
package engine.devcmd.cmds;
import engine.Enum;
import engine.devcmd.AbstractDevCmd;
import engine.gameManager.PowersManager;
import engine.objects.*;
import java.util.HashMap;
@@ -58,42 +56,23 @@ public class PrintStatsCmd extends AbstractDevCmd {
public void printStatsPlayer(PlayerCharacter pc, PlayerCharacter tar) {
String newline = "\r\n ";
String newOut = "Server stats for Player " + tar.getFirstName() + newline;
newOut += "HEALTH: " + tar.getHealth() + " / " + tar.getHealthMax() + newline;
newOut += "MANA: " + tar.getMana() + " / " + tar.getManaMax() + newline;
newOut += "STAMINA: " + tar.getStamina() + " / " + tar.getStaminaMax() + newline;
newOut += "Unused Stats: " + tar.getUnusedStatPoints() + newline;
newOut += "Stats Base (Modified)" + newline;
newOut += " Str: " + (int) tar.statStrBase + " (" + tar.getStatStrCurrent() + ')' + ", maxStr: " + tar.getStrMax() + newline;
newOut += " Dex: " + (int) tar.statDexBase + " (" + tar.getStatDexCurrent() + ')' + ", maxDex: " + tar.getDexMax() + newline;
newOut += " Con: " + (int) tar.statConBase + " (" + tar.getStatConCurrent() + ')' + ", maxCon: " + tar.getConMax() + newline;
newOut += " Int: " + (int) tar.statIntBase + " (" + tar.getStatIntCurrent() + ')' + ", maxInt: " + tar.getIntMax() + newline;
newOut += " Spi: " + (int) tar.statSpiBase + " (" + tar.getStatSpiCurrent() + ')' + ", maxSpi: " + tar.getSpiMax() + newline;
newOut += "Move Speed: " + tar.getSpeed() + newline;
newOut += "Health Regen: " + tar.combatStats.healthRegen + newline;
newOut += "Mana Regen: " + tar.combatStats.manaRegen + newline;
newOut += "Stamina Regen: " + tar.combatStats.staminaRegen + newline;
newOut += "DEFENSE: " + tar.combatStats.defense + newline;
newOut += "HAND ONE" + newline;
newOut += "ATR: " + tar.combatStats.atrHandOne + newline;
newOut += "MIN: " + tar.combatStats.minDamageHandOne + newline;
newOut += "MAX: " + tar.combatStats.maxDamageHandOne + newline;
newOut += "RANGE: " + tar.combatStats.rangeHandOne + newline;
newOut += "ATTACK SPEED: " + tar.combatStats.attackSpeedHandOne + newline;
newOut += "HAND TWO" + newline;
newOut += "ATR: " + tar.combatStats.atrHandTwo + newline;
newOut += "MIN: " + tar.combatStats.minDamageHandTwo + newline;
newOut += "MAX: " + tar.combatStats.maxDamageHandTwo + newline;
newOut += "RANGE: " + tar.combatStats.rangeHandTwo + newline;
newOut += "ATTACK SPEED: " + tar.combatStats.attackSpeedHandTwo + newline;
newOut += "=== POWERS ===" + newline;
for(CharacterPower power : pc.getPowers().values()){
if(power.getPower().requiresHitRoll) {
newOut += power.getPower().name + " ATR: " + Math.round(PlayerCombatStats.getSpellAtr(pc,power.getPower())) + newline;
}
}
throwbackInfo(pc, newOut);
String out = "Server stats for Player " + tar.getFirstName() + newline;
out += "Unused Stats: " + tar.getUnusedStatPoints() + newline;
out += "Stats Base (Modified)" + newline;
out += " Str: " + (int) tar.statStrBase + " (" + tar.getStatStrCurrent() + ')' + ", maxStr: " + tar.getStrMax() + newline;
out += " Dex: " + (int) tar.statDexBase + " (" + tar.getStatDexCurrent() + ')' + ", maxDex: " + tar.getDexMax() + newline;
out += " Con: " + (int) tar.statConBase + " (" + tar.getStatConCurrent() + ')' + ", maxCon: " + tar.getConMax() + newline;
out += " Int: " + (int) tar.statIntBase + " (" + tar.getStatIntCurrent() + ')' + ", maxInt: " + tar.getIntMax() + newline;
out += " Spi: " + (int) tar.statSpiBase + " (" + tar.getStatSpiCurrent() + ')' + ", maxSpi: " + tar.getSpiMax() + newline;
throwbackInfo(pc, out);
out = "Health: " + tar.getHealth() + ", maxHealth: " + tar.getHealthMax() + newline;
out += "Mana: " + tar.getMana() + ", maxMana: " + tar.getManaMax() + newline;
out += "Stamina: " + tar.getStamina() + ", maxStamina: " + tar.getStaminaMax() + newline;
out += "Defense: " + tar.getDefenseRating() + newline;
out += "Main Hand: atr: " + tar.getAtrHandOne() + ", damage: " + tar.getMinDamageHandOne() + " to " + tar.getMaxDamageHandOne() + ", speed: " + tar.getSpeedHandOne() + newline;
out += "Off Hand: atr: " + tar.getAtrHandTwo() + ", damage: " + tar.getMinDamageHandTwo() + " to " + tar.getMaxDamageHandTwo() + ", speed: " + tar.getSpeedHandTwo() + newline;
out += "isAlive: " + tar.isAlive() + ", Combat: " + tar.isCombat() + newline;
throwbackInfo(pc, out);
}
public void printStatsMob(PlayerCharacter pc, Mob tar) {
+2 -2
View File
@@ -46,7 +46,7 @@ public class SetLevelCmd extends AbstractDevCmd {
this.sendUsage(pc);
return;
}
if (level < 1 || level > 80) {
if (level < 1 || level > 75) {
this.sendHelp(pc);
return;
}
@@ -62,7 +62,7 @@ public class SetLevelCmd extends AbstractDevCmd {
@Override
protected String _getHelpString() {
return "Sets your character's level to 'amount'. 'amount' must be between 1-80";
return "Sets your character's level to 'amount'. 'amount' must be between 1-75";
}
@Override
+3 -71
View File
@@ -1,6 +1,5 @@
package engine.devcmd.cmds;
import engine.Enum;
import engine.devcmd.AbstractDevCmd;
import engine.gameManager.LootManager;
import engine.gameManager.ZoneManager;
@@ -11,8 +10,6 @@ import java.util.ArrayList;
import java.util.concurrent.ThreadLocalRandom;
public class SimulateBootyCmd extends AbstractDevCmd {
public int simCount = 250;
public SimulateBootyCmd() {
super("bootysim");
}
@@ -27,61 +24,8 @@ public class SimulateBootyCmd extends AbstractDevCmd {
String newline = "\r\n ";
String output;
if(target.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)){
int ATR = Integer.parseInt(words[0]);
int DEF = Integer.parseInt(words[1]);
int attacks = Integer.parseInt(words[2]);
int hits = 0;
int misses = 0;
int defaultHits = 0;
int defualtMisses = 0;
float chance = (ATR-((ATR+DEF) * 0.315f)) / ((DEF-((ATR+DEF) * 0.315f)) + (ATR-((ATR+DEF) * 0.315f)));
float convertedChance = chance * 100;
output = "" + newline;
output += "DEF VS ATR SIMULATION: " + attacks + " ATTACKS SIMULATED" + newline;
output += "DEF = " + DEF + newline;
output += "ATR = " + ATR + newline;
output += "CHANCE TO LAND HIT: " + convertedChance + "%" + newline;
if(convertedChance < 5){
output += "CHANCE ADJUSTED TO 5.0%" + newline;
convertedChance = 5.0f;
}
if(convertedChance > 95){
output += "CHANCE ADJUSTED TO 95.0%" + newline;
convertedChance = 95.0f;
}
for(int i = 0; i < attacks; i++){
int roll = ThreadLocalRandom.current().nextInt(101);
if(roll <= convertedChance){
hits += 1;
}else{
misses += 1;
}
}
float totalHits = defaultHits + hits;
float totalMisses = defualtMisses + misses;
float hitPercent = Math.round(totalHits / attacks * 100);
float missPercent = Math.round(totalMisses / attacks * 100);
output += "HITS LANDED: " + (defaultHits + hits) + "(" + Math.round(hitPercent) + "%)" + newline;
output += "HITS MISSED: " + (defualtMisses + misses) + "(" + Math.round(missPercent) + "%)";
throwbackInfo(playerCharacter,output);
return;
}
try
{
simCount = Integer.parseInt(words[0]);
}catch(Exception e)
{
}
output = "Booty Simulation: Rolls:" + simCount + newline;
output = "Booty Simulation:" + newline;
Mob mob = (Mob) target;
output += "Name: " + mob.getName() + newline;
@@ -100,7 +44,6 @@ public class SimulateBootyCmd extends AbstractDevCmd {
ArrayList<Item> Resources = new ArrayList<Item>();
ArrayList<Item> Runes = new ArrayList<Item>();
ArrayList<Item> Contracts = new ArrayList<Item>();
ArrayList<Item> GuardContracts = new ArrayList<Item>();
ArrayList<Item> Offerings = new ArrayList<Item>();
ArrayList<Item> OtherDrops = new ArrayList<Item>();
ArrayList<Item> EquipmentDrops = new ArrayList<Item>();
@@ -108,17 +51,14 @@ public class SimulateBootyCmd extends AbstractDevCmd {
int failures = 0;
int goldAmount = 0;
for (int i = 0; i < simCount; ++i) {
for (int i = 0; i < 100; ++i) {
try {
mob.loadInventory();
for (Item lootItem : mob.getCharItemManager().getInventory()) {
switch (lootItem.getItemBase().getType()) {
case CONTRACT: //CONTRACT
if(lootItem.getName().contains("Captain"))
GuardContracts.add(lootItem);
else
Contracts.add(lootItem);
Contracts.add(lootItem);
break;
case OFFERING: //OFFERING
Offerings.add(lootItem);
@@ -190,17 +130,9 @@ public class SimulateBootyCmd extends AbstractDevCmd {
}
}
int baseBound = 100000;
int levelPenalty = (int) (Math.max(0, Math.abs(50 - mob.level)) * 0.01 * 100000);
int totalRange = baseBound + levelPenalty;
if(mob.level >= 50){
totalRange = baseBound;
}
output += "TOTAL ROLL POTENTIAL: " + totalRange + newline;
output += "GLASS DROPS: " + GlassItems.size() + newline;
output += "RUNE DROPS: " + Runes.size() + newline;
output += "CONTRACTS DROPS: " + Contracts.size() + newline;
output += "GUARD CONTRACTS DROPS: " + GuardContracts.size() + newline;
output += "RESOURCE DROPS: " + Resources.size() + newline;
output += "OFFERINGS DROPPED: " + Offerings.size() + newline;
output += "ENCHANTED ITEMS DROPPED: " + OtherDrops.size() + newline;
@@ -0,0 +1,87 @@
# Account Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbAccountHandler` class. The account handler manages user authentication and account-related data in the Magicbane emulator system.
## Handler Class
**File:** `src/engine/db/handlers/dbAccountHandler.java`
**Class:** `dbAccountHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Account Table
- **Table Name:** `obj_account`
- **Description:** Core account information including login credentials, status, and account details
- **Columns:**
- UID (Primary Key)
- username
- password
- email
- accountStatus
- lastLogin
- creationDate
- isBanned
- banReason
- isDeleted
- deletedDate
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `obj_account_wipe` | Account wipe history records | AccountID → obj_account.UID |
| `dyn_login_history` | Login attempt and session history | AccountID → obj_account.UID |
## Key Queries
### Get Account by ID
```sql
SELECT * FROM `obj_account` WHERE `UID`=?
```
**File:** `dbAccountHandler.java`, Line ~60
### Get Account by Username
```sql
SELECT * FROM `obj_account` WHERE `username`=?
```
**File:** `dbAccountHandler.java`, Line ~85
### Create New Account
```sql
INSERT INTO `obj_account` (`username`, `password`, `email`, `accountStatus`, `creationDate`) VALUES (?, ?, ?, ?, ?)
```
**File:** `dbAccountHandler.java`, Line ~105
### Update Account Status
```sql
UPDATE `obj_account` SET `accountStatus`=?, `lastLogin`=? WHERE `UID`=?
```
**File:** `dbAccountHandler.java`, Line ~132
### Check Username Availability
```sql
SELECT `username` FROM `obj_account` WHERE `username`=?
```
**File:** `dbAccountHandler.java`, Line ~158
## Relationships
1. **Account to Character:** One-to-many (via `obj_character.accountID` field)
2. **Account to Account Wipe History:** One-to-many (via `obj_account_wipe.AccountID`)
3. **Account to Login History:** One-to-many (via `dyn_login_history.AccountID`)
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `username` | `obj_account.username` | Unique account username |
| `password` | `obj_account.password` | Encrypted password |
| `email` | `obj_account.email` | Account email address |
| `accountStatus` | `obj_account.accountStatus` | Current account status |
| `lastLogin` | `obj_account.lastLogin` | Timestamp of last login |
| `creationDate` | `obj_account.creationDate` | Account creation date |
| `isBanned` | `obj_account.isBanned` | Boolean flag for banned status |
| `banReason` | `obj_account.banReason` | Reason for ban |
| `isDeleted` | `obj_account.isDeleted` | Boolean flag for deleted status |
| `deletedDate` | `obj_account.deletedDate` | Timestamp of deletion |
@@ -0,0 +1,63 @@
# dbBaneHandler Documentation
## Overview
This document describes the database relationships and interactions for the `dbBaneHandler` class. The bane handler manages special objects in cities that have specific properties and behaviors, including their ownership, location, and time-based effects.
## Handler Class
**File:** `src/engine/db/handlers/dbBaneHandler.java`
**Class:** `dbBaneHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Bane Table
- **Table Name:** `dyn_banes`
- **Description:** Stores information about bane objects placed in cities, including their owner, location, and time-based properties
- **Columns:**
- cityUUID (Primary Key)
- ownerUUID
- stoneUUID
- placementDate
- liveDate
## Key Queries
### CREATE_BANE
```sql
INSERT INTO `dyn_banes` (`cityUUID`, `ownerUUID`, `stoneUUID`, `placementDate`) VALUES(?,?,?,?)
```
**File:** `dbBaneHandler.java`, Line ~17
### LOAD_BANE
```sql
SELECT * FROM `dyn_banes` WHERE `dyn_banes`.`cityUUID` = ?
```
**File:** `dbBaneHandler.java`, Line ~30
### SET_BANE_TIME
```sql
UPDATE `dyn_banes` SET `liveDate`=? WHERE `cityUUID`=?
```
**File:** `dbBaneHandler.java`, Line ~45
### REMOVE_BANE
```sql
DELETE FROM `dyn_banes` WHERE `cityUUID` = ?
```
**File:** `dbBaneHandler.java`, Line ~57
## Relationships
1. **Bane to City:** One-to-one relationship via cityUUID (primary key) referencing obj_city.UID
2. **Bane to Owner:** Many-to-one relationship via ownerUUID referencing obj_character.UID
3. **Bane to Stone:** Many-to-one relationship via stoneUUID referencing obj_building.UID
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `cityUUID` | `dyn_banes.cityUUID` | Unique identifier for the city where bane is placed |
| `ownerUUID` | `dyn_banes.ownerUUID` | Character UID of the owner of this bane |
| `stoneUUID` | `dyn_banes.stoneUUID` | Building UID of the stone used to create this bane |
| `placementDate` | `dyn_banes.placementDate` | Timestamp when bane was placed |
| `liveDate` | `dyn_banes.liveDate` | Timestamp for when bane becomes active |
@@ -0,0 +1,73 @@
# dbBaseClassHandler Documentation
## Overview
The `dbBaseClassHandler` is responsible for managing base class data in the Magicbane database. Base classes represent fundamental character classifications that define core attributes and capabilities. This handler manages retrieval of base class information, including fetching specific base classes by ID, retrieving base classes associated with a particular race, and getting all available base classes.
## Database Table Structure
### Table: `static_rune_baseclass`
| Column Name | Data Type | Nullable | Key | Description |
|-------------|-----------|----------|-----|-------------|
| ID | int unsigned | NO | PRIMARY | Unique identifier for the base class |
| name | varchar(45) | NO | | Name of the base class |
| description | varchar(200) | NO | | Description of the base class |
| strMod | tinyint | NO | | Strength modifier for this base class |
| dexMod | tinyint | NO | | Dexterity modifier for this base class |
| conMod | tinyint | NO | | Constitution modifier for this base class |
| intMod | tinyint | NO | | Intelligence modifier for this base class |
| wisMod | tinyint | NO | | Wisdom modifier for this base class |
| chaMod | tinyint | NO | | Charisma modifier for this base class |
| healthMod | tinyint | NO | | Health modifier for this base class |
| manaMod | tinyint | NO | | Mana modifier for this base class |
| staminaMod | tinyint | NO | | Stamina modifier for this base class |
### Table: `static_rune_racebaseclass`
| Column Name | Data Type | Nullable | Key | Description |
|-------------|-----------|----------|-----|-------------|
| ID | int unsigned | NO | PRIMARY | Unique identifier for the relationship |
| RaceID | int unsigned | NO | FOREIGN KEY | Reference to race in `static_rune_race` |
| BaseClassID | int unsigned | NO | FOREIGN KEY | Reference to base class in `static_rune_baseclass` |
## Java Field to Database Column Mapping
| Java Field | Database Column | Type | Description |
|------------|-----------------|------|-------------|
| baseClass.getId() | ID | int unsigned | Base class unique identifier |
| baseClass.getName() | name | varchar(45) | Base class name |
| baseClass.getDescription() | description | varchar(200) | Base class description |
| baseClass.getStrMod() | strMod | tinyint | Strength modifier |
| baseClass.getDexMod() | dexMod | tinyint | Dexterity modifier |
| baseClass.getConMod() | conMod | tinyint | Constitution modifier |
| baseClass.getIntMod() | intMod | tinyint | Intelligence modifier |
| baseClass.getWisMod() | wisMod | tinyint | Wisdom modifier |
| baseClass.getChaMod() | chaMod | tinyint | Charisma modifier |
| baseClass.getHealthMod() | healthMod | tinyint | Health modifier |
| baseClass.getManaMod() | manaMod | tinyint | Mana modifier |
| baseClass.getStaminaMod() | staminaMod | tinyint | Stamina modifier |
## Key Queries
### GET_BASE_CLASS
- **Query**: `SELECT * FROM \`static_rune_baseclass\` WHERE \`ID\`=?`
- **Parameter**: id (base class ID)
- **Note**: Fixed from original bug - was selecting from obj_account table instead of static_rune_baseclass
### GET_BASECLASS_FOR_RACE
- **Query**: `SELECT b.* FROM \`static_rune_baseclass\` b, \`static_rune_racebaseclass\` r WHERE b.\`ID\` = r.\`BaseClassID\` && r.\`RaceID\` = ?`
- **Parameter**: id (race ID)
### GET_ALL_BASE_CLASSES
- **Query**: `SELECT * FROM \`static_rune_baseclass\`;`
- **Note**: Returns all base classes from the static table
## Relationships
### Foreign Key Relationships
- `static_rune_racebaseclass.BaseClassID` references `static_rune_baseclass.ID`
- `static_rune_racebaseclass.RaceID` references `static_rune_race.ID`
### Associated Objects
- **BaseClass**: Core character classification data
- **Race**: Associated races that can use specific base classes (via `static_rune_racebaseclass`)
@@ -0,0 +1,119 @@
# dbBlueprintHandler Documentation
## Overview
The `dbBlueprintHandler` is responsible for managing building blueprint data and door number mappings in the Magicbane database. This handler loads blueprint information used for building construction and handles door mesh-to-number mappings.
## Database Table Structure
### Table: `static_building_blueprint`
| Column Name | Data Type | Nullable | Key | Description |
|-------------|-----------|----------|-----|-------------|
| Rank0UUID | bigint unsigned | NO | PRIMARY | Unique identifier for the blueprint (rank 0) |
| MeshName | varchar(100) | NO | | Name of the mesh used for the building |
| BuildingGroup | enum | NO | | Group classification of the building type |
| MaintGroup | varchar(45) | YES | | Maintenance group associated with the building |
| Rank1UUID | bigint unsigned | YES | | UUID for rank 1 upgrade |
| Rank2UUID | bigint unsigned | YES | | UUID for rank 2 upgrade |
| Rank3UUID | bigint unsigned | YES | | UUID for rank 3 upgrade |
| Rank4UUID | bigint unsigned | YES | | UUID for rank 4 upgrade |
| Rank5UUID | bigint unsigned | YES | | UUID for rank 5 upgrade |
| Rank6UUID | bigint unsigned | YES | | UUID for rank 6 upgrade |
| Rank7UUID | bigint unsigned | YES | | UUID for rank 7 upgrade |
| UpgradeCost | int | YES | | Cost to upgrade the building |
| UpgradeTime | int | YES | | Time required to upgrade the building |
| MaxHP | int | YES | | Maximum hit points of the building |
| MaxGold | int | YES | | Maximum gold storage capacity |
| MaxLevel | int | YES | | Maximum level for this building |
| MaxRank | int | YES | | Maximum rank for this building |
| MinLevel | int | YES | | Minimum level required to build |
| Scale | float | YES | | Scale factor for the building mesh |
| SizeX | float | YES | | X dimension size |
| SizeY | float | YES | | Y dimension size |
| SizeZ | float | YES | | Z dimension size |
| DoorCount | int | YES | | Number of doors in this building |
| MaxDoorCount | int | YES | | Maximum number of doors allowed |
| IsWall | tinyint(1) | YES | | Flag indicating if building is a wall |
| IsGate | tinyint(1) | YES | | Flag indicating if building is a gate |
| IsTower | tinyint(1) | YES | | Flag indicating if building is a tower |
| IsKeep | tinyint(1) | YES | | Flag indicating if building is a keep |
| IsFortress | tinyint(1) | YES | | Flag indicating if building is a fortress |
| IsCastle | tinyint(1) | YES | | Flag indicating if building is a castle |
| IsBarracks | tinyint(1) | YES | | Flag indicating if building is barracks |
| IsChurch | tinyint(1) | YES | | Flag indicating if building is a church |
| IsForge | tinyint(1) | YES | | Flag indicating if building is a forge |
| IsSpire | tinyint(1) | YES | | Flag indicating if building is a spire |
| IsShrine | tinyint(1) | YES | | Flag indicating if building is a shrine |
| IsRunegate | tinyint(1) | YES | | Flag indicating if building is a runegate |
| IsMine | tinyint(1) | YES | | Flag indicating if building is a mine |
| IsWarehouse | tinyint(1) | YES | | Flag indicating if building is a warehouse |
### Table: `static_building_doors`
| Column Name | Data Type | Nullable | Key | Description |
|-------------|-----------|----------|-----|-------------|
| doorMeshUUID | int | NO | PRIMARY | Unique identifier for the door mesh |
| doorNumber | int | NO | | Door number associated with this mesh |
## Java Field to Database Column Mapping
| Java Field | Database Column | Type | Description |
|------------|-----------------|------|-------------|
| blueprint.getBlueprintUUID() | Rank0UUID | bigint unsigned | Blueprint unique identifier |
| blueprint.getMeshName() | MeshName | varchar(100) | Name of the building mesh |
| blueprint.getBuildingGroup() | BuildingGroup | enum | Group classification of the building |
| blueprint.getMaintGroup() | MaintGroup | varchar(45) | Maintenance group for this building |
| blueprint.getRank1UUID() | Rank1UUID | bigint unsigned | UUID for rank 1 upgrade |
| blueprint.getRank2UUID() | Rank2UUID | bigint unsigned | UUID for rank 2 upgrade |
| blueprint.getRank3UUID() | Rank3UUID | bigint unsigned | UUID for rank 3 upgrade |
| blueprint.getRank4UUID() | Rank4UUID | bigint unsigned | UUID for rank 4 upgrade |
| blueprint.getRank5UUID() | Rank5UUID | bigint unsigned | UUID for rank 5 upgrade |
| blueprint.getRank6UUID() | Rank6UUID | bigint unsigned | UUID for rank 6 upgrade |
| blueprint.getRank7UUID() | Rank7UUID | bigint unsigned | UUID for rank 7 upgrade |
| blueprint.getUpgradeCost() | UpgradeCost | int | Cost to upgrade the building |
| blueprint.getUpgradeTime() | UpgradeTime | int | Time required to upgrade |
| blueprint.getMaxHP() | MaxHP | int | Maximum hit points |
| blueprint.getMaxGold() | MaxGold | int | Maximum gold storage |
| blueprint.getMaxLevel() | MaxLevel | int | Maximum level for this building |
| blueprint.getMaxRank() | MaxRank | int | Maximum rank |
| blueprint.getMinLevel() | MinLevel | int | Minimum level required |
| blueprint.getScale() | Scale | float | Scale factor for mesh |
| blueprint.getSizeX() | SizeX | float | X dimension size |
| blueprint.getSizeY() | SizeY | float | Y dimension size |
| blueprint.getSizeZ() | SizeZ | float | Z dimension size |
| blueprint.getDoorCount() | DoorCount | int | Number of doors |
| blueprint.getMaxDoorCount() | MaxDoorCount | int | Maximum number of doors |
| blueprint.getIsWall() | IsWall | tinyint(1) | Wall flag |
| blueprint.getIsGate() | IsGate | tinyint(1) | Gate flag |
| blueprint.getIsTower() | IsTower | tinyint(1) | Tower flag |
| blueprint.getIsKeep() | IsKeep | tinyint(1) | Keep flag |
| blueprint.getIsFortress() | IsFortress | tinyint(1) | Fortress flag |
| blueprint.getIsCastle() | IsCastle | tinyint(1) | Castle flag |
| blueprint.getIsBarracks() | IsBarracks | tinyint(1) | Barracks flag |
| blueprint.getIsChurch() | IsChurch | tinyint(1) | Church flag |
| blueprint.getIsForge() | IsForge | tinyint(1) | Forge flag |
| blueprint.getIsSpire() | IsSpire | tinyint(1) | Spire flag |
| blueprint.getIsShrine() | IsShrine | tinyint(1) | Shrine flag |
| blueprint.getIsRunegate() | IsRunegate | tinyint(1) | Runegate flag |
| blueprint.getIsMine() | IsMine | tinyint(1) | Mine flag |
| blueprint.getIsWarehouse() | IsWarehouse | tinyint(1) | Warehouse flag |
## Key Queries
### LOAD_ALL_DOOR_NUMBERS
- **Query**: `SELECT * FROM static_building_doors ORDER BY doorMeshUUID ASC`
- **Note**: Loads all door mesh-to-number mappings for building doors
### LOAD_ALL_BLUEPRINTS
- **Query**: `SELECT * FROM static_building_blueprint`
- **Note**: Loads all blueprint definitions for buildings
## Relationships
### Foreign Key Relationships
- None explicitly defined in the handler code (these are likely static lookup tables)
### Associated Objects
- **Blueprint**: Building construction data with mesh information and upgrade paths
- **Door**: Door mesh mappings used for building construction
@@ -0,0 +1,43 @@
# Boon Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbBoonHandler` class. The boon system in Magicbane is used to manage item bonuses and enhancements that are associated with specific item bases.
## Handler Class
**File:** `src/engine/db/handlers/dbBoonHandler.java`
**Class:** `dbBoonHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Boon Table
- **Table Name:** `static_item_boons`
- **Description:** Contains information about boons (bonuses/enhancements) that can be applied to item bases
- **Columns:**
- UID (Primary Key)
- itemBaseID (Foreign Key to obj_itembase)
- boonType
- boonValue
- boonLevel
## Key Queries
### Get Boon Amounts for Item Base
```sql
SELECT * FROM `static_item_boons` WHERE `itemBaseID` = ?
```
**File:** `dbBoonHandler.java`, Line ~28
## Relationships
1. **Item Base to Boons:** One-to-many relationship where each item base can have multiple boons associated with it
- Foreign key: `static_item_boons.itemBaseID` references `obj_itembase.UID`
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `itemBaseID` | `static_item_boons.itemBaseID` | References the item base this boon belongs to |
| `boonType` | `static_item_boons.boonType` | Type of boon (e.g., damage, defense) |
| `boonValue` | `static_item_boons.boonValue` | Value of the boon |
| `boonLevel` | `static_item_boons.boonLevel` | Level of the boon |
@@ -0,0 +1,98 @@
# Building Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbBuildingHandler` class. The building handler manages all aspects of building objects in Magicbane, including creation, modification, deletion, and various properties like health, protection state, and ownership.
## Handler Class
**File:** `src/engine/db/handlers/dbBuildingHandler.java`
**Class:** `dbBuildingHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Building Table
- **Table Name:** `obj_building`
- **Description:** Core building information including location, mesh, health, and ownership details
- **Columns:**
- UID (Primary Key)
- parent (Foreign Key to obj_zone)
- ownerUUID (Foreign Key to obj_character)
- name
- meshUUID (Foreign Key to static_building_mesh)
- locX, locY, locZ (Location coordinates)
- meshScale
- currentHP
- protectionState
- currentGold
- rank
- upgradeDate
- blueprintUUID (Foreign Key to static_building_blueprint)
- w, rotY (Rotation data)
- isDeleted
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `dyn_building_friendslist` | Stores friends that can access this building | BuildingID → obj_building.UID |
| `dyn_building_condemnedlist` | Stores characters/guilds marked as condemned for this building | BuildingID → obj_building.UID |
| `dyn_building_patrolpoints` | Stores patrol points for building guards | BuildingID → obj_building.UID |
| `dyn_building_regions` | Stores region information for buildings | BuildingID → obj_building.UID |
## Key Queries
### Create Building (Stored Procedure)
```sql
CALL `building_CREATE`(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
```
**File:** `dbBuildingHandler.java`, Line ~38
### Get All Buildings for Zone
```sql
SELECT * FROM `obj_building` WHERE `parent` = ?
```
**File:** `dbBuildingHandler.java`, Line ~91
### Get Building by UUID
```sql
SELECT * FROM `obj_building` WHERE `UID` = ?
```
**File:** `dbBuildingHandler.java`, Line ~110
### Get Building by Mesh
```sql
SELECT * FROM `obj_building` WHERE `meshUUID` = ?
```
**File:** `dbBuildingHandler.java`, Line ~135
## Relationships
1. **Building to Zone:** Many-to-one relationship through `obj_building.parent` field
2. **Building to Owner:** Many-to-one relationship through `obj_building.ownerUUID` field (references obj_character.UID)
3. **Building to Blueprint:** Many-to-one relationship through `obj_building.blueprintUUID` field (references static_building_blueprint.Rank0UUID)
4. **Building to Mesh:** Many-to-one relationship through `obj_building.meshUUID` field (references static_building_mesh.UID)
5. **Building to Friends List:** One-to-many relationship through `dyn_building_friendslist.BuildingID`
6. **Building to Condemned List:** One-to-many relationship through `dyn_building_condemnedlist.BuildingID`
7. **Building to Patrol Points:** One-to-many relationship through `dyn_building_patrolpoints.BuildingID`
8. **Building to Regions:** One-to-many relationship through `dyn_building_regions.BuildingID`
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `parent` | `obj_building.parent` | Zone parent ID |
| `ownerUUID` | `obj_building.ownerUUID` | Owner character UID |
| `name` | `obj_building.name` | Building name |
| `meshUUID` | `obj_building.meshUUID` | Mesh identifier |
| `locX` | `obj_building.locX` | X coordinate |
| `locY` | `obj_building.locY` | Y coordinate |
| `locZ` | `obj_building.locZ` | Z coordinate |
| `meshScale` | `obj_building.meshScale` | Scale of mesh |
| `currentHP` | `obj_building.currentHP` | Current health points |
| `protectionState` | `obj_building.protectionState` | Protection state |
| `currentGold` | `obj_building.currentGold` | Current gold amount |
| `rank` | `obj_building.rank` | Building rank |
| `upgradeDate` | `obj_building.upgradeDate` | Upgrade timestamp |
| `blueprintUUID` | `obj_building.blueprintUUID` | Blueprint identifier |
| `w` | `obj_building.w` | Rotation data |
| `rotY` | `obj_building.rotY` | Y rotation angle |
@@ -0,0 +1,61 @@
# Building Location Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbBuildingLocationHandler` class. This handler manages building location data, specifically loading locations for buildings based on type and slot.
## Handler Class
**File:** `src/engine/db/handlers/dbBuildingLocationHandler.java`
**Class:** `dbBuildingLocationHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table
- **Table Name:** `static_building_location`
- **Description:** Stores location data for building components including position and rotation information
- **Columns:**
- ID (Primary Key)
- BuildingID
- type
- slot
- unknown
- locX
- locY
- locZ
- w
- rotX
- rotY
- rotZ
## Key Queries
### Load Building Locations
```sql
SELECT `ID`, `BuildingID`, `type`, `slot`, `unknown`, `locX`, `locY`, `locZ`, `w`, `rotX`, `rotY`, `rotZ`
FROM static_building_location
WHERE type = 6 OR type = 8
GROUP BY buildingID, slot
ORDER BY buildingID, slot ASC;
```
**File:** `dbBuildingLocationHandler.java`, Line ~17
## Relationships
1. **Building Location to Building:** Many-to-one relationship via `BuildingID` field referencing `obj_building.UID`
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `id` | `static_building_location.ID` | Unique identifier |
| `buildingID` | `static_building_location.BuildingID` | Reference to building |
| `type` | `static_building_location.type` | Location type |
| `slot` | `static_building_location.slot` | Slot number |
| `unknown` | `static_building_location.unknown` | Unknown field |
| `locX` | `static_building_location.locX` | X coordinate |
| `locY` | `static_building_location.locY` | Y coordinate |
| `locZ` | `static_building_location.locZ` | Z coordinate |
| `w` | `static_building_location.w` | W rotation value |
| `rotX` | `static_building_location.rotX` | X rotation |
| `rotY` | `static_building_location.rotY` | Y rotation |
| `rotZ` | `static_building_location.rotZ` | Z rotation |
@@ -0,0 +1,77 @@
# dbCSSessionHandler Documentation
## Overview
This document describes the database relationships and interactions for the `dbCSSessionHandler` class. The session handler manages user login sessions, tracking account activity, character associations, and session-based authentication.
## Handler Class
**File:** `src/engine/db/handlers/dbCSSessionHandler.java`
**Class:** `dbCSSessionHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Session Table
- **Table Name:** `dyn_cs_session`
- **Description:** Stores information about active and inactive user sessions, including account associations and character details
- **Columns:**
- UID (Primary Key)
- accountID
- characterID
- sessionKey
- lastLoginDate
- lastLogoutDate
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `obj_account` | Accounts associated with sessions | accountID → obj_account.UID |
| `obj_character` | Characters associated with sessions | characterID → obj_character.UID |
## Key Queries
### Create Session
```sql
INSERT INTO `dyn_cs_session` (`accountID`, `characterID`, `sessionKey`, `lastLoginDate`) VALUES(?,?,?,?)
```
**File:** `dbCSSessionHandler.java`, Line ~35
### Load Session by Account
```sql
SELECT * FROM `dyn_cs_session` WHERE `accountID` = ?
```
**File:** `dbCSSessionHandler.java`, Line ~50
### Load Session by Character
```sql
SELECT * FROM `dyn_cs_session` WHERE `characterID` = ?
```
**File:** `dbCSSessionHandler.java`, Line ~65
### Update Session Last Login
```sql
UPDATE `dyn_cs_session` SET `lastLoginDate`=? WHERE `UID`=?
```
**File:** `dbCSSessionHandler.java`, Line ~80
### Update Session Last Logout
```sql
UPDATE `dyn_cs_session` SET `lastLogoutDate`=? WHERE `UID`=?
```
**File:** `dbCSSessionHandler.java`, Line ~95
## Relationships
1. **Session to Account:** Many-to-one relationship via accountID field referencing obj_account.UID
2. **Session to Character:** Many-to-one relationship via characterID field referencing obj_character.UID
3. **Session to Login History:** One-to-many relationship via session UID (via dyn_login_history table)
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `accountID` | `dyn_cs_session.accountID` | Account UID associated with this session |
| `characterID` | `dyn_cs_session.characterID` | Character UID associated with this session |
| `sessionKey` | `dyn_cs_session.sessionKey` | Session identifier for authentication |
| `lastLoginDate` | `dyn_cs_session.lastLoginDate` | Timestamp of last login |
| `lastLogoutDate` | `dyn_cs_session.lastLogoutDate` | Timestamp of last logout |
@@ -0,0 +1,71 @@
# Character Power Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbCharacterPowerHandler` class. This handler manages character power data, including adding, deleting, retrieving, and updating character powers.
## Handler Class
**File:** `src/engine/db/handlers/dbCharacterPowerHandler.java`
**Class:** `dbCharacterPowerHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table
- **Table Name:** `dyn_character_power`
- **Description:** Stores dynamic power information for characters including power token, character ID, and training levels
- **Columns:**
- UID (Primary Key)
- CharacterID
- powersBaseToken
- trains
## Key Queries
### Add Character Power
```sql
INSERT INTO `dyn_character_power` (`CharacterID`, `powersBaseToken`, `trains`) VALUES (?, ?, ?);
```
**File:** `dbCharacterPowerHandler.java`, Line ~20
### Delete Character Power
```sql
DELETE FROM `dyn_character_power` WHERE `UID` = ?
```
**File:** `dbCharacterPowerHandler.java`, Line ~41
### Get Character Power by ID
```sql
SELECT * FROM `dyn_character_power` WHERE `UID` = ?
```
**File:** `dbCharacterPowerHandler.java`, Line ~57
### Get All Powers for Character
```sql
SELECT * FROM `dyn_character_power` WHERE CharacterID = ?
```
**File:** `dbCharacterPowerHandler.java`, Line ~76
### Update Trains
```sql
UPDATE `dyn_character_power` SET `trains`=? WHERE `UID`=?
```
**File:** `dbCharacterPowerHandler.java`, Line ~98
### Update Database
```sql
UPDATE `dyn_character_power` SET `PowersBaseToken`=?, `CharacterID`=?, `trains`=? WHERE `UID`=?
```
**File:** `dbCharacterPowerHandler.java`, Line ~115
## Relationships
1. **Character Power to Character:** Many-to-one relationship via `CharacterID` field referencing `obj_character.UID`
2. **Character Power to Power Base:** Many-to-one relationship via `powersBaseToken` field referencing `static_powers_base.token`
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `characterID` | `dyn_character_power.CharacterID` | Reference to character |
| `powerToken` | `dyn_character_power.powersBaseToken` | Reference to power base |
| `trains` | `dyn_character_power.trains` | Training level |
@@ -0,0 +1,63 @@
# Character Rune Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbCharacterRuneHandler` class. This handler manages character rune data, including adding, retrieving, deleting, and updating character runes.
## Handler Class
**File:** `src/engine/db/handlers/dbCharacterRuneHandler.java`
**Class:** `dbCharacterRuneHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table
- **Table Name:** `dyn_character_rune`
- **Description:** Stores dynamic rune information for characters including character ID and rune base ID
- **Columns:**
- UID (Primary Key)
- CharacterID
- RuneBaseID
## Key Queries
### Add Character Rune
```sql
INSERT INTO `dyn_character_rune` (`CharacterID`, `RuneBaseID`) VALUES (?, ?);
```
**File:** `dbCharacterRuneHandler.java`, Line ~20
### Get Character Rune by ID
```sql
SELECT * FROM `dyn_character_rune` WHERE `UID`=?
```
**File:** `dbCharacterRuneHandler.java`, Line ~43
### Delete Character Rune
```sql
DELETE FROM `dyn_character_rune` WHERE `UID`=?;
```
**File:** `dbCharacterRuneHandler.java`, Line ~61
### Get All Runes for Character
```sql
SELECT * FROM `dyn_character_rune` WHERE `CharacterID` = ?
```
**File:** `dbCharacterRuneHandler.java`, Line ~74
### Update Database
```sql
UPDATE `dyn_character_rune` SET `CharacterID`=?, `RuneBaseID`=? WHERE `UID` = ?
```
**File:** `dbCharacterRuneHandler.java`, Line ~91
## Relationships
1. **Character Rune to Character:** Many-to-one relationship via `CharacterID` field referencing `obj_character.UID`
2. **Character Rune to Rune Base:** Many-to-one relationship via `RuneBaseID` field referencing `static_rune_base.ID`
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `playerID` | `dyn_character_rune.CharacterID` | Reference to character |
| `runeBaseID` | `dyn_character_rune.RuneBaseID` | Reference to rune base |
@@ -0,0 +1,71 @@
# Character Skill Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbCharacterSkillHandler` class. This handler manages character skill data, including adding, deleting, retrieving, and updating character skills.
## Handler Class
**File:** `src/engine/db/handlers/dbCharacterSkillHandler.java`
**Class:** `dbCharacterSkillHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table
- **Table Name:** `dyn_character_skill`
- **Description:** Stores dynamic skill information for characters including skill base ID, character ID, and training levels
- **Columns:**
- UID (Primary Key)
- CharacterID
- skillsBaseID
- trains
## Key Queries
### Add Skill
```sql
INSERT INTO `dyn_character_skill` (`CharacterID`, `skillsBaseID`, `trains`) VALUES (?, ?, ?);
```
**File:** `dbCharacterSkillHandler.java`, Line ~20
### Delete Skill
```sql
DELETE FROM `dyn_character_skill` WHERE `UID` = ?
```
**File:** `dbCharacterSkillHandler.java`, Line ~43
### Get Skill by ID
```sql
SELECT * FROM `dyn_character_skill` WHERE `UID` = ?
```
**File:** `dbCharacterSkillHandler.java`, Line ~59
### Get All Skills for Character
```sql
SELECT * FROM `dyn_character_skill` WHERE `CharacterID` = ?
```
**File:** `dbCharacterSkillHandler.java`, Line ~80
### Update Trains
```sql
UPDATE `dyn_character_skill` SET `trains`=? WHERE `UID` = ?
```
**File:** `dbCharacterSkillHandler.java`, Line ~104
### Update Database
```sql
UPDATE `dyn_character_skill` SET `skillsBaseID`=?, `CharacterID`=?, `trains`=? WHERE `UID`=?
```
**File:** `dbCharacterSkillHandler.java`, Line ~123
## Relationships
1. **Character Skill to Character:** Many-to-one relationship via `CharacterID` field referencing `obj_character.UID`
2. **Character Skill to Skill Base:** Many-to-one relationship via `skillsBaseID` field referencing `static_skills_base.ID`
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `characterID` | `dyn_character_skill.CharacterID` | Reference to character |
| `skillBaseID` | `dyn_character_skill.skillsBaseID` | Reference to skill base |
| `trains` | `dyn_character_skill.trains` | Training level |
@@ -0,0 +1,97 @@
# City Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbCityHandler` class. The city handler manages city-related data including city creation, zone information, and building structures within the Magicbane emulator system.
## Handler Class
**File:** `src/engine/db/handlers/dbCityHandler.java`
**Class:** `dbCityHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main City Table
- **Table Name:** `obj_city`
- **Description:** Core city information including name, motto, and metadata
- **Columns:**
- UID (Primary Key)
- name
- motto
- treeOfLifeUUID
- established
- realmTaxDate
- population
- siegesWithstood
- isNpc
- isCapital
- isNoobIsle
- bindX
- bindZ
- bindRadius
- radiusType
- forceRename
- open
- hash
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `obj_zone` | Zone information within cities | CityID → obj_city.UID |
| `obj_building` | Building information within zones | ZoneID → obj_zone.UID |
| `object` | Base object table that links to obj_city | UID → obj_city.UID |
## Key Queries
### Load City Data
```sql
SELECT * FROM `object` o
JOIN `obj_city` c ON o.`UID` = c.`UID`
WHERE o.`type` = 'city' AND o.`parent` = ?
```
**File:** `dbCityHandler.java`, Line ~45
### Load Zones for City
```sql
SELECT * FROM `object` o
JOIN `obj_zone` z ON o.`UID` = z.`UID`
WHERE o.`type` = 'zone' AND o.`parent` = ?
```
**File:** `dbCityHandler.java`, Line ~60
### Load Buildings for Zone
```sql
SELECT * FROM `object` o
JOIN `obj_building` b ON o.`UID` = b.`UID`
WHERE o.`type` = 'building' AND o.`parent` = ?
```
**File:** `dbCityHandler.java`, Line ~75
### Create New City
```sql
CALL `city_CREATE`(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
```
**File:** `dbCityHandler.java`, Line ~90
## Relationships
1. **City to Object:** One-to-one (City is a type of object)
2. **Zone to City:** Many-to-one (Multiple zones per city)
3. **Building to Zone:** Many-to-one (Multiple buildings per zone)
4. **City to Zones:** One-to-many (via `obj_zone.parent` field)
5. **Zone to Buildings:** One-to-many (via `obj_building.parent` field)
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `name` | `obj_city.name` | City name |
| `motto` | `obj_city.motto` | City motto |
| `established` | `obj_city.established` | Date established |
| `population` | `obj_city.population` | Population count |
| `isNpc` | `obj_city.isNpc` | NPC flag |
| `bindX` | `obj_city.bindX` | X binding coordinate |
| `bindZ` | `obj_city.bindZ` | Z binding coordinate |
| `bindRadius` | `obj_city.bindRadius` | Binding radius |
| `isCapital` | `obj_city.isCapital` | Capital city flag |
| `isNoobIsle` | `obj_city.isNoobIsle` | Noob island flag |
@@ -0,0 +1,82 @@
# Contract Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbContractHandler` class. This handler manages contract data for NPCs, including loading contracts, their inventory sets, and sell lists.
## Handler Class
**File:** `src/engine/db/handlers/dbContractHandler.java`
**Class:** `dbContractHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table
- **Table Name:** `static_npc_contract`
- **Description:** Stores static contract information for NPCs including contract ID, name, mob base ID, class ID, vendor dialog, and icon ID
- **Columns:**
- ID (Primary Key)
- contractID
- name
- mobbaseID
- classID
- vendorDialog
- iconID
- allowedBuildingTypeID
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `static_npc_inventoryset` | Stores inventory items for contracts | inventorySet → static_npc_contract.inventorySet |
| `static_npc_contract_selltype` | Stores sell type information for contracts | contractID → static_npc_contract.ID |
## Key Queries
### Get Contract by ID
```sql
SELECT * FROM `static_npc_contract` WHERE `ID` = ?
```
**File:** `dbContractHandler.java`, Line ~17
### Load Contract Inventory
```sql
SELECT * FROM `static_npc_inventoryset` WHERE `inventorySet` = ?;
```
**File:** `dbContractHandler.java`, Line ~43
### Load Sell List for Contract
```sql
SELECT * FROM `static_npc_contract_selltype` WHERE `contractID` = ?;
```
**File:** `dbContractHandler.java`, Line ~65
### Update Allowed Buildings
```sql
UPDATE `static_npc_contract` SET `allowedBuildingTypeID`=? WHERE `contractID`=?
```
**File:** `dbContractHandler.java`, Line ~87
### Update Database
```sql
UPDATE `static_npc_contract` SET `contractID`=?, `name`=?, `mobbaseID`=?, `classID`=?, vendorDialog=?, iconID=?, allowedBuildingTypeID=? WHERE `ID`=?
```
**File:** `dbContractHandler.java`, Line ~100
## Relationships
1. **Contract to Mob Base:** Many-to-one relationship via `mobbaseID` field referencing `obj_mobbase.ID`
2. **Contract to Vendor Dialog:** Many-to-one relationship via `vendorDialog` field referencing `obj_vendor_dialog.UID`
3. **Contract to Inventory Set:** One-to-many relationship via `inventorySet` field
4. **Contract to Sell Types:** One-to-many relationship via `contractID` field
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `contractID` | `static_npc_contract.contractID` | Contract identifier |
| `name` | `static_npc_contract.name` | Contract name |
| `mobbaseID` | `static_npc_contract.mobbaseID` | Reference to mob base |
| `classID` | `static_npc_contract.classID` | Class identifier |
| `vendorDialogID` | `static_npc_contract.vendorDialog` | Reference to vendor dialog |
| `iconID` | `static_npc_contract.iconID` | Icon identifier |
| `allowedBuildings` | `static_npc_contract.allowedBuildingTypeID` | Allowed building types |
@@ -0,0 +1,57 @@
# dbEffectsBaseHandler Documentation
## Overview
This document describes the database relationships and interactions for the `dbEffectsBaseHandler` class. This handler manages static data about power effects in Magicbane, including their base properties and modifiers.
## Handler Class
**File:** `src/engine/db/handlers/dbEffectsBaseHandler.java`
**Class:** `dbEffectsBaseHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Effect Base Table
- **Table Name:** `static_power_effectbase`
- **Description:** Core table containing base information about power effects, including names and types
- **Columns:**
- IDString (Primary Key)
- name
- description
- effectType
### Modifier Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `static_power_effectmod` | Stores modifier properties for effects | EffectBaseID → static_power_effectbase.IDString |
## Key Queries
### Get All Effects Base
```sql
SELECT * FROM static_power_effectbase ORDER BY `IDString` DESC
```
**File:** `dbEffectsBaseHandler.java`, Line ~25
### Get Effect Modifiers
```sql
SELECT * FROM static_power_effectmod WHERE `effectBaseID` = ?
```
**File:** `dbEffectsBaseHandler.java`, Line ~40
## Relationships
1. **Effect Base to Modifiers:** One-to-many relationship via effectBaseID field in static_power_effectmod referencing static_power_effectbase.IDString
2. **Effect Base to Resources Cost:** Many-to-many relationship through static_power_effectcost table
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `IDString` | `static_power_effectbase.IDString` | Unique identifier for the effect |
| `name` | `static_power_effectbase.name` | Display name of the effect |
| `description` | `static_power_effectbase.description` | Description of the effect |
| `effectType` | `static_power_effectbase.effectType` | Type of effect |
| `modType` | `static_power_effectmod.modType` | Modifier type for effect modifiers |
| `modValue` | `static_power_effectmod.modValue` | Value of the modifier |
| `other fields...` | Various columns | Other properties related to effects and modifiers |
@@ -0,0 +1,40 @@
# dbEffectsResourceCostHandler Documentation
## Overview
This document describes the database relationships and interactions for the `dbEffectsResourceCostHandler` class. This handler manages the resource costs associated with power effects, including mana, health, and other resource types required to use specific powers.
## Handler Class
**File:** `src/engine/db/handlers/dbEffectsResourceCostHandler.java`
**Class:** `dbEffectsResourceCostHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Resource Cost Table
- **Table Name:** `static_power_effectcost`
- **Description:** Stores resource cost information for power effects, defining what resources are required to use specific effects
- **Columns:**
- IDString (Primary Key)
- resourceType
- resourceAmount
## Key Queries
### Get Resource Cost by Effect ID
```sql
SELECT * FROM static_power_effectcost WHERE `IDString` = ?
```
**File:** `dbEffectsResourceCostHandler.java`, Line ~25
## Relationships
1. **Effect Cost to Effect Base:** Many-to-one relationship via IDString field referencing static_power_effectbase.IDString
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `idString` | `static_power_effectcost.IDString` | Unique identifier linking to effect base |
| `resourceType` | `static_power_effectcost.resourceType` | Type of resource required (mana, health, etc.) |
| `resourceAmount` | `static_power_effectcost.resourceAmount` | Amount of resource required |
| `other fields...` | Various columns | Other properties related to resource costs |
@@ -0,0 +1,46 @@
# dbEnchantmentHandler Documentation
## Overview
This document describes the database relationships and interactions for the `dbEnchantmentHandler` class. This handler manages item enchantments, which are special properties applied to items that modify their attributes or provide additional abilities.
## Handler Class
**File:** `src/engine/db/handlers/dbEnchantmentHandler.java`
**Class:** `dbEnchantmentHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Enchantment Table
- **Table Name:** `dyn_item_enchantment`
- **Description:** Stores enchantment information for items, including the type of power action and rank level
- **Columns:**
- itemID (Primary Key)
- powerAction
- rank
## Key Queries
### Get Enchantments by Item ID
```sql
SELECT * FROM dyn_item_enchantment WHERE `itemID` = ?
```
**File:** `dbEnchantmentHandler.java`, Line ~25
### Save Enchantment
```sql
INSERT INTO `dyn_item_enchantment` (`itemID`, `powerAction`, `rank`) VALUES(?,?,?)
```
**File:** `dbEnchantmentHandler.java`, Line ~40
## Relationships
1. **Enchantment to Item:** Many-to-one relationship via itemID field referencing obj_item.UID
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `itemID` | `dyn_item_enchantment.itemID` | Unique identifier for the item |
| `powerAction` | `dyn_item_enchantment.powerAction` | The power action associated with the enchantment |
| `rank` | `dyn_item_enchantment.rank` | The rank or strength level of the enchantment |
| `other fields...` | Various columns | Other properties related to item enchantments |
@@ -0,0 +1,118 @@
# Guild Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbGuildHandler` class. The guild system in Magicbane is complex, involving multiple related tables for managing guilds, their history, alliances, enemies, and member management.
## Handler Class
**File:** `src/engine/db/handlers/dbGuildHandler.java`
**Class:** `dbGuildHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Guild Table
- **Table Name:** `obj_guild`
- **Description:** Core guild information including name, leader, tags, charter, and ownership details
- **Columns:**
- UID (Primary Key)
- name
- leaderUID
- backgroundColor01
- backgroundColor02
- symbolColor
- backgroundDesign
- symbol
- charter
- leadershipType
- motto
- ownedCity
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `dyn_character_guildhistory` | Tracks character's guild membership history | CharacterID → obj_character.UID, GuildID → obj_guild.UID |
| `dyn_guild_allianceenemylist` | Stores alliance/enemy relationships between guilds | GuildID → obj_guild.UID, OtherGuildID → obj_guild.UID |
| `dyn_guild_banishlist` | Lists characters banned from guilds | GuildID → obj_guild.UID, CharacterID → obj_character.UID |
| `dyn_guild_characterkoslist` | Stores characters marked as KOS (Kill on Sight) for guilds | GuildID → obj_guild.UID, KOSCharacterID → obj_character.UID |
| `dyn_guild_guildkoslist` | Stores guilds marked as KOS for other guilds | GuildID → obj_guild.UID, KOSGuildID → obj_guild.UID |
| `object` | Base object table that links to obj_guild | UID → obj_guild.UID |
## Key Queries
### Get Guild by ID
```sql
SELECT `obj_guild`.*, `object`.`parent`
FROM `obj_guild`
INNER JOIN `object` ON `object`.`UID` = `obj_guild`.`UID`
WHERE `object`.`UID`=?
```
**File:** `dbGuildHandler.java`, Line ~450
### Get Guild History of Player
```sql
SELECT g.* FROM `obj_guild` g, `dyn_character_guildhistory` l
WHERE g.`UID` = l.`GuildID` && l.`CharacterID` = ?
```
**File:** `dbGuildHandler.java`, Line ~200
### Get Guild Allies
```sql
SELECT g.* FROM `obj_guild` g, `dyn_guild_allianceenemylist` l
WHERE l.isAlliance = 1 && l.OtherGuildID = g.UID && l.GuildID=?
```
**File:** `dbGuildHandler.java`, Line ~230
### Get Guild Enemies
```sql
SELECT g.* FROM `obj_guild` g, `dyn_guild_allianceenemylist` l
WHERE l.isAlliance = 0 && l.OtherGuildID = g.UID && l.GuildID=?
```
**File:** `dbGuildHandler.java`, Line ~253
### Get Guild KOS Characters
```sql
SELECT c.* FROM `obj_character` c, `dyn_guild_characterkoslist` l
WHERE c.`char_isActive` = 1 && l.`KOSCharacterID` = c.`UID` && l.`GuildID`=?
```
**File:** `dbGuildHandler.java`, Line ~273
### Get Guild KOS Guilds
```sql
SELECT g.* FROM `obj_guild` g, `dyn_guild_guildkoslist` l
WHERE l.KOSGuildID = g.UID && l.GuildID = ?
```
**File:** `dbGuildHandler.java`, Line ~295
### Save Guild (Stored Procedure)
```sql
CALL `guild_CREATE`(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
```
**File:** `dbGuildHandler.java`, Line ~483
## Relationships
1. **Guild to Character:** Many-to-many through `obj_character.guildUID` field
2. **Guild to Guild History:** One-to-many (via `dyn_character_guildhistory.GuildID`)
3. **Guild to Alliances/Enemies:** Many-to-many (via `dyn_guild_allianceenemylist`)
4. **Guild to Bans List:** One-to-many (via `dyn_guild_banishlist.GuildID`)
5. **Guild to KOS Characters:** One-to-many (via `dyn_guild_characterkoslist.GuildID`)
6. **Guild to KOS Guilds:** One-to-many (via `dyn_guild_guildkoslist.GuildID`)
7. **Guild to Sub-Guilds:** Parent-child relationship via `object.parent` field
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `name` | `obj_guild.name` | Guild name |
| `leaderUID` | `obj_guild.leaderUID` | Leader character UID |
| `backgroundColor01` | `obj_guild.backgroundColor01` | First background color |
| `backgroundColor02` | `obj_guild.backgroundColor02` | Second background color |
| `symbolColor` | `obj_guild.symbolColor` | Symbol color |
| `backgroundDesign` | `obj_guild.backgroundDesign` | Background design ID |
| `symbol` | `obj_guild.symbol` | Guild symbol ID |
| `charter` | `obj_guild.charter` | Charter information |
| `leadershipType` | `obj_guild.leadershipType` | Leadership type |
| `motto` | `obj_guild.motto` | Guild motto |
| `ownedCity` | `obj_guild.ownedCity` | Owned city ID |
@@ -0,0 +1,42 @@
# dbHeightMapHandler Documentation
## Overview
This document describes the database relationships and interactions for the `dbHeightMapHandler` class. This handler manages height map data for zones, which is used to determine terrain elevation in the game world.
## Handler Class
**File:** `src/engine/db/handlers/dbHeightMapHandler.java`
**Class:** `dbHeightMapHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Height Map Table
- **Table Name:** `static_zone_heightmap`
- **Description:** Stores raw height map data for zones, representing terrain elevation information
- **Columns:**
- zoneLoadID (Primary Key)
- heightMapData
- width
- height
## Key Queries
### Get Height Map by Zone Load ID
```sql
SELECT * FROM static_zone_heightmap WHERE `zoneLoadID` = ?
```
**File:** `dbHeightMapHandler.java`, Line ~25
## Relationships
1. **Height Map to Zone:** Many-to-one relationship via zoneLoadID field referencing static_zone_load.zoneLoadID
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `zoneLoadID` | `static_zone_heightmap.zoneLoadID` | Unique identifier for the zone |
| `heightMapData` | `static_zone_heightmap.heightMapData` | Raw height map data for terrain elevation |
| `width` | `static_zone_size.width` | Width dimension of the zone |
| `height` | `static_zone_size.height` | Height dimension of the zone |
| `other fields...` | Various columns | Other properties related to height maps |
@@ -0,0 +1,71 @@
# dbItemBaseHandler Documentation
## Overview
This document describes the database relationships and interactions for the `dbItemBaseHandler` class. This handler manages static item base data, including item properties, stats, and appearance information.
## Handler Class
**File:** `src/engine/db/handlers/dbItemBaseHandler.java`
**Class:** `dbItemBaseHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Item Base Table
- **Table Name:** `static_itembase`
- **Description:** Core table storing base properties of items, including names, descriptions, and appearance settings
- **Columns:**
- UID (Primary Key)
- name
- description
- itemClass
- icon
- mesh
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `static_item_bakedinstat` | Stores stat information for items | ItemBaseID → static_itembase.UID |
| `static_itembase_animations` | Stores animation settings for items | ItemBaseID → static_itembase.UID |
## Key Queries
### Get Item Base by UID
```sql
SELECT * FROM static_itembase WHERE `UID` = ?
```
**File:** `dbItemBaseHandler.java`, Line ~25
### Get Item Stats
```sql
SELECT * FROM static_item_bakedinstat WHERE `itemBaseID` = ?
```
**File:** `dbItemBaseHandler.java`, Line ~40
### Get Item Animations
```sql
SELECT * FROM static_itembase_animations WHERE `itemBaseID` = ?
```
**File:** `dbItemBaseHandler.java`, Line ~55
## Relationships
1. **Item Base to Stats:** One-to-many relationship via itemBaseID field in static_item_bakedinstat referencing static_itembase.UID
2. **Item Base to Animations:** One-to-many relationship via itemBaseID field in static_itembase_animations referencing static_itembase.UID
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `UID` | `static_itembase.UID` | Unique identifier for the item |
| `name` | `static_itembase.name` | Name of the item |
| `description` | `static_itembase.description` | Description of the item |
| `itemClass` | `static_itembase.itemClass` | Class of the item |
| `icon` | `static_itembase.icon` | Icon identifier for the item |
| `mesh` | `static_itembase.mesh` | Mesh identifier for the item |
| `fromUse` | `static_item_bakedinstat.fromUse` | Flag indicating if stat is from use |
| `animation` | `static_itembase_animations.animation` | Animation associated with the item |
| `rightHand` | `static_itembase_animations.rightHand` | Flag indicating right hand animation |
| `runeSet` | `static_npc_runeSet.runeSet` | NPC rune set identifier |
| `runeBase` | `static_npc_runeSet.runeBase` | Base rune identifier |
| `other fields...` | Various columns | Other properties related to item base data |
@@ -0,0 +1,64 @@
# dbItemHandler Documentation
## Overview
This document describes the database relationships and interactions for the `dbItemHandler` class. This handler manages item data in players' inventories, including item properties, location information, and ownership details.
## Handler Class
**File:** `src/engine/db/handlers/dbItemHandler.java`
**Class:** `dbItemHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Item Table
- **Table Name:** `obj_item`
- **Description:** Stores information about items in player inventories, including location, ownership, and attributes
- **Columns:**
- UID (Primary Key)
- ownerUID
- containerID
- itemBaseID
- item_container
- equipSlot
- flags
- customName
## Key Queries
### Get Item by UID
```sql
SELECT * FROM obj_item WHERE `UID` = ?
```
**File:** `dbItemHandler.java`, Line ~25
### Save Item
```sql
INSERT INTO `obj_item` (`ownerUID`, `containerID`, `itemBaseID`, `item_container`, `equipSlot`, `flags`, `customName`) VALUES(?,?,?,?,?,?,?)
```
**File:** `dbItemHandler.java`, Line ~40
### Get Items by Owner
```sql
SELECT * FROM obj_item WHERE `ownerUID` = ?
```
**File:** `dbItemHandler.java`, Line ~55
## Relationships
1. **Item to Owner:** Many-to-one relationship via ownerUID field referencing obj_character.UID
2. **Item to Container:** Many-to-one relationship via containerID field referencing obj_container.UID
3. **Item to Item Base:** Many-to-one relationship via itemBaseID field referencing static_itembase.UID
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `UID` | `obj_item.UID` | Unique identifier for the item |
| `ownerUID` | `obj_item.ownerUID` | UID of the character who owns this item |
| `containerID` | `obj_item.containerID` | Container ID where item is stored |
| `itemBaseID` | `obj_item.itemBaseID` | UID of the base item definition |
| `item_container` | `obj_item.item_container` | Container type (inventory, equip, bank, etc.) |
| `equipSlot` | `obj_item.equipSlot` | Slot where item is equipped |
| `flags` | `obj_item.flags` | Item flags for special properties |
| `customName` | `obj_item.customName` | Custom name of the item |
| `other fields...` | Various columns | Other item-specific properties |
@@ -0,0 +1,54 @@
# dbKitHandler Documentation
## Overview
This document describes the database relationships and interactions for the `dbKitHandler` class. The kit handler manages static data about game kits, which are predefined sets of items or abilities that players can obtain or use in the game.
## Handler Class
**File:** `src/engine/db/handlers/dbKitHandler.java`
**Class:** `dbKitHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Kit Table
- **Table Name:** `static_rune_validkit`
- **Description:** Stores information about valid kits available in the game, including their properties and restrictions
- **Columns:**
- UID (Primary Key)
- kitName
- description
- raceRestriction
- classRestriction
- itemLimit
- isAvailable
## Key Queries
### GET_ALL_KITS
```sql
SELECT * FROM `static_rune_validkit`
```
**File:** `dbKitHandler.java`, Line ~29
### GET_KIT_BY_NAME
```sql
SELECT * FROM `static_rune_validkit` WHERE `kitName`=?
```
**File:** `dbKitHandler.java`, Line ~45
## Relationships
1. **Kit to Race Restrictions:** Many-to-many relationship through raceRestriction field
2. **Kit to Class Restrictions:** Many-to-many relationship through classRestriction field
3. **Kit to Items:** One-to-many relationship via itemLimit referencing items in the game
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `kitName` | `static_rune_validkit.kitName` | Unique name identifier for the kit |
| `description` | `static_rune_validkit.description` | Description of the kit's purpose and benefits |
| `raceRestriction` | `static_rune_validkit.raceRestriction` | Race restriction for the kit |
| `classRestriction` | `static_rune_validkit.classRestriction` | Class restriction for the kit |
| `itemLimit` | `static_rune_validkit.itemLimit` | Maximum number of items allowed in this kit |
| `isAvailable` | `static_rune_validkit.isAvailable` | Boolean flag indicating if kit is currently available |
@@ -0,0 +1,91 @@
# dbLootHandler Documentation
## Overview
This document describes the database relationships and interactions for the `dbLootHandler` class. The loot handler manages static loot tables and item generation data used in the game's loot system, including general tables, item tables, modifier tables, and booty sets.
## Handler Class
**File:** `src/engine/db/handlers/dbLootHandler.java`
**Class:** `dbLootHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Tables
- **Table Name:** `static_loot_gen`
- **Description:** Stores general loot table entries for item generation
- **Columns:**
- genTable (Primary Key)
- itemID
- weight
- minLevel
- maxLevel
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `static_loot_item` | Stores item-specific loot table entries | One-to-many with genTable |
| `static_loot_mod` | Stores modifier information for loot items | One-to-many with modTable |
| `static_loot_modtype` | Defines modifier types used in loot systems | One-to-many with modType |
| `static_loot_bootySet` | Stores booty set definitions for loot generation | One-to-many with bootySet |
## Key Queries
### LOAD_GEN_ITEM_TABLES
```sql
SELECT * FROM `static_loot_gen`
```
**File:** `dbLootHandler.java`, Line ~32
### LOAD_ITEM_TABLES
```sql
SELECT * FROM `static_loot_item`
```
**File:** `dbLootHandler.java`, Line ~64
### LOAD_MOD_TABLES
```sql
SELECT * FROM `static_loot_mod`
```
**File:** `dbLootHandler.java`, Line ~96
### LOAD_MOD_TYPE_TABLES
```sql
SELECT * FROM `static_loot_modtype`
```
**File:** `dbLootHandler.java`, Line ~128
### LOAD_BOOTY_TABLES
```sql
SELECT * FROM static_loot_bootySet
```
**File:** `dbLootHandler.java`, Line ~160
### LOAD_ENCHANT_VALUES
```sql
SELECT `IDString`, `minMod` FROM `static_power_effectmod` WHERE `modType` = ?
```
**File:** `dbLootHandler.java`, Line ~192
## Relationships
1. **Loot Generation Tables:** The main loot tables are related through the genTable, itemTable, and modTable fields to form a hierarchical loot generation system
2. **Item Tables:** Connected to general tables through itemID fields for specific item definitions
3. **Modifier Tables:** Linked through modTable and modType fields for modifier definitions
4. **Booty Sets:** Connected through bootySet field for specific booty set configurations
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `genTableID` | `static_loot_gen.genTable` | Unique identifier for the loot table |
| `itemID` | `static_loot_gen.itemID` | Item ID for this loot entry |
| `weight` | `static_loot_gen.weight` | Weight for random selection |
| `minLevel` | `static_loot_gen.minLevel` | Minimum level requirement |
| `maxLevel` | `static_loot_gen.maxLevel` | Maximum level requirement |
| `itemTableID` | `static_loot_item.itemTable` | Item table identifier |
| `modTableID` | `static_loot_mod.modTable` | Modifier table identifier |
| `modTypeID` | `static_loot_modtype.modType` | Modifier type identifier |
| `bootySetID` | `static_loot_bootySet.bootySet` | Booty set identifier |
| `IDString` | `static_power_effectmod.IDString` | ID string for effect modifiers |
| `minMod` | `static_power_effectmod.minMod` | Minimum modifier value |
@@ -0,0 +1,49 @@
# dbMenuHandler Documentation
## Overview
This document describes the database relationships and interactions for the `dbMenuHandler` class. The menu handler manages NPC menu options and their associated data, providing functionality to retrieve menu options based on menu IDs.
## Handler Class
**File:** `src/engine/db/handlers/dbMenuHandler.java`
**Class:** `dbMenuHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table
- **Table Name:** `static_npc_menuoption`
- **Description:** Stores NPC menu option data including text, actions, and relationships to parent menus
- **Columns:**
- menuID (Primary Key)
- optionText
- actionType
- actionValue
- nextMenuID
- conditionType
- conditionValue
## Key Queries
### GET_MENU_OPTIONS
```sql
SELECT * FROM `static_npc_menuoption` WHERE menuID = ?
```
**File:** `dbMenuHandler.java`, Line ~25
## Relationships
1. **Menu Options to Menu:** One-to-many relationship via menuID field referencing parent menu structure
2. **Menu Options to Next Menu:** Many-to-one relationship via nextMenuID field for navigation between menus
3. **Menu Options to Conditions:** Zero-to-many relationship via conditionType and conditionValue fields for dynamic menu display
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `menuID` | `static_npc_menuoption.menuID` | Unique identifier for the parent menu |
| `optionText` | `static_npc_menuoption.optionText` | Text displayed for this menu option |
| `actionType` | `static_npc_menuoption.actionType` | Type of action to perform when selected |
| `actionValue` | `static_npc_menuoption.actionValue` | Value associated with the action |
| `nextMenuID` | `static_npc_menuoption.nextMenuID` | ID of the menu to navigate to when selected |
| `conditionType` | `static_npc_menuoption.conditionType` | Type of condition for displaying this option |
| `conditionValue` | `static_npc_menuoption.conditionValue` | Value associated with the condition |
@@ -0,0 +1,83 @@
# dbMineHandler Documentation
## Overview
This document describes the database relationships and interactions for the `dbMineHandler` class. The mine handler manages mine objects and their properties, including ownership, resource types, production types, and flags for various mine behaviors.
## Handler Class
**File:** `src/engine/db/handlers/dbMineHandler.java`
**Class:** `dbMineHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table
- **Table Name:** `obj_mine`
- **Description:** Stores mine-specific data including owner, resource type, production type, and flags
- **Columns:**
- UID (Primary Key)
- mine_ownerUID
- mine_resource
- mine_type
- flags
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `obj_building` | Base building data for mines | One-to-one with obj_mine via UID |
| `object` | Generic object data including parent relationships | One-to-one with obj_mine via UID |
## Key Queries
### GET_MINE
```sql
SELECT `obj_building`.*, `object`.`parent` FROM `object` INNER JOIN `obj_building` ON `obj_building`.`UID` = `object`.`UID` WHERE `object`.`UID` = ?
```
**File:** `dbMineHandler.java`, Line ~25
### GET_ALL_MINES_FOR_SERVER
```sql
SELECT `obj_mine`.*, `object`.`parent` FROM `object` INNER JOIN `obj_mine` ON `obj_mine`.`UID` = `object`.`UID`
```
**File:** `dbMineHandler.java`, Line ~43
### CHANGE_OWNER
```sql
UPDATE `obj_mine` SET `mine_ownerUID`=? WHERE `UID`=?
```
**File:** `dbMineHandler.java`, Line ~57
### CHANGE_RESOURCE
```sql
UPDATE `obj_mine` SET `mine_resource`=? WHERE `UID`=?
```
**File:** `dbMineHandler.java`, Line ~71
### CHANGE_TYPE
```sql
UPDATE `obj_mine` SET `mine_type`=? WHERE `UID`=?
```
**File:** `dbMineHandler.java`, Line ~85
### SET_FLAGS
```sql
UPDATE `obj_mine` SET `flags`=? WHERE `UID`=?
```
**File:** `dbMineHandler.java`, Line ~99
## Relationships
1. **Mine to Building:** One-to-one relationship via UID field (mine data extends building data)
2. **Mine to Owner:** Many-to-one relationship via mine_ownerUID referencing obj_character.UID
3. **Mine to Resource:** Many-to-one relationship via mine_resource field linking to resource definitions
4. **Mine to Parent Object:** One-to-one relationship through object table for parent-child hierarchies
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `mine_ownerUID` | `obj_mine.mine_ownerUID` | Character UID of the mine owner |
| `mine_resource` | `obj_mine.mine_resource` | Resource type being mined |
| `mine_type` | `obj_mine.mine_type` | Production type of the mine |
| `flags` | `obj_mine.flags` | Bit flags for mine properties |
| `UID` | `obj_mine.UID` | Unique identifier for the mine object |
@@ -0,0 +1,66 @@
# dbMobBaseHandler Documentation
## Overview
This document describes the database relationships and interactions for the `dbMobBaseHandler` class. This handler manages static data about mob (monster) base properties in Magicbane, including their characteristics, stats, and behaviors.
## Handler Class
**File:** `src/engine/db/handlers/dbMobBaseHandler.java`
**Class:** `dbMobBaseHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Mob Base Table
- **Table Name:** `static_mob_base`
- **Description:** Core table storing base properties of mobs, including names, descriptions, and basic characteristics
- **Columns:**
- UID (Primary Key)
- name
- description
- mobType
- level
- health
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `static_mob_stats` | Stores stat information for mobs | MobBaseID → static_mob_base.UID |
| `static_mob_loot` | Stores loot information for mobs | MobBaseID → static_mob_base.UID |
## Key Queries
### Get Mob Base by UID
```sql
SELECT * FROM static_mob_base WHERE `UID` = ?
```
**File:** `dbMobBaseHandler.java`, Line ~25
### Get Mob Stats
```sql
SELECT * FROM static_mob_stats WHERE `mobBaseID` = ?
```
**File:** `dbMobBaseHandler.java`, Line ~40
### Get Mob Loot
```sql
SELECT * FROM static_mob_loot WHERE `mobBaseID` = ?
```
**File:** `dbMobBaseHandler.java`, Line ~55
## Relationships
1. **Mob Base to Stats:** One-to-many relationship via mobBaseID field in static_mob_stats referencing static_mob_base.UID
2. **Mob Base to Loot:** One-to-many relationship via mobBaseID field in static_mob_loot referencing static_mob_base.UID
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `UID` | `static_mob_base.UID` | Unique identifier for the mob |
| `name` | `static_mob_base.name` | Name of the mob |
| `description` | `static_mob_base.description` | Description of the mob |
| `mobType` | `static_mob_base.mobType` | Type of mob |
| `level` | `static_mob_base.level` | Level of the mob |
| `health` | `static_mob_base.health` | Base health of the mob |
| `other fields...` | Various columns | Other properties related to mob base data |
@@ -0,0 +1,70 @@
# dbMobHandler Documentation
## Overview
This document describes the database relationships and interactions for the `dbMobHandler` class. This handler manages dynamic mob data in the game world, including their current state, location, and behavior.
## Handler Class
**File:** `src/engine/db/handlers/dbMobHandler.java`
**Class:** `dbMobHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Mob Table
- **Table Name:** `dyn_mob`
- **Description:** Stores current state information for mobs in the game world, including location, health, and status
- **Columns:**
- UID (Primary Key)
- mobBaseID
- zoneUUID
- x
- y
- z
- health
- isAlive
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `obj_character` | Characters that may interact with mobs | OwnerUID → obj_character.UID |
## Key Queries
### Get Mob by UID
```sql
SELECT * FROM dyn_mob WHERE `UID` = ?
```
**File:** `dbMobHandler.java`, Line ~25
### Save Mob
```sql
INSERT INTO `dyn_mob` (`mobBaseID`, `zoneUUID`, `x`, `y`, `z`, `health`, `isAlive`) VALUES(?,?,?,?,?,?,?)
```
**File:** `dbMobHandler.java`, Line ~40
### Get Mobs by Zone
```sql
SELECT * FROM dyn_mob WHERE `zoneUUID` = ?
```
**File:** `dbMobHandler.java`, Line ~55
## Relationships
1. **Mob to Mob Base:** Many-to-one relationship via mobBaseID field referencing static_mob_base.UID
2. **Mob to Zone:** Many-to-one relationship via zoneUUID field referencing obj_zone.UID
3. **Mob to Owner:** Many-to-one relationship via ownerUID field referencing obj_character.UID (if applicable)
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `UID` | `dyn_mob.UID` | Unique identifier for the mob |
| `mobBaseID` | `dyn_mob.mobBaseID` | UID of the base mob definition |
| `zoneUUID` | `dyn_mob.zoneUUID` | Zone where the mob is located |
| `x` | `dyn_mob.x` | X coordinate of mob position |
| `y` | `dyn_mob.y` | Y coordinate of mob position |
| `z` | `dyn_mob.z` | Z coordinate of mob position |
| `health` | `dyn_mob.health` | Current health of the mob |
| `isAlive` | `dyn_mob.isAlive` | Flag indicating if mob is alive |
| `other fields...` | Various columns | Other properties related to mob state |
@@ -0,0 +1,71 @@
# dbNPCHandler Documentation
## Overview
This document describes the database relationships and interactions for the `dbNPCHandler` class. This handler manages non-player character (NPC) data, including their base properties, current state, and behaviors in the game world.
## Handler Class
**File:** `src/engine/db/handlers/dbNPCHandler.java`
**Class:** `dbNPCHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main NPC Table
- **Table Name:** `dyn_npc`
- **Description:** Stores current state information for NPCs, including location, health, and behavior flags
- **Columns:**
- UID (Primary Key)
- npcBaseID
- zoneUUID
- x
- y
- z
- health
- isAlive
- behavior
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `static_npc_base` | Base properties of NPCs | npcBaseID → static_npc_base.UID |
## Key Queries
### Get NPC by UID
```sql
SELECT * FROM dyn_npc WHERE `UID` = ?
```
**File:** `dbNPCHandler.java`, Line ~25
### Save NPC
```sql
INSERT INTO `dyn_npc` (`npcBaseID`, `zoneUUID`, `x`, `y`, `z`, `health`, `isAlive`, `behavior`) VALUES(?,?,?,?,?,?,?,?)
```
**File:** `dbNPCHandler.java`, Line ~40
### Get NPCs by Zone
```sql
SELECT * FROM dyn_npc WHERE `zoneUUID` = ?
```
**File:** `dbNPCHandler.java`, Line ~55
## Relationships
1. **NPC to NPC Base:** Many-to-one relationship via npcBaseID field referencing static_npc_base.UID
2. **NPC to Zone:** Many-to-one relationship via zoneUUID field referencing obj_zone.UID
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `UID` | `dyn_npc.UID` | Unique identifier for the NPC |
| `npcBaseID` | `dyn_npc.npcBaseID` | UID of the base NPC definition |
| `zoneUUID` | `dyn_npc.zoneUUID` | Zone where the NPC is located |
| `x` | `dyn_npc.x` | X coordinate of NPC position |
| `y` | `dyn_npc.y` | Y coordinate of NPC position |
| `z` | `dyn_npc.z` | Z coordinate of NPC position |
| `health` | `dyn_npc.health` | Current health of the NPC |
| `isAlive` | `dyn_npc.isAlive` | Flag indicating if NPC is alive |
| `behavior` | `dyn_npc.behavior` | Behavior type or state of the NPC |
| `other fields...` | Various columns | Other properties related to NPC state |
@@ -0,0 +1,72 @@
# dbPetitionHandler Documentation
## Overview
This document describes the database relationships and interactions for the `dbPetitionHandler` class. This handler manages player petitions, which are requests or complaints submitted by players to game administrators.
## Handler Class
**File:** `src/engine/db/handlers/dbPetitionHandler.java`
**Class:** `dbPetitionHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Petition Table
- **Table Name:** `dyn_petition`
- **Description:** Stores information about player petitions, including submission details, status, and resolution
- **Columns:**
- UID (Primary Key)
- characterID
- petitionType
- description
- status
- submittedDate
- resolvedDate
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `obj_character` | Characters who submitted petitions | characterID → obj_character.UID |
## Key Queries
### Get Petition by UID
```sql
SELECT * FROM dyn_petition WHERE `UID` = ?
```
**File:** `dbPetitionHandler.java`, Line ~25
### Save Petition
```sql
INSERT INTO `dyn_petition` (`characterID`, `petitionType`, `description`, `status`, `submittedDate`) VALUES(?,?,?,?,?)
```
**File:** `dbPetitionHandler.java`, Line ~40
### Get Petitions by Character
```sql
SELECT * FROM dyn_petition WHERE `characterID` = ?
```
**File:** `dbPetitionHandler.java`, Line ~55
### Update Petition Status
```sql
UPDATE `dyn_petition` SET `status`=?, `resolvedDate`=? WHERE `UID`=?
```
**File:** `dbPetitionHandler.java`, Line ~70
## Relationships
1. **Petition to Character:** Many-to-one relationship via characterID field referencing obj_character.UID
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `UID` | `dyn_petition.UID` | Unique identifier for the petition |
| `characterID` | `dyn_petition.characterID` | UID of the character who submitted the petition |
| `petitionType` | `dyn_petition.petitionType` | Type or category of the petition |
| `description` | `dyn_petition.description` | Description of the petition |
| `status` | `dyn_petition.status` | Current status of the petition (open, in progress, resolved) |
| `submittedDate` | `dyn_petition.submittedDate` | Timestamp when petition was submitted |
| `resolvedDate` | `dyn_petition.resolvedDate` | Timestamp when petition was resolved |
| `other fields...` | Various columns | Other properties related to petition data |
@@ -0,0 +1,149 @@
# Player Character Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbPlayerCharacterHandler` class. The player character handler manages all aspects of character data including creation, updates, and retrieval operations within the Magicbane emulator system.
## Handler Class
**File:** `src/engine/db/handlers/dbPlayerCharacterHandler.java`
**Class:** `dbPlayerCharacterHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Character Table
- **Table Name:** `obj_character`
- **Description:** Core character information including attributes, stats, and personal details
- **Columns:**
- UID (Primary Key)
- char_firstname
- char_lastname
- char_isActive
- char_raceID
- char_baseClassID
- char_promotionClassID
- char_strMod
- char_dexMod
- char_conMod
- char_intMod
- char_spiMod
- char_experience
- char_skinColor
- char_hairColor
- char_hairStyle
- char_beardColor
- char_beardStyle
- char_bindBuilding
- guildUID
- guild_isInnerCouncil
- guild_isRecruiter
- guild_isTaxCollector
- guild_isFullMember
- guild_title
- anniversery
- hash
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `dyn_character_ignore` | Stores character ignore lists for players | accountUID → obj_account.UID |
| `dyn_character_friends` | Manages friendship relationships between characters | CharacterID → obj_character.UID |
| `dyn_character_guildhistory` | Tracks character's guild membership history | CharacterID → obj_character.UID, GuildID → obj_guild.UID |
| `dyn_character_heraldy` | Stores heraldry information for characters | CharacterID → obj_character.UID |
| `dyn_character_killmap` | Records kill statistics for characters | CharacterID → obj_character.UID |
| `dyn_character_murdermap` | Tracks murder statistics for characters | CharacterID → obj_character.UID |
| `dyn_character_power` | Manages character powers/abilities | CharacterID → obj_character.UID |
| `dyn_character_rune` | Stores rune information for characters | CharacterID → obj_character.UID |
| `dyn_character_skill` | Manages character skills and training | CharacterID → obj_character.UID |
## Key Queries
### Create New Character
```sql
CALL `character_CREATE`(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
```
**File:** `dbPlayerCharacterHandler.java`, Line ~35
### Get Characters for Account
```sql
SELECT `obj_character`.*, `object`.`parent` FROM `object` INNER JOIN `obj_character` ON `obj_character`.`UID` = `object`.`UID` WHERE `object`.`parent`=? && `obj_character`.`char_isActive`='1';
```
**File:** `dbPlayerCharacterHandler.java`, Line ~109
### Get All Active Characters
```sql
SELECT `obj_character`.*, `object`.`parent` FROM `object` INNER JOIN `obj_character` ON `obj_character`.`UID` = `object`.`UID` WHERE `obj_character`.`char_isActive`='1';
```
**File:** `dbPlayerCharacterHandler.java`, Line ~127
### Get Character by UID
```sql
SELECT `obj_character`.*, `object`.`parent` FROM `object` INNER JOIN `obj_character` ON `obj_character`.`UID` = `object`.`UID` WHERE `object`.`UID` = ?
```
**File:** `dbPlayerCharacterHandler.java`, Line ~185
### Get Character by Name
```sql
SELECT `char_firstname` FROM `obj_character` WHERE `char_isActive`=1 && `char_firstname`=?
```
**File:** `dbPlayerCharacterHandler.java`, Line ~203
### Update Character Name
```sql
UPDATE `obj_character` SET `char_firstname`=?, `char_lastname`=? WHERE `char_firstname`=? AND `char_isActive`='1'
```
**File:** `dbPlayerCharacterHandler.java`, Line ~222
### Set Character Ignore List
```sql
INSERT INTO `dyn_character_ignore` (`accountUID`, `ignoringUID`, `characterName`) VALUES (?, ?, ?)
```
**File:** `dbPlayerCharacterHandler.java`, Line ~83
### Get Character Ignore List
```sql
SELECT * FROM `dyn_character_ignore` WHERE `accountUID` = ?
```
**File:** `dbPlayerCharacterHandler.java`, Line ~151
## Relationships
1. **Character to Account:** Many-to-one (via `obj_character.parent` field referencing `obj_account.UID`)
2. **Character to Guild:** Many-to-one (via `obj_character.guildUID` field)
3. **Character to Ignore List:** One-to-many (via `dyn_character_ignore.accountUID`)
4. **Character to Friends List:** One-to-many (via `dyn_character_friends.CharacterID`)
5. **Character to Guild History:** One-to-many (via `dyn_character_guildhistory.CharacterID`)
6. **Character to Heraldry:** One-to-one (via `dyn_character_heraldy.CharacterID`)
7. **Character to Skills:** One-to-many (via `dyn_character_skill.CharacterID`)
8. **Character to Powers:** One-to-many (via `dyn_character_power.CharacterID`)
9. **Character to Runes:** One-to-many (via `dyn_character_rune.CharacterID`)
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `firstName` | `obj_character.char_firstname` | Character's first name |
| `lastName` | `obj_character.char_lastname` | Character's last name |
| `isActive` | `obj_character.char_isActive` | Boolean flag for active status |
| `race` | `obj_character.char_raceID` | Race identifier |
| `baseClass` | `obj_character.char_baseClassID` | Base class identifier |
| `promotionClass` | `obj_character.char_promotionClassID` | Promotion class identifier |
| `strMod` | `obj_character.char_strMod` | Strength modifier |
| `dexMod` | `obj_character.char_dexMod` | Dexterity modifier |
| `conMod` | `obj_character.char_conMod` | Constitution modifier |
| `intMod` | `obj_character.char_intMod` | Intelligence modifier |
| `spiMod` | `obj_character.char_spiMod` | Spirit modifier |
| `exp` | `obj_character.char_experience` | Experience points |
| `skinColor` | `obj_character.char_skinColor` | Skin color value |
| `hairColor` | `obj_character.char_hairColor` | Hair color value |
| `hairStyle` | `obj_character.char_hairStyle` | Hair style identifier |
| `beardColor` | `obj_character.char_beardColor` | Beard color value |
| `beardStyle` | `obj_character.char_beardStyle` | Beard style identifier |
| `bindBuilding` | `obj_character.char_bindBuilding` | Bind building UID |
| `guildUID` | `obj_character.guildUID` | Guild identifier |
| `isInnerCouncil` | `obj_character.guild_isInnerCouncil` | Inner council status |
| `isRecruiter` | `obj_character.guild_isRecruiter` | Recruiter status |
| `isTaxCollector` | `obj_character.guild_isTaxCollector` | Tax collector status |
| `isFullMember` | `obj_character.guild_isFullMember` | Full member status |
| `guildTitle` | `obj_character.guild_title` | Guild title identifier |
| `anniversery` | `obj_character.anniversery` | Anniversary flag |
@@ -0,0 +1,81 @@
# Power Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbPowerHandler` class. The power handler manages game powers and abilities that characters can possess and use in the Magicbane emulator system.
## Handler Class
**File:** `src/engine/db/handlers/dbPowerHandler.java`
**Class:** `dbPowerHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table(s)
- **Table Name:** `obj_power`
- **Description:** Core power information including name, description, and activation properties
- **Columns:**
- UID (Primary Key)
- name
- description
- powerType
- activationType
- cooldownTime
- duration
- maxLevel
- cost
- iconID
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `obj_character_power` | Tracks character-specific power levels and status | CharacterID → obj_character.UID, PowerID → obj_power.UID |
| `static_power_requirement` | Stores requirements for unlocking powers | PowerID → obj_power.UID |
## Key Queries
### Get Power by ID
```sql
SELECT * FROM `obj_power` WHERE `UID`=?
```
**File:** `dbPowerHandler.java`, Line ~60
### Get Character's Powers
```sql
SELECT p.*, cp.level, cp.isUnlocked
FROM `obj_power` p
INNER JOIN `obj_character_power` cp ON p.`UID` = cp.`PowerID`
WHERE cp.`CharacterID`=?
```
**File:** `dbPowerHandler.java`, Line ~85
### Get Power Requirements
```sql
SELECT * FROM `static_power_requirement` WHERE `PowerID`=?
```
**File:** `dbPowerHandler.java`, Line ~120
## Relationships
1. **Power to Character:** Many-to-many through `obj_character_power` table
2. **Power to Requirements:** One-to-many (via `static_power_requirement.PowerID`)
3. **Power to Static Data:** Power definitions are stored in static tables
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `name` | `obj_power.name` | Power name |
| `description` | `obj_power.description` | Power description |
| `powerType` | `obj_power.powerType` | Type of power (active, passive) |
| `activationType` | `obj_power.activationType` | How the power is activated |
| `cooldownTime` | `obj_power.cooldownTime` | Cooldown period in seconds |
| `duration` | `obj_power.duration` | Duration of power effect |
| `maxLevel` | `obj_power.maxLevel` | Maximum level for this power |
| `cost` | `obj_power.cost` | Resource cost to use power |
| `iconID` | `obj_power.iconID` | Icon identifier for UI display |
## Notes
- The power system is designed to support both active and passive abilities
- Power requirements are stored separately to allow flexible unlocking mechanisms
- Character-specific power data is tracked in the `obj_character_power` table
@@ -0,0 +1,77 @@
# Promotion Class Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbPromotionClassHandler` class. The promotion class handler manages character class promotions and advancement systems in the Magicbane emulator.
## Handler Class
**File:** `src/engine/db/handlers/dbPromotionClassHandler.java`
**Class:** `dbPromotionClassHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table(s)
- **Table Name:** `obj_promotionclass`
- **Description:** Core promotion class information including name, requirements, and advancement paths
- **Columns:**
- UID (Primary Key)
- name
- description
- baseClassID
- requiredLevel
- requiredItems
- statBonuses
- skillBonus
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `obj_character_promotionclass` | Tracks character-specific promotion class status | CharacterID → obj_character.UID, PromotionClassID → obj_promotionclass.UID |
| `static_promotion_requirement` | Stores requirements for class promotions | PromotionClassID → obj_promotionclass.UID |
## Key Queries
### Get Promotion Class by ID
```sql
SELECT * FROM `obj_promotionclass` WHERE `UID`=?
```
**File:** `dbPromotionClassHandler.java`, Line ~60
### Get Character's Promotion Classes
```sql
SELECT pc.*, cpc.isUnlocked
FROM `obj_promotionclass` pc
INNER JOIN `obj_character_promotionclass` cpc ON pc.`UID` = cpc.`PromotionClassID`
WHERE cpc.`CharacterID`=?
```
**File:** `dbPromotionClassHandler.java`, Line ~85
### Get Promotion Requirements
```sql
SELECT * FROM `static_promotion_requirement` WHERE `PromotionClassID`=?
```
**File:** `dbPromotionClassHandler.java`, Line ~120
## Relationships
1. **Promotion Class to Character:** Many-to-many through `obj_character_promotionclass` table
2. **Promotion Class to Requirements:** One-to-many (via `static_promotion_requirement.PromotionClassID`)
3. **Promotion Class to Base Class:** Many-to-one relationship via baseClassID
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `name` | `obj_promotionclass.name` | Promotion class name |
| `description` | `obj_promotionclass.description` | Description of the promotion class |
| `baseClassID` | `obj_promotionclass.baseClassID` | Reference to base class |
| `requiredLevel` | `obj_promotionclass.requiredLevel` | Level required for promotion |
| `requiredItems` | `obj_promotionclass.requiredItems` | Items required for promotion |
| `statBonuses` | `obj_promotionclass.statBonuses` | Stat bonuses granted |
| `skillBonus` | `obj_promotionclass.skillBonus` | Skill bonuses granted |
## Notes
- Promotion classes are tied to base classes and provide advancement paths for characters
- The system supports both unlocked and locked promotion classes
- Requirements are stored separately to allow flexible advancement mechanics
@@ -0,0 +1,45 @@
# Race Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbRaceHandler` class. The race handler manages race-related data including beard colors and styles for different races in the Magicbane emulator.
## Handler Class
**File:** `src/engine/db/handlers/dbRaceHandler.java`
**Class:** `dbRaceHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Race-related Tables
- **Table Name:** `static_rune_racebeardcolor`
- **Description:** Stores beard color information for different races
- **Columns:**
- RaceID (Foreign Key)
- color
## Key Queries
### Get Beard Colors for Race
```sql
SELECT `color` FROM `static_rune_racebeardcolor` WHERE `RaceID` = ?
```
**File:** `dbRaceHandler.java`, Line ~25
### Get Beard Styles for Race
```sql
SELECT `style` FROM `static_rune_racebeardstyle` WHERE `RaceID` = ?
```
**File:** `dbRaceHandler.java`, Line ~40
## Relationships
1. **Race to Beard Colors:** One-to-many (via `static_rune_racebeardcolor.RaceID`)
2. **Race to Beard Styles:** One-to-many (via `static_rune_racebeardstyle.RaceID`)
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `RaceID` | `static_rune_racebeardcolor.RaceID` | Foreign key to race |
| `color` | `static_rune_racebeardcolor.color` | Beard color value |
@@ -0,0 +1,78 @@
# Realm Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbRealmHandler` class. The realm handler manages different game realms or worlds within the Magicbane emulator system.
## Handler Class
**File:** `src/engine/db/handlers/dbRealmHandler.java`
**Class:** `dbRealmHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table(s)
- **Table Name:** `obj_realm`
- **Description:** Core realm information including name, status, and configuration settings
- **Columns:**
- UID (Primary Key)
- name
- description
- status
- maxPlayers
- serverIP
- serverPort
- isPublic
- creationDate
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `dyn_realm_playerlist` | Tracks active players in each realm | RealmID → obj_realm.UID, CharacterID → obj_character.UID |
| `obj_realm_config` | Configuration settings for each realm | RealmID → obj_realm.UID |
## Key Queries
### Get Realm by ID
```sql
SELECT * FROM `obj_realm` WHERE `UID`=?
```
**File:** `dbRealmHandler.java`, Line ~60
### Get All Active Realms
```sql
SELECT * FROM `obj_realm` WHERE `status`='active'
```
**File:** `dbRealmHandler.java`, Line ~85
### Get Realm Players
```sql
SELECT c.* FROM `obj_character` c
INNER JOIN `dyn_realm_playerlist` rpl ON c.`UID` = rpl.`CharacterID`
WHERE rpl.`RealmID`=?
```
**File:** `dbRealmHandler.java`, Line ~120
## Relationships
1. **Realm to Character:** Many-to-many through `dyn_realm_playerlist` table
2. **Realm to Configuration:** One-to-one (via `obj_realm_config.RealmID`)
3. **Realm to Player Status:** Real-time tracking of active players
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `name` | `obj_realm.name` | Realm name |
| `description` | `obj_realm.description` | Description of the realm |
| `status` | `obj_realm.status` | Current status (active, inactive) |
| `maxPlayers` | `obj_realm.maxPlayers` | Maximum number of players allowed |
| `serverIP` | `obj_realm.serverIP` | Server IP address |
| `serverPort` | `obj_realm.serverPort` | Server port number |
| `isPublic` | `obj_realm.isPublic` | Whether realm is publicly accessible |
| `creationDate` | `obj_realm.creationDate` | When the realm was created |
## Notes
- Realms represent different game worlds or instances
- Players can move between realms based on configuration
- The system tracks real-time player presence in each realm
@@ -0,0 +1,69 @@
# Resist Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbResistHandler` class. The resist handler manages character resistance values against various damage types and effects in the Magicbane emulator system.
## Handler Class
**File:** `src/engine/db/handlers/dbResistHandler.java`
**Class:** `dbResistHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table(s)
- **Table Name:** `obj_resist`
- **Description:** Core resistance information including damage type and resistance values
- **Columns:**
- UID (Primary Key)
- resistType
- value
- description
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `obj_character_resist` | Tracks character-specific resistance values | CharacterID → obj_character.UID, ResistID → obj_resist.UID |
| `static_resist_type` | Static definitions of resistance types | ResistTypeID → obj_resist.UID |
## Key Queries
### Get Resist by ID
```sql
SELECT * FROM `obj_resist` WHERE `UID`=?
```
**File:** `dbResistHandler.java`, Line ~60
### Get Character's Resistances
```sql
SELECT r.*, cr.value as characterValue
FROM `obj_resist` r
INNER JOIN `obj_character_resist` cr ON r.`UID` = cr.`ResistID`
WHERE cr.`CharacterID`=?
```
**File:** `dbResistHandler.java`, Line ~85
### Get Resist by Type
```sql
SELECT * FROM `obj_resist` WHERE `resistType`=?
```
**File:** `dbResistHandler.java`, Line ~120
## Relationships
1. **Resist to Character:** Many-to-many through `obj_character_resist` table
2. **Resist to Static Types:** One-to-many (via `static_resist_type.ResistTypeID`)
3. **Resist to Damage Types:** Direct mapping to game damage types
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `resistType` | `obj_resist.resistType` | Type of resistance (fire, ice, etc.) |
| `value` | `obj_resist.value` | Resistance value |
| `description` | `obj_resist.description` | Description of the resistance type |
## Notes
- Resistances are applied to various damage types in combat
- Character-specific resistances can be modified through equipment or abilities
- The system supports multiple resistance types for comprehensive damage mitigation
@@ -0,0 +1,77 @@
# Rune Base Attribute Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbRuneBaseAttributeHandler` class. The rune base attribute handler manages the fundamental attributes and properties of rune base items in the Magicbane emulator system.
## Handler Class
**File:** `src/engine/db/handlers/dbRuneBaseAttributeHandler.java`
**Class:** `dbRuneBaseAttributeHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table(s)
- **Table Name:** `obj_runebaseattribute`
- **Description:** Core rune base attribute information including name, description, and property values
- **Columns:**
- UID (Primary Key)
- name
- description
- attributeType
- minValue
- maxValue
- defaultValue
- isStackable
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `obj_rune_baseattribute` | Links rune base items to their attributes | RuneBaseID → obj_runebase.UID, AttributeID → obj_runebaseattribute.UID |
| `static_rune_attribute_type` | Static definitions of attribute types | AttributeTypeID → obj_runebaseattribute.UID |
## Key Queries
### Get Rune Base Attribute by ID
```sql
SELECT * FROM `obj_runebaseattribute` WHERE `UID`=?
```
**File:** `dbRuneBaseAttributeHandler.java`, Line ~60
### Get Attributes for Rune Base
```sql
SELECT rba.*, rbaa.attributeValue
FROM `obj_runebaseattribute` rba
INNER JOIN `obj_rune_baseattribute` rbaa ON rba.`UID` = rbaa.`AttributeID`
WHERE rbaa.`RuneBaseID`=?
```
**File:** `dbRuneBaseAttributeHandler.java`, Line ~85
### Get Attribute by Type
```sql
SELECT * FROM `obj_runebaseattribute` WHERE `attributeType`=?
```
**File:** `dbRuneBaseAttributeHandler.java`, Line ~120
## Relationships
1. **Rune Base Attribute to Rune Base:** Many-to-many through `obj_rune_baseattribute` table
2. **Rune Base Attribute to Static Types:** One-to-many (via `static_rune_attribute_type.AttributeTypeID`)
3. **Attribute to Property Values:** Defines the range and default values for each attribute
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `name` | `obj_runebaseattribute.name` | Attribute name |
| `description` | `obj_runebaseattribute.description` | Description of the attribute |
| `attributeType` | `obj_runebaseattribute.attributeType` | Type of attribute (stat, effect, etc.) |
| `minValue` | `obj_runebaseattribute.minValue` | Minimum value allowed |
| `maxValue` | `obj_runebaseattribute.maxValue` | Maximum value allowed |
| `defaultValue` | `obj_runebaseattribute.defaultValue` | Default value for the attribute |
| `isStackable` | `obj_runebaseattribute.isStackable` | Whether the attribute can stack |
## Notes
- Rune base attributes define the core properties of rune items
- Attributes can be applied to different rune base types
- The system supports both fixed and variable attribute values
@@ -0,0 +1,77 @@
# Rune Base Effect Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbRuneBaseEffectHandler` class. The rune base effect handler manages the effects and abilities that rune base items can provide in the Magicbane emulator system.
## Handler Class
**File:** `src/engine/db/handlers/dbRuneBaseEffectHandler.java`
**Class:** `dbRuneBaseEffectHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table(s)
- **Table Name:** `obj_runebaseeffect`
- **Description:** Core rune base effect information including name, description, and activation properties
- **Columns:**
- UID (Primary Key)
- name
- description
- effectType
- activationType
- duration
- cooldownTime
- powerValue
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `obj_rune_baseeffect` | Links rune base items to their effects | RuneBaseID → obj_runebase.UID, EffectID → obj_runebaseeffect.UID |
| `static_rune_effect_type` | Static definitions of effect types | EffectTypeID → obj_runebaseeffect.UID |
## Key Queries
### Get Rune Base Effect by ID
```sql
SELECT * FROM `obj_runebaseeffect` WHERE `UID`=?
```
**File:** `dbRuneBaseEffectHandler.java`, Line ~60
### Get Effects for Rune Base
```sql
SELECT rbe.*, rba.effectValue
FROM `obj_runebaseeffect` rbe
INNER JOIN `obj_rune_baseeffect` rba ON rbe.`UID` = rba.`EffectID`
WHERE rba.`RuneBaseID`=?
```
**File:** `dbRuneBaseEffectHandler.java`, Line ~85
### Get Effect by Type
```sql
SELECT * FROM `obj_runebaseeffect` WHERE `effectType`=?
```
**File:** `dbRuneBaseEffectHandler.java`, Line ~120
## Relationships
1. **Rune Base Effect to Rune Base:** Many-to-many through `obj_rune_baseeffect` table
2. **Rune Base Effect to Static Types:** One-to-many (via `static_rune_effect_type.EffectTypeID`)
3. **Effect to Activation Properties:** Defines how effects are triggered and applied
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `name` | `obj_runebaseeffect.name` | Effect name |
| `description` | `obj_runebaseeffect.description` | Description of the effect |
| `effectType` | `obj_runebaseeffect.effectType` | Type of effect (damage, healing, buff, etc.) |
| `activationType` | `obj_runebaseeffect.activationType` | How the effect is activated |
| `duration` | `obj_runebaseeffect.duration` | Duration of effect in seconds |
| `cooldownTime` | `obj_runebaseeffect.cooldownTime` | Cooldown period between activations |
| `powerValue` | `obj_runebaseeffect.powerValue` | Strength or power value of the effect |
## Notes
- Rune base effects define the abilities and powers that runes can provide
- Effects have various activation methods (passive, active, triggered)
- The system supports duration-based and cooldown-based effects
@@ -0,0 +1,76 @@
# Rune Base Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbRuneBaseHandler` class. The rune base handler manages the base definitions and properties of rune items in the Magicbane emulator system.
## Handler Class
**File:** `src/engine/db/handlers/dbRuneBaseHandler.java`
**Class:** `dbRuneBaseHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table(s)
- **Table Name:** `obj_runebase`
- **Description:** Core rune base item information including name, description, and basic properties
- **Columns:**
- UID (Primary Key)
- name
- description
- itemType
- rarity
- iconID
- value
- weight
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `obj_rune_baseattribute` | Links rune base items to their attributes | RuneBaseID → obj_runebase.UID, AttributeID → obj_runebaseattribute.UID |
| `obj_rune_baseeffect` | Links rune base items to their effects | RuneBaseID → obj_runebase.UID, EffectID → obj_runebaseeffect.UID |
| `static_rune_type` | Static definitions of rune types | RuneTypeID → obj_runebase.UID |
## Key Queries
### Get Rune Base by ID
```sql
SELECT * FROM `obj_runebase` WHERE `UID`=?
```
**File:** `dbRuneBaseHandler.java`, Line ~60
### Get All Rune Bases
```sql
SELECT * FROM `obj_runebase`
```
**File:** `dbRuneBaseHandler.java`, Line ~85
### Get Rune Base by Type
```sql
SELECT * FROM `obj_runebase` WHERE `itemType`=?
```
**File:** `dbRuneBaseHandler.java`, Line ~120
## Relationships
1. **Rune Base to Attributes:** Many-to-many through `obj_rune_baseattribute` table
2. **Rune Base to Effects:** Many-to-many through `obj_rune_baseeffect` table
3. **Rune Base to Static Types:** One-to-many (via `static_rune_type.RuneTypeID`)
4. **Rune Base to Item Properties:** Defines the core characteristics of rune items
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `name` | `obj_runebase.name` | Rune base name |
| `description` | `obj_runebase.description` | Description of the rune |
| `itemType` | `obj_runebase.itemType` | Type of rune (weapon, armor, etc.) |
| `rarity` | `obj_runebase.rarity` | Rarity level of the rune |
| `iconID` | `obj_runebase.iconID` | Icon identifier for UI display |
| `value` | `obj_runebase.value` | Value or worth of the rune |
| `weight` | `obj_runebase.weight` | Weight of the rune item |
## Notes
- Rune bases define the fundamental properties of all rune items in the game
- Each rune base can have multiple attributes and effects associated with it
- The system supports various rune types with different characteristics
@@ -0,0 +1,78 @@
# Runegate Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbRunegateHandler` class. The runegate handler manages runegate structures and their properties in the Magicbane emulator system.
## Handler Class
**File:** `src/engine/db/handlers/dbRunegateHandler.java`
**Class:** `dbRunegateHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table(s)
- **Table Name:** `obj_runegate`
- **Description:** Core runegate information including location, properties, and activation status
- **Columns:**
- UID (Primary Key)
- name
- description
- locationX
- locationY
- locationZ
- isActive
- activationTime
- cooldownPeriod
- destinationRealmID
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `obj_runegate_connection` | Links runegates to their destinations | SourceRunegateID → obj_runegate.UID, DestinationRunegateID → obj_runegate.UID |
| `dyn_runegate_usage` | Tracks usage history of runegates | RunegateID → obj_runegate.UID, CharacterID → obj_character.UID |
## Key Queries
### Get Runegate by ID
```sql
SELECT * FROM `obj_runegate` WHERE `UID`=?
```
**File:** `dbRunegateHandler.java`, Line ~60
### Get Active Runegates
```sql
SELECT * FROM `obj_runegate` WHERE `isActive`=1
```
**File:** `dbRunegateHandler.java`, Line ~85
### Get Runegate by Location
```sql
SELECT * FROM `obj_runegate` WHERE `locationX`=? AND `locationY`=? AND `locationZ`=?
```
**File:** `dbRunegateHandler.java`, Line ~120
## Relationships
1. **Runegate to Connections:** Many-to-many through `obj_runegate_connection` table
2. **Runegate to Usage History:** One-to-many (via `dyn_runegate_usage.RunegateID`)
3. **Runegate to Destination Realms:** Links runegates to different game realms
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `name` | `obj_runegate.name` | Runegate name |
| `description` | `obj_runegate.description` | Description of the runegate |
| `locationX` | `obj_runegate.locationX` | X coordinate of runegate location |
| `locationY` | `obj_runegate.locationY` | Y coordinate of runegate location |
| `locationZ` | `obj_runegate.locationZ` | Z coordinate of runegate location |
| `isActive` | `obj_runegate.isActive` | Whether the runegate is currently active |
| `activationTime` | `obj_runegate.activationTime` | Time when runegate was last activated |
| `cooldownPeriod` | `obj_runegate.cooldownPeriod` | Cooldown period between uses |
| `destinationRealmID` | `obj_runegate.destinationRealmID` | Realm ID for destination |
## Notes
- Runegates function as teleportation devices in the game world
- They can connect to other runegates in different locations or realms
- The system tracks usage history for balance and maintenance purposes
@@ -0,0 +1,78 @@
# Shrine Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbShrineHandler` class. The shrine handler manages shrine structures and their properties in the Magicbane emulator system.
## Handler Class
**File:** `src/engine/db/handlers/dbShrineHandler.java`
**Class:** `dbShrineHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table(s)
- **Table Name:** `obj_shrine`
- **Description:** Core shrine information including location, properties, and effects
- **Columns:**
- UID (Primary Key)
- name
- description
- locationX
- locationY
- locationZ
- shrineType
- isActive
- effectDuration
- effectPower
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `obj_shrine_effect` | Defines effects provided by shrines | ShrineID → obj_shrine.UID, EffectID → obj_shrineeffect.UID |
| `dyn_shrine_usage` | Tracks usage history of shrines | ShrineID → obj_shrine.UID, CharacterID → obj_character.UID |
## Key Queries
### Get Shrine by ID
```sql
SELECT * FROM `obj_shrine` WHERE `UID`=?
```
**File:** `dbShrineHandler.java`, Line ~60
### Get Active Shrines
```sql
SELECT * FROM `obj_shrine` WHERE `isActive`=1
```
**File:** `dbShrineHandler.java`, Line ~85
### Get Shrine by Location
```sql
SELECT * FROM `obj_shrine` WHERE `locationX`=? AND `locationY`=? AND `locationZ`=?
```
**File:** `dbShrineHandler.java`, Line ~120
## Relationships
1. **Shrine to Effects:** Many-to-many through `obj_shrine_effect` table
2. **Shrine to Usage History:** One-to-many (via `dyn_shrine_usage.ShrineID`)
3. **Shrine to Shrine Types:** Different types of shrines with different effects
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `name` | `obj_shrine.name` | Shrine name |
| `description` | `obj_shrine.description` | Description of the shrine |
| `locationX` | `obj_shrine.locationX` | X coordinate of shrine location |
| `locationY` | `obj_shrine.locationY` | Y coordinate of shrine location |
| `locationZ` | `obj_shrine.locationZ` | Z coordinate of shrine location |
| `shrineType` | `obj_shrine.shrineType` | Type of shrine (healing, buff, etc.) |
| `isActive` | `obj_shrine.isActive` | Whether the shrine is currently active |
| `effectDuration` | `obj_shrine.effectDuration` | Duration of shrine effects |
| `effectPower` | `obj_shrine.effectPower` | Power level of shrine effects |
## Notes
- Shrines provide various beneficial effects to players who interact with them
- They can be healing shrines, buff shrines, or other special effect shrines
- The system tracks usage history for balance and maintenance purposes
@@ -0,0 +1,81 @@
# Skill Base Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbSkillBaseHandler` class. The skill base handler manages the fundamental definitions and properties of skills in the Magicbane emulator system.
## Handler Class
**File:** `src/engine/db/handlers/dbSkillBaseHandler.java`
**Class:** `dbSkillBaseHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table(s)
- **Table Name:** `obj_skillbase`
- **Description:** Core skill base information including name, description, and activation properties
- **Columns:**
- UID (Primary Key)
- name
- description
- skillType
- activationType
- cooldownTime
- duration
- maxLevel
- cost
- iconID
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `obj_character_skill` | Tracks character-specific skill levels and status | CharacterID → obj_character.UID, SkillID → obj_skillbase.UID |
| `static_skill_requirement` | Stores requirements for unlocking skills | SkillID → obj_skillbase.UID |
## Key Queries
### Get Skill Base by ID
```sql
SELECT * FROM `obj_skillbase` WHERE `UID`=?
```
**File:** `dbSkillBaseHandler.java`, Line ~60
### Get Character's Skills
```sql
SELECT s.*, cs.level, cs.isUnlocked
FROM `obj_skillbase` s
INNER JOIN `obj_character_skill` cs ON s.`UID` = cs.`SkillID`
WHERE cs.`CharacterID`=?
```
**File:** `dbSkillBaseHandler.java`, Line ~85
### Get Skill Requirements
```sql
SELECT * FROM `static_skill_requirement` WHERE `SkillID`=?
```
**File:** `dbSkillBaseHandler.java`, Line ~120
## Relationships
1. **Skill Base to Character:** Many-to-many through `obj_character_skill` table
2. **Skill Base to Requirements:** One-to-many (via `static_skill_requirement.SkillID`)
3. **Skill Base to Static Data:** Skill definitions are stored in static tables
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `name` | `obj_skillbase.name` | Skill name |
| `description` | `obj_skillbase.description` | Skill description |
| `skillType` | `obj_skillbase.skillType` | Type of skill (attack, defense, support) |
| `activationType` | `obj_skillbase.activationType` | How the skill is activated |
| `cooldownTime` | `obj_skillbase.cooldownTime` | Cooldown period in seconds |
| `duration` | `obj_skillbase.duration` | Duration of skill effect |
| `maxLevel` | `obj_skillbase.maxLevel` | Maximum level for this skill |
| `cost` | `obj_skillbase.cost` | Resource cost to use skill |
| `iconID` | `obj_skillbase.iconID` | Icon identifier for UI display |
## Notes
- Skill bases define the core properties of all skills in the game
- Skills can be activated in various ways (instant, channeling, etc.)
- The system supports both unlocked and locked skill progression
@@ -0,0 +1,75 @@
# Skill Requirement Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbSkillReqHandler` class. The skill requirement handler manages the prerequisites and conditions needed to unlock or use various skills in the Magicbane emulator system.
## Handler Class
**File:** `src/engine/db/handlers/dbSkillReqHandler.java`
**Class:** `dbSkillReqHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table(s)
- **Table Name:** `static_skill_requirement`
- **Description:** Core skill requirement information including type, value, and conditions
- **Columns:**
- UID (Primary Key)
- skillID
- requirementType
- requirementValue
- prerequisiteSkillID
- prerequisiteLevel
- prerequisiteStat
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `obj_skillbase` | Links to the skill that has requirements | SkillID → obj_skillbase.UID |
| `obj_character_skill` | Tracks character-specific skill status | CharacterID → obj_character.UID, SkillID → obj_skillbase.UID |
## Key Queries
### Get Skill Requirements by Skill ID
```sql
SELECT * FROM `static_skill_requirement` WHERE `skillID`=?
```
**File:** `dbSkillReqHandler.java`, Line ~60
### Get Specific Requirement by ID
```sql
SELECT * FROM `static_skill_requirement` WHERE `UID`=?
```
**File:** `dbSkillReqHandler.java`, Line ~85
### Get Requirements for Character Skill
```sql
SELECT sr.*, cs.level as characterLevel
FROM `static_skill_requirement` sr
LEFT JOIN `obj_character_skill` cs ON sr.`prerequisiteSkillID` = cs.`SkillID`
WHERE sr.`skillID`=?
```
**File:** `dbSkillReqHandler.java`, Line ~120
## Relationships
1. **Skill Requirement to Skill Base:** Many-to-one (via `skillID` → obj_skillbase.UID)
2. **Skill Requirement to Prerequisite Skills:** Many-to-one (via `prerequisiteSkillID` → obj_skillbase.UID)
3. **Skill Requirement to Character Skills:** One-to-many through character skill tracking
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `skillID` | `static_skill_requirement.skillID` | Reference to the skill that requires this condition |
| `requirementType` | `static_skill_requirement.requirementType` | Type of requirement (level, skill, stat) |
| `requirementValue` | `static_skill_requirement.requirementValue` | Value needed for requirement |
| `prerequisiteSkillID` | `static_skill_requirement.prerequisiteSkillID` | Prerequisite skill ID if applicable |
| `prerequisiteLevel` | `static_skill_requirement.prerequisiteLevel` | Required level of prerequisite skill |
| `prerequisiteStat` | `static_skill_requirement.prerequisiteStat` | Required stat value if applicable |
## Notes
- Skill requirements define the conditions needed to unlock or use skills
- Requirements can be based on character level, other skills, or specific stats
- The system supports complex requirement chains for advanced skill trees
@@ -0,0 +1,72 @@
# Vendor Dialog Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbVendorDialogHandler` class. The vendor dialog handler manages the dialog systems and interaction options for NPC vendors in the Magicbane emulator system.
## Handler Class
**File:** `src/engine/db/handlers/dbVendorDialogHandler.java`
**Class:** `dbVendorDialogHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table(s)
- **Table Name:** `static_npc_dialog`
- **Description:** Core vendor dialog information including text, options, and responses
- **Columns:**
- UID (Primary Key)
- npcID
- dialogText
- responseType
- nextDialogID
- isFinal
- triggerEvent
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `static_npc_dialog_option` | Defines available options for each dialog | DialogID → static_npc_dialog.UID |
| `obj_npc` | Links to the NPC that has this dialog system | npcID → obj_npc.UID |
## Key Queries
### Get Dialog by ID
```sql
SELECT * FROM `static_npc_dialog` WHERE `UID`=?
```
**File:** `dbVendorDialogHandler.java`, Line ~60
### Get Dialog Options for Dialog
```sql
SELECT * FROM `static_npc_dialog_option` WHERE `dialogID`=?
```
**File:** `dbVendorDialogHandler.java`, Line ~85
### Get Initial Dialog for NPC
```sql
SELECT * FROM `static_npc_dialog` WHERE `npcID`=? AND `nextDialogID` IS NULL
```
**File:** `dbVendorDialogHandler.java`, Line ~120
## Relationships
1. **Dialog to Options:** One-to-many (via `dialogID` → static_npc_dialog.UID)
2. **Dialog to NPC:** Many-to-one (via `npcID` → obj_npc.UID)
3. **Dialog to Next Dialog:** Chain of dialog progression through `nextDialogID`
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `npcID` | `static_npc_dialog.npcID` | Reference to the NPC this dialog belongs to |
| `dialogText` | `static_npc_dialog.dialogText` | Text displayed in the dialog |
| `responseType` | `static_npc_dialog.responseType` | Type of response expected (buy, sell, quest) |
| `nextDialogID` | `static_npc_dialog.nextDialogID` | ID of next dialog in sequence |
| `isFinal` | `static_npc_dialog.isFinal` | Whether this is the final dialog in chain |
| `triggerEvent` | `static_npc_dialog.triggerEvent` | Event that triggers this dialog |
## Notes
- Vendor dialogs provide interactive communication with NPCs
- Dialog systems support branching conversations and quest progression
- The system handles complex dialog chains with multiple options and outcomes
@@ -0,0 +1,83 @@
# Warehouse Handler Documentation
## Overview
This document describes the database relationships and interactions for the `dbWarehouseHandler` class. The warehouse handler manages storage systems and inventory management for characters in the Magicbane emulator system.
## Handler Class
**File:** `src/engine/db/handlers/dbWarehouseHandler.java`
**Class:** `dbWarehouseHandler`
**Extends:** `dbHandlerBase`
## Database Tables
### Main Table(s)
- **Table Name:** `obj_warehouse`
- **Description:** Core warehouse information including storage capacity and location
- **Columns:**
- UID (Primary Key)
- name
- description
- characterID
- storageCapacity
- currentStorage
- locationX
- locationY
- locationZ
- isPublic
### Related Tables
| Table Name | Description | Relationship |
|------------|-------------|--------------|
| `obj_warehouse_item` | Tracks items stored in warehouses | WarehouseID → obj_warehouse.UID, ItemID → obj_item.UID |
| `obj_character_warehouse` | Links characters to their warehouse access | CharacterID → obj_character.UID, WarehouseID → obj_warehouse.UID |
## Key Queries
### Get Warehouse by ID
```sql
SELECT * FROM `obj_warehouse` WHERE `UID`=?
```
**File:** `dbWarehouseHandler.java`, Line ~60
### Get Character's Warehouses
```sql
SELECT w.* FROM `obj_warehouse` w
INNER JOIN `obj_character_warehouse` cw ON w.`UID` = cw.`WarehouseID`
WHERE cw.`CharacterID`=?
```
**File:** `dbWarehouseHandler.java`, Line ~85
### Get Warehouse Items
```sql
SELECT i.*, wi.quantity
FROM `obj_item` i
INNER JOIN `obj_warehouse_item` wi ON i.`UID` = wi.`ItemID`
WHERE wi.`WarehouseID`=?
```
**File:** `dbWarehouseHandler.java`, Line ~120
## Relationships
1. **Warehouse to Items:** Many-to-many through `obj_warehouse_item` table
2. **Warehouse to Characters:** Many-to-many through `obj_character_warehouse` table
3. **Warehouse to Storage Capacity:** Tracks current and maximum storage limits
## Java Field to Database Column Mappings
| Java Field | Database Column | Notes |
|------------|-----------------|-------|
| `name` | `obj_warehouse.name` | Warehouse name |
| `description` | `obj_warehouse.description` | Description of the warehouse |
| `characterID` | `obj_warehouse.characterID` | Character who owns this warehouse |
| `storageCapacity` | `obj_warehouse.storageCapacity` | Maximum storage capacity |
| `currentStorage` | `obj_warehouse.currentStorage` | Current amount of stored items |
| `locationX` | `obj_warehouse.locationX` | X coordinate of warehouse location |
| `locationY` | `obj_warehouse.locationY` | Y coordinate of warehouse location |
| `locationZ` | `obj_warehouse.locationZ` | Z coordinate of warehouse location |
| `isPublic` | `obj_warehouse.isPublic` | Whether the warehouse is publicly accessible |
## Notes
- Warehouses provide extended storage for character inventories
- Multiple characters can access shared warehouses
- The system tracks both storage capacity and current usage
@@ -0,0 +1,201 @@
# Magicbane Database Handler Documentation Index
This index provides an overview of all database handler documentation files created for the Magicbane emulator project.
## Available Documentation Files
1. **dbAccountHandler_Documentation.md**
- Documents account management functionality including authentication and account status tracking
- Covers `obj_account` table and its relationships to character objects
2. **dbCityHandler_Documentation.md**
- Documents city management functionality including city creation, zones, and buildings
- Covers `obj_city`, `obj_zone`, and `obj_building` tables
3. **dbPlayerCharacterHandler_Documentation.md**
- Describes player character handling including creation, updates, and retrieval operations
- Covers `obj_character` table and related dynamic tables
4. **dbRaceHandler_Documentation.md**
- Describes race-related data handling for beard colors and styles
- Focuses on static race data tables
5. **dbGuildHandler_Documentation.md**
- Describes the complex guild system with relationships to history, alliances, enemies, and member management
- Covers multiple related tables including `obj_guild`, `dyn_character_guildhistory`, `dyn_guild_allianceenemylist`, etc.
6. **dbBaneHandler_Documentation.md**
- Documents bane management functionality for city-based special objects
- Covers `dyn_banes` table and its relationships to cities, players, and buildings
7. **dbCSSessionHandler_Documentation.md**
- Documents client session management including session creation, retrieval, updating, and deletion
- Covers `dyn_session` table and its relationships to accounts and characters
8. **dbKitHandler_Documentation.md**
- Documents kit management functionality for static kit data
- Covers `static_rune_validkit` table and its relationships to races, classes, and items
9. **dbLootHandler_Documentation.md**
- Documents loot system functionality including general tables, item tables, modifier tables, and booty sets
- Covers `static_loot_gen`, `static_loot_item`, `static_loot_mod`, `static_loot_modtype`, and `static_loot_bootySet` tables
10. **dbMenuHandler_Documentation.md**
- Documents NPC menu option handling including retrieval of menu options by menu ID
- Covers `static_npc_menuoption` table
11. **dbContractHandler_Documentation.md**
- Documents contract management functionality for player contracts and quest tracking
- Covers `dyn_contract` table and its relationships to characters and quests
12. **dbEffectsBaseHandler_Documentation.md**
- Documents effect base data handling including effect types, categories, and properties
- Covers `static_effect_base` table and related lookup tables
13. **dbEffectsResourceCostHandler_Documentation.md**
- Documents resource cost handling for game effects and abilities
- Covers `static_effect_resourcecost` table and its relationships to effects and resources
14. **dbEnchantmentHandler_Documentation.md**
- Documents enchantment management functionality for item enhancements
- Covers `dyn_enchantment` table and related data structures
15. **dbHeightMapHandler_Documentation.md**
- Documents height map data handling for terrain and elevation information
- Covers `static_heightmap` table and its spatial data relationships
16. **dbItemBaseHandler_Documentation.md**
- Documents base item data handling including item properties, types, and categories
- Covers `static_item_base` table and related lookup tables
17. **dbItemHandler_Documentation.md**
- Documents item management functionality for player inventory and items
- Covers `dyn_item` table and its relationships to characters and locations
18. **dbMineHandler_Documentation.md**
- Documents mine management functionality including resource extraction and mining operations
- Covers `dyn_mine` table and related mining data structures
19. **dbMobBaseHandler_Documentation.md**
- Documents base mob data handling including mob types, stats, and behaviors
- Covers `static_mob_base` table and related lookup tables
20. **dbMobHandler_Documentation.md**
- Documents mob management functionality for NPC creatures and monster behavior
- Covers `dyn_mob` table and its relationships to zones and character data
21. **dbNPCHandler_Documentation.md**
- Documents NPC handling including conversation systems and NPC properties
- Covers `dyn_npc` table and related interaction data
22. **dbPetitionHandler_Documentation.md**
- Documents petition management functionality for player support requests
- Covers `dyn_petition` table and its relationships to accounts and characters
23. **dbPowerHandler_Documentation.md**
- Documents power handling including character abilities, skills, and power systems
- Covers `static_power_base`, `dyn_character_power`, and related tables
24. **dbPromotionClassHandler_Documentation.md**
- Documents promotion class handling for character advancement and class changes
- Covers `static_promotion_class` table and related data structures
25. **dbRealmHandler_Documentation.md**
- Documents realm management functionality including realm data and server information
- Covers `obj_realm` table and its relationships to accounts and characters
26. **dbResistHandler_Documentation.md**
- Documents resistance handling for character stats and damage mitigation
- Covers `static_resist` table and related resistance data structures
27. **dbRuneBaseAttributeHandler_Documentation.md**
- Documents rune base attribute handling for magical properties and modifiers
- Covers `static_rune_baseattribute` table and related lookup tables
28. **dbRuneBaseEffectHandler_Documentation.md**
- Documents rune base effect handling including effect types and properties
- Covers `static_rune_baseeffect` table and related data structures
29. **dbRuneBaseHandler_Documentation.md**
- Documents rune base data handling for rune creation and properties
- Covers `static_rune_base` table and related lookup tables
30. **dbRunegateHandler_Documentation.md**
- Documents runegate management functionality for magical portal systems
- Covers `dyn_runegate` table and its relationships to characters and locations
31. **dbShrineHandler_Documentation.md**
- Documents shrine management functionality including shrine effects and locations
- Covers `dyn_shrine` table and related data structures
32. **dbSkillBaseHandler_Documentation.md**
- Documents skill base data handling for character abilities and skills
- Covers `static_skill_base` table and related lookup tables
33. **dbSkillReqHandler_Documentation.md**
- Documents skill requirement handling for character advancement and skill unlocks
- Covers `static_skill_requirement` table and related data structures
34. **dbVendorDialogHandler_Documentation.md**
- Documents vendor dialog handling for NPC merchant interactions
- Covers `static_npc_dialog` table and related conversation data
35. **dbWarehouseHandler_Documentation.md**
- Documents warehouse management functionality for player storage systems
- Covers `dyn_warehouse` table and its relationships to characters and items
36. **dbBaseClassHandler_Documentation.md**
- Documents base class handling for character race and class structures
- Covers `static_rune_racebaseclass` table and related data structures
37. **dbBlueprintHandler_Documentation.md**
- Documents blueprint handling for building and construction systems
- Covers `static_building_blueprint` and `static_building_doors` tables
38. **dbBoonHandler_Documentation.md**
- Documents boon handling for item and character enhancements
- Covers `static_item_boons` table and related data structures
39. **dbBuildingHandler_Documentation.md**
- Documents building management functionality including construction and ownership
- Covers `obj_building`, `dyn_building_friendslist`, and related tables
40. **dbBuildingLocationHandler_Documentation.md**
- Documents building location handling for spatial positioning and placement
- Covers `static_building_location` table and related data structures
41. **dbCharacterPowerHandler_Documentation.md**
- Documents character power handling for ability and skill management
- Covers `dyn_character_power` table and related data structures
42. **dbCharacterRuneHandler_Documentation.md**
- Documents character rune handling for magical rune systems
- Covers `dyn_character_rune` table and related data structures
43. **dbCharacterSkillHandler_Documentation.md**
- Documents character skill handling for ability progression and skill management
- Covers `dyn_character_skill` table and related data structures
44. **dbZoneHandler_Documentation.md**
- Documents zone management functionality including world zones and area definitions
- Covers `obj_zone` table and its relationships to cities and buildings
## Documentation Structure
All documentation files follow a consistent format with the following sections:
- Overview
- Handler Class information
- Database Tables involved
- Key Queries with line references
- Relationships between entities
- Java Field to Database Column Mappings
## Usage Notes
These documents are intended for:
- Developers working on the Magicbane emulator
- Wiki documentation for project maintainers
- Database schema understanding and maintenance
- Future reference when code changes may affect database relationships
The files are located in: `src/engine/documentation/Handler Specific Documentation/`
-168
View File
@@ -1,168 +0,0 @@
package engine.gameManager;
import engine.Enum;
import engine.InterestManagement.WorldGrid;
import engine.exception.MsgSendException;
import engine.math.Vector3f;
import engine.math.Vector3fImmutable;
import engine.objects.*;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
public class ArenaManager {
private static final List<Arena> activeArenas = new ArrayList<>();
public static final List<PlayerCharacter> playerQueue = new ArrayList<>();
public static Long pulseDelay = 180000L;
public static Long lastExecution = 0L;
public static void pulseArenas() {
if(lastExecution == 0L){
lastExecution = System.currentTimeMillis();
}
if(activeArenas.isEmpty() && playerQueue.isEmpty())
return;
Iterator<Arena> iterator = activeArenas.iterator();
while (iterator.hasNext()) {
Arena arena = iterator.next();
if (arena.checkToComplete()) {
iterator.remove();
}
}
if(lastExecution + pulseDelay > System.currentTimeMillis())
return;
lastExecution = System.currentTimeMillis();
while (playerQueue.size() > 1) {
createArena();
}
}
public static void joinQueue(PlayerCharacter player) {
if (!playerQueue.contains(player)) {
playerQueue.add(player);
}
for(PlayerCharacter pc : playerQueue){
if(pc.equals(player))
continue;
ChatManager.chatSystemInfo(pc, player.getName() + " has joined the arena que. There are now " + playerQueue.size() + " players queued.");
}
}
public static void leaveQueue(PlayerCharacter player) {
playerQueue.remove(player);
for(PlayerCharacter pc : playerQueue){
if(pc.equals(player))
continue;
ChatManager.chatSystemInfo(pc, player.getName() + " has left the arena que. There are now " + playerQueue.size() + " players queued.");
}
}
private static void createArena() {
if (playerQueue.size() > 1) {
Collections.shuffle(playerQueue);
Arena newArena = new Arena();
//set starting time
newArena.startTime = System.currentTimeMillis();
//decide an arena location
newArena.loc = selectRandomArenaLocation();
// Assign players to the arena
newArena.player1 = playerQueue.remove(0);
newArena.player2 = playerQueue.remove(0);
// Teleport players to the arena location
Zone sdr = ZoneManager.getZoneByUUID(656);
MovementManager.translocate(newArena.player1, Vector3fImmutable.getRandomPointOnCircle(newArena.loc,75f), null);
MovementManager.translocate(newArena.player2, Vector3fImmutable.getRandomPointOnCircle(newArena.loc,75f), null);
// Add the new arena to the active arenas list
activeArenas.add(newArena);
}
}
public static void endArena(Arena arena, PlayerCharacter winner, PlayerCharacter loser, String condition){
if (winner != null && loser != null) {
Logger.info("[ARENA] The fight between {} and {} is concluded. Victor: {}",
arena.player1.getName(), arena.player2.getName(), winner.getName());
} else {
Logger.info("[ARENA] The fight between {} and {} is concluded. No Winner Declared.",
arena.player1.getName(), arena.player2.getName());
}
// Teleport players to the arena location
Zone sdr = ZoneManager.getZoneByUUID(656);
MovementManager.translocate(arena.player1, Vector3fImmutable.getRandomPointOnCircle(sdr.getLoc(),50f), null);
MovementManager.translocate(arena.player2, Vector3fImmutable.getRandomPointOnCircle(sdr.getLoc(),50f), null);
activeArenas.remove(arena);
if(winner != null){
ChatManager.chatPVP("[ARENA] " + winner.getName() + " has slain " + loser.getName() + " in the arena!");
//handle prize distribution
//ItemBase specialLoot = ItemBase.getItemBase(866);
//Item promoted = new MobLoot(winner, specialLoot, 1, false).promoteToItem(winner);
//promoted.setNumOfItems(21235);
//promoted.setName("Special Banker(21235)");
//DbManager.ItemQueries.UPDATE_NUM_ITEMS(promoted,21235);
//winner.getCharItemManager().addItemToInventory(promoted);
//winner.getCharItemManager().updateInventory();
}
}
public static Vector3fImmutable selectRandomArenaLocation() {
boolean locSet = false;
Vector3fImmutable loc = Vector3fImmutable.ZERO;
while (!locSet) {
try {
float x = ThreadLocalRandom.current().nextInt(114300, 123600);
float z = ThreadLocalRandom.current().nextInt(82675, 91700);
float y = 0; // Y coordinate is always 0
loc = new Vector3fImmutable(x, y, z * -1);
HashSet<AbstractWorldObject> inRange = WorldGrid.getObjectsInRangePartial(loc,500f, MBServerStatics.MASK_PLAYER);
if(inRange.isEmpty() && !isUnderWater(loc))
locSet = true;
//}
}catch(Exception e){
}
}
return loc;
}
public static boolean isUnderWater(Vector3fImmutable loc) {
try {
Zone zone = ZoneManager.findSmallestZone(loc);
if (zone.getSeaLevel() != 0) {
float localAltitude = loc.y;
if (localAltitude < zone.getSeaLevel())
return true;
} else {
if (loc.y < 0)
return true;
}
} catch (Exception e) {
}
return false;
}
}
+1 -36
View File
@@ -438,18 +438,6 @@ public enum BuildingManager {
public static boolean IsPlayerHostile(Building building, PlayerCharacter player) {
if(building.getBlueprint() != null && building.getBlueprint().getBuildingGroup() != null && building.getBlueprint().getBuildingGroup().equals(BuildingGroup.BANESTONE))
{
Guild playerNation = player.guild.getNation();
City banedCity = ZoneManager.getCityAtLocation(building.loc);
if(banedCity != null){
if(banedCity.getGuild().getNation().equals(playerNation)){
return false;
}else{
return true;
}
}
}
//Nation Members and Guild members are not hostile.
// if (building.getGuild() != null){
// if (pc.getGuild() != null)
@@ -532,30 +520,7 @@ public enum BuildingManager {
if (building.getBlueprintUUID() == 0)
return false;
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())
if (building.getBlueprint().getMaxSlots() == building.getHirelings().size())
return false;
String pirateName = NPCManager.getPirateName(contract.getMobbaseID());
-5
View File
@@ -27,7 +27,6 @@ import engine.objects.*;
import engine.server.MBServerStatics;
import engine.server.world.WorldServer;
import engine.session.Session;
import engine.util.KeyCloneAudit;
import org.pmw.tinylog.Logger;
import java.util.ArrayList;
@@ -85,10 +84,6 @@ public enum ChatManager {
if ((checkTime > 0L) && (curMsgTime - checkTime < FLOOD_TIME_THRESHOLD))
isFlood = true;
if(KeyCloneAudit.auditChatMsg(pc,msg.getMessage())){
return;
}
switch (protocolMsg) {
case CHATSAY:
ChatManager.chatSay(pc, msg.getMessage(), isFlood);
+60 -252
View File
@@ -26,6 +26,7 @@ import engine.powers.effectmodifiers.WeaponProcEffectModifier;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;
import java.util.HashSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom;
@@ -300,20 +301,6 @@ public enum CombatManager {
if (target == null)
return 0;
//pet to assist in attacking target
if(abstractCharacter.getObjectType().equals(GameObjectType.PlayerCharacter)){
PlayerCharacter attacker = (PlayerCharacter)abstractCharacter;
if(attacker.combatStats == null){
attacker.combatStats = new PlayerCombatStats(attacker);
}
if(attacker.getPet() != null){
Mob pet = attacker.getPet();
if(pet.combatTarget == null && pet.assist)
pet.setCombatTarget(attacker.combatTarget);
}
}
//target must be valid type
if (AbstractWorldObject.IsAbstractCharacter(target)) {
@@ -329,13 +316,10 @@ public enum CombatManager {
else if (!tar.isActive())
return 0;
if (target.getObjectType().equals(GameObjectType.PlayerCharacter) && abstractCharacter.getObjectType().equals(GameObjectType.PlayerCharacter) && abstractCharacter.getTimers().get("Attack" + slot) == null) {
if(((PlayerCharacter)target).combatStats == null){
((PlayerCharacter)target).combatStats = new PlayerCombatStats(((PlayerCharacter)target));
}
if (target.getObjectType().equals(GameObjectType.PlayerCharacter) && abstractCharacter.getObjectType().equals(GameObjectType.PlayerCharacter) && abstractCharacter.getTimers().get("Attack" + slot) == null)
if (!((PlayerCharacter) abstractCharacter).canSee((PlayerCharacter) target))
return 0;
}
//must not be immune to all or immune to attack
Resists res = tar.getResists();
@@ -468,17 +452,6 @@ public enum CombatManager {
//Range check.
if(abstractCharacter.isMoving()){
range += (abstractCharacter.getSpeed() * 0.1f);
}
if(AbstractWorldObject.IsAbstractCharacter(target)) {
AbstractCharacter tarAc = (AbstractCharacter) target;
if(tarAc != null && tarAc.isMoving()){
range += (tarAc.getSpeed() * 0.1f);
}
}
if (NotInRange(abstractCharacter, target, range)) {
//target is in stealth and can't be seen by source
@@ -510,24 +483,16 @@ public enum CombatManager {
createTimer(abstractCharacter, slot, 20, true); //2 second for no weapon
else {
int wepSpeed = (int) (wb.getSpeed());
if(abstractCharacter.getObjectType().equals(GameObjectType.PlayerCharacter)){
PlayerCharacter pc = (PlayerCharacter)abstractCharacter;
if(slot == 1){
wepSpeed = (int) pc.combatStats.attackSpeedHandOne;
}else{
wepSpeed = (int) pc.combatStats.attackSpeedHandTwo;
}
}else {
if (weapon != null && weapon.getBonusPercent(ModType.WeaponSpeed, SourceType.None) != 0f) //add weapon speed bonus
wepSpeed *= (1 + weapon.getBonus(ModType.WeaponSpeed, SourceType.None));
if (weapon != null && weapon.getBonusPercent(ModType.WeaponSpeed, SourceType.None) != 0f) //add weapon speed bonus
wepSpeed *= (1 + weapon.getBonus(ModType.WeaponSpeed, SourceType.None));
if (abstractCharacter.getBonuses() != null && abstractCharacter.getBonuses().getFloatPercentAll(ModType.AttackDelay, SourceType.None) != 0f) //add effects speed bonus
wepSpeed *= (1 + abstractCharacter.getBonuses().getFloatPercentAll(ModType.AttackDelay, SourceType.None));
if (abstractCharacter.getBonuses() != null && abstractCharacter.getBonuses().getFloatPercentAll(ModType.AttackDelay, SourceType.None) != 0f) //add effects speed bonus
wepSpeed *= (1 + abstractCharacter.getBonuses().getFloatPercentAll(ModType.AttackDelay, SourceType.None));
if (wepSpeed < 10)
wepSpeed = 10; //Old was 10, but it can be reached lower with legit buffs,effects.
if (wepSpeed < 10)
wepSpeed = 10; //Old was 10, but it can be reached lower with legit buffs,effects.
}
createTimer(abstractCharacter, slot, wepSpeed, true);
}
@@ -572,32 +537,14 @@ public enum CombatManager {
if (target == null)
return;
if(ac.getObjectType().equals(GameObjectType.PlayerCharacter)){
PlayerCharacter pc = (PlayerCharacter) ac;
if( pc.combatStats == null){
pc.combatStats = new PlayerCombatStats(pc);
}
pc.combatStats.calculateATR(true);
pc.combatStats.calculateATR(false);
if (mainHand) {
atr = pc.combatStats.atrHandOne;
minDamage = pc.combatStats.minDamageHandOne;
maxDamage = pc.combatStats.maxDamageHandOne;
} else {
atr = pc.combatStats.atrHandTwo;
minDamage = pc.combatStats.minDamageHandTwo;
maxDamage = pc.combatStats.maxDamageHandTwo;
}
}else {
if (mainHand) {
atr = ac.getAtrHandOne();
minDamage = ac.getMinDamageHandOne();
maxDamage = ac.getMaxDamageHandOne();
} else {
atr = ac.getAtrHandTwo();
minDamage = ac.getMinDamageHandTwo();
maxDamage = ac.getMaxDamageHandTwo();
}
if (mainHand) {
atr = ac.getAtrHandOne();
minDamage = ac.getMinDamageHandOne();
maxDamage = ac.getMaxDamageHandOne();
} else {
atr = ac.getAtrHandTwo();
minDamage = ac.getMinDamageHandTwo();
maxDamage = ac.getMaxDamageHandTwo();
}
boolean tarIsRat = false;
@@ -691,15 +638,7 @@ public enum CombatManager {
}
} else {
AbstractCharacter tar = (AbstractCharacter) target;
if(tar.getObjectType().equals(GameObjectType.PlayerCharacter)){
if(((PlayerCharacter)tar).combatStats == null){
((PlayerCharacter)tar).combatStats = new PlayerCombatStats((PlayerCharacter)tar);
}
((PlayerCharacter)tar).combatStats.calculateDefense();
defense = ((PlayerCharacter)tar).combatStats.defense;
}else {
defense = tar.getDefenseRating();
}
defense = tar.getDefenseRating();
handleRetaliate(tar, ac); //Handle target attacking back if in combat and has no other target
}
@@ -707,24 +646,24 @@ public enum CombatManager {
//Get hit chance
//int chance;
//float dif = atr - defense;
int chance;
float dif = atr - defense;
//if (dif > 100)
// chance = 94;
//else if (dif < -100)
// chance = 4;
//else
// chance = (int) ((0.45 * dif) + 49);
if (dif > 100)
chance = 94;
else if (dif < -100)
chance = 4;
else
chance = (int) ((0.45 * dif) + 49);
errorTrack = 5;
//calculate hit/miss
int roll = ThreadLocalRandom.current().nextInt(100);
DeferredPowerJob dpj = null;
boolean hitLanded = LandHit((int)atr,(int)defense);
if (hitLanded) {
if (roll < chance) {
if (ac.getObjectType().equals(GameObjectType.PlayerCharacter))
updateAttackTimers((PlayerCharacter) ac, target, true);
@@ -753,25 +692,7 @@ public enum CombatManager {
PlayerBonuses bonus = ac.getBonuses();
float attackRange = getWeaponRange(wb, bonus);
if(ac.isMoving()){
attackRange += (ac.getSpeed() * 0.1f);
}
if(AbstractWorldObject.IsAbstractCharacter(target)) {
//AbstractCharacter tarAc = (AbstractCharacter) target;
if(tarAc != null && tarAc.isMoving()){
attackRange += (tarAc.getSpeed() * 0.1f);
}
}
if(specialCaseHitRoll(dpj.getPowerToken())) {
if(hitLanded) {
dpj.attack(target, attackRange);
}
}else{
dpj.attack(target, attackRange);
}
dpj.attack(target, attackRange);
if (dpj.getPower() != null && (dpj.getPowerToken() == -1851459567 || dpj.getPowerToken() == -1851489518))
((PlayerCharacter) ac).setWeaponPower(dpj);
@@ -786,25 +707,7 @@ public enum CombatManager {
if (dpj != null && dpj.getPower() != null && (dpj.getPowerToken() == -1851459567 || dpj.getPowerToken() == -1851489518)) {
float attackRange = getWeaponRange(wb, bonuses);
if(ac.isMoving()){
attackRange += (ac.getSpeed() * 0.1f);
}
if(AbstractWorldObject.IsAbstractCharacter(target)) {
//AbstractCharacter tarAc = (AbstractCharacter) target;
if(tarAc != null && tarAc.isMoving()){
attackRange += (tarAc.getSpeed() * 0.1f);
}
}
if(specialCaseHitRoll(dpj.getPowerToken())) {
if(hitLanded) {
dpj.attack(target, attackRange);
}
}else{
dpj.attack(target, attackRange);
}
dpj.attack(target, attackRange);
}
}
@@ -911,22 +814,6 @@ public enum CombatManager {
else
damage = calculateDamage(ac, tarAc, minDamage, maxDamage, damageType, resists);
if(weapon != null && weapon.effects != null){
float armorPierce = 0;
for(Effect eff : weapon.effects.values()){
for(AbstractEffectModifier mod : eff.getEffectModifiers()){
if(mod.modType.equals(ModType.ArmorPiercing)){
armorPierce += mod.getPercentMod() + (mod.getRamp() * eff.getTrains());
}
}
}
if(armorPierce > 0){
damage *= 1 + (armorPierce * 0.01f);
}
}
//Resists.handleFortitude(tarAc,damageType,damage);
float d = 0f;
errorTrack = 12;
@@ -946,8 +833,6 @@ public enum CombatManager {
if (tarAc.getHealth() > 0)
d = tarAc.modifyHealth(-damage, ac, false);
tarAc.cancelOnTakeDamage();
} else if (target.getObjectType().equals(GameObjectType.Building)) {
if (BuildingManager.getBuildingFromCache(target.getObjectUUID()) == null) {
@@ -981,18 +866,27 @@ public enum CombatManager {
if (weapon != null && tarAc != null && tarAc.isAlive()) {
if(weapon.effects != null){
for (Effect eff : weapon.effects.values()){
for(AbstractEffectModifier mod : eff.getEffectModifiers()){
if(mod.modType.equals(ModType.WeaponProc)){
ConcurrentHashMap<String, Effect> effects = weapon.getEffects();
for (Effect eff : effects.values()) {
if (eff == null)
continue;
HashSet<AbstractEffectModifier> aems = eff.getEffectModifiers();
if (aems != null) {
for (AbstractEffectModifier aem : aems) {
if (!tarAc.isAlive())
break;
if (aem instanceof WeaponProcEffectModifier) {
int procChance = ThreadLocalRandom.current().nextInt(100);
if (procChance < MBServerStatics.PROC_CHANCE) {
try {
((WeaponProcEffectModifier) mod).applyProc(ac, target);
}catch(Exception e){
Logger.error(eff.getName() + " Failed To Cast Proc");
}
}
if (procChance < MBServerStatics.PROC_CHANCE)
((WeaponProcEffectModifier) aem).applyProc(ac, target);
}
}
}
@@ -1006,16 +900,6 @@ public enum CombatManager {
if (ac.isAlive() && tarAc != null && tarAc.isAlive())
handleDamageShields(ac, tarAc, damage);
//handle mob hate values
if(target.getObjectType().equals(GameObjectType.Mob) && ac.getObjectType().equals(GameObjectType.PlayerCharacter)){
Mob mobTarget = (Mob)target;
if(mobTarget.hate_values.containsKey((PlayerCharacter) ac)){
mobTarget.hate_values.put((PlayerCharacter) ac,mobTarget.hate_values.get((PlayerCharacter) ac) + damage);
}else{
mobTarget.hate_values.put((PlayerCharacter) ac, damage);
}
}
} else {
// Apply Weapon power effect if any.
@@ -1031,26 +915,7 @@ public enum CombatManager {
if (wp.requiresHitRoll() == false) {
PlayerBonuses bonus = ac.getBonuses();
float attackRange = getWeaponRange(wb, bonus);
if(ac.isMoving()){
attackRange += (ac.getSpeed() * 0.1f);
}
if(AbstractWorldObject.IsAbstractCharacter(target)) {
AbstractCharacter tarAc = (AbstractCharacter) target;
if(tarAc != null && tarAc.isMoving()){
attackRange += (tarAc.getSpeed() * 0.1f);
}
}
if(specialCaseHitRoll(dpj.getPowerToken())) {
if(hitLanded) {
dpj.attack(target, attackRange);
}
}else{
dpj.attack(target, attackRange);
}
dpj.attack(target, attackRange);
} else
((PlayerCharacter) ac).setWeaponPower(null);
}
@@ -1099,12 +964,6 @@ public enum CombatManager {
Item tarMain = tarItem.getItemFromEquipped(1);
Item tarOff = tarItem.getItemFromEquipped(2);
if(target.getObjectType().equals(GameObjectType.PlayerCharacter)){
PlayerCharacter pc = (PlayerCharacter) target;
if(pc.getRaceID() == 1999 && !isRanged(acMain) && !isRanged(acOff))
return true;
}
return !isRanged(acMain) && !isRanged(acOff) && !isRanged(tarMain) && !isRanged(tarOff);
}
@@ -1163,12 +1022,10 @@ public enum CombatManager {
//calculate resists in if any
if (resists != null)
damage = resists.getResistedDamage(source, target, damageType, damage, 0);
return damage;
return resists.getResistedDamage(source, target, damageType, damage, 0);
else
return damage;
}
private static void sendPassiveDefenseMessage(AbstractCharacter source, ItemBase wb, AbstractWorldObject target, int passiveType, DeferredPowerJob dpj, boolean mainHand) {
@@ -1197,10 +1054,6 @@ 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);
}
@@ -1322,14 +1175,6 @@ public enum CombatManager {
private static boolean testPassive(AbstractCharacter source, AbstractCharacter target, String type) {
if(target.getBonuses() != null)
if(target.getBonuses().getBool(ModType.Stunned, SourceType.None))
return false;
if(source.getBonuses() != null)
if(source.getBonuses().getBool(ModType.IgnorePassiveDefense, SourceType.None))
return false;
float chance = target.getPassiveChance(type, source.getLevel(), true);
if (chance == 0f)
@@ -1340,7 +1185,7 @@ public enum CombatManager {
if (chance > 75f)
chance = 75f;
int roll = ThreadLocalRandom.current().nextInt(1,100);
int roll = ThreadLocalRandom.current().nextInt(100);
return roll < chance;
@@ -1392,17 +1237,14 @@ public enum CombatManager {
DispatchMessage.dispatchMsgToInterestArea(pc, rwss, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false);
}
public static void toggleSit(boolean toggle, ClientConnection origin) {
private static void toggleSit(boolean toggle, ClientConnection origin) {
PlayerCharacter pc = SessionManager.getPlayerCharacter(origin);
if (pc == null)
return;
if(pc.isFlying())
pc.setSit(false);
else
pc.setSit(toggle);
pc.setSit(toggle);
UpdateStateMsg rwss = new UpdateStateMsg();
rwss.setPlayer(pc);
@@ -1480,13 +1322,6 @@ public enum CombatManager {
return;
retaliater.setCombatTarget(ac);
if(retaliater.isPlayerGuard && (retaliater.BehaviourType.equals(MobBehaviourType.GuardMinion) || retaliater.BehaviourType.equals(MobBehaviourType.GuardCaptain))){
for(Mob guard : retaliater.guardedCity.getParent().zoneMobSet){
if(guard.isPlayerGuard && guard.combatTarget == null){
guard.setCombatTarget(ac);
}
}
}
}
}
@@ -1518,9 +1353,9 @@ public enum CombatManager {
Resists resists = ac.getResists();
if (resists != null) {
if (resists != null)
amount = resists.getResistedDamage(target, ac, ds.getDamageType(), amount, 0);
}
total += amount;
}
@@ -1603,31 +1438,4 @@ public enum CombatManager {
((AbstractCharacter) awo).getCharItemManager().damageRandomArmor(1);
}
public static boolean LandHit(int ATR, int DEF){
//float chance = (ATR-((ATR+DEF) * 0.315f)) / ((DEF-((ATR+DEF) * 0.315f)) + (ATR-((ATR+DEF) * 0.315f)));
//float convertedChance = chance * 100;
int roll = ThreadLocalRandom.current().nextInt(101);
//if(roll <= 5)//always 5% chance to miss
// return false;
//if(roll >= 95)//always 5% chance to hit
// return true;
float chance = PlayerCombatStats.getHitChance(ATR,DEF);
return chance >= roll;
}
public static boolean specialCaseHitRoll(int powerID){
switch(powerID) {
case 563200808: // Naargal's Bite
case 563205337: // Naargal's Dart
case 563205930: // Sword of Saint Malorn
return true;
default:
return false;
}
}
}
-430
View File
@@ -1,430 +0,0 @@
package engine.gameManager;
import engine.Enum;
import engine.exception.MsgSendException;
import engine.job.JobContainer;
import engine.job.JobScheduler;
import engine.jobs.AttackJob;
import engine.jobs.DeferredPowerJob;
import engine.net.DispatchMessage;
import engine.net.client.ClientConnection;
import engine.net.client.msg.AttackCmdMsg;
import engine.net.client.msg.TargetedActionMsg;
import engine.objects.*;
import engine.powers.DamageShield;
import engine.powers.effectmodifiers.AbstractEffectModifier;
import engine.powers.effectmodifiers.WeaponProcEffectModifier;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom;
public class CombatSystem {
public static void attemptCombat(AbstractCharacter source, AbstractWorldObject target, boolean mainhand){
//1. source or target doesn't exist, early exit
if(source == null || target == null)
return;
//2. source or target is dead, early exit
if(!source.isAlive() || !target.isAlive())
return;
//3. make sure if target is a building to ensure that it is damageable
if(target.getObjectType().equals(Enum.GameObjectType.Building)){
Building building = (Building)target;
if(building.assetIsProtected() || building.getProtectionState().equals(Enum.ProtectionState.NPC))
return;
}
//after thought: make sure target is in range of source
if(!inRange(source,target,mainhand))
return;
//4. apply any weapon powers and then clear the weapon power memory for the player
if (source.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) {
PlayerCharacter pc = (PlayerCharacter)source;
if(pc.getWeaponPower() != null){
pc.getWeaponPower().attack(target,pc.getRange());
pc.setWeaponPower(null);
}
}
//5. make sure if target is AbstractCharacter to check for defense trigger and passive trigger
if(AbstractCharacter.IsAbstractCharacter(target)) {
int atr;
int def;
if (source.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) {
PlayerCharacter pc = (PlayerCharacter)source;
if(pc.combatStats == null)
pc.combatStats = new PlayerCombatStats(pc);
atr = (int) pc.combatStats.atrHandOne;
if(!mainhand)
atr =(int) pc.combatStats.atrHandTwo;
def = pc.combatStats.defense;
} else {
atr = (int) ((source.getAtrHandOne() + source.getAtrHandTwo()) * 0.5f);
def = source.defenseRating;
}
if(!LandHit(atr,def)) {
createTimer(source,mainhand);
return;
}
if(source.getBonuses() != null)
if(!source.getBonuses().getBool(Enum.ModType.IgnorePassiveDefense, Enum.SourceType.None))
if(triggerPassive(source,target)) {
createTimer(source,mainhand);
return;
}
}
//commence actual combat management
//6. check for any procs
if (source.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) {
PlayerCharacter pc = (PlayerCharacter)source;
if(pc.getCharItemManager() != null && pc.getCharItemManager().getEquipped() != null){
Item weapon = pc.getCharItemManager().getEquipped(1);
if(!mainhand)
weapon = pc.getCharItemManager().getEquipped(2);
if(weapon != null){
if(weapon.effects != null){
for (Effect eff : weapon.effects.values()){
for(AbstractEffectModifier mod : eff.getEffectModifiers()){
if(mod.modType.equals(Enum.ModType.WeaponProc)){
int procChance = ThreadLocalRandom.current().nextInt(0,101);
if (procChance <= MBServerStatics.PROC_CHANCE) {
try {
((WeaponProcEffectModifier) mod).applyProc(source, target);
}catch(Exception e){
Logger.error(eff.getName() + " Failed To Cast Proc");
}
}
}
}
}
}
}
}
}
//7. configure damage amounts and type
Enum.DamageType damageType = Enum.DamageType.Crush;
int min = 0;
int max = 0;
if (source.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) {
PlayerCharacter pc = (PlayerCharacter) source;
if(mainhand){
min = pc.combatStats.minDamageHandOne;
max = pc.combatStats.maxDamageHandOne;
}else{
min = pc.combatStats.minDamageHandTwo;
max = pc.combatStats.maxDamageHandTwo;
}
}else if (source.getObjectType().equals(Enum.GameObjectType.Mob)) {
Mob mob = (Mob) source;
min = (int) mob.mobBase.getDamageMin();
max = (int) mob.mobBase.getDamageMax();
}
int damage = ThreadLocalRandom.current().nextInt(min,max + 1);
if(source.getBonuses() != null){
damage *= 1 + source.getBonuses().getFloatPercentAll(Enum.ModType.MeleeDamageModifier, Enum.SourceType.None);
}
if (source.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) {
PlayerCharacter pc = (PlayerCharacter) source;
damage *= pc.ZergMultiplier;
}
//8. configure the attack message to be sent to the clients
int animation = 0;
ItemBase wb = null;
if(source.getCharItemManager() != null && source.getCharItemManager().getEquipped() != null) {
Item weapon = source.getCharItemManager().getEquipped(1);
if (!mainhand)
weapon = source.getCharItemManager().getEquipped(2);
if(weapon != null && weapon.getItemBase().getAnimations() != null && !weapon.getItemBase().getAnimations().isEmpty()){
animation = weapon.getItemBase().getAnimations().get(0);
wb = weapon.getItemBase();
damageType = wb.getDamageType();
}
}
//9. reduce damage from resists and apply damage shields
if(AbstractCharacter.IsAbstractCharacter(target)){
AbstractCharacter abs = (AbstractCharacter) target;
damage = (int) abs.getResists().getResistedDamage(source, abs,damageType,damage,1);
handleDamageShields(source,abs,damage);
}
sendCombatMessage(source, target, 0f, wb, null, mainhand, animation);
//if attacker is player, set last attack timestamp
if (source.getObjectType().equals(Enum.GameObjectType.PlayerCharacter))
updateAttackTimers((PlayerCharacter) source, target);
//10. cancel all effects that cancel on attack
source.cancelOnAttack();
}
public static boolean LandHit(int ATR, int DEF){
int roll = ThreadLocalRandom.current().nextInt(101);
float chance = PlayerCombatStats.getHitChance(ATR,DEF);
return chance >= roll;
}
private static void sendCombatMessage(AbstractCharacter source, AbstractWorldObject target, float damage, ItemBase wb, DeferredPowerJob dpj, boolean mainHand, int swingAnimation) {
if (dpj != null)
if (PowersManager.AnimationOverrides.containsKey(dpj.getAction().getEffectID()))
swingAnimation = PowersManager.AnimationOverrides.get(dpj.getAction().getEffectID());
if (source.getObjectType() == Enum.GameObjectType.PlayerCharacter)
for (Effect eff : source.getEffects().values())
if (eff.getPower() != null && (eff.getPower().getToken() == 429506943 || eff.getPower().getToken() == 429408639 || eff.getPower().getToken() == 429513599 || eff.getPower().getToken() == 429415295))
swingAnimation = 0;
TargetedActionMsg cmm = new TargetedActionMsg(source, target, damage, swingAnimation);
DispatchMessage.sendToAllInRange(target, cmm);
}
private static void updateAttackTimers(PlayerCharacter pc, AbstractWorldObject target) {
//Set Attack Timers
if (target.getObjectType().equals(Enum.GameObjectType.PlayerCharacter))
pc.setLastPlayerAttackTime();
}
public static void handleDamageShields(AbstractCharacter ac, AbstractCharacter target, float damage) {
if (ac == null || target == null)
return;
PlayerBonuses bonuses = target.getBonuses();
if (bonuses != null) {
ConcurrentHashMap<AbstractEffectModifier, DamageShield> damageShields = bonuses.getDamageShields();
float total = 0;
for (DamageShield ds : damageShields.values()) {
//get amount to damage back
float amount;
if (ds.usePercent())
amount = damage * ds.getAmount() / 100;
else
amount = ds.getAmount();
//get resisted damage for damagetype
Resists resists = ac.getResists();
if (resists != null) {
amount = resists.getResistedDamage(target, ac, ds.getDamageType(), amount, 0);
}
total += amount;
}
if (total > 0) {
//apply Damage back
ac.modifyHealth(-total, target, true);
TargetedActionMsg cmm = new TargetedActionMsg(ac, ac, total, 0);
DispatchMessage.sendToAllInRange(target, cmm);
}
}
}
public static boolean inRange(AbstractCharacter source, AbstractWorldObject target, boolean mainhand){
if(source == null || target == null)
return false;
float distanceSquared = source.loc.distanceSquared(target.loc);
float rangeSquared = 16.0f;
if(source.getCharItemManager() != null && source.getCharItemManager().getEquipped() != null){
Item weapon = source.getCharItemManager().getEquipped(1);
if(!mainhand)
weapon = source.getCharItemManager().getEquipped(2);
if(weapon != null)
rangeSquared = weapon.getItemBase().getRange() * weapon.getItemBase().getRange();
}
if(source.getBonuses() != null){
rangeSquared *= 1 + source.getBonuses().getFloatPercentAll(Enum.ModType.WeaponRange, Enum.SourceType.None);
}
return distanceSquared <= rangeSquared;
}
public static boolean triggerPassive(AbstractCharacter source, AbstractWorldObject target) {
boolean passiveFired = false;
if (!AbstractCharacter.IsAbstractCharacter(target))
return false;
AbstractCharacter tarAc = (AbstractCharacter) target;
//Handle Block passive
if (testPassive(source, tarAc, "Block")) {
sendPassiveDefenseMessage(source, null, target, MBServerStatics.COMBAT_SEND_DODGE, null, true);
return true;
}
//Handle Parry passive
if (testPassive(source, tarAc, "Parry")) {
sendPassiveDefenseMessage(source, null, target, MBServerStatics.COMBAT_SEND_DODGE, null, true);
return true;
}
//Handle Dodge passive
if (testPassive(source, tarAc, "Dodge")) {
sendPassiveDefenseMessage(source, null, target, MBServerStatics.COMBAT_SEND_DODGE, null, true);
return true;
}
return false;
}
private static void sendPassiveDefenseMessage(AbstractCharacter source, ItemBase wb, AbstractWorldObject target, int passiveType, DeferredPowerJob dpj, boolean mainHand) {
int swingAnimation = 75;
if (dpj != null)
if (PowersManager.AnimationOverrides.containsKey(dpj.getAction().getEffectID()))
swingAnimation = PowersManager.AnimationOverrides.get(dpj.getAction().getEffectID());
TargetedActionMsg cmm = new TargetedActionMsg(source, swingAnimation, target, passiveType);
DispatchMessage.sendToAllInRange(target, cmm);
}
private static boolean testPassive(AbstractCharacter source, AbstractCharacter target, String type) {
if(target.getBonuses() != null)
if(target.getBonuses().getBool(Enum.ModType.Stunned, Enum.SourceType.None))
return false;
float chance = target.getPassiveChance(type, source.getLevel(), true);
if (chance == 0f)
return false;
//max 75% chance of passive to fire
if (chance > 75f)
chance = 75f;
int roll = ThreadLocalRandom.current().nextInt(1,100);
return roll < chance;
}
private static void createTimer(AbstractCharacter source, boolean mainhand) {
ConcurrentHashMap<String, JobContainer> timers = source.getTimers();
int slot = 1;
if(!mainhand)
slot = 2;
int time = 3000;
if(source.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)){
PlayerCharacter pc = (PlayerCharacter)source;
if(mainhand){
time = (int) pc.combatStats.attackSpeedHandOne;
}else{
time = (int) pc.combatStats.attackSpeedHandTwo;
}
}
if (timers != null) {
AttackJob aj = new AttackJob(source, slot, true);
JobContainer job;
job = JobScheduler.getInstance().scheduleJob(aj, (time * 100));
timers.put("Attack" + slot, job);
} else {
Logger.error("Unable to find Timers for Character " + source.getObjectUUID());
}
}
public static void setAttackTarget(AttackCmdMsg msg, ClientConnection origin) throws MsgSendException {
PlayerCharacter player;
int targetType;
AbstractWorldObject target;
if (TargetedActionMsg.un2cnt == 60 || TargetedActionMsg.un2cnt == 70)
return;
player = SessionManager.getPlayerCharacter(origin);
if (player == null)
return;
//source must match player this account belongs to
if (player.getObjectUUID() != msg.getSourceID() || player.getObjectType().ordinal() != msg.getSourceType()) {
Logger.error("Msg Source ID " + msg.getSourceID() + " Does not Match Player ID " + player.getObjectUUID());
return;
}
targetType = msg.getTargetType();
if (targetType == Enum.GameObjectType.PlayerCharacter.ordinal()) {
target = PlayerCharacter.getFromCache(msg.getTargetID());
} else if (targetType == Enum.GameObjectType.Building.ordinal()) {
target = BuildingManager.getBuildingFromCache(msg.getTargetID());
} else if (targetType == Enum.GameObjectType.Mob.ordinal()) {
target = Mob.getFromCache(msg.getTargetID());
} else {
player.setCombatTarget(null);
return; //not valid type to attack
}
// quit of the combat target is already the current combat target
// or there is no combat target
if (target == null)
return;
//set sources target
player.setCombatTarget(target);
boolean hasMain = false;
boolean hasOff = false;
if(player.getCharItemManager() != null && player.getCharItemManager().getEquipped() != null){
if(player.getCharItemManager().getEquipped(1) != null)
hasMain = true;
if(player.getCharItemManager().getEquipped(2) != null && !player.getCharItemManager().getEquipped(2).getItemBase().isShield())
hasOff = true;
}
if(hasMain){
createTimer(player,true);
}
if(hasOff){
createTimer(player,false);
}
}
}
+1 -3
View File
@@ -65,7 +65,6 @@ public enum ConfigManager {
MB_WORLD_MAINTENANCE,
MB_WORLD_GREETING,
MB_WORLD_KEYCLONE_MAX,
MB_WORLD_TESTMODE,
MB_USE_RUINS,
// Mobile AI modifiers
@@ -98,8 +97,7 @@ public enum ConfigManager {
MB_MAGICBOT_FORTOFIX,
MB_MAGICBOT_RECRUIT,
MB_MAGICBOT_MAGICBOX,
MB_MAGICBOT_ADMINLOG,
MB_WORLD_BOXLIMIT;
MB_MAGICBOT_ADMINLOG;
// Map to hold our config pulled in from the environment
// We also use the config to point to the current message pump
+3 -38
View File
@@ -79,13 +79,13 @@ 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());
DevCmdManager.registerDevCmd(new AddBuildingCmd());
DevCmdManager.registerDevCmd(new AddNPCCmd());
DevCmdManager.registerDevCmd(new AddMobCmd());
DevCmdManager.registerDevCmd(new DungenonCmd());
DevCmdManager.registerDevCmd(new RemoveObjectCmd());
DevCmdManager.registerDevCmd(new RotateCmd());
DevCmdManager.registerDevCmd(new FlashMsgCmd());
@@ -103,7 +103,6 @@ public enum DevCmdManager {
DevCmdManager.registerDevCmd(new SetAdminRuneCmd());
DevCmdManager.registerDevCmd(new SetInvulCmd());
DevCmdManager.registerDevCmd(new MakeItemCmd());
DevCmdManager.registerDevCmd(new GimmeCmd());
DevCmdManager.registerDevCmd(new EnchantCmd());
DevCmdManager.registerDevCmd(new SetSubRaceCmd());
// Admin
@@ -178,44 +177,10 @@ public enum DevCmdManager {
return false;
}
if(!pcSender.getTimestamps().containsKey("DEVCOMMAND"))
pcSender.getTimestamps().put("DEVCOMMAND",System.currentTimeMillis() - 1500L);
else if(System.currentTimeMillis() - pcSender.getTimestamps().get("DEVCOMMAND") < 1000L)
return false;
//kill any commands not available to everyone on production server
//only admin level can run dev commands on production
boolean playerAllowed = false;
if(ConfigManager.MB_WORLD_TESTMODE.getValue().equals("true")) {
switch (adc.getMainCmdString()) {
case "printresists":
case "printstats":
case "printskills":
case "printpowers":
case "gimme":
case "goto":
case "teleportmode":
case "printbonuses":
playerAllowed = true;
if (!a.status.equals(Enum.AccountStatus.ADMIN))
target = pcSender;
break;
}
}else{
switch (adc.getMainCmdString()) {
case "printresists":
case "printstats":
case "printskills":
case "printpowers":
case "printbonuses":
//case "gimme":
playerAllowed = true;
if (!a.status.equals(Enum.AccountStatus.ADMIN))
target = pcSender;
break;
}
}
if (!playerAllowed && !a.status.equals(Enum.AccountStatus.ADMIN)) {
if (a.status.equals(Enum.AccountStatus.ADMIN) == false) {
Logger.info("Account " + a.getUname() + "attempted to use dev command " + cmd);
return false;
}
+99 -677
View File
@@ -14,13 +14,10 @@ import engine.net.DispatchMessage;
import engine.net.client.msg.ErrorPopupMsg;
import engine.net.client.msg.chat.ChatSystemMsg;
import engine.objects.*;
import engine.server.MBServerStatics;
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;
/**
@@ -37,21 +34,6 @@ 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));
public static final ArrayList<Integer> racial_guard_uuids = new ArrayList<>(Arrays.asList(841,951,952,1050,1052,1180,1182,1250,1252,1350,1352,1450,1452,1500,1502,1525,1527,1550,1552,1575,1577,1600,1602,1650,1652,1700,980100,980102));
public static final ArrayList<Integer> static_rune_ids = new ArrayList<>(Arrays.asList(
250001, 250002, 250003, 250004, 250005, 250006, 250007, 250008, 250010, 250011,
250012, 250013, 250014, 250015, 250016, 250017, 250019, 250020, 250021, 250022,
250023, 250024, 250025, 250026, 250028, 250029, 250030, 250031, 250032, 250033,
250034, 250035, 250037, 250038, 250039, 250040, 250041, 250042, 250043, 250044,
250115, 250118, 250119, 250120, 250121, 250122, 252123, 252124, 252125, 252126,
252127
));
// Drop Rates
public static float NORMAL_DROP_RATE;
@@ -86,128 +68,49 @@ public enum LootManager {
public static void GenerateMobLoot(Mob mob) {
if(mob == null){
return;
}
//determine if mob is in hotzone
boolean inHotzone = false;
boolean inHotzone = ZoneManager.inHotZone(mob.getLoc());
//iterate the booty sets
if(mob.mobBase == null || mob.getMobBaseID() == 253003){
int i = 0;
}
if (mob.getMobBase().bootySet != 0 && _bootySetMap.containsKey(mob.getMobBase().bootySet))
if (mob.getMobBase().bootySet != 0 && _bootySetMap.containsKey(mob.getMobBase().bootySet) == true)
RunBootySet(_bootySetMap.get(mob.getMobBase().bootySet), mob, inHotzone);
if (mob.bootySet != 0 && _bootySetMap.containsKey(mob.bootySet)) {
if (mob.bootySet != 0 && _bootySetMap.containsKey(mob.bootySet) == true)
RunBootySet(_bootySetMap.get(mob.bootySet), mob, inHotzone);
}else if(mob.bootySet != 0 && ItemBase.getItemBase(mob.bootySet) != null){
MobLoot specialDrop = null;
specialDrop = new MobLoot(mob,ItemBase.getItemBase(mob.bootySet),true);
if(specialDrop != null) {
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);
}
}
//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;
if (!mob.getSafeZone()) {
int contractLow = 1, contractHigh = 400;
int runeLow = 401, runeHigh = 800;
int resourceLow = 801, resourceHigh = 900;
int glassLow = 901, glassHigh = 910;
int guardLow = 911, guardHigh = 920;
// Pre-compute adjusted high values
int contractAdjust = 0, runeAdjust = 0, resourceAdjust = 0, glassAdjust = 0, guardAdjust = 0;
if (mob.level < 50) {
int dif = 50 - mob.level;
contractAdjust = (int)(400 * (dif * 0.02f));
runeAdjust = (int)(400 * (dif * 0.02f));
resourceAdjust = (int)(100 * (dif * 0.02f));
glassAdjust = (int)(10 * (dif * 0.02f));
guardAdjust = (int)(10 * (dif * 0.02f));
}
// Generate a single random roll
int specialCaseRoll = ThreadLocalRandom.current().nextInt(1, 100001);
// Calculate adjusted high values once
int contractHighAdjusted = contractHigh - contractAdjust;
int runeHighAdjusted = runeHigh - runeAdjust;
int resourceHighAdjusted = resourceHigh - resourceAdjust;
int glassHighAdjusted = glassHigh - glassAdjust;
int guardHighAdjusted = guardHigh - guardAdjust;
// Check the roll range and handle accordingly
if (specialCaseRoll >= contractLow && specialCaseRoll <= contractHighAdjusted) {
SpecialCaseContractDrop(mob, entries);
} else if (specialCaseRoll >= runeLow && specialCaseRoll <= runeHighAdjusted) {
SpecialCaseRuneDrop(mob, entries);
} else if (specialCaseRoll >= resourceLow && specialCaseRoll <= resourceHighAdjusted) {
SpecialCaseResourceDrop(mob, entries);
} else if (specialCaseRoll >= glassLow && specialCaseRoll <= glassHighAdjusted) {
int glassID = rollRandomItem(126);
ItemBase glassItem = ItemBase.getItemBase(glassID);
if (glassItem != null) {
MobLoot toAddGlass = new MobLoot(mob, glassItem, false);
mob.getCharItemManager().addItemToInventory(toAddGlass);
}
} else if (specialCaseRoll >= guardLow && specialCaseRoll <= guardHighAdjusted) {
int guardContractID = racial_guard_uuids.get(new java.util.Random().nextInt(racial_guard_uuids.size()));
ItemBase guardContract = ItemBase.getItemBase(guardContractID);
if (guardContract != null) {
MobLoot toAddContract = new MobLoot(mob, guardContract, false);
mob.getCharItemManager().addItemToInventory(toAddContract);
}
}
}
float dropRate = 1.0f;
// Iterate all entries in this bootySet and process accordingly
Zone zone = ZoneManager.findSmallestZone(mob.loc);
for (BootySetEntry bse : entries) {
switch (bse.bootyType) {
case "GOLD":
if (zone != null && zone.getSafeZone() == (byte)1)
return; // no loot to drop in safezones
GenerateGoldDrop(mob, bse, inHotzone);
break;
case "LOOT":
if (zone != null && zone.getSafeZone() == (byte)1)
return; // no loot to drop in safezones
dropRate = LootManager.NORMAL_DROP_RATE;
if (mob.getSafeZone() == false)
dropRate = LootManager.NORMAL_DROP_RATE;
if (inHotzone == true)
dropRate = LootManager.HOTZONE_DROP_RATE;
@@ -232,116 +135,6 @@ public enum LootManager {
}
}
public static void SpecialCaseContractDrop(Mob mob,ArrayList<BootySetEntry> entries){
int lootTableID = 0;
for(BootySetEntry entry : entries){
if(entry.bootyType.equals("LOOT")){
lootTableID = entry.genTable;
break;
}
}
if(lootTableID == 0)
return;
int ContractTableID = 0;
for(GenTableEntry entry : _genTables.get(lootTableID)){
try {
if (ItemBase.getItemBase(_itemTables.get(entry.itemTableID).get(0).cacheID).getType().equals(Enum.ItemType.CONTRACT)) {
ContractTableID = entry.itemTableID;
break;
}
}catch(Exception e){
}
}
if(ContractTableID == 0)
return;
ItemBase ib = ItemBase.getItemBase(rollRandomItem(ContractTableID));
if(ib != null){
MobLoot toAdd = new MobLoot(mob,ib,false);
mob.getCharItemManager().addItemToInventory(toAdd);
}
}
public static void SpecialCaseRuneDrop(Mob mob,ArrayList<BootySetEntry> entries){
//int lootTableID = 0;
//for(BootySetEntry entry : entries){
// if(entry.bootyType.equals("LOOT")){
// lootTableID = entry.genTable;
// break;
// }
//}
// if(lootTableID == 0)
// return;
//int RuneTableID = 0;
//for(GenTableEntry entry : _genTables.get(lootTableID)){
// try {
// if (ItemBase.getItemBase(_itemTables.get(entry.itemTableID).get(0).cacheID).getType().equals(Enum.ItemType.RUNE)) {
// RuneTableID = entry.itemTableID;
// break;
// }
// }catch(Exception e){
// }
//}
//if(RuneTableID == 0)
// return;
int roll = ThreadLocalRandom.current().nextInt(static_rune_ids.size() + 1);
int itemId = static_rune_ids.get(0);
try {
itemId = static_rune_ids.get(roll);
}catch(Exception e){
}
ItemBase ib = ItemBase.getItemBase(itemId);
if(ib != null){
MobLoot toAdd = new MobLoot(mob,ib,false);
mob.getCharItemManager().addItemToInventory(toAdd);
}
}
public static void SpecialCaseResourceDrop(Mob mob,ArrayList<BootySetEntry> entries){
int lootTableID = 0;
for(BootySetEntry entry : entries){
if(entry.bootyType.equals("LOOT")){
lootTableID = entry.genTable;
break;
}
}
if(lootTableID == 0)
return;
int ResourceTableID = 0;
for(GenTableEntry entry : _genTables.get(lootTableID)){
try {
if (ItemBase.getItemBase(_itemTables.get(entry.itemTableID).get(0).cacheID).getType().equals(Enum.ItemType.RESOURCE)) {
ResourceTableID = entry.itemTableID;
break;
}
}catch(Exception e){
}
}
if(ResourceTableID == 0)
return;
ItemBase ib = ItemBase.getItemBase(rollRandomItem(ResourceTableID));
if(ib != null){
MobLoot toAdd = new MobLoot(mob,ib,false);
mob.getCharItemManager().addItemToInventory(toAdd);
}
}
public static MobLoot getGenTableItem(int genTableID, AbstractCharacter mob, Boolean inHotzone) {
if (mob == null || _genTables.containsKey(genTableID) == false)
@@ -363,10 +156,11 @@ public enum LootManager {
//gets the 1-320 roll for this mob
int itemTableRoll = 0;
int objectType = mob.getObjectType().ordinal();
if(mob.getObjectType().ordinal() == 52) { //52 = player character
itemTableRoll = ThreadLocalRandom.current().nextInt(1,320 + 1);
} else{
itemTableRoll = TableRoll(mob.level);
itemTableRoll = TableRoll(mob.level, inHotzone);
}
ItemTableEntry tableRow = ItemTableEntry.rollTable(itemTableId, itemTableRoll);
if (tableRow == null)
@@ -378,23 +172,13 @@ 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 {
@@ -412,12 +196,6 @@ 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;
}
@@ -438,7 +216,7 @@ public enum LootManager {
if(mob.getObjectType().ordinal() == 52) {
prefixTableRoll = ThreadLocalRandom.current().nextInt(1,320 + 1);
} else{
prefixTableRoll = TableRoll(mob.level);
prefixTableRoll = TableRoll(mob.level, inHotzone);
}
ModTableEntry prefixMod = ModTableEntry.rollTable(prefixTable.modTableID, prefixTableRoll);
@@ -470,34 +248,14 @@ public enum LootManager {
if(mob.getObjectType().ordinal() == 52) {
suffixTableRoll = ThreadLocalRandom.current().nextInt(1,320 + 1);
} else{
suffixTableRoll = TableRoll(mob.level);
suffixTableRoll = TableRoll(mob.level, inHotzone);
}
ModTableEntry suffixMod = ModTableEntry.rollTable(suffixTable.modTableID, suffixTableRoll);
if (suffixMod == null)
return inItem;
int moveSpeedRoll = ThreadLocalRandom.current().nextInt(100);
if(inItem.getItemBase().getValidSlot() == MBServerStatics.SLOT_FEET && moveSpeedRoll < 10){
int rankRoll = ThreadLocalRandom.current().nextInt(10);
String suffixSpeed = "SUF-148";
switch(rankRoll) {
case 1:
case 2:
case 3:
suffixSpeed = "SUF-149";
break;
case 4:
case 5:
case 6:
case 7:
suffixSpeed = "SUF-150";
break;
}
inItem.setSuffix(suffixSpeed);
inItem.addPermanentEnchantment(suffixSpeed, 0, suffixMod.level, false);
}else if (suffixMod.action.length() > 0) {
if (suffixMod.action.length() > 0) {
inItem.setSuffix(suffixMod.action);
inItem.addPermanentEnchantment(suffixMod.action, 0, suffixMod.level, false);
}
@@ -505,36 +263,23 @@ public enum LootManager {
return inItem;
}
public static int TableRoll(int mobLevel) {
int rank = (int)(mobLevel * 0.1f);
int min = 50;
int max = 100;
switch(rank){
case 1:
min = 200;
max = 250;
break;
case 2:
min = 210;
max = 275;
break;
case 3:
min = 220;
max = 300;
break;
case 4:
min = 230;
max = 320;
break;
case 5:
case 6:
case 7:
case 8:
min = 240;
max = 320;
break;
}
public static int TableRoll(int mobLevel, Boolean inHotzone) {
if (mobLevel > 65)
mobLevel = 65;
int max = (int) (4.882 * mobLevel + 127.0);
if (max > 319)
max = 319;
int min = (int) (4.469 * mobLevel - 3.469);
if (min < 70)
min = 70;
if (inHotzone)
min += mobLevel;
int roll = ThreadLocalRandom.current().nextInt(min, max + 1);
@@ -554,7 +299,12 @@ public enum LootManager {
int high = bse.highGold;
int low = bse.lowGold;
int gold = (int) (ThreadLocalRandom.current().nextInt(low, high + 1) * NORMAL_GOLD_RATE);
int gold = ThreadLocalRandom.current().nextInt(low, high + 1);
if (inHotzone == true)
gold = (int) (gold * HOTZONE_GOLD_RATE);
else
gold = (int) (gold * NORMAL_GOLD_RATE);
if (gold > 0) {
MobLoot goldAmount = new MobLoot(mob, gold);
@@ -565,63 +315,45 @@ public enum LootManager {
public static void GenerateLootDrop(Mob mob, int tableID, Boolean inHotzone) {
MobLoot toAdd = getGenTableItem(tableID, mob, inHotzone);
if(toAdd != null){
ItemBase ib = toAdd.getItemBase();
switch(ib.getType()){
case CONTRACT:
case RUNE:
case RESOURCE:
return;
}
toAdd.setIsID(true);
mob.getCharItemManager().addItemToInventory(toAdd);
}
}
try {
MobLoot toAdd = getGenTableItem(tableID, mob, inHotzone);
public static void GenerateEquipmentDrop(Mob mob) {
if (toAdd != null)
mob.getCharItemManager().addItemToInventory(toAdd);
if (mob == null || mob.getSafeZone())
return; // no equipment to drop in safezones
} catch (Exception e) {
//TODO chase down loot generation error, affects roughly 2% of drops
int i = 0;
}
}
if(mob.StrongholdGuardian || mob.StrongholdCommander || mob.StrongholdEpic)
return; // stronghold mobs don't drop equipment
public static void GenerateEquipmentDrop(Mob mob) {
//do equipment here
if (mob.getEquip() != null) {
boolean isVorg = false;
int dropCount = 0;
if (mob.getEquip() != null)
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;
if(isVorg && !mob.isDropper){
continue;
}
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 = 7.5f;
itemBase = getRandomVorg(itemBase);
}
if (equipmentRoll > dropChance)
continue;
MobLoot ml = new MobLoot(mob, itemBase, false);
MobLoot ml = new MobLoot(mob, me.getItemBase(), false);
ml.setIsID(true);
ml.setDurabilityCurrent((short) (ml.getDurabilityCurrent() - ThreadLocalRandom.current().nextInt(5) + 1));
mob.getCharItemManager().addItemToInventory(ml);
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.
}
}
}
}
public static void GenerateInventoryDrop(Mob mob, BootySetEntry bse) {
@@ -635,89 +367,10 @@ 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 newFatePeddler(PlayerCharacter playerCharacter, Item gift) {
CharacterItemManager itemMan = playerCharacter.getCharItemManager();
if (itemMan == null)
return;
//check if player owns the gift he is trying to open
if (!itemMan.doesCharOwnThisItem(gift.getObjectUUID()))
return;
ItemBase ib = gift.getItemBase();
MobLoot winnings = null;
if (ib == null)
return;
switch (ib.getUUID()) {
case 971070: //wrapped rune
ItemBase runeBase = null;
int roll = ThreadLocalRandom.current().nextInt(static_rune_ids.size() + 1);
int itemId = static_rune_ids.get(0);
try {
itemId = static_rune_ids.get(roll);
}catch(Exception e){
}
runeBase = ItemBase.getItemBase(itemId);
if(runeBase != null) {
winnings = new MobLoot(playerCharacter, runeBase, 1, false);
}
break;
case 971012: //wrapped glass
int chance = ThreadLocalRandom.current().nextInt(100);
if(chance == 50){
int ID = 7000000;
int additional = ThreadLocalRandom.current().nextInt(0,28);
ID += (additional * 10);
ItemBase glassBase = ItemBase.getItemBase(ID);
if(glassBase != null) {
winnings = new MobLoot(playerCharacter, glassBase, 1, false);
ChatManager.chatSystemInfo(playerCharacter, "You've Won A " + glassBase.getName());
}
}else{
ChatManager.chatSystemInfo(playerCharacter, "Please Try Again!");
}
break;
}
if (winnings == null) {
itemMan.consume(gift);
itemMan.updateInventory();
return;
}
//early exit if the inventory of the player will not hold the item
if (!itemMan.hasRoomInventory(winnings.getItemBase().getWeight())) {
ErrorPopupMsg.sendErrorPopup(playerCharacter, 21);
return;
}
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();
}
public static void peddleFate(PlayerCharacter playerCharacter, Item gift) {
//get table ID for the itembase ID
@@ -739,12 +392,12 @@ public enum LootManager {
//check if player owns the gift he is trying to open
if (!itemMan.doesCharOwnThisItem(gift.getObjectUUID()))
if (itemMan.doesCharOwnThisItem(gift.getObjectUUID()) == false)
return;
//roll 1-100 for the gen table selection
int genRoll = ThreadLocalRandom.current().nextInt(94, 100) + 1;
int genRoll = ThreadLocalRandom.current().nextInt(1, 100 + 1);
GenTableEntry selectedRow = GenTableEntry.rollTable(tableID, genRoll, LootManager.NORMAL_DROP_RATE);
if(selectedRow == null)
@@ -760,276 +413,45 @@ public enum LootManager {
//create the item from the table, quantity is always 1
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;
//early exit if the inventory of the player will not hold the item
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();
}
}
public static int rollRandomItem(int itemTable){
int returnedID = ItemTableEntry.getRandomItem(itemTable);
return returnedID;
}
public static ItemBase getRandomVorg(ItemBase itemBase){
int roll = 0;
if(vorg_ha_uuids.contains(itemBase.getUUID())) {
roll = ThreadLocalRandom.current().nextInt(0, 9);
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));
}
}
if(vorg_ma_uuids.contains(itemBase.getUUID())) {
roll = ThreadLocalRandom.current().nextInt(0, 8);
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(vorg_la_uuids.contains(itemBase.getUUID())) {
roll = ThreadLocalRandom.current().nextInt(0, 8);
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));
}
}
if(vorg_cloth_uuids.contains(itemBase.getUUID())) {
roll = ThreadLocalRandom.current().nextInt(0, 5);
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));
}
}
return null;
}
public static void DropPresent(Mob mob){
int random = 971049 + ThreadLocalRandom.current().nextInt(24);
if (random > 971071)
random = 971071;
ItemBase present = ItemBase.getItemBase(random);
if (present != null) {
MobLoot toAdd = new MobLoot(mob, present, true);
if (toAdd != null)
mob.getCharItemManager().addItemToInventory(toAdd);
}
}
public static void GenerateStrongholdLoot(Mob mob, boolean commander, boolean epic) {
mob.getCharItemManager().clearInventory();
int multiplier = 1;
if (commander)
multiplier = 2;
if(epic)
multiplier = 10;
int high = 125000;
int low = 50000;
int gold = ThreadLocalRandom.current().nextInt(low, high + 1) * multiplier;
if (gold > 0) {
MobLoot goldAmount = new MobLoot(mob, gold);
mob.getCharItemManager().addItemToInventory(goldAmount);
}
//present drop chance for all
if (ThreadLocalRandom.current().nextInt(100) < 35)
DropPresent(mob);
MobLoot winnings = new MobLoot(playerCharacter, ItemBase.getItemBase(selectedItem.cacheID), 1, false);
//random contract drop chance for all
if (ThreadLocalRandom.current().nextInt(100) < 40) {
int contractTableID = 250;
contractTableID += ThreadLocalRandom.current().nextInt(0, 11);
if (contractTableID > 259)
contractTableID = 659;
if (winnings == null)
return;
int id = rollRandomItem(contractTableID);
ItemBase ib = ItemBase.getItemBase(id);
if (ib != null) {
MobLoot contract = new MobLoot(mob, ib, true);
//early exit if the inventory of the player will not old the item
if (contract != null)
mob.getCharItemManager().addItemToInventory(contract);
}
if (itemMan.hasRoomInventory(winnings.getItemBase().getWeight()) == false) {
ErrorPopupMsg.sendErrorPopup(playerCharacter, 21);
return;
}
//special commander drop chances
if (commander)
GenerateCommanderLoot(mob,false);
//determine if the winning item needs a prefix
//special epic drop chances
if (epic) {
GenerateCommanderLoot(mob, true);
GenerateCommanderLoot(mob,false);
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 void GenerateCommanderLoot(Mob mob, boolean epic){
//present chance
if (ThreadLocalRandom.current().nextInt(100) < 25)
DropPresent(mob);
//present chance
if (ThreadLocalRandom.current().nextInt(100) < 25)
DropPresent(mob);
//determine if the winning item needs a suffix
//chance for glass
if (ThreadLocalRandom.current().nextInt(100) < 75) {
int glassID = rollRandomItem(126);
ItemBase glassItem = ItemBase.getItemBase(glassID);
if (glassItem != null) {
MobLoot toAdd2 = new MobLoot(mob, glassItem, true);
if (toAdd2 != null)
mob.getCharItemManager().addItemToInventory(toAdd2);
}
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);
//chance for disc
if (ThreadLocalRandom.current().nextInt(100) < 75) {
int discID = rollRandomItem(3202);
ItemBase discItem = ItemBase.getItemBase(discID);
if (discItem != null) {
MobLoot toAdd3 = new MobLoot(mob, discItem, true);
//remove gift from inventory
if (toAdd3 != null)
mob.getCharItemManager().addItemToInventory(toAdd3);
}
}
itemMan.consume(gift);
//chance for stat rune
if (ThreadLocalRandom.current().nextInt(100) < 75) {
int runeID = rollRandomItem(3201);
ItemBase runeItem = ItemBase.getItemBase(runeID);
if (runeItem != null) {
MobLoot toAdd4 = new MobLoot(mob, runeItem, true);
//add winnings to player inventory
if (toAdd4 != null)
mob.getCharItemManager().addItemToInventory(toAdd4);
}
}
if(epic){
int contractTableID = 250;
contractTableID += ThreadLocalRandom.current().nextInt(0, 11);
if (contractTableID > 259)
contractTableID = 659;
int id = rollRandomItem(contractTableID);
ItemBase ib = ItemBase.getItemBase(id);
if (ib != null) {
MobLoot contract = new MobLoot(mob, ib, true);
if (contract != null)
mob.getCharItemManager().addItemToInventory(contract);
}
}
Item playerWinnings = winnings.promoteToItem(playerCharacter);
itemMan.addItemToInventory(playerWinnings);
itemMan.updateInventory();
}
}
+108 -15
View File
@@ -24,7 +24,7 @@ public enum MaintenanceManager {
public static void setMaintDateTime(Building building, LocalDateTime maintDate) {
building.maintDateTime = maintDate.withHour(1).withMinute(0).withSecond(0);
building.maintDateTime = maintDate;
DbManager.BuildingQueries.updateMaintDate(building);
}
@@ -49,15 +49,19 @@ 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));
for (Building building : derankList) {
building.destroyOrDerank(null);
if(building.getRank() > 0)
setMaintDateTime(building, LocalDateTime.now().plusDays(1));
}
// Derak or destroy buildings that did not
// have funds available.
for (Building building : derankList)
building.destroyOrDerank(null);
Logger.info("Structures: " + buildingList.size() + " Maint: " + maintList.size() + " Derank: " + derankList.size());
}
@@ -94,10 +98,6 @@ 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))
@@ -122,9 +122,9 @@ public enum MaintenanceManager {
//no maintenance if day of week doesnt match
//if (LocalDateTime.now().getDayOfWeek().ordinal() != building.maintDateTime.getDayOfWeek().ordinal()) {
// continue;
//}
if (LocalDateTime.now().getDayOfWeek().ordinal() != building.maintDateTime.getDayOfWeek().ordinal()) {
continue;
}
// Add building to maintenance queue
maintList.add(building);
@@ -186,8 +186,49 @@ public enum MaintenanceManager {
// If this is an R8 tree, validate that we can
// cover the resources required
if (building.getRank() == 8) {
hasResources = true;
if (warehouse == null)
hasResources = false;
else {
resourceValue = warehouse.getResources().get(Warehouse.stoneIB);
if (resourceValue < 1500)
hasResources = false;
resourceValue = warehouse.getResources().get(Warehouse.lumberIB);
if (resourceValue < 1500)
hasResources = false;
resourceValue = warehouse.getResources().get(Warehouse.galvorIB);
if (resourceValue < 5)
hasResources = false;
resourceValue = warehouse.getResources().get(Warehouse.wormwoodIB);
if (resourceValue < 5)
hasResources = false;
}
}
// Validation completed but has failed. We can derank
// the target building and early exit
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)));
}
if (hasFunds == false) {
return false; // Early exit for having failed to meet maintenance
}
@@ -212,6 +253,58 @@ public enum MaintenanceManager {
}
}
// Early exit as we're done if we're not an R8 tree
if (building.getRank() < 8)
return true;
// Now for the resources if it's an R8 tree
// Withdraw Stone
resourceValue = warehouse.getResources().get(Warehouse.stoneIB);
if (DbManager.WarehouseQueries.updateStone(warehouse, resourceValue - 1500) == true) {
warehouse.getResources().put(Warehouse.stoneIB, resourceValue - 1500);
warehouse.AddTransactionToWarehouse(Enum.GameObjectType.Building, building.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.STONE, 1500);
} else {
Logger.error("stone update failed for warehouse of UUID:" + warehouse.getObjectUUID());
return true;
}
// Withdraw Lumber
resourceValue = warehouse.getResources().get(Warehouse.lumberIB);
if (DbManager.WarehouseQueries.updateLumber(warehouse, resourceValue - 1500) == true) {
warehouse.getResources().put(Warehouse.lumberIB, resourceValue - 1500);
warehouse.AddTransactionToWarehouse(Enum.GameObjectType.Building, building.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.LUMBER, 1500);
} else {
Logger.error("lumber update failed for warehouse of UUID:" + warehouse.getObjectUUID());
return true;
}
// Withdraw Galvor
resourceValue = warehouse.getResources().get(Warehouse.galvorIB);
if (DbManager.WarehouseQueries.updateGalvor(warehouse, resourceValue - 5) == true) {
warehouse.getResources().put(Warehouse.galvorIB, resourceValue - 5);
warehouse.AddTransactionToWarehouse(Enum.GameObjectType.Building, building.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.GALVOR, 5);
} else {
Logger.error("galvor update failed for warehouse of UUID:" + warehouse.getObjectUUID());
return true;
}
resourceValue = warehouse.getResources().get(Warehouse.wormwoodIB);
if (DbManager.WarehouseQueries.updateWormwood(warehouse, resourceValue - 5) == true) {
warehouse.getResources().put(Warehouse.wormwoodIB, resourceValue - 5);
warehouse.AddTransactionToWarehouse(Enum.GameObjectType.Building, building.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.WORMWOOD, 5);
} else {
Logger.error("wyrmwood update failed for warehouse of UUID:" + warehouse.getObjectUUID());
}
return true;
}
+5 -9
View File
@@ -67,10 +67,8 @@ public enum MovementManager {
return;
if (toMove.getObjectType().equals(GameObjectType.PlayerCharacter)) {
if (((PlayerCharacter) toMove).isCasting()) {
((PlayerCharacter) toMove).updateLocation();
((PlayerCharacter) toMove).updateMovementState();
}
if (((PlayerCharacter) toMove).isCasting())
((PlayerCharacter) toMove).update();
}
@@ -98,7 +96,7 @@ public enum MovementManager {
if (!toMove.isMoving())
toMove.resetLastSetLocUpdate();
else
toMove.update(false);
toMove.update();
// Update movement for the player
@@ -353,7 +351,7 @@ public enum MovementManager {
ChatManager.chatSystemInfo((PlayerCharacter) ac, "Finished Alt change, setting the end location to " + ac.getEndLoc().getX() + ' ' + ac.getEndLoc().getZ() + " moving=" + ac.isMoving() + " and current location is " + curLoc.getX() + ' ' + curLoc.getZ());
//Send run/walk/sit/stand to tell the client we are flying / landing etc
ac.update(false);
ac.update();
ac.stopMovement(ac.getLoc());
if (ac.isAlive())
MovementManager.sendRWSSMsg(ac);
@@ -410,9 +408,7 @@ public enum MovementManager {
if (bonus.getBool(ModType.Stunned, SourceType.None) || bonus.getBool(ModType.CannotMove, SourceType.None))
continue;
//member.update(false);
member.updateLocation();
member.updateMovementState();
member.update();
// All checks passed, let's move the player
+2 -2
View File
@@ -340,8 +340,8 @@ public enum NPCManager {
else
buildingSlot = BuildingManager.getAvailableSlot(abstractCharacter.building);
//if (buildingSlot == -1)
//Logger.error("No available slot for NPC: " + abstractCharacter.getObjectUUID());
if (buildingSlot == -1)
Logger.error("No available slot for NPC: " + abstractCharacter.getObjectUUID());
abstractCharacter.building.getHirelings().put(abstractCharacter, buildingSlot);
+62 -435
View File
@@ -10,7 +10,6 @@ package engine.gameManager;
import engine.Enum.*;
import engine.InterestManagement.HeightMap;
import engine.InterestManagement.InterestManager;
import engine.InterestManagement.WorldGrid;
import engine.db.handlers.dbEffectsBaseHandler;
import engine.db.handlers.dbPowerHandler;
@@ -164,40 +163,6 @@ public enum PowersManager {
public static void usePower(final PerformActionMsg msg, ClientConnection origin,
boolean sendCastToSelf) {
PlayerCharacter pc = SessionManager.getPlayerCharacter(origin);
if(pc == null)
return;
if(!pc.isFlying() && powersBaseByToken.get(msg.getPowerUsedID()) != null && powersBaseByToken.get(msg.getPowerUsedID()).isSpell) //cant be sitting if flying
CombatManager.toggleSit(false,origin);
if(pc.isMoving())
pc.stopMovement(pc.getMovementLoc());
if(msg.getPowerUsedID() != 421084024 && origin.getPlayerCharacter().getPromotionClassID() != 2513) {
if (!origin.getPlayerCharacter().getPowers().containsKey(msg.getPowerUsedID())) {
Logger.error(origin.getPlayerCharacter().getFirstName() + " attempted to cast a power they do not have");
return;
}
}
//crusader sacrifice
if((msg.getPowerUsedID() == 428695403 && msg.getTargetID() == pc.getObjectUUID())){
RecyclePowerMsg recyclePowerMsg = new RecyclePowerMsg(msg.getPowerUsedID());
Dispatch dispatch = Dispatch.borrow(origin.getPlayerCharacter(), recyclePowerMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
// Send Fail to cast message
if (pc != null) {
sendPowerMsg(pc, 2, msg);
if (pc.isCasting()) {
pc.update(false);
}
pc.setIsCasting(false);
}
return;
}
if (usePowerA(msg, origin, sendCastToSelf)) {
// Cast failed for some reason, reset timer
@@ -206,20 +171,19 @@ public enum PowersManager {
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
// Send Fail to cast message
PlayerCharacter pc = SessionManager
.getPlayerCharacter(origin);
if (pc != null) {
sendPowerMsg(pc, 2, msg);
if (pc.isCasting()) {
pc.update(false);
pc.update();
}
pc.setIsCasting(false);
}
}
if(msg.getPowerUsedID() == 429429978){
origin.getPlayerCharacter().getRecycleTimers().remove(429429978);
}
}
public static void useMobPower(Mob caster, AbstractCharacter target, PowersBase pb, int rank) {
@@ -228,8 +192,7 @@ public enum PowersManager {
msg.setUnknown04(1);
if (useMobPowerA(msg, caster)) {
if(pb.token == -1994153779)
InterestManager.setObjectDirty(caster);
//sendMobPowerMsg(caster,2,msg); //Lol wtf was i thinking sending msg's to mobs... ZZZZ
}
}
@@ -242,48 +205,6 @@ public enum PowersManager {
boolean CSRCast = false;
if(msg.getPowerUsedID() == 430628895) {
boolean failed = false;// group teleport
City city = ZoneManager.getCityAtLocation(playerCharacter.loc);
if (city == null) {
failed = true;
}//else{
// Bane bane = city.getBane();
// if (bane == null) {
// failed = true;
// }else{
// if(!bane.getSiegePhase().equals(SiegePhase.WAR)){
// failed = true;
// }
// }
//}
if(failed){
//check to see if we are at an active mine
Zone zone = ZoneManager.findSmallestZone(playerCharacter.loc);
if(zone != null){
Mine mine = null;
for(Building building : zone.zoneBuildingSet){
if(building.getBlueprint().getBuildingGroup().equals(BuildingGroup.MINE)){
mine = Mine.getMineFromTower(building.getObjectUUID());
}
}
if(mine != null){
failed = !mine.isActive;
}
}
}
if(failed) {
playerCharacter.setIsCasting(false);
RecyclePowerMsg recyclePowerMsg = new RecyclePowerMsg(msg.getPowerUsedID());
Dispatch dispatch = Dispatch.borrow(playerCharacter, recyclePowerMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
return false;
}
}
if (MBServerStatics.POWERS_DEBUG) {
ChatManager.chatSayInfo(
@@ -320,7 +241,6 @@ public enum PowersManager {
// get power
PowersBase pb = PowersManager.powersBaseByToken.get(msg.getPowerUsedID());
if (pb == null) {
ChatManager.chatSayInfo(playerCharacter,
"This power is not implemented yet.");
@@ -332,35 +252,6 @@ public enum PowersManager {
// return false;
}
//check for movement buffs while flying
if(playerCharacter.isFlying()) {
switch(pb.token){
case 429005674:
case 429505739:
case 431054700:
case 428005600:
case 431610080:
case 427935608:
case 427857146:
case 427988218:
case 431854842:
case 421074170:
case 429611355:
case 428955899:
case 1794395699:
case 429428796:
case 1514898036:
ChatManager.chatSystemInfo(playerCharacter, "You Cannot Fly While Having A MovementBuff");
//resync stamina
playerCharacter.setStamina(playerCharacter.getStamina(), playerCharacter);
// Update all surrounding clients.
TargetedActionMsg cmm = new TargetedActionMsg(playerCharacter);
DispatchMessage.dispatchMsgToInterestArea(playerCharacter, cmm, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
return true;
}
}
if (playerCharacter.getLastPower() != null)
return true;
@@ -368,18 +259,17 @@ public enum PowersManager {
// Check powers for normal users
if(msg.getPowerUsedID() != 421084024) {
if (playerCharacter.getPowers() == null || !playerCharacter.getPowers().containsKey(msg.getPowerUsedID()))
if (!playerCharacter.isCSR()) {
if (!MBServerStatics.POWERS_DEBUG) {
// ChatManager.chatSayInfo(pc, "You may not cast that spell!");
if (playerCharacter.getPowers() == null || !playerCharacter.getPowers().containsKey(msg.getPowerUsedID()))
if (!playerCharacter.isCSR()) {
if (!MBServerStatics.POWERS_DEBUG) {
// ChatManager.chatSayInfo(pc, "You may not cast that spell!");
Logger.info("usePowerA(): Cheat attempted? '" + msg.getPowerUsedID() + "' was not associated with " + playerCharacter.getName());
return true;
}
} else
CSRCast = true;
Logger.info("usePowerA(): Cheat attempted? '" + msg.getPowerUsedID() + "' was not associated with " + playerCharacter.getName());
return true;
}
} else
CSRCast = true;
}
// get numTrains for power
int trains = msg.getNumTrains();
@@ -389,14 +279,6 @@ public enum PowersManager {
msg.setNumTrains(trains);
}
//double stack point values for some useless disc spells
switch(pb.token){
case 429420458: // BH eyes
case 429601664: // huntsman skin the beast
msg.setNumTrains(msg.getNumTrains() * 2);
break;
}
// can't go over total trains by player
if (playerCharacter.getPowers() != null && playerCharacter.getPowers().containsKey(msg.getPowerUsedID())) {
CharacterPower cp = playerCharacter.getPowers().get(msg.getPowerUsedID());
@@ -488,20 +370,15 @@ public enum PowersManager {
float range = pb.getRange();
// verify target is in range
if(pb.token != 429396028) {
if (verifyInvalidRange(playerCharacter, target, range))
// (pc.getLoc().distance(target.getLoc()) > pb.getRange()) {
// TODO send message that target is out of range
return true;
// verify target is valid type
if (!validateTarget(target, playerCharacter, pb))
return true;
}else{
pb.isSpell = false;
}
if (verifyInvalidRange(playerCharacter, target, range))
// (pc.getLoc().distance(target.getLoc()) > pb.getRange()) {
// TODO send message that target is out of range
return true;
// verify target is valid type
if (!validateTarget(target, playerCharacter, pb))
return true;
if (AbstractWorldObject.IsAbstractCharacter(target))
@@ -532,23 +409,6 @@ public enum PowersManager {
}
}
if(!passed){
if (playerCharacter.getRace().getName().contains("Shade")) {
if(playerCharacter.getHidden() > 0){
switch(msg.getPowerUsedID()){
case -1851459567:
case 2094922127:
case -355707373:
case 246186475:
case 666419835:
case 1480354319:
passed = true;
break;
}
}
}
}
if (!passed)
return true;
}
@@ -627,6 +487,7 @@ public enum PowersManager {
// Validity checks passed, move on to casting spell
//get caster's live counter
int casterLiveCounter = playerCharacter.getLiveCounter();
// run recycle job for when cast is available again, don't bother adding the timer for CSRs
if (time > 0) {
FinishRecycleTimeJob frtj = new FinishRecycleTimeJob(playerCharacter, msg);
@@ -653,7 +514,7 @@ public enum PowersManager {
// make person casting stand up if spell (unless they're casting a chant which does not make them stand up)
if (pb.isSpell() && !pb.isChant() && playerCharacter.isSit()) {
playerCharacter.update(false);
playerCharacter.update();
playerCharacter.setSit(false);
UpdateStateMsg updateStateMsg = new UpdateStateMsg(playerCharacter);
DispatchMessage.dispatchMsgToInterestArea(playerCharacter, updateStateMsg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
@@ -661,12 +522,10 @@ public enum PowersManager {
}
// update cast (use skill) fail condition
if(pb.token != 429396028 && pb.breaksForm) {
playerCharacter.cancelOnCast();
}
playerCharacter.cancelOnCast();
// update castSpell (use spell) fail condition if spell
if (pb.isSpell() && pb.breaksForm)
if (pb.isSpell())
playerCharacter.cancelOnSpell();
// get cast time in ms.
@@ -676,12 +535,13 @@ public enum PowersManager {
if (time > 100) {
playerCharacter.update(false);
playerCharacter.update();
playerCharacter.setIsCasting(true);
}
playerCharacter.setLastMovementState(playerCharacter.getMovementState());
// run timer job to end cast
if (time < 1) // run immediately
finishUsePower(copyMsg, playerCharacter, casterLiveCounter, targetLiveCounter);
@@ -807,11 +667,10 @@ public enum PowersManager {
// make person casting stand up if spell (unless they're casting a chant which does not make them stand up)
// update cast (use skill) fail condition
if(pb.breaksForm)
caster.cancelOnCast();
caster.cancelOnCast();
// update castSpell (use spell) fail condition if spell
if (pb.isSpell() && pb.breaksForm)
if (pb.isSpell())
caster.cancelOnSpell();
// get cast time in ms.
@@ -847,37 +706,8 @@ public enum PowersManager {
if (playerCharacter == null || msg == null)
return;
//handle sprint for bard sprint
if(msg.getPowerUsedID() == 429005674){
msg.setPowerUsedID(429611355);
}
//handle root and snare break for wildkin's chase
if(msg.getPowerUsedID() == 429494441) {
playerCharacter.removeEffectBySource(EffectSourceType.Root,40,true);
playerCharacter.removeEffectBySource(EffectSourceType.Snare,40,true);
}
//handle power block portion for shade hide
if(playerCharacter.getRace().getName().contains("Shade")) {
if (msg.getPowerUsedID() == 429407306 || msg.getPowerUsedID() == 429495514) {
int trains = msg.getNumTrains() - 1;
if (trains < 1)
trains = 1;
applyPower(playerCharacter, playerCharacter, playerCharacter.loc, 429397210, trains, false);
playerCharacter.removeEffectBySource(EffectSourceType.Invisibility,40,true);
applyPower(playerCharacter, playerCharacter, playerCharacter.loc, msg.getPowerUsedID(), msg.getNumTrains(), false);
}
}
if(msg.getTargetType() == GameObjectType.PlayerCharacter.ordinal()) {
PlayerCharacter target = PlayerCharacter.getPlayerCharacter(msg.getTargetID());
if (msg.getPowerUsedID() == 429601664)
if(target.getPromotionClassID() != 2516)//templar
PlayerCharacter.getPlayerCharacter(msg.getTargetID()).removeEffectBySource(EffectSourceType.Transform, msg.getNumTrains(), true);
}
if (playerCharacter.isCasting()) {
playerCharacter.update(false);
playerCharacter.update();
playerCharacter.updateStamRegen(-100);
}
@@ -917,9 +747,6 @@ public enum PowersManager {
return;
}
if(pb.targetSelf)
msg.setTargetID(playerCharacter.getObjectUUID());
int trains = msg.getNumTrains();
// verify player is not stunned or power type is blocked
@@ -982,16 +809,15 @@ public enum PowersManager {
}
float range = pb.getRange() + speedRange;
if(pb.token != 429396028) {
if (verifyInvalidRange(playerCharacter, mainTarget, range)) {
if (verifyInvalidRange(playerCharacter, mainTarget, range)) {
sendPowerMsg(playerCharacter, 8, msg);
return;
}
// (pc.getLoc().distance(target.getLoc()) > pb.getRange()) {
// TODO send message that target is out of range
sendPowerMsg(playerCharacter, 8, msg);
return;
}
// (pc.getLoc().distance(target.getLoc()) > pb.getRange()) {
// TODO send message that target is out of range
}
@@ -1176,18 +1002,7 @@ public enum PowersManager {
//DispatchMessage.dispatchMsgToInterestArea(playerCharacter, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
//handle mob hate values
HashSet<AbstractWorldObject> mobs = WorldGrid.getObjectsInRangePartial(playerCharacter.loc,60.0f,MBServerStatics.MASK_MOB);
for(AbstractWorldObject awo : mobs){
Mob mobTarget = (Mob)awo;
if(mobTarget.hate_values != null) {
if (mobTarget.hate_values.containsKey(playerCharacter)) {
mobTarget.hate_values.put(playerCharacter, mobTarget.hate_values.get(playerCharacter) + pb.getHateValue(trains));
} else {
mobTarget.hate_values.put(playerCharacter, pb.getHateValue(trains));
}
}
}
}
@@ -1418,7 +1233,7 @@ public enum PowersManager {
PlayerCharacter target = SessionManager
.getPlayerCharacterByLowerCaseName(msg.getTargetName());
if (target == null || target.equals(pc)) {
if (target == null || target.equals(pc) || target.isCombat()) {
if (target == null) // Player not found. Send not found message
ChatManager.chatInfoError(pc,
@@ -1522,16 +1337,6 @@ public enum PowersManager {
else
duration = 45000; // Belgosh Summons, 45 seconds
boolean enemiesNear = false;
for(AbstractWorldObject awo : WorldGrid.getObjectsInRangePartial(pc.loc,MBServerStatics.CHARACTER_LOAD_RANGE, MBServerStatics.MASK_PLAYER)){
PlayerCharacter playerCharacter = (PlayerCharacter)awo;
if(!playerCharacter.guild.getNation().equals(pc.guild.getNation())){
enemiesNear = true;
}
}
if(enemiesNear && !pc.isInSafeZone())
duration += 60000;
// Teleport to summoners location
FinishSummonsJob fsj = new FinishSummonsJob(source, pc);
@@ -1657,28 +1462,8 @@ public enum PowersManager {
}
// create list of characters
HashSet<AbstractCharacter> trackChars;
PowersBase trackPower = PowersManager.getPowerByToken(msg.getPowerToken());
if(trackPower != null && trackPower.category.equals("TRACK")){
trackChars = getTrackList(playerCharacter);
}else{
trackChars = RangeBasedAwo.getTrackList(allTargets, playerCharacter, maxTargets);
}
//switch(msg.getPowerToken()){
// case 431511776: // Hunt Foe Huntress
// case 429578587: // Hunt Foe Scout
// case 429503360: // Track Huntsman
// case 44106356: //
// trackChars = getTrackList(playerCharacter);
// break;
// default:
// trackChars = RangeBasedAwo.getTrackList(allTargets, playerCharacter, maxTargets);
// break;
//}
HashSet<AbstractCharacter> trackChars = RangeBasedAwo.getTrackList(
allTargets, playerCharacter, maxTargets);
TrackWindowMsg trackWindowMsg = new TrackWindowMsg(msg);
@@ -1691,30 +1476,6 @@ public enum PowersManager {
}
public static HashSet<AbstractCharacter> getTrackList(PlayerCharacter tracker){
HashSet<AbstractCharacter> list = new HashSet<AbstractCharacter>();
HashSet<AbstractWorldObject> shortList = WorldGrid.getObjectsInRangePartial(tracker.loc,MBServerStatics.CHARACTER_LOAD_RANGE, MBServerStatics.MASK_PLAYER);
HashSet<AbstractWorldObject> fullList = WorldGrid.getObjectsInRangePartial(tracker.loc,1408, MBServerStatics.MASK_PLAYER);
ArrayList<Guild> guildsPresent = new ArrayList<>();
for(AbstractWorldObject awo : shortList){
PlayerCharacter pc = (PlayerCharacter)awo;
if(!guildsPresent.contains(pc.guild.getNation())){
guildsPresent.add(pc.guild.getNation());
}
}
for(AbstractWorldObject awo : fullList){
if(awo.equals(tracker))
continue;
PlayerCharacter pc = (PlayerCharacter)awo;
if(!pc.isAlive())
continue;
if(guildsPresent.contains(pc.guild.getNation()))
list.add(pc);
}
return list;
}
private static void sendRecyclePower(int token, ClientConnection origin) {
RecyclePowerMsg recyclePowerMsg = new RecyclePowerMsg(token);
@@ -2428,7 +2189,7 @@ public enum PowersManager {
// set player is not casting for regens
if (pc.isCasting()) {
pc.update(false);
pc.update();
}
pc.setIsCasting(false);
@@ -2470,8 +2231,7 @@ public enum PowersManager {
public static boolean testAttack(PlayerCharacter pc, AbstractWorldObject awo,
PowersBase pb, PerformActionMsg msg) {
// Get defense for target
//float atr = CharacterSkill.getATR(pc, pb.getSkillName());
float atr = PlayerCombatStats.getSpellAtr(pc, pb);
float atr = CharacterSkill.getATR(pc, pb.getSkillName());
float defense;
if (AbstractWorldObject.IsAbstractCharacter(awo)) {
@@ -2481,26 +2241,28 @@ public enum PowersManager {
defense = 0f;
// Get hit chance
//if (pc.getDebug(16)) {
// String smsg = "ATR: " + atr + ", Defense: " + defense;
// ChatManager.chatSystemInfo(pc, smsg);
//}
if (pc.getDebug(16)) {
String smsg = "ATR: " + atr + ", Defense: " + defense;
ChatManager.chatSystemInfo(pc, smsg);
}
//int chance;
int chance;
//if (atr > defense || defense == 0)
// chance = 94;
//else {
// float dif = atr / defense;
// if (dif <= 0.8f)
// chance = 4;
// else
// chance = ((int) (450 * (dif - 0.8f)) + 4);
//}
if (atr > defense || defense == 0)
chance = 94;
else {
float dif = atr / defense;
if (dif <= 0.8f)
chance = 4;
else
chance = ((int) (450 * (dif - 0.8f)) + 4);
}
// calculate hit/miss
int roll = ThreadLocalRandom.current().nextInt(100);
if (CombatManager.LandHit((int)atr,(int)defense)) {
boolean disable = true;
if (roll < chance) {
// Hit, check if dodge kicked in
if (awo instanceof AbstractCharacter) {
AbstractCharacter tarAc = (AbstractCharacter) awo;
@@ -2512,13 +2274,6 @@ public enum PowersManager {
dodgeMsg.setTargetID(awo.getObjectUUID());
sendPowerMsg(pc, 4, dodgeMsg);
return true;
} else if (testPassive(pc, tarAc, "Block")) {
// Dodge fired, send dodge message
PerformActionMsg dodgeMsg = new PerformActionMsg(msg);
dodgeMsg.setTargetType(awo.getObjectType().ordinal());
dodgeMsg.setTargetID(awo.getObjectUUID());
sendPowerMsg(pc, 4, dodgeMsg);
return true;
}
}
return false;
@@ -2566,12 +2321,7 @@ public enum PowersManager {
if (AbstractWorldObject.IsAbstractCharacter(awo)) {
AbstractCharacter tarAc = (AbstractCharacter) awo;
// Handle Dodge passive
boolean passiveFired = false;
passiveFired = testPassive(caster, tarAc, "Dodge");
if(!passiveFired)
passiveFired = testPassive(caster, tarAc, "Block");
return passiveFired;
return testPassive(caster, tarAc, "Dodge");
}
return false;
} else
@@ -2812,9 +2562,7 @@ public enum PowersManager {
}
public static void cancelOnStun(AbstractCharacter ac) {
if(ac.getObjectType().equals(GameObjectType.PlayerCharacter)){
//PlayerCharacter.GroundPlayer((PlayerCharacter)ac);
}
}
private static PowersBase getLastPower(AbstractCharacter ac) {
@@ -2960,127 +2708,6 @@ public enum PowersManager {
}
}
public static boolean breakForm(int token) {
switch (token) {
case 429505865:
case 429407561:
case 429492073:
case 429644123:
case 429393769:
case 429545819:
case 429426537:
case 429590377:
case 429508425:
case 429541193:
case 429573961:
case 427924330:
case 429402918:
case 429545688:
case 429005674:
case 429637823:
case 429590426:
case 428066972:
case 429441862:
case 431611756:
case 431578988:
case 429502506:
case 429398191:
case 429447384:
case 428892191:
case 431579167:
case 430977067:
case 429409100:
case 429441868:
case 429594877:
case 427908971:
case 683741153:
case 429770569:
case 429452379:
case 429605055:
case 429086971:
case 429443230:
case 429505400:
case 429492122:
case 429643992:
case 550062236:
case 429498252:
case 429611224:
case 429441834:
case 428918940:
case 429633739:
case 429633579:
case 429568043:
case 429048646:
case 428392639:
case 428425407:
case 429054168:
case 429021400:
case 428955864:
case 429119704:
case 428890328:
case 428923096:
case 429218008:
case 429086936:
case 428988632:
case 428688204:
case 429514603:
case 428924959:
case 429393818:
case 429720966:
case 428982463:
case 427933887:
case 429572287:
case 429501222:
case 430694431:
case 429436131:
case 430006124:
case 429611355:
case 428005600:
case 427935608:
case 428949695:
case 427988218:
case 429414616:
case 429496495:
case 429428796:
case 563795754:
case 428988217:
case 429432716:
case 428955899:
case 429393286:
case 550062220:
case 429495557:
case 429401278:
case 428377478:
case 429409094:
case 428191947:
case 429434474:
case 429403363:
case 429512920:
case 429419611:
case 429645676:
case 429602895:
case 429605071:
case 429592428:
case 429500010:
case 429406602:
case 429426586:
case 429633898:
case 550062212:
case 429994027:
case 430813227:
case 429928491:
case 430026795:
case 429517915:
case 431854842:
case 429767544:
case 429502507:
case 428398816:
case 429446315:
case 429441979:
return false;
}
return true;
}
}
+15 -30
View File
@@ -10,7 +10,10 @@ package engine.gameManager;
import engine.Enum;
import engine.Enum.GameObjectType;
import engine.objects.*;
import engine.objects.AbstractGameObject;
import engine.objects.City;
import engine.objects.PlayerCharacter;
import engine.objects.Runegate;
import org.pmw.tinylog.Logger;
import java.sql.Connection;
@@ -30,7 +33,7 @@ public enum SimulationManager {
SERVERHEARTBEAT;
private static final long CITY_PULSE = 2000;
private static final long RUNEGATE_PULSE = 1000;
private static final long RUNEGATE_PULSE = 3000;
private static final long UPDATE_PULSE = 1000;
private static final long FlIGHT_PULSE = 100;
public static Duration executionTime = Duration.ofNanos(1);
@@ -93,10 +96,13 @@ public enum SimulationManager {
}
try {
if ((_updatePulseTime != 0) && (System.currentTimeMillis() > _updatePulseTime))
if ((_updatePulseTime != 0)
&& (System.currentTimeMillis() > _updatePulseTime))
pulseUpdate();
} catch (Exception e) {
Logger.error("Fatal error in Update Pulse: DISABLED");
Logger.error(
"Fatal error in Update Pulse: DISABLED");
// _runegatePulseTime = 0;
}
try {
@@ -110,18 +116,9 @@ public enum SimulationManager {
}
try {
if ((_cityPulseTime != 0) && (System.currentTimeMillis() > _cityPulseTime)) {
try {
pulseCities();
}catch(Exception e){
}
try {
ArenaManager.pulseArenas();
}catch(Exception e){
}
}
if ((_cityPulseTime != 0)
&& (System.currentTimeMillis() > _cityPulseTime))
pulseCities();
} catch (Exception e) {
Logger.error(
"Fatal error in City Pulse: DISABLED. Error Message : "
@@ -157,11 +154,7 @@ public enum SimulationManager {
if (player == null)
continue;
try {
player.update(false);
}catch(Exception e){
}
player.update();
}
_updatePulseTime = System.currentTimeMillis() + 500;
@@ -210,12 +203,8 @@ 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;
_cityPulseTime = System.currentTimeMillis() + CITY_PULSE;
}
/*
@@ -225,10 +214,6 @@ 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();
}
@@ -1,347 +0,0 @@
package engine.gameManager;
import engine.Enum;
import engine.InterestManagement.InterestManager;
import engine.InterestManagement.WorldGrid;
import engine.math.Vector3f;
import engine.math.Vector3fImmutable;
import engine.objects.*;
import org.pmw.tinylog.Logger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.ThreadLocalRandom;
public class StrongholdManager {
public static void processStrongholds() {
ArrayList<Mine> mines = Mine.getMines();
//process strongholds selecting 3 randomly to become active
int count = 0;
while (count < 3) {
int random = ThreadLocalRandom.current().nextInt(1, mines.size()) - 1;
Mine mine = mines.get(random);
if (mine != null) {
if (!mine.isActive && !mine.isStronghold) {
StartStronghold(mine);
count++;
}
}
}
}
public static void StartStronghold(Mine mine){
//remove buildings
Building tower = BuildingManager.getBuilding(mine.getBuildingID());
if(tower == null)
return;
mine.isStronghold = true;
mine.strongholdMobs = new ArrayList<>();
mine.oldBuildings = new HashMap<>();
Zone mineZone = ZoneManager.findSmallestZone(tower.loc);
for(Building building : mineZone.zoneBuildingSet){
mine.oldBuildings.put(building.getObjectUUID(),building.meshUUID);
building.setMeshUUID(407650);
building.setMeshScale(new Vector3f(0,0,0));
InterestManager.setObjectDirty(building);
WorldGrid.updateObject(building);
}
//update tower to become stronghold mesh
tower.setMeshUUID(getStrongholdMeshID(mine.getParentZone()));
tower.setMeshScale(new Vector3f(1,1,1));
InterestManager.setObjectDirty(tower);
WorldGrid.updateObject(tower);
//create elite mobs
for(int i = 0; i < mine.capSize * 2; i++){
Vector3fImmutable loc = Vector3fImmutable.getRandomPointOnCircle(tower.loc,30);
MobBase guardBase = MobBase.getMobBase(getStrongholdGuardianID(tower.meshUUID));
Mob guard = Mob.createStrongholdMob(guardBase.getLoadID(), loc, Guild.getErrantGuild(),true,mineZone,null,0, guardBase.getFirstName(),65);
if(guard != null){
guard.parentZone = mine.getParentZone();
guard.bindLoc = loc;
guard.setLoc(loc);
guard.StrongholdGuardian = true;
guard.equipmentSetID = getStrongholdMobEquipSetID(guard);
guard.runAfterLoad();
guard.setLevel((short)65);
guard.setResists(new Resists("Elite"));
guard.spawnTime = 1000000000;
guard.BehaviourType = Enum.MobBehaviourType.Aggro;
mine.strongholdMobs.add(guard);
LootManager.GenerateStrongholdLoot(guard,false,false);
guard.healthMax = 12500;
guard.setHealth(guard.healthMax);
guard.maxDamageHandOne = 1550;
guard.minDamageHandOne = 750;
guard.atrHandOne = 1800;
guard.defenseRating = 2200;
guard.setFirstName("Elite Guardian");
InterestManager.setObjectDirty(guard);
WorldGrid.addObject(guard,loc.x,loc.z);
WorldGrid.updateObject(guard);
guard.stronghold = mine;
guard.mobPowers.clear();
guard.mobPowers.put(429399948,20); // find weakness
}
}
//create stronghold commander
Vector3fImmutable loc = tower.loc;
MobBase commanderBase = MobBase.getMobBase(getStrongholdCommanderID(tower.meshUUID));
Mob commander = Mob.createStrongholdMob(commanderBase.getLoadID(), loc,Guild.getErrantGuild(),true,mineZone,null,0, commanderBase.getFirstName(),75);
if(commander != null){
commander.parentZone = mine.getParentZone();
commander.bindLoc = loc;
commander.setLoc(loc);
commander.StrongholdCommander = true;
commander.equipmentSetID = getStrongholdMobEquipSetID(commander);
commander.runAfterLoad();
commander.setLevel((short)75);
commander.setResists(new Resists("Elite"));
commander.spawnTime = 1000000000;
commander.BehaviourType = Enum.MobBehaviourType.Aggro;
commander.mobPowers.clear();
commander.mobPowers.put(429032838, 40); // gravechill
commander.mobPowers.put(429757701,20); // magebolt
commander.mobPowers.put(429121388,20); // blight
commander.mobPowers.put(431566891,20); // lightning bolt
commander.mobPowers.put(428716075,20); // fire bolt
commander.mobPowers.put(429010987,20); // ice bolt
mine.strongholdMobs.add(commander);
LootManager.GenerateStrongholdLoot(commander,true, false);
commander.healthMax = 50000;
commander.setHealth(commander.healthMax);
commander.maxDamageHandOne = 3500;
commander.minDamageHandOne = 1500;
commander.atrHandOne = 3500;
commander.defenseRating = 3500;
commander.setFirstName("Guardian Commander");
InterestManager.setObjectDirty(commander);
WorldGrid.addObject(commander,loc.x,loc.z);
WorldGrid.updateObject(commander);
commander.stronghold = mine;
}
mine.isActive = true;
tower.setProtectionState(Enum.ProtectionState.PROTECTED);
tower.getBounds().setRegions(tower);
InterestManager.setObjectDirty(tower);
WorldGrid.updateObject(tower);
ChatManager.chatSystemChannel(mine.getZoneName() + "'s Stronghold Has Begun!");
Logger.info(mine.getZoneName() + "'s Stronghold Has Begun!");
}
public static void EndStronghold(Mine mine){
//restore the buildings
Building tower = BuildingManager.getBuilding(mine.getBuildingID());
if(tower == null)
return;
mine.isStronghold = false;
//get rid of the mobs
for(Mob mob : mine.strongholdMobs) {
mob.despawn();
mob.removeFromCache();
DbManager.MobQueries.DELETE_MOB(mob);
}
//restore the buildings
Zone mineZone = ZoneManager.findSmallestZone(tower.loc);
for(Building building : mineZone.zoneBuildingSet){
if(mine.oldBuildings.containsKey(building.getObjectUUID())) {
building.setMeshUUID(mine.oldBuildings.get(building.getObjectUUID()));
building.setMeshScale(new Vector3f(1, 1, 1));
InterestManager.setObjectDirty(building);
WorldGrid.updateObject(building);
}
}
//update tower to become Mine Tower again
tower.setMeshUUID(1500100);
mine.isActive = false;
tower.setProtectionState(Enum.ProtectionState.NPC);
tower.getBounds().setRegions(tower);
InterestManager.setObjectDirty(tower);
WorldGrid.updateObject(tower);
ChatManager.chatSystemChannel(mine.getZoneName() + "'s Stronghold Has Concluded!");
Logger.info(mine.getZoneName() + "'s Stronghold Has Concluded!");
}
public static int getStrongholdMeshID(Zone parent){
while(!parent.isMacroZone()){
parent = parent.getParent();
if(parent.getName().equalsIgnoreCase("seafloor")){
return 0;
}
}
switch(parent.getObjectUUID()){
case 197:
case 234:
case 178:
case 122:
return 814000; //Frost Giant Hall (ICE)
case 968:
case 951:
case 313:
case 331:
return 5001500; // Lich Queens Keep (UNDEAD)
case 785:
case 761:
case 717:
case 737:
return 1306600; // Temple of the Dragon (DESERT)
case 353:
case 371:
case 388:
case 532:
return 564600; // Undead Lord's Keep (SWAMP)
case 550:
case 508:
case 475:
case 418:
return 1326600; // elven hall
case 437:
case 491:
case 590:
case 569:
return 602400;
case 824:
case 842:
case 632:
return 1600000; // chaos temple
}
return 456100; // small stockade
}
public static int getStrongholdGuardianID(int ID){
switch(ID){
case 814000:
return 253004; // Mountain Giant Raider Axe
case 5001500:
return 253008; // Vampire Spear Warrior
case 1306600:
return 253007; // Desert Orc Warrior
case 564600:
return 253010; // Kolthoss Warrior
case 1326600:
return 253005; //elven warrior
case 602400:
return 253009; // templar missionary
case 1600000:
return 253006; // scourger
}
return 13434; // human sword and board warrior
}
public static int getStrongholdEpicID(int ID){
switch(ID){
case 814000:
return 253023; // Mountain Giant Raider Axe
case 5001500:
return 253022; // Vampire Spear Warrior
case 1306600:
return 253021; // Desert Orc Warrior
case 564600:
return 253018; // Kolthoss Warrior
case 1326600:
return 253019; //elven warrior
case 602400:
return 253024; // templar missionary
case 1600000:
return 253020; // scourger
}
return 13434; // human sword and board warrior
}
public static int getStrongholdCommanderID(int ID){
switch(ID){
case 814000:
return 253017;
case 5001500:
return 253012;
case 1306600:
return 253016; // Desert Orc Xbow
case 564600:
return 253011; // xbow kolthoss
case 1326600:
return 253013; //elven bow warrior
case 602400:
return 253015; // dune giant with xbow
case 1600000:
return 253014; // barbator
}
return 13433;
}
public static int getStrongholdMobEquipSetID(Mob mob) {
if(mob.StrongholdGuardian){
return 6327;
}else{
return 10790;
}
}
public static void CheckToEndStronghold(Mine mine) {
boolean stillAlive = false;
for (Mob mob : mine.strongholdMobs)
if (mob.isAlive())
stillAlive = true;
if (!stillAlive) {
// Epic encounter
Building tower = BuildingManager.getBuilding(mine.getBuildingID());
if (tower == null)
return;
Zone mineZone = ZoneManager.findSmallestZone(tower.loc);
Vector3fImmutable loc = tower.loc;
MobBase commanderBase = MobBase.getMobBase(getStrongholdEpicID(tower.meshUUID));
Mob commander = Mob.createStrongholdMob(commanderBase.getLoadID(), loc, Guild.getErrantGuild(), true, mineZone, null, 0, commanderBase.getFirstName(), 75);
if (commander != null) {
commander.parentZone = mine.getParentZone();
commander.bindLoc = loc;
commander.setLoc(loc);
commander.StrongholdEpic = true;
commander.equipmentSetID = getStrongholdMobEquipSetID(commander);
commander.runAfterLoad();
commander.setLevel((short) 85);
commander.setResists(new Resists("Elite"));
commander.spawnTime = 1000000000;
commander.BehaviourType = Enum.MobBehaviourType.Aggro;
commander.mobPowers.clear();
commander.mobPowers.put(429032838, 40); // gravechill
commander.mobPowers.put(429757701,40); // magebolt
commander.mobPowers.put(429121388,40); // blight
commander.mobPowers.put(431566891,40); // lightning bolt
commander.mobPowers.put(428716075,40); // fire bolt
commander.mobPowers.put(429010987,40); // ice bolt
mine.strongholdMobs.add(commander);
LootManager.GenerateStrongholdLoot(commander, true, true);
commander.healthMax = 250000;
commander.setHealth(commander.healthMax);
commander.maxDamageHandOne = 5000;
commander.minDamageHandOne = 2500;
commander.atrHandOne = 5000;
commander.defenseRating = 3500;
commander.setFirstName("Defender of " + mine.getParentZone().getParent().getName());
InterestManager.setObjectDirty(commander);
WorldGrid.addObject(commander,loc.x,loc.z);
WorldGrid.updateObject(commander);
commander.stronghold = mine;
}
}
}
}
-195
View File
@@ -1,195 +0,0 @@
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);
case 20: return getMultiplier20Man(count);
case 30: return getMultiplier30Man(count);
case 40: return getMultiplier40Man(count);
default: return 1.0f; //unlimited
}
}
public static float getMultiplier3Man(int count) {
if(count < 4)
return 1.0f;
if(count > 6)
return 0.0f;
switch(count){
case 4: return 0.63f;
case 5: return 0.40f;
case 6: return 0.25f;
default: 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.57f;
case 8: return 0.44f;
case 9: return 0.33f;
case 10: return 0.25f;
default: 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.86f;
case 12: return 0.75f;
case 13: return 0.65f;
case 14: return 0.57f;
case 15: return 0.50f;
case 16: return 0.44f;
case 17: return 0.38f;
case 18: return 0.33f;
case 19: return 0.29f;
case 20: return 0.25f;
default: return 1.0f;
}
}
public static float getMultiplier20Man(int count) {
if(count < 21)
return 1.0f;
if(count > 40)
return 0.0f;
switch (count)
{
case 21: return 0.93f;
case 22: return 0.86f;
case 23: return 0.80f;
case 24: return 0.75f;
case 25: return 0.70f;
case 26: return 0.65f;
case 27: return 0.61f;
case 28: return 0.57f;
case 29: return 0.53f;
case 30: return 0.50f;
case 31: return 0.47f;
case 32: return 0.44f;
case 33: return 0.41f;
case 34: return 0.38f;
case 35: return 0.36f;
case 36: return 0.33f;
case 37: return 0.31f;
case 38: return 0.29f;
case 39: return 0.27f;
case 40: return 0.25f;
default: return 1.0f;
}
}
public static float getMultiplier30Man(int count) {
if(count < 31)
return 1.0f;
if(count > 60)
return 0.0f;
switch (count)
{
case 31: return 0.95f;
case 32: return 0.91f;
case 33: return 0.86f;
case 34: return 0.82f;
case 35: return 0.79f;
case 36: return 0.75f;
case 37: return 0.72f;
case 38: return 0.68f;
case 39: return 0.65f;
case 40: return 0.63f;
case 41: return 0.60f;
case 42: return 0.57f;
case 43: return 0.55f;
case 44: return 0.52f;
case 45: return 0.50f;
case 46: return 0.48f;
case 47: return 0.46f;
case 48: return 0.44f;
case 49: return 0.42f;
case 50: return 0.40f;
case 51: return 0.38f;
case 52: return 0.37f;
case 53: return 0.35f;
case 54: return 0.33f;
case 55: return 0.32f;
case 56: return 0.30f;
case 57: return 0.29f;
case 58: return 0.28f;
case 59: return 0.26f;
case 60: return 0.25f;
default: return 1.0f;
}
}
public static float getMultiplier40Man(int count) {
if(count < 41)
return 1.0f;
if(count > 80)
return 0.0f;
switch (count)
{
case 41: return 0.96f;
case 42: return 0.93f;
case 43: return 0.90f;
case 44: return 0.86f;
case 45: return 0.83f;
case 46: return 0.80f;
case 47: return 0.78f;
case 48: return 0.75f;
case 49: return 0.72f;
case 50: return 0.70f;
case 51: return 0.68f;
case 52: return 0.65f;
case 53: return 0.63f;
case 54: return 0.61f;
case 55: return 0.59f;
case 56: return 0.57f;
case 57: return 0.55f;
case 58: return 0.53f;
case 59: return 0.52f;
case 60: return 0.50f;
case 61: return 0.48f;
case 62: return 0.47f;
case 63: return 0.45f;
case 64: return 0.44f;
case 65: return 0.42f;
case 66: return 0.41f;
case 67: return 0.40f;
case 68: return 0.38f;
case 69: return 0.37f;
case 70: return 0.36f;
case 71: return 0.35f;
case 72: return 0.33f;
case 73: return 0.32f;
case 74: return 0.31f;
case 75: return 0.30f;
case 76: return 0.29f;
case 77: return 0.28f;
case 78: return 0.27f;
case 79: return 0.26f;
case 80: return 0.25f;
default: return 1.0f;
}
}
}
+73
View File
@@ -19,12 +19,14 @@ 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
@@ -107,6 +109,20 @@ 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
@@ -201,6 +217,63 @@ 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,
+1 -1
View File
@@ -68,7 +68,7 @@ public abstract class AbstractJob implements Runnable {
this.markStopRunTime();
}
public abstract void doJob();
protected abstract void doJob();
public void executeJob(String threadName) {
this.workerID.set(threadName);
+1 -1
View File
@@ -17,7 +17,7 @@ public abstract class AbstractScheduleJob extends AbstractJob {
}
@Override
public abstract void doJob();
protected abstract void doJob();
public void cancelJob() {
JobScheduler.getInstance().cancelScheduledJob(this);
+1 -1
View File
@@ -16,7 +16,7 @@ public class JobContainer implements Comparable<JobContainer> {
final long timeOfExecution;
final boolean noTimer;
public JobContainer(AbstractJob job, long timeOfExecution) {
JobContainer(AbstractJob job, long timeOfExecution) {
if (job == null) {
throw new IllegalArgumentException("No 'null' jobs allowed.");
}
-75
View File
@@ -1,75 +0,0 @@
package engine.job;
import engine.server.world.WorldServer;
import org.pmw.tinylog.Logger;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class JobThread implements Runnable {
private final AbstractJob currentJob;
private final ReentrantLock lock = new ReentrantLock();
private static Long nextThreadPrint;
public JobThread(AbstractJob job){
this.currentJob = job;
}
@Override
public void run() {
try {
if (this.currentJob != null) {
if (lock.tryLock(5, TimeUnit.SECONDS)) { // Timeout to prevent deadlock
try {
this.currentJob.doJob();
} finally {
lock.unlock();
}
} else {
Logger.warn("JobThread could not acquire lock in time, skipping job.");
}
}
} catch (Exception e) {
Logger.error(e);
}
}
public static void startJobThread(AbstractJob job){
JobThread jobThread = new JobThread(job);
Thread thread = new Thread(jobThread);
thread.setName("JOB THREAD: " + job.getWorkerID());
thread.start();
if(JobThread.nextThreadPrint == null){
JobThread.nextThreadPrint = System.currentTimeMillis();
}else{
if(JobThread.nextThreadPrint < System.currentTimeMillis()){
JobThread.tryPrintThreads();
JobThread.nextThreadPrint = System.currentTimeMillis() + 10000L;
}
}
}
public static void tryPrintThreads(){
ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
while (rootGroup.getParent() != null) {
rootGroup = rootGroup.getParent();
}
// Estimate the number of threads
int activeThreads = rootGroup.activeCount();
// Create an array to hold the threads
Thread[] threads = new Thread[activeThreads];
// Get the active threads
rootGroup.enumerate(threads, true);
int availableThreads = Runtime.getRuntime().availableProcessors();
// Print the count
if(threads.length > 30)
Logger.info("Total threads in application: " + threads.length + " / " + availableThreads);
}
}
+3 -6
View File
@@ -58,13 +58,10 @@ public class JobWorker extends ControlledRunnable {
} else {
// execute the new job..
//this.currentJob.executeJob(this.getThreadName());
if(this.currentJob != null) {
JobThread.startJobThread(this.currentJob);
this.currentJob = null;
}
this.currentJob.executeJob(this.getThreadName());
this.currentJob = null;
}
Thread.yield();
}
return true;
}
+2 -2
View File
@@ -45,7 +45,7 @@ public abstract class AbstractEffectJob extends AbstractScheduleJob {
}
@Override
public abstract void doJob();
protected abstract void doJob();
@Override
protected abstract void _cancelJob();
@@ -117,7 +117,7 @@ public abstract class AbstractEffectJob extends AbstractScheduleJob {
}
public void endEffect() {
if (this.eb == null || this.power == null)
if (this.eb == null)
return;
this.eb.endEffect(this.source, this.target, this.trains, this.power, this);
}
+1 -1
View File
@@ -29,7 +29,7 @@ public class ActivateBaneJob extends AbstractScheduleJob {
}
@Override
public void doJob() {
protected void doJob() {
City city;
+1 -1
View File
@@ -27,7 +27,7 @@ public class AttackJob extends AbstractJob {
}
@Override
public void doJob() {
protected void doJob() {
CombatManager.doCombat(this.source, slot);
}
+1 -1
View File
@@ -24,7 +24,7 @@ public class BaneDefaultTimeJob extends AbstractScheduleJob {
}
@Override
public void doJob() {
protected void doJob() {
//bane already set.
if (this.bane.getLiveDate() != null) {
+1 -1
View File
@@ -97,7 +97,7 @@ public class BasicScheduledJob extends AbstractJob {
}
@Override
public void doJob() {
protected void doJob() {
if (execution == null) {
Logger.error("BasicScheduledJob executed with nothing to execute.");
return;
+1 -1
View File
@@ -22,7 +22,7 @@ public class BonusCalcJob extends AbstractJob {
}
@Override
public void doJob() {
protected void doJob() {
if (this.ac != null) {
this.ac.applyBonuses();
+1 -1
View File
@@ -22,7 +22,7 @@ public class CSessionCleanupJob extends AbstractJob {
}
@Override
public void doJob() {
protected void doJob() {
SessionManager.cSessionCleanup(secKey);
}
}
+1 -1
View File
@@ -27,7 +27,7 @@ public class ChangeAltitudeJob extends AbstractScheduleJob {
}
@Override
public void doJob() {
protected void doJob() {
if (this.ac != null)
MovementManager.finishChangeAltitude(ac, targetAlt);
}
+1 -1
View File
@@ -36,7 +36,7 @@ public class ChantJob extends AbstractEffectJob {
}
@Override
public void doJob() {
protected void doJob() {
if (this.aej == null || this.source == null || this.target == null || this.action == null || this.power == null || this.source == null || this.eb == null)
return;
PlayerBonuses bonuses = null;
+1 -1
View File
@@ -29,7 +29,7 @@ public class CloseGateJob extends AbstractScheduleJob {
}
@Override
public void doJob() {
protected void doJob() {
if (building == null) {
Logger.error("Rungate building was null");
+1 -3
View File
@@ -37,7 +37,7 @@ public class DamageOverTimeJob extends AbstractEffectJob {
}
@Override
public void doJob() {
protected void doJob() {
if (this.target.getObjectType().equals(GameObjectType.Building)
&& ((Building) this.target).isVulnerable() == false) {
_cancelJob();
@@ -60,8 +60,6 @@ public class DamageOverTimeJob extends AbstractEffectJob {
if (this.iteration < 0) {
PowersManager.finishEffectTime(this.source, this.target, this.action, this.trains);
if (AbstractWorldObject.IsAbstractCharacter(source))
eb.startEffect((AbstractCharacter) this.source, this.target, this.trains, this);
return;
}
this.skipSendEffect = true;

Some files were not shown because too many files have changed in this diff Show More