Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f60b228d5 | ||
|
|
69aa91d403 |
+8203
File diff suppressed because one or more lines are too long
+9
-11
@@ -2822,6 +2822,7 @@ public class Enum {
|
||||
|
||||
public enum MobBehaviourType {
|
||||
None(null, false, false, false, false, false),
|
||||
//Power
|
||||
Power(null, false, true, true, true, false),
|
||||
PowerHelpee(Power, false, true, true, false, true),
|
||||
PowerHelpeeWimpy(Power, true, false, true, false, false),
|
||||
@@ -2846,7 +2847,6 @@ public class Enum {
|
||||
//Independent Types
|
||||
SimpleStandingGuard(null, false, false, false, false, false),
|
||||
Pet1(null, false, false, true, false, false),
|
||||
SiegeEngine(null, false, false, false, false, false),
|
||||
Simple(null, false, false, true, false, false),
|
||||
Helpee(null, false, true, true, false, true),
|
||||
HelpeeWimpy(null, true, false, true, false, false),
|
||||
@@ -2857,12 +2857,13 @@ public class Enum {
|
||||
HamletGuard(null, false, true, false, false, false),
|
||||
AggroWanderer(null, false, false, true, false, false);
|
||||
|
||||
public final MobBehaviourType BehaviourHelperType;
|
||||
public final boolean isWimpy;
|
||||
public final boolean isAgressive;
|
||||
public final boolean canRoam;
|
||||
public final boolean callsForHelp;
|
||||
public final boolean respondsToCallForHelp;
|
||||
private static HashMap<Integer, MobBehaviourType> _behaviourTypes = new HashMap<>();
|
||||
public MobBehaviourType BehaviourHelperType;
|
||||
public boolean isWimpy;
|
||||
public boolean isAgressive;
|
||||
public boolean canRoam;
|
||||
public boolean callsForHelp;
|
||||
public boolean respondsToCallForHelp;
|
||||
|
||||
MobBehaviourType(MobBehaviourType helpeebehaviourType, boolean wimpy, boolean agressive, boolean canroam, boolean callsforhelp, boolean respondstocallforhelp) {
|
||||
this.BehaviourHelperType = helpeebehaviourType;
|
||||
@@ -2877,11 +2878,8 @@ public class Enum {
|
||||
|
||||
public enum AIAgentType {
|
||||
MOBILE,
|
||||
GUARDCAPTAIN,
|
||||
GUARDMINION,
|
||||
GUARDWALLARCHER,
|
||||
PET,
|
||||
CHARMED,
|
||||
SIEGEENGINE;
|
||||
GUARD;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,9 @@ import engine.gameManager.DbManager;
|
||||
import engine.gameManager.ZoneManager;
|
||||
import engine.math.Vector2f;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.objects.AbstractWorldObject;
|
||||
import engine.objects.Zone;
|
||||
import engine.util.MapLoader;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
@@ -91,7 +93,7 @@ public class HeightMap {
|
||||
|
||||
// We needed to flip the image as OpenGL and Shadowbane both use the bottom left corner as origin.
|
||||
|
||||
// this.heightmapImage = MapLoader.flipImage(this.heightmapImage);
|
||||
this.heightmapImage = MapLoader.flipImage(this.heightmapImage);
|
||||
|
||||
// Calculate the data we do not load from table
|
||||
|
||||
@@ -121,26 +123,35 @@ public class HeightMap {
|
||||
this.outsetX = 128;
|
||||
this.outsetZ = 128;
|
||||
|
||||
|
||||
// Cache the full extents to avoid the calculation
|
||||
|
||||
this.fullExtentsX = halfExtentsX * 2;
|
||||
this.fullExtentsY = halfExtentsY * 2;
|
||||
|
||||
|
||||
// load the heightmap image.
|
||||
|
||||
|
||||
// We needed to flip the image as OpenGL and Shadowbane both use the bottom left corner as origin.
|
||||
|
||||
this.heightmapImage = null;
|
||||
|
||||
// Calculate the data we do not load from table
|
||||
|
||||
this.bucketWidthX = halfExtentsX;
|
||||
this.bucketWidthY = halfExtentsY;
|
||||
this.bucketWidthX = 1;
|
||||
this.bucketWidthY = 1;
|
||||
|
||||
this.pixelColorValues = new int[this.fullExtentsX][this.fullExtentsY];
|
||||
this.pixelColorValues = new int[this.fullExtentsX + 1][this.fullExtentsY + 1];
|
||||
|
||||
for (int y = 0; y < this.fullExtentsY; y++) {
|
||||
for (int x = 0; x < this.fullExtentsX; x++) {
|
||||
for (int y = 0; y <= this.fullExtentsY; y++) {
|
||||
for (int x = 0; x <= this.fullExtentsX; x++) {
|
||||
pixelColorValues[x][y] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HeightMap.heightmapByLoadNum.put(this.zoneLoadID, this);
|
||||
}
|
||||
|
||||
public HeightMap(Zone zone) {
|
||||
@@ -159,21 +170,26 @@ public class HeightMap {
|
||||
this.fullExtentsX = halfExtentsX * 2;
|
||||
this.fullExtentsY = halfExtentsY * 2;
|
||||
|
||||
|
||||
// We needed to flip the image as OpenGL and Shadowbane both use the bottom left corner as origin.
|
||||
|
||||
this.heightmapImage = null;
|
||||
|
||||
// Calculate the data we do not load from table
|
||||
|
||||
this.bucketWidthX = halfExtentsX;
|
||||
this.bucketWidthY = halfExtentsY;
|
||||
this.bucketWidthX = 1;
|
||||
this.bucketWidthY = 1;
|
||||
|
||||
this.pixelColorValues = new int[this.fullExtentsX][this.fullExtentsY];
|
||||
this.pixelColorValues = new int[this.fullExtentsX + 1][this.fullExtentsY + 1];
|
||||
|
||||
for (int y = 0; y < this.fullExtentsY; y++) {
|
||||
for (int x = 0; x < this.fullExtentsX; x++) {
|
||||
pixelColorValues[x][y] = 0;
|
||||
for (int y = 0; y <= this.fullExtentsY; y++) {
|
||||
for (int x = 0; x <= this.fullExtentsX; x++) {
|
||||
pixelColorValues[x][y] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HeightMap.heightmapByLoadNum.put(this.zoneLoadID, this);
|
||||
}
|
||||
|
||||
public static void GeneratePlayerCityHeightMap() {
|
||||
@@ -206,9 +222,113 @@ public class HeightMap {
|
||||
return nextZone;
|
||||
}
|
||||
|
||||
public static float getWorldHeight(Zone currentZone, Vector3fImmutable worldLoc) {
|
||||
public static float getWorldHeight(AbstractWorldObject worldObject) {
|
||||
|
||||
Vector2f parentLoc = new Vector2f(-1, -1);
|
||||
Zone currentZone = ZoneManager.findSmallestZone(worldObject.getLoc());
|
||||
|
||||
if (currentZone == null)
|
||||
return worldObject.getAltitude();
|
||||
|
||||
currentZone = getNextZoneWithTerrain(currentZone);
|
||||
|
||||
if (currentZone == ZoneManager.getSeaFloor())
|
||||
return currentZone.getAbsY() + worldObject.getAltitude();
|
||||
|
||||
Zone parentZone = getNextZoneWithTerrain(currentZone.getParent());
|
||||
HeightMap heightMap = currentZone.getHeightMap();
|
||||
|
||||
Vector2f zoneLoc = ZoneManager.worldToZoneSpace(worldObject.getLoc(), currentZone);
|
||||
Vector3fImmutable localLocFromCenter = ZoneManager.worldToLocal(worldObject.getLoc(), currentZone);
|
||||
|
||||
if ((parentZone != null) && (parentZone.getHeightMap() != null))
|
||||
parentLoc = ZoneManager.worldToZoneSpace(worldObject.getLoc(), parentZone);
|
||||
|
||||
float interaltitude = currentZone.getHeightMap().getInterpolatedTerrainHeight(zoneLoc);
|
||||
|
||||
float worldAltitude = currentZone.getWorldAltitude();
|
||||
|
||||
float realWorldAltitude = interaltitude + worldAltitude;
|
||||
|
||||
//OUTSET
|
||||
|
||||
if (parentZone != null) {
|
||||
|
||||
float parentXRadius = currentZone.getBounds().getHalfExtents().x;
|
||||
float parentZRadius = currentZone.getBounds().getHalfExtents().y;
|
||||
|
||||
float offsetX = Math.abs((localLocFromCenter.x / parentXRadius));
|
||||
float offsetZ = Math.abs((localLocFromCenter.z / parentZRadius));
|
||||
|
||||
float bucketScaleX = heightMap.outsetX / parentXRadius;
|
||||
float bucketScaleZ = heightMap.outsetZ / parentZRadius;
|
||||
|
||||
if (bucketScaleX <= 0.40000001)
|
||||
bucketScaleX = heightMap.outsetZ / parentXRadius;
|
||||
|
||||
if (bucketScaleX > 0.40000001)
|
||||
bucketScaleX = 0.40000001f;
|
||||
|
||||
if (bucketScaleZ <= 0.40000001)
|
||||
bucketScaleZ = heightMap.outsetX / parentZRadius;
|
||||
|
||||
if (bucketScaleZ > 0.40000001)
|
||||
bucketScaleZ = 0.40000001f;
|
||||
|
||||
float outsideGridSizeX = 1 - bucketScaleX; //32/256
|
||||
float outsideGridSizeZ = 1 - bucketScaleZ;
|
||||
float weight;
|
||||
|
||||
double scale;
|
||||
|
||||
if (offsetX > outsideGridSizeX && offsetX > offsetZ) {
|
||||
weight = (offsetX - outsideGridSizeX) / bucketScaleX;
|
||||
scale = Math.atan2((.5 - weight) * 3.1415927, 1);
|
||||
|
||||
float scaleChild = (float) ((scale + 1) * .5);
|
||||
float scaleParent = 1 - scaleChild;
|
||||
|
||||
float parentAltitude = parentZone.getHeightMap().getInterpolatedTerrainHeight(parentLoc);
|
||||
float parentCenterAltitude = parentZone.getHeightMap().getInterpolatedTerrainHeight(ZoneManager.worldToZoneSpace(currentZone.getLoc(), parentZone));
|
||||
|
||||
parentCenterAltitude += currentZone.getYCoord();
|
||||
parentCenterAltitude += interaltitude;
|
||||
|
||||
float firstScale = parentAltitude * scaleParent;
|
||||
float secondScale = parentCenterAltitude * scaleChild;
|
||||
float outsetALt = firstScale + secondScale;
|
||||
|
||||
outsetALt += currentZone.getParent().getWorldAltitude();
|
||||
realWorldAltitude = outsetALt;
|
||||
|
||||
} else if (offsetZ > outsideGridSizeZ) {
|
||||
|
||||
weight = (offsetZ - outsideGridSizeZ) / bucketScaleZ;
|
||||
scale = Math.atan2((.5 - weight) * 3.1415927, 1);
|
||||
|
||||
float scaleChild = (float) ((scale + 1) * .5);
|
||||
float scaleParent = 1 - scaleChild;
|
||||
float parentAltitude = parentZone.getHeightMap().getInterpolatedTerrainHeight(parentLoc);
|
||||
float parentCenterAltitude = parentZone.getHeightMap().getInterpolatedTerrainHeight(ZoneManager.worldToZoneSpace(currentZone.getLoc(), parentZone));
|
||||
|
||||
parentCenterAltitude += currentZone.getYCoord();
|
||||
parentCenterAltitude += interaltitude;
|
||||
float firstScale = parentAltitude * scaleParent;
|
||||
float secondScale = parentCenterAltitude * scaleChild;
|
||||
float outsetALt = firstScale + secondScale;
|
||||
|
||||
outsetALt += currentZone.getParent().getWorldAltitude();
|
||||
realWorldAltitude = outsetALt;
|
||||
}
|
||||
}
|
||||
|
||||
return realWorldAltitude;
|
||||
}
|
||||
|
||||
public static float getWorldHeight(Vector3fImmutable worldLoc) {
|
||||
|
||||
Vector2f parentLoc = new Vector2f(-1, -1);
|
||||
Zone currentZone = ZoneManager.findSmallestZone(worldLoc);
|
||||
|
||||
if (currentZone == null)
|
||||
return 0;
|
||||
@@ -232,7 +352,7 @@ public class HeightMap {
|
||||
|
||||
float interaltitude = currentZone.getHeightMap().getInterpolatedTerrainHeight(zoneLoc);
|
||||
|
||||
float worldAltitude = currentZone.worldAltitude;
|
||||
float worldAltitude = currentZone.getWorldAltitude();
|
||||
|
||||
float realWorldAltitude = interaltitude + worldAltitude;
|
||||
|
||||
@@ -240,6 +360,9 @@ public class HeightMap {
|
||||
|
||||
if (parentZone != null) {
|
||||
|
||||
// if (currentZone.getHeightMap() != null && parentZone.getHeightMap() != null && parentZone.getParent() != null && parentZone.getParent().getHeightMap() != null)
|
||||
// return realWorldAltitude;
|
||||
|
||||
float parentXRadius = currentZone.getBounds().getHalfExtents().x;
|
||||
float parentZRadius = currentZone.getBounds().getHalfExtents().y;
|
||||
|
||||
@@ -255,6 +378,7 @@ public class HeightMap {
|
||||
|
||||
double scale;
|
||||
|
||||
|
||||
if (offsetX > outsideGridSizeX && offsetX > offsetZ) {
|
||||
weight = (offsetX - outsideGridSizeX) / bucketScaleX;
|
||||
scale = Math.atan2((.5 - weight) * 3.1415927, 1);
|
||||
@@ -272,7 +396,7 @@ public class HeightMap {
|
||||
float secondScale = parentCenterAltitude * scaleChild;
|
||||
float outsetALt = firstScale + secondScale;
|
||||
|
||||
outsetALt += currentZone.getParent().worldAltitude;
|
||||
outsetALt += currentZone.getParent().getWorldAltitude();
|
||||
realWorldAltitude = outsetALt;
|
||||
|
||||
} else if (offsetZ > outsideGridSizeZ) {
|
||||
@@ -291,7 +415,7 @@ public class HeightMap {
|
||||
float secondScale = parentCenterAltitude * scaleChild;
|
||||
float outsetALt = firstScale + secondScale;
|
||||
|
||||
outsetALt += currentZone.getParent().worldAltitude;
|
||||
outsetALt += currentZone.getParent().getWorldAltitude();
|
||||
realWorldAltitude = outsetALt;
|
||||
}
|
||||
}
|
||||
@@ -299,13 +423,85 @@ public class HeightMap {
|
||||
return realWorldAltitude;
|
||||
}
|
||||
|
||||
public static float getWorldHeight(Vector3fImmutable worldLoc) {
|
||||
public static float getOutsetHeight(float interpolatedAltitude, Zone zone, Vector3fImmutable worldLocation) {
|
||||
|
||||
Zone currentZone = ZoneManager.findSmallestZone(worldLoc);
|
||||
Vector2f parentLoc;
|
||||
float outsetALt = 0;
|
||||
|
||||
if (currentZone == null)
|
||||
return 0;
|
||||
return getWorldHeight(currentZone, worldLoc);
|
||||
if (zone.getParent() == null || zone.getParent().getHeightMap() == null)
|
||||
return interpolatedAltitude + zone.getWorldAltitude();
|
||||
|
||||
if (zone.getParent() != null && zone.getParent().getHeightMap() != null) {
|
||||
|
||||
parentLoc = ZoneManager.worldToZoneSpace(worldLocation, zone.getParent());
|
||||
|
||||
Vector3fImmutable localLocFromCenter = ZoneManager.worldToLocal(worldLocation, zone);
|
||||
|
||||
float parentXRadius = zone.getBounds().getHalfExtents().x;
|
||||
float parentZRadius = zone.getBounds().getHalfExtents().y;
|
||||
|
||||
float bucketScaleX = zone.getHeightMap().outsetX / parentXRadius;
|
||||
float bucketScaleZ = zone.getHeightMap().outsetZ / parentZRadius;
|
||||
|
||||
float outsideGridSizeX = 1 - bucketScaleX; //32/256
|
||||
float outsideGridSizeZ = 1 - bucketScaleZ;
|
||||
|
||||
float weight;
|
||||
double scale;
|
||||
|
||||
float offsetX = Math.abs((localLocFromCenter.x / parentXRadius));
|
||||
float offsetZ = Math.abs((localLocFromCenter.z / parentZRadius));
|
||||
|
||||
if (offsetX > outsideGridSizeX && offsetX > offsetZ) {
|
||||
weight = (offsetX - outsideGridSizeX) / bucketScaleX;
|
||||
scale = Math.atan2((.5 - weight) * 3.1415927, 1);
|
||||
|
||||
float scaleChild = (float) ((scale + 1) * .5);
|
||||
float scaleParent = 1 - scaleChild;
|
||||
|
||||
float parentAltitude = zone.getParent().getHeightMap().getInterpolatedTerrainHeight(parentLoc);
|
||||
float parentCenterAltitude = zone.getParent().getHeightMap().getInterpolatedTerrainHeight(ZoneManager.worldToZoneSpace(zone.getLoc(), zone.getParent()));
|
||||
|
||||
parentCenterAltitude += zone.getYCoord();
|
||||
parentCenterAltitude += interpolatedAltitude;
|
||||
|
||||
float firstScale = parentAltitude * scaleParent;
|
||||
float secondScale = parentCenterAltitude * scaleChild;
|
||||
outsetALt = firstScale + secondScale;
|
||||
|
||||
outsetALt += zone.getParent().getAbsY();
|
||||
|
||||
} else if (offsetZ > outsideGridSizeZ) {
|
||||
|
||||
weight = (offsetZ - outsideGridSizeZ) / bucketScaleZ;
|
||||
scale = Math.atan2((.5 - weight) * 3.1415927, 1);
|
||||
|
||||
float scaleChild = (float) ((scale + 1) * .5);
|
||||
float scaleParent = 1 - scaleChild;
|
||||
float parentAltitude = zone.getParent().getHeightMap().getInterpolatedTerrainHeight(parentLoc);
|
||||
float parentCenterAltitude = zone.getHeightMap().getInterpolatedTerrainHeight(ZoneManager.worldToZoneSpace(zone.getLoc(), zone));
|
||||
|
||||
parentCenterAltitude += zone.getYCoord();
|
||||
parentCenterAltitude += interpolatedAltitude;
|
||||
|
||||
float firstScale = parentAltitude * scaleParent;
|
||||
float secondScale = parentCenterAltitude * scaleChild;
|
||||
outsetALt = firstScale + secondScale;
|
||||
|
||||
outsetALt += zone.getParent().getAbsY();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return outsetALt;
|
||||
}
|
||||
|
||||
public static Vector2f getGridOffset(Vector2f gridSquare) {
|
||||
|
||||
int floorX = (int) gridSquare.x;
|
||||
int floorY = (int) gridSquare.y;
|
||||
|
||||
return new Vector2f(gridSquare.x - floorX, gridSquare.y - floorY);
|
||||
|
||||
}
|
||||
|
||||
@@ -319,6 +515,7 @@ public class HeightMap {
|
||||
|
||||
HeightMap.GeneratePlayerCityHeightMap();
|
||||
|
||||
|
||||
// Clear all heightmap image data as it's no longer needed.
|
||||
|
||||
for (HeightMap heightMap : HeightMap.heightmapByLoadNum.values()) {
|
||||
@@ -344,18 +541,14 @@ public class HeightMap {
|
||||
if (zoneLoc.x < 0)
|
||||
zoneLoc.setX(0);
|
||||
|
||||
if (zoneLoc.x >= this.fullExtentsX)
|
||||
zoneLoc.setX(this.fullExtentsX);
|
||||
if (zoneLoc.x > this.fullExtentsX - 1)
|
||||
zoneLoc.setX((this.fullExtentsX - 1) + .9999999f);
|
||||
|
||||
if (zoneLoc.y < 0)
|
||||
zoneLoc.setY(0);
|
||||
|
||||
if (zoneLoc.y > this.fullExtentsY)
|
||||
zoneLoc.setY(this.fullExtentsY);
|
||||
|
||||
// Flip Y coordinates
|
||||
|
||||
zoneLoc.setY(this.fullExtentsY - zoneLoc.y);
|
||||
if (zoneLoc.y > this.fullExtentsY - 1)
|
||||
zoneLoc.setY((this.fullExtentsY - 1) + .9999999f);
|
||||
|
||||
float xBucket = (zoneLoc.x / this.bucketWidthX);
|
||||
float yBucket = (zoneLoc.y / this.bucketWidthY);
|
||||
@@ -376,10 +569,13 @@ public class HeightMap {
|
||||
int maxX = (int) (this.fullExtentsX / this.bucketWidthX);
|
||||
int maxY = (int) (this.fullExtentsY / this.bucketWidthY);
|
||||
|
||||
//flip the Y so it grabs from the bottom left instead of top left.
|
||||
//zoneLoc.setY(maxZoneHeight - zoneLoc.y);
|
||||
|
||||
gridSquare = getGridSquare(zoneLoc);
|
||||
|
||||
int gridX = (int) gridSquare.x;
|
||||
int gridY = (int) gridSquare.y;
|
||||
int gridY = (int) (gridSquare.y);
|
||||
|
||||
if (gridX > maxX)
|
||||
gridX = maxX;
|
||||
@@ -422,6 +618,48 @@ public class HeightMap {
|
||||
return interpolatedHeight;
|
||||
}
|
||||
|
||||
public float getInterpolatedTerrainHeight(Vector3fImmutable zoneLoc3f) {
|
||||
|
||||
Vector2f zoneLoc = new Vector2f(zoneLoc3f.x, zoneLoc3f.z);
|
||||
|
||||
Vector2f gridSquare;
|
||||
|
||||
if (zoneLoc.x < 0 || zoneLoc.x > this.fullExtentsX)
|
||||
return -1;
|
||||
|
||||
if (zoneLoc.y < 0 || zoneLoc.y > this.fullExtentsY)
|
||||
return -1;
|
||||
|
||||
//flip the Y so it grabs from the bottom left instead of top left.
|
||||
//zoneLoc.setY(maxZoneHeight - zoneLoc.y);
|
||||
|
||||
gridSquare = getGridSquare(zoneLoc);
|
||||
|
||||
int gridX = (int) gridSquare.x;
|
||||
int gridY = (int) (gridSquare.y);
|
||||
|
||||
float offsetX = (gridSquare.x - gridX);
|
||||
float offsetY = gridSquare.y - gridY;
|
||||
|
||||
//get height of the 4 vertices.
|
||||
|
||||
float topLeftHeight = pixelColorValues[gridX][gridY];
|
||||
float topRightHeight = pixelColorValues[gridX + 1][gridY];
|
||||
float bottomLeftHeight = pixelColorValues[gridX][gridY + 1];
|
||||
float bottomRightHeight = pixelColorValues[gridX + 1][gridY + 1];
|
||||
|
||||
float interpolatedHeight;
|
||||
|
||||
interpolatedHeight = topRightHeight * (1 - offsetY) * (offsetX);
|
||||
interpolatedHeight += (bottomRightHeight * offsetY * offsetX);
|
||||
interpolatedHeight += (bottomLeftHeight * (1 - offsetX) * offsetY);
|
||||
interpolatedHeight += (topLeftHeight * (1 - offsetX) * (1 - offsetY));
|
||||
|
||||
interpolatedHeight *= (float) this.maxHeight / 256; // Scale height
|
||||
|
||||
return interpolatedHeight;
|
||||
}
|
||||
|
||||
private void generatePixelData() {
|
||||
|
||||
Color color;
|
||||
@@ -440,6 +678,11 @@ public class HeightMap {
|
||||
|
||||
}
|
||||
|
||||
public float getScaledHeightForColor(float color) {
|
||||
|
||||
return (color / 256) * this.maxHeight;
|
||||
}
|
||||
|
||||
public float getBucketWidthX() {
|
||||
return bucketWidthX;
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ public enum InterestManager implements Runnable {
|
||||
|
||||
else {
|
||||
if (pc != null)
|
||||
if (pcc.getSeeInvis() < pc.hidden)
|
||||
if (pcc.getSeeInvis() < pc.getHidden())
|
||||
continue;
|
||||
|
||||
if (!cc.sendMsg(uom)) {
|
||||
@@ -340,7 +340,7 @@ public enum InterestManager implements Runnable {
|
||||
if (loadedPlayer.getObjectUUID() == player.getObjectUUID())
|
||||
continue;
|
||||
|
||||
if (player.getSeeInvis() < loadedPlayer.hidden)
|
||||
if (player.getSeeInvis() < loadedPlayer.getHidden())
|
||||
continue;
|
||||
|
||||
if (loadedPlayer.safemodeInvis())
|
||||
@@ -372,7 +372,7 @@ public enum InterestManager implements Runnable {
|
||||
|
||||
if (playerLoadedObject.getObjectType().equals(GameObjectType.PlayerCharacter)) {
|
||||
PlayerCharacter loadedPlayer = (PlayerCharacter) playerLoadedObject;
|
||||
if (player.getSeeInvis() < loadedPlayer.hidden)
|
||||
if (player.getSeeInvis() < loadedPlayer.getHidden())
|
||||
toRemove.add(playerLoadedObject);
|
||||
else if (loadedPlayer.safemodeInvis())
|
||||
toRemove.add(playerLoadedObject);
|
||||
@@ -437,7 +437,7 @@ public enum InterestManager implements Runnable {
|
||||
|
||||
// dont load if invis
|
||||
|
||||
if (player.getSeeInvis() < awopc.hidden)
|
||||
if (player.getSeeInvis() < awopc.getHidden())
|
||||
continue;
|
||||
|
||||
lcm = new LoadCharacterMsg(awopc, PlayerCharacter.hideNonAscii());
|
||||
@@ -467,7 +467,7 @@ public enum InterestManager implements Runnable {
|
||||
if (awonpc.despawned == true)
|
||||
continue;
|
||||
|
||||
awonpc.playerAgroMap.put(player.getObjectUUID(), 0f);
|
||||
awonpc.playerAgroMap.put(player.getObjectUUID(), false);
|
||||
((Mob) awonpc).setCombatTarget(null);
|
||||
lcm = new LoadCharacterMsg(awonpc, PlayerCharacter.hideNonAscii());
|
||||
|
||||
@@ -480,7 +480,7 @@ public enum InterestManager implements Runnable {
|
||||
if (!awonpc.isAlive())
|
||||
continue;
|
||||
|
||||
awonpc.playerAgroMap.put(player.getObjectUUID(), 0f);
|
||||
awonpc.playerAgroMap.put(player.getObjectUUID(), false);
|
||||
|
||||
if ((awonpc.agentType.equals(Enum.AIAgentType.MOBILE)))
|
||||
((Mob) awonpc).setCombatTarget(null);
|
||||
|
||||
@@ -28,27 +28,31 @@ public class dbMobHandler extends dbHandlerBase {
|
||||
this.localObjectType = engine.Enum.GameObjectType.valueOf(this.localClass.getSimpleName());
|
||||
}
|
||||
|
||||
public Mob PERSIST(Mob toAdd) {
|
||||
public Mob ADD_MOB(Mob toAdd) {
|
||||
|
||||
Mob mobile = null;
|
||||
|
||||
try (Connection connection = DbManager.getConnection();
|
||||
PreparedStatement preparedStatement = connection.prepareStatement("CALL `mob_CREATE`(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);")) {
|
||||
|
||||
preparedStatement.setLong(1, toAdd.parentZoneUUID);
|
||||
preparedStatement.setInt(2, toAdd.loadID);
|
||||
preparedStatement.setInt(3, toAdd.guildUUID);
|
||||
preparedStatement.setFloat(4, toAdd.bindLoc.x);
|
||||
preparedStatement.setFloat(5, toAdd.bindLoc.y);
|
||||
preparedStatement.setFloat(6, toAdd.bindLoc.z);
|
||||
PreparedStatement preparedStatement = connection.prepareStatement("CALL `mob_CREATE`(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);")) {
|
||||
|
||||
preparedStatement.setLong(1, toAdd.getParentZoneID());
|
||||
preparedStatement.setInt(2, toAdd.getMobBaseID());
|
||||
preparedStatement.setInt(3, toAdd.getGuildUUID());
|
||||
preparedStatement.setFloat(4, toAdd.getSpawnX());
|
||||
preparedStatement.setFloat(5, toAdd.getSpawnY());
|
||||
preparedStatement.setFloat(6, toAdd.getSpawnZ());
|
||||
preparedStatement.setInt(7, 0);
|
||||
preparedStatement.setFloat(8, toAdd.spawnRadius);
|
||||
preparedStatement.setInt(9, toAdd.spawnTime);
|
||||
preparedStatement.setInt(10, toAdd.contractUUID);
|
||||
preparedStatement.setInt(11, toAdd.buildingUUID);
|
||||
preparedStatement.setInt(12, toAdd.level);
|
||||
preparedStatement.setString(13, toAdd.firstName);
|
||||
preparedStatement.setString(14, toAdd.behaviourType.toString());
|
||||
preparedStatement.setFloat(8, toAdd.getSpawnRadius());
|
||||
preparedStatement.setInt(9, toAdd.getTrueSpawnTime());
|
||||
|
||||
if (toAdd.getContract() != null)
|
||||
preparedStatement.setInt(10, toAdd.getContract().getContractID());
|
||||
else
|
||||
preparedStatement.setInt(10, 0);
|
||||
|
||||
preparedStatement.setInt(11, toAdd.getBuildingID());
|
||||
preparedStatement.setInt(12, toAdd.getLevel());
|
||||
preparedStatement.setString(13, toAdd.getFirstName());
|
||||
|
||||
ResultSet rs = preparedStatement.executeQuery();
|
||||
|
||||
@@ -102,17 +106,17 @@ public class dbMobHandler extends dbHandlerBase {
|
||||
return row_count;
|
||||
}
|
||||
|
||||
public void LOAD_GUARD_MINIONS(Mob guardCaptain) {
|
||||
public void LOAD_PATROL_POINTS(Mob captain) {
|
||||
|
||||
try (Connection connection = DbManager.getConnection();
|
||||
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `dyn_guards` WHERE `captainUID` = ?")) {
|
||||
|
||||
preparedStatement.setInt(1, guardCaptain.getObjectUUID());
|
||||
preparedStatement.setInt(1, captain.getObjectUUID());
|
||||
ResultSet rs = preparedStatement.executeQuery();
|
||||
|
||||
while (rs.next()) {
|
||||
String minionName = rs.getString("minionName");
|
||||
Mob toCreate = Mob.createGuardMinion(guardCaptain, guardCaptain.getLevel(), minionName);
|
||||
String name = rs.getString("name");
|
||||
Mob toCreate = Mob.createGuardMob(captain, captain.getGuild(), captain.getParentZone(), captain.building.getLoc(), captain.getLevel(), name);
|
||||
|
||||
if (toCreate == null)
|
||||
return;
|
||||
@@ -127,13 +131,15 @@ public class dbMobHandler extends dbHandlerBase {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean ADD_GUARD_MINION(final long captainUID, final String minionName) {
|
||||
public boolean ADD_TO_GUARDS(final long captainUID, final int mobBaseID, final String name, final int slot) {
|
||||
|
||||
try (Connection connection = DbManager.getConnection();
|
||||
PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO `dyn_guards` (`captainUID`, `minionName`) VALUES (?,?)")) {
|
||||
PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO `dyn_guards` (`captainUID`, `mobBaseID`,`name`, `slot`) VALUES (?,?,?,?)")) {
|
||||
|
||||
preparedStatement.setLong(1, captainUID);
|
||||
preparedStatement.setString(2, minionName);
|
||||
preparedStatement.setInt(2, mobBaseID);
|
||||
preparedStatement.setString(3, name);
|
||||
preparedStatement.setInt(4, slot);
|
||||
|
||||
return (preparedStatement.executeUpdate() > 0);
|
||||
|
||||
@@ -143,13 +149,14 @@ public class dbMobHandler extends dbHandlerBase {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean REMOVE_GUARD_MINION(final long captainUID, final String minionName) {
|
||||
public boolean REMOVE_FROM_GUARDS(final long captainUID, final int mobBaseID, final int slot) {
|
||||
|
||||
try (Connection connection = DbManager.getConnection();
|
||||
PreparedStatement preparedStatement = connection.prepareStatement("DELETE FROM `dyn_guards` WHERE `captainUID`=? AND `minionName`=? LIMIT 1;")) {
|
||||
PreparedStatement preparedStatement = connection.prepareStatement("DELETE FROM `dyn_guards` WHERE `captainUID`=? AND `mobBaseID`=? AND `slot` =?")) {
|
||||
|
||||
preparedStatement.setLong(1, captainUID);
|
||||
preparedStatement.setString(2, minionName);
|
||||
preparedStatement.setInt(2, mobBaseID);
|
||||
preparedStatement.setInt(3, slot);
|
||||
|
||||
return (preparedStatement.executeUpdate() > 0);
|
||||
|
||||
@@ -159,20 +166,6 @@ public class dbMobHandler extends dbHandlerBase {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean REMOVE_ALL_MINIONS(final long captainUID) {
|
||||
|
||||
try (Connection connection = DbManager.getConnection();
|
||||
PreparedStatement preparedStatement = connection.prepareStatement("DELETE FROM `dyn_guards` WHERE `captainUID`=?;")) {
|
||||
|
||||
preparedStatement.setLong(1, captainUID);
|
||||
|
||||
return (preparedStatement.executeUpdate() > 0);
|
||||
|
||||
} catch (SQLException e) {
|
||||
Logger.error(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<Mob> GET_ALL_MOBS_FOR_ZONE(Zone zone) {
|
||||
|
||||
|
||||
@@ -15,9 +15,15 @@ import engine.gameManager.PowersManager;
|
||||
import engine.objects.Mob;
|
||||
import engine.objects.PreparedStatementShared;
|
||||
import engine.powers.EffectsBase;
|
||||
import engine.powers.MobPowerEntry;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class dbPowerHandler extends dbHandlerBase {
|
||||
@@ -80,4 +86,43 @@ public class dbPowerHandler extends dbHandlerBase {
|
||||
}
|
||||
}
|
||||
|
||||
public static HashMap<Integer, ArrayList<MobPowerEntry>> LOAD_MOB_POWERS() {
|
||||
|
||||
HashMap<Integer, ArrayList<MobPowerEntry>> mobPowers = new HashMap<>();
|
||||
MobPowerEntry mobPowerEntry;
|
||||
|
||||
int mobbaseID;
|
||||
int recordsRead = 0;
|
||||
|
||||
try (Connection connection = DbManager.getConnection();
|
||||
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM static_npc_mobbase_powers ORDER BY `id` ASC;")) {
|
||||
|
||||
ResultSet rs = preparedStatement.executeQuery();
|
||||
|
||||
while (rs.next()) {
|
||||
|
||||
recordsRead++;
|
||||
|
||||
mobbaseID = rs.getInt("mobbaseUUID");
|
||||
mobPowerEntry = new MobPowerEntry(rs);
|
||||
|
||||
if (mobPowers.get(mobbaseID) == null) {
|
||||
ArrayList<MobPowerEntry> powerList = new ArrayList<>();
|
||||
powerList.add(mobPowerEntry);
|
||||
mobPowers.put(mobbaseID, powerList);
|
||||
} else {
|
||||
ArrayList<MobPowerEntry> powerList = mobPowers.get(mobbaseID);
|
||||
powerList.add(mobPowerEntry);
|
||||
mobPowers.put(mobbaseID, powerList);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
Logger.error(e);
|
||||
return mobPowers;
|
||||
}
|
||||
|
||||
Logger.info("read: " + recordsRead + " cached: " + mobPowers.size());
|
||||
return mobPowers;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@ package engine.db.handlers;
|
||||
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.objects.RuneBase;
|
||||
import engine.powers.RunePowerEntry;
|
||||
import engine.powers.RuneSkillAdjustEntry;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.sql.Connection;
|
||||
@@ -29,84 +27,6 @@ public class dbRuneBaseHandler extends dbHandlerBase {
|
||||
this.localObjectType = engine.Enum.GameObjectType.valueOf(this.localClass.getSimpleName());
|
||||
}
|
||||
|
||||
public static HashMap<Integer, ArrayList<RunePowerEntry>> LOAD_RUNE_POWERS() {
|
||||
|
||||
HashMap<Integer, ArrayList<RunePowerEntry>> mobPowers = new HashMap<>();
|
||||
RunePowerEntry runePowerEntry;
|
||||
|
||||
int rune_id;
|
||||
int recordsRead = 0;
|
||||
|
||||
try (Connection connection = DbManager.getConnection();
|
||||
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM static_rune_powers")) {
|
||||
|
||||
ResultSet rs = preparedStatement.executeQuery();
|
||||
|
||||
while (rs.next()) {
|
||||
|
||||
recordsRead++;
|
||||
|
||||
rune_id = rs.getInt("rune_id");
|
||||
runePowerEntry = new RunePowerEntry(rs);
|
||||
|
||||
if (mobPowers.get(rune_id) == null) {
|
||||
ArrayList<RunePowerEntry> runePowerList = new ArrayList<>();
|
||||
runePowerList.add(runePowerEntry);
|
||||
mobPowers.put(rune_id, runePowerList);
|
||||
} else {
|
||||
ArrayList<RunePowerEntry> powerList = mobPowers.get(rune_id);
|
||||
powerList.add(runePowerEntry);
|
||||
mobPowers.put(rune_id, powerList);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
Logger.error(e);
|
||||
return mobPowers;
|
||||
}
|
||||
|
||||
Logger.info("read: " + recordsRead + " cached: " + mobPowers.size());
|
||||
return mobPowers;
|
||||
}
|
||||
|
||||
public static HashMap<Integer, ArrayList<RuneSkillAdjustEntry>> LOAD_RUNE_SKILL_ADJUSTS() {
|
||||
|
||||
HashMap<Integer, ArrayList<RuneSkillAdjustEntry>> runeSkillAdjusts = new HashMap<>();
|
||||
RuneSkillAdjustEntry runeSkillAdjustEntry;
|
||||
|
||||
int rune_id;
|
||||
int recordsRead = 0;
|
||||
|
||||
try (Connection connection = DbManager.getConnection();
|
||||
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM static_rune_skill_adjusts")) {
|
||||
|
||||
ResultSet rs = preparedStatement.executeQuery();
|
||||
|
||||
while (rs.next()) {
|
||||
|
||||
recordsRead++;
|
||||
|
||||
rune_id = rs.getInt("rune_id");
|
||||
runeSkillAdjustEntry = new RuneSkillAdjustEntry(rs);
|
||||
|
||||
if (runeSkillAdjusts.get(rune_id) == null) {
|
||||
ArrayList<RuneSkillAdjustEntry> skillAdjustList = new ArrayList<>();
|
||||
skillAdjustList.add(runeSkillAdjustEntry);
|
||||
runeSkillAdjusts.put(rune_id, skillAdjustList);
|
||||
} else {
|
||||
ArrayList<RuneSkillAdjustEntry> powerList = runeSkillAdjusts.get(rune_id);
|
||||
powerList.add(runeSkillAdjustEntry);
|
||||
runeSkillAdjusts.put(rune_id, powerList);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
Logger.error(e);
|
||||
return runeSkillAdjusts;
|
||||
}
|
||||
|
||||
Logger.info("read: " + recordsRead + " cached: " + runeSkillAdjusts.size());
|
||||
return runeSkillAdjusts;
|
||||
}
|
||||
|
||||
public void GET_RUNE_REQS(final RuneBase rb) {
|
||||
|
||||
try (Connection connection = DbManager.getConnection();
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
package engine.devcmd.cmds;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.devcmd.AbstractDevCmd;
|
||||
import engine.gameManager.ChatManager;
|
||||
@@ -44,7 +43,7 @@ public class AddMobCmd extends AbstractDevCmd {
|
||||
MobBase mb = (MobBase) mobbaseAGO;
|
||||
int loadID = mb.getObjectUUID();
|
||||
Mob mob = Mob.createMob(loadID, Vector3fImmutable.getRandomPointInCircle(pc.getLoc(), 100),
|
||||
null, zone, null, null, "", 1, Enum.AIAgentType.MOBILE);
|
||||
null, true, zone, null, 0, "", 1);
|
||||
if (mob != null) {
|
||||
mob.updateDatabase();
|
||||
this.setResult(String.valueOf(mob.getDBID()));
|
||||
@@ -85,7 +84,7 @@ public class AddMobCmd extends AbstractDevCmd {
|
||||
|
||||
|
||||
Mob mob = Mob.createMob(loadID, pc.getLoc(),
|
||||
null, zone, null, null, "", 1, Enum.AIAgentType.MOBILE);
|
||||
null, true, zone, null, 0, "", 1);
|
||||
if (mob != null) {
|
||||
mob.updateDatabase();
|
||||
ChatManager.chatSayInfo(pc,
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.devcmd.cmds;
|
||||
|
||||
import engine.InterestManagement.HeightMap;
|
||||
import engine.devcmd.AbstractDevCmd;
|
||||
import engine.gameManager.ZoneManager;
|
||||
import engine.math.Vector2f;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.objects.AbstractGameObject;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import engine.objects.Zone;
|
||||
|
||||
public class AuditHeightMapCmd extends AbstractDevCmd {
|
||||
|
||||
public AuditHeightMapCmd() {
|
||||
super("auditheightmap");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _doCmd(PlayerCharacter pcSender, String[] words,
|
||||
AbstractGameObject target) {
|
||||
|
||||
int count = Integer.parseInt(words[0]);
|
||||
long start = System.currentTimeMillis();
|
||||
for (int i = 0; i < count; i++) {
|
||||
|
||||
|
||||
Zone currentZone = ZoneManager.findSmallestZone(pcSender.getLoc());
|
||||
|
||||
|
||||
Vector3fImmutable currentLoc = Vector3fImmutable.getRandomPointInCircle(currentZone.getLoc(), currentZone.getBounds().getHalfExtents().x < currentZone.getBounds().getHalfExtents().y ? currentZone.getBounds().getHalfExtents().x : currentZone.getBounds().getHalfExtents().y);
|
||||
|
||||
Vector2f zoneLoc = ZoneManager.worldToZoneSpace(currentLoc, currentZone);
|
||||
|
||||
if (currentZone != null && currentZone.getHeightMap() != null) {
|
||||
float altitude = currentZone.getHeightMap().getInterpolatedTerrainHeight(zoneLoc);
|
||||
float outsetAltitude = HeightMap.getOutsetHeight(altitude, currentZone, pcSender.getLoc());
|
||||
}
|
||||
|
||||
}
|
||||
long end = System.currentTimeMillis();
|
||||
|
||||
long delta = end - start;
|
||||
|
||||
this.throwbackInfo(pcSender, "Audit Heightmap took " + delta + " ms to run " + count + " times!");
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String _getUsageString() {
|
||||
return "' /auditmobs [zone.UUID]'";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String _getHelpString() {
|
||||
return "Audits all the mobs in a zone.";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import engine.InterestManagement.HeightMap;
|
||||
import engine.devcmd.AbstractDevCmd;
|
||||
import engine.gameManager.ZoneManager;
|
||||
import engine.math.Vector2f;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.objects.AbstractGameObject;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import engine.objects.Zone;
|
||||
@@ -25,41 +26,201 @@ public class GetHeightCmd extends AbstractDevCmd {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _doCmd(PlayerCharacter playerCharacter, String[] words,
|
||||
protected void _doCmd(PlayerCharacter pc, String[] words,
|
||||
AbstractGameObject target) {
|
||||
|
||||
Zone currentZone;
|
||||
Zone parentZone;
|
||||
Zone heightmapZone;
|
||||
boolean end = true;
|
||||
|
||||
currentZone = ZoneManager.findSmallestZone(playerCharacter.getLoc());
|
||||
heightmapZone = HeightMap.getNextZoneWithTerrain(currentZone);
|
||||
parentZone = HeightMap.getNextZoneWithTerrain(currentZone.getParent());
|
||||
float height = HeightMap.getWorldHeight(pc);
|
||||
|
||||
float currentHeight = HeightMap.getWorldHeight(currentZone, playerCharacter.getLoc());
|
||||
float parentHeight = HeightMap.getWorldHeight(parentZone, playerCharacter.getLoc());
|
||||
this.throwbackInfo(pc, "Altitude : " + height);
|
||||
|
||||
this.throwbackInfo(playerCharacter, "Current Zone : " + currentZone.getName());
|
||||
this.throwbackInfo(playerCharacter, "Heightmap Zone : " + heightmapZone.getName());
|
||||
this.throwbackInfo(playerCharacter, "Height returned: " + currentHeight);
|
||||
this.throwbackInfo(pc, "Character Height: " + pc.getCharacterHeight());
|
||||
this.throwbackInfo(pc, "Character Height to start swimming: " + pc.centerHeight);
|
||||
|
||||
Zone zone = ZoneManager.findSmallestZone(pc.getLoc());
|
||||
this.throwbackInfo(pc, "Water Level : " + zone.getSeaLevel());
|
||||
this.throwbackInfo(pc, "Character Water Level Above : " + (pc.getCharacterHeight() + height - zone.getSeaLevel()));
|
||||
|
||||
if (end)
|
||||
return;
|
||||
|
||||
Vector2f gridSquare;
|
||||
Vector2f gridOffset;
|
||||
Vector2f parentGrid;
|
||||
Vector2f parentLoc = new Vector2f(-1, -1);
|
||||
|
||||
Zone currentZone = ZoneManager.findSmallestZone(pc.getLoc());
|
||||
|
||||
if (currentZone == null)
|
||||
return;
|
||||
|
||||
Zone parentZone = currentZone.getParent();
|
||||
|
||||
HeightMap heightMap = currentZone.getHeightMap();
|
||||
|
||||
|
||||
//find the next parents heightmap if the currentzone heightmap is null.
|
||||
while (heightMap == null) {
|
||||
|
||||
if (currentZone == ZoneManager.getSeaFloor()) {
|
||||
this.throwbackInfo(pc, "Could not find a heightmap to get height.");
|
||||
break;
|
||||
}
|
||||
|
||||
this.throwbackError(pc, "Heightmap does not exist for " + currentZone.getName());
|
||||
this.throwbackInfo(pc, "Using parent zone instead: ");
|
||||
currentZone = currentZone.getParent();
|
||||
heightMap = currentZone.getHeightMap();
|
||||
}
|
||||
|
||||
|
||||
if ((heightMap == null) || (currentZone == ZoneManager.getSeaFloor())) {
|
||||
this.throwbackInfo(pc, currentZone.getName() + " has no heightmap ");
|
||||
this.throwbackInfo(pc, "Current altitude: " + currentZone.absY);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2f zoneLoc = ZoneManager.worldToZoneSpace(pc.getLoc(), currentZone);
|
||||
|
||||
Vector3fImmutable seaFloorLocalLoc = ZoneManager.worldToLocal(pc.getLoc(), ZoneManager.getSeaFloor());
|
||||
this.throwbackInfo(pc, "SeaFloor Local : " + seaFloorLocalLoc.x + " , " + seaFloorLocalLoc.y);
|
||||
|
||||
|
||||
this.throwbackInfo(pc, "Local Zone Location : " + zoneLoc.x + " , " + zoneLoc.y);
|
||||
Vector3fImmutable localLocFromCenter = ZoneManager.worldToLocal(pc.getLoc(), currentZone);
|
||||
Vector3fImmutable parentLocFromCenter = ZoneManager.worldToLocal(pc.getLoc(), currentZone.getParent());
|
||||
this.throwbackInfo(pc, "Local Zone Location from center : " + localLocFromCenter);
|
||||
this.throwbackInfo(pc, "parent Zone Location from center : " + parentLocFromCenter);
|
||||
|
||||
Vector2f parentZoneLoc = ZoneManager.worldToZoneSpace(pc.getLoc(), currentZone.getParent());
|
||||
this.throwbackInfo(pc, "Parent Zone Location from Bottom Left : " + parentZoneLoc);
|
||||
|
||||
if ((parentZone != null) && (parentZone.getHeightMap() != null)) {
|
||||
parentLoc = ZoneManager.worldToZoneSpace(pc.getLoc(), parentZone);
|
||||
parentGrid = parentZone.getHeightMap().getGridSquare(parentLoc);
|
||||
} else
|
||||
parentGrid = new Vector2f(-1, -1);
|
||||
|
||||
gridSquare = heightMap.getGridSquare(zoneLoc);
|
||||
gridOffset = HeightMap.getGridOffset(gridSquare);
|
||||
|
||||
float interaltitude = currentZone.getHeightMap().getInterpolatedTerrainHeight(zoneLoc);
|
||||
|
||||
this.throwbackInfo(pc, currentZone.getName());
|
||||
this.throwbackInfo(pc, "Current Grid Square: " + gridSquare.x + " , " + gridSquare.y);
|
||||
this.throwbackInfo(pc, "Grid Offset: " + gridOffset.x + " , " + gridOffset.y);
|
||||
this.throwbackInfo(pc, "Parent Grid: " + parentGrid.x + " , " + parentGrid.y);
|
||||
|
||||
if (parentGrid.x != -1) {
|
||||
float parentAltitude = parentZone.getHeightMap().getInterpolatedTerrainHeight(parentLoc);
|
||||
this.throwbackInfo(pc, "Parent ALTITUDE: " + (parentAltitude));
|
||||
this.throwbackInfo(pc, "Parent Interpolation: " + (parentAltitude + parentZone.getWorldAltitude()));
|
||||
}
|
||||
this.throwbackInfo(pc, "interpolated height: " + interaltitude);
|
||||
|
||||
this.throwbackInfo(pc, "interpolated height with World: " + (interaltitude + currentZone.getWorldAltitude()));
|
||||
|
||||
float realWorldAltitude = interaltitude + currentZone.getWorldAltitude();
|
||||
|
||||
//OUTSET
|
||||
if (parentZone != null) {
|
||||
float parentXRadius = currentZone.getBounds().getHalfExtents().x;
|
||||
float parentZRadius = currentZone.getBounds().getHalfExtents().y;
|
||||
|
||||
float offsetX = Math.abs((localLocFromCenter.x / parentXRadius));
|
||||
float offsetZ = Math.abs((localLocFromCenter.z / parentZRadius));
|
||||
|
||||
float bucketScaleX = 100 / parentXRadius;
|
||||
float bucketScaleZ = 200 / parentZRadius;
|
||||
|
||||
float outsideGridSizeX = 1 - bucketScaleX; //32/256
|
||||
float outsideGridSizeZ = 1 - bucketScaleZ;
|
||||
float weight;
|
||||
|
||||
double scale;
|
||||
|
||||
|
||||
if (offsetX > outsideGridSizeX && offsetX > offsetZ) {
|
||||
weight = (offsetX - outsideGridSizeX) / bucketScaleX;
|
||||
scale = Math.atan2((.5 - weight) * 3.1415927, 1);
|
||||
|
||||
float scaleChild = (float) ((scale + 1) * .5);
|
||||
float scaleParent = 1 - scaleChild;
|
||||
|
||||
|
||||
float parentAltitude = parentZone.getHeightMap().getInterpolatedTerrainHeight(parentLoc);
|
||||
float parentCenterAltitude = parentZone.getHeightMap().getInterpolatedTerrainHeight(ZoneManager.worldToZoneSpace(currentZone.getLoc(), parentZone));
|
||||
|
||||
parentCenterAltitude += currentZone.getYCoord();
|
||||
parentCenterAltitude += interaltitude;
|
||||
|
||||
float firstScale = parentAltitude * scaleParent;
|
||||
float secondScale = parentCenterAltitude * scaleChild;
|
||||
float outsetALt = firstScale + secondScale;
|
||||
|
||||
outsetALt += currentZone.getParent().getAbsY();
|
||||
realWorldAltitude = outsetALt;
|
||||
|
||||
} else if (offsetZ > outsideGridSizeZ) {
|
||||
|
||||
weight = (offsetZ - outsideGridSizeZ) / bucketScaleZ;
|
||||
scale = Math.atan2((.5 - weight) * 3.1415927, 1);
|
||||
|
||||
float scaleChild = (float) ((scale + 1) * .5);
|
||||
float scaleParent = 1 - scaleChild;
|
||||
float parentAltitude = parentZone.getHeightMap().getInterpolatedTerrainHeight(parentLoc);
|
||||
float parentCenterAltitude = parentZone.getHeightMap().getInterpolatedTerrainHeight(ZoneManager.worldToZoneSpace(currentZone.getLoc(), parentZone));
|
||||
|
||||
parentCenterAltitude += currentZone.getYCoord();
|
||||
parentCenterAltitude += interaltitude;
|
||||
float firstScale = parentAltitude * scaleParent;
|
||||
float secondScale = parentCenterAltitude * scaleChild;
|
||||
float outsetALt = firstScale + secondScale;
|
||||
|
||||
outsetALt += currentZone.getParent().getAbsY();
|
||||
realWorldAltitude = outsetALt;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
float strMod = pc.statStrBase - 40;
|
||||
|
||||
strMod *= .00999999998f;
|
||||
|
||||
strMod += 1f;
|
||||
|
||||
float radius = 0;
|
||||
switch (pc.getRaceID()) {
|
||||
case 2017:
|
||||
radius = 3.1415927f;
|
||||
case 2000:
|
||||
|
||||
|
||||
}
|
||||
strMod *= 1.5707964f;
|
||||
|
||||
strMod += 3.1415927f;
|
||||
|
||||
strMod -= .5f;
|
||||
|
||||
|
||||
realWorldAltitude += strMod;
|
||||
|
||||
this.throwbackInfo(pc, "interpolated height with World: " + realWorldAltitude);
|
||||
|
||||
Vector2f zoneLoc = ZoneManager.worldToZoneSpace(playerCharacter.getLoc(), heightmapZone);
|
||||
Vector2f gridSquare = heightmapZone.getHeightMap().getGridSquare(zoneLoc);
|
||||
|
||||
this.throwbackInfo(playerCharacter, "Grid : " + (int) gridSquare.x + "x" + (int) gridSquare.y);
|
||||
this.throwbackInfo(playerCharacter, "Parent : " + parentZone.getName());
|
||||
this.throwbackInfo(playerCharacter, "Height returned : " + parentHeight);
|
||||
this.throwbackInfo(playerCharacter, "Character Height: " + playerCharacter.getCharacterHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String _getHelpString() {
|
||||
return "Queries heightmap engine";
|
||||
return "Temporarily Changes SubRace";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String _getUsageString() {
|
||||
return "' /getheight";
|
||||
return "' /subrace mobBaseID";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -440,9 +440,7 @@ public class InfoCmd extends AbstractDevCmd {
|
||||
output += "isSummonedPet: true";
|
||||
else
|
||||
output += "isSummonedPet: false";
|
||||
|
||||
|
||||
PlayerCharacter owner = (PlayerCharacter) targetMob.guardCaptain;
|
||||
PlayerCharacter owner = targetMob.getOwner();
|
||||
if (owner != null)
|
||||
output += " owner: " + owner.getObjectUUID();
|
||||
output += newline;
|
||||
|
||||
@@ -103,19 +103,15 @@ public class PrintStatsCmd extends AbstractDevCmd {
|
||||
main = getWeaponBase(1, equip);
|
||||
ItemBase off = null;
|
||||
|
||||
if(equip != null){
|
||||
if(equip.get(2) != null && !equip.get(2).getItemBase().isShield()){
|
||||
//off hand weapon
|
||||
out += "Attack Rating: " + tar.atrHandTwo + newline;
|
||||
out += "Damage: " + tar.minDamageHandTwo + " - " + tar.maxDamageHandTwo + newline;
|
||||
out += "Range: " + tar.rangeHandTwo + newline;
|
||||
out += "Attack Speed: " + tar.speedHandTwo + newline;
|
||||
} else{
|
||||
out += "Attack Rating: " + tar.atrHandOne + newline;
|
||||
out += "Damage: " + tar.minDamageHandOne + " - " + tar.maxDamageHandOne + newline;
|
||||
out += "Range: " + tar.rangeHandOne + newline;
|
||||
out += "Attack Speed: " + tar.speedHandOne + newline;
|
||||
}
|
||||
if (equip != null)
|
||||
getWeaponBase(2, equip);
|
||||
if (main == null && off == null) {
|
||||
out += "Main Hand: atr: " + tar.getAtrHandOne() + ", damage: " + tar.getMinDamageHandOne() + " to " + tar.getMaxDamageHandOne() + ", speed: " + tar.getSpeedHandOne() + ", range: 6" + newline;
|
||||
} else {
|
||||
if (main != null)
|
||||
out += "Main Hand: atr: " + tar.getAtrHandOne() + ", damage: " + tar.getMinDamageHandOne() + " to " + tar.getMaxDamageHandOne() + ", speed: " + tar.getSpeedHandOne() + ", range: " + main.getRange() + newline;
|
||||
if (off != null)
|
||||
out += "Main Hand: atr: " + tar.getAtrHandTwo() + ", damage: " + tar.getMinDamageHandTwo() + " to " + tar.getMaxDamageHandTwo() + ", speed: " + tar.getSpeedHandTwo() + ", range: " + off.getRange() + newline;
|
||||
}
|
||||
out += "isAlive: " + tar.isAlive() + ", Combat: " + tar.isCombat() + newline;
|
||||
|
||||
|
||||
@@ -59,25 +59,22 @@ public class PurgeObjectsCmd extends AbstractDevCmd {
|
||||
|
||||
|
||||
if (npc != null) {
|
||||
for (Integer minionUUID : npc.minions) {
|
||||
Mob mob = Mob.getMob(minionUUID);
|
||||
for (Mob mob : npc.getSiegeMinionMap().keySet()) {
|
||||
WorldGrid.RemoveWorldObject(mob);
|
||||
WorldGrid.removeObject(mob, pc);
|
||||
|
||||
//Mob.getRespawnMap().remove(mob);
|
||||
if (mob.getParentZone() != null)
|
||||
mob.getParentZone().zoneMobSet.remove(mob);
|
||||
}
|
||||
|
||||
DbManager.NPCQueries.DELETE_NPC(npc);
|
||||
DbManager.removeFromCache(GameObjectType.NPC,
|
||||
npc.getObjectUUID());
|
||||
WorldGrid.RemoveWorldObject(npc);
|
||||
} else if (mobA != null) {
|
||||
for (Integer minionUUID : mobA.minions) {
|
||||
Mob mob = Mob.getMob(minionUUID);
|
||||
for (Mob mob : mobA.getSiegeMinionMap().keySet()) {
|
||||
WorldGrid.RemoveWorldObject(mob);
|
||||
WorldGrid.removeObject(mob, pc);
|
||||
|
||||
//Mob.getRespawnMap().remove(mob);
|
||||
if (mob.getParentZone() != null)
|
||||
mob.getParentZone().zoneMobSet.remove(mob);
|
||||
}
|
||||
@@ -154,11 +151,10 @@ public class PurgeObjectsCmd extends AbstractDevCmd {
|
||||
|
||||
|
||||
if (npc != null) {
|
||||
for (Integer minionUUID : npc.minions) {
|
||||
Mob mob = Mob.getMob(minionUUID);
|
||||
for (Mob mob : npc.getSiegeMinionMap().keySet()) {
|
||||
WorldGrid.RemoveWorldObject(mob);
|
||||
WorldGrid.removeObject(mob, pc);
|
||||
|
||||
//Mob.getRespawnMap().remove(mob);
|
||||
if (mob.getParentZone() != null)
|
||||
mob.getParentZone().zoneMobSet.remove(mob);
|
||||
}
|
||||
@@ -167,11 +163,10 @@ public class PurgeObjectsCmd extends AbstractDevCmd {
|
||||
npc.getObjectUUID());
|
||||
WorldGrid.RemoveWorldObject(npc);
|
||||
} else if (mobA != null) {
|
||||
for (Integer minionUUID : mobA.minions) {
|
||||
Mob mob = Mob.getMob(minionUUID);
|
||||
for (Mob mob : mobA.getSiegeMinionMap().keySet()) {
|
||||
WorldGrid.RemoveWorldObject(mob);
|
||||
WorldGrid.removeObject(mob, pc);
|
||||
|
||||
//Mob.getRespawnMap().remove(mob);
|
||||
if (mob.getParentZone() != null)
|
||||
mob.getParentZone().zoneMobSet.remove(mob);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ package engine.devcmd.cmds;
|
||||
|
||||
import engine.Enum.BuildingGroup;
|
||||
import engine.Enum.DbObjectType;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.InterestManagement.WorldGrid;
|
||||
import engine.devcmd.AbstractDevCmd;
|
||||
import engine.gameManager.BuildingManager;
|
||||
@@ -137,16 +138,49 @@ public class RemoveObjectCmd extends AbstractDevCmd {
|
||||
Warehouse.warehouseByBuildingUUID.remove(building.getObjectUUID());
|
||||
}
|
||||
|
||||
|
||||
//remove cached shrines.
|
||||
if ((building.getBlueprintUUID() != 0)
|
||||
&& (building.getBlueprint().getBuildingGroup() == BuildingGroup.SHRINE))
|
||||
Shrine.RemoveShrineFromCacheByBuilding(building);
|
||||
|
||||
// Remove hirelings for this building
|
||||
for (AbstractCharacter ac : building.getHirelings().keySet()) {
|
||||
NPC npc = null;
|
||||
Mob mobA = null;
|
||||
|
||||
if (ac.getObjectType() == GameObjectType.NPC)
|
||||
npc = (NPC) ac;
|
||||
else if (ac.getObjectType() == GameObjectType.Mob)
|
||||
mobA = (Mob) ac;
|
||||
|
||||
if (npc != null) {
|
||||
for (Mob mob : npc.getSiegeMinionMap().keySet()) {
|
||||
WorldGrid.RemoveWorldObject(mob);
|
||||
WorldGrid.removeObject(mob, pc);
|
||||
//Mob.getRespawnMap().remove(mob);
|
||||
if (mob.getParentZone() != null)
|
||||
mob.getParentZone().zoneMobSet.remove(mob);
|
||||
}
|
||||
DbManager.NPCQueries.DELETE_NPC(npc);
|
||||
DbManager.removeFromCache(npc);
|
||||
WorldGrid.RemoveWorldObject(npc);
|
||||
WorldGrid.removeObject(npc, pc);
|
||||
} else if (mobA != null) {
|
||||
for (Mob mob : mobA.getSiegeMinionMap().keySet()) {
|
||||
WorldGrid.RemoveWorldObject(mob);
|
||||
WorldGrid.removeObject(mob, pc);
|
||||
//Mob.getRespawnMap().remove(mob);
|
||||
if (mob.getParentZone() != null)
|
||||
mob.getParentZone().zoneMobSet.remove(mob);
|
||||
}
|
||||
DbManager.MobQueries.DELETE_MOB(mobA);
|
||||
DbManager.removeFromCache(mobA);
|
||||
WorldGrid.RemoveWorldObject(mobA);
|
||||
WorldGrid.removeObject(mobA, pc);
|
||||
}
|
||||
|
||||
for (AbstractCharacter abstractCharacter : building.getHirelings().keySet())
|
||||
BuildingManager.removeHireling(building, abstractCharacter);
|
||||
|
||||
}
|
||||
Zone zone = building.getParentZone();
|
||||
DbManager.BuildingQueries.DELETE_FROM_DATABASE(building);
|
||||
DbManager.removeFromCache(building);
|
||||
@@ -175,13 +209,11 @@ public class RemoveObjectCmd extends AbstractDevCmd {
|
||||
if (npc.building != null)
|
||||
npc.building.getHirelings().remove(npc);
|
||||
|
||||
for (Integer minionUUID : npc.minions) {
|
||||
Mob minionMob = Mob.getMob(minionUUID);
|
||||
WorldGrid.RemoveWorldObject(minionMob);
|
||||
WorldGrid.removeObject(minionMob, pc);
|
||||
|
||||
if (minionMob.getParentZone() != null)
|
||||
minionMob.getParentZone().zoneMobSet.remove(minionMob);
|
||||
for (Mob mob : npc.getSiegeMinionMap().keySet()) {
|
||||
WorldGrid.RemoveWorldObject(mob);
|
||||
WorldGrid.removeObject(mob, pc);
|
||||
if (mob.getParentZone() != null)
|
||||
mob.getParentZone().zoneMobSet.remove(mob);
|
||||
}
|
||||
|
||||
DbManager.NPCQueries.DELETE_NPC(npc);
|
||||
|
||||
@@ -159,7 +159,7 @@ public class SetSubRaceCmd extends AbstractDevCmd {
|
||||
// pum.setEffectID(token);
|
||||
// pum.setSourceType(pc.getObjectType().ordinal());
|
||||
// pum.setSourceID(pc.getObjectUUID());
|
||||
// pum.setStartLocType(pc.getObjectType().ordinal());
|
||||
// pum.setTargetType(pc.getObjectType().ordinal());
|
||||
// pum.setTargetID(pc.getObjectUUID());
|
||||
// pum.setNumTrains(40);
|
||||
// pum.setDuration(-1);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package engine.devcmd.cmds;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.devcmd.AbstractDevCmd;
|
||||
import engine.gameManager.ZoneManager;
|
||||
import engine.math.Vector3fImmutable;
|
||||
@@ -111,7 +110,7 @@ public class SplatMobCmd extends AbstractDevCmd {
|
||||
|
||||
mobile = Mob.createMob(_mobileUUID,
|
||||
Vector3fImmutable.getRandomPointInCircle(_currentLocation, _targetRange),
|
||||
null, serverZone, null, null, "", 1, Enum.AIAgentType.MOBILE);
|
||||
null, true, serverZone, null, 0, "", 1);
|
||||
|
||||
if (mobile != null) {
|
||||
mobile.updateDatabase();
|
||||
|
||||
@@ -104,7 +104,7 @@ public class ZoneInfoCmd extends AbstractDevCmd {
|
||||
output += newline;
|
||||
output += "Sea Level = " + zone.getSeaLevel();
|
||||
output += newline;
|
||||
output += "World Altitude = " + zone.worldAltitude;
|
||||
output += "World Altitude = " + zone.getWorldAltitude();
|
||||
throwbackInfo(player, output);
|
||||
|
||||
City city = ZoneManager.getCityAtLocation(player.getLoc());
|
||||
|
||||
@@ -9,17 +9,12 @@
|
||||
|
||||
package engine.devcmd.cmds;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.devcmd.AbstractDevCmd;
|
||||
import engine.gameManager.PowersManager;
|
||||
import engine.mobileAI.MobAI;
|
||||
import engine.objects.AbstractGameObject;
|
||||
import engine.objects.Mob;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import engine.powers.RunePowerEntry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@@ -61,95 +56,36 @@ public class aiInfoCmd extends AbstractDevCmd {
|
||||
Mob mob = (Mob) target;
|
||||
output = "Mob AI Information:" + newline;
|
||||
output += mob.getName() + newline;
|
||||
output += mob.agentType.toString() + newline;
|
||||
|
||||
int contractID = 0;
|
||||
|
||||
if (mob.isPlayerGuard() == true) {
|
||||
|
||||
if (mob.agentType.equals(Enum.AIAgentType.GUARDMINION))
|
||||
contractID = mob.guardCaptain.contract.getContractID();
|
||||
else
|
||||
contractID = mob.contract.getContractID();
|
||||
}
|
||||
|
||||
if (contractID != 0) {
|
||||
|
||||
if (mob.agentType.equals(Enum.AIAgentType.GUARDMINION)) {
|
||||
output += "Captain Contract: " + contractID + newline;
|
||||
output += "Captain UUID: " + mob.guardCaptain.getObjectUUID() + newline;
|
||||
} else
|
||||
output += "Contract: " + contractID + newline;
|
||||
}
|
||||
|
||||
if (mob.behaviourType != null) {
|
||||
output += "BehaviourType: " + mob.behaviourType.toString() + newline;
|
||||
if (mob.behaviourType.BehaviourHelperType != null) {
|
||||
output += "Behaviour Helper Type: " + mob.behaviourType.BehaviourHelperType.toString() + newline;
|
||||
if (mob.BehaviourType != null) {
|
||||
output += "BehaviourType: " + mob.BehaviourType.toString() + newline;
|
||||
if (mob.BehaviourType.BehaviourHelperType != null) {
|
||||
output += "Behaviour Helper Type: " + mob.BehaviourType.BehaviourHelperType.toString() + newline;
|
||||
} else {
|
||||
output += "Behaviour Helper Type: NULL" + newline;
|
||||
}
|
||||
output += "Wimpy: " + mob.behaviourType.isWimpy + newline;
|
||||
output += "Agressive: " + mob.behaviourType.isAgressive + newline;
|
||||
output += "Can Roam: " + mob.behaviourType.canRoam + newline;
|
||||
output += "Calls For Help: " + mob.behaviourType.callsForHelp + newline;
|
||||
output += "Responds To Call For Help: " + mob.behaviourType.respondsToCallForHelp + newline;
|
||||
} else {
|
||||
output += "BehaviourType: NULL" + newline;
|
||||
}
|
||||
output += "Wimpy: " + mob.BehaviourType.isWimpy + newline;
|
||||
output += "Agressive: " + mob.BehaviourType.isAgressive + newline;
|
||||
output += "Can Roam: " + mob.BehaviourType.canRoam + newline;
|
||||
output += "Calls For Help: " + mob.BehaviourType.callsForHelp + newline;
|
||||
output += "Responds To Call For Help: " + mob.BehaviourType.respondsToCallForHelp + newline;
|
||||
} else {
|
||||
output += "BehaviourType: NULL" + newline;
|
||||
}
|
||||
output += "Aggro Range: " + mob.getAggroRange() + newline;
|
||||
output += "Player Aggro Map Size: " + mob.playerAgroMap.size() + newline;
|
||||
if (mob.playerAgroMap.size() > 0) {
|
||||
output += "Players Loaded:" + newline;
|
||||
}
|
||||
for (Map.Entry<Integer, Float> entry : mob.playerAgroMap.entrySet()) {
|
||||
output += "Player ID: " + entry.getKey() + " Hate Value: " + entry.getValue() + newline;
|
||||
for (Map.Entry<Integer, Boolean> entry : mob.playerAgroMap.entrySet()) {
|
||||
output += "Player ID: " + entry.getKey() + " Hate Value: " + (PlayerCharacter.getPlayerCharacter(entry.getKey())).getHateValue() + newline;
|
||||
}
|
||||
if (mob.getCombatTarget() != null)
|
||||
output += "Current Target: " + mob.getCombatTarget().getName() + newline;
|
||||
else
|
||||
output += "Current Target: NULL" + newline;
|
||||
|
||||
if (mob.guardedCity != null)
|
||||
output += "Patrolling: " + mob.guardedCity.getCityName() + newline;
|
||||
output += "See Invis Level: " + mob.mobBase.getSeeInvis() + newline;
|
||||
output += "Can Cast: " + MobAI.canCast(mob) + newline;
|
||||
output += "Powers:" + newline;
|
||||
|
||||
ArrayList<RunePowerEntry> powerEntries = new ArrayList<>(PowersManager.getPowersForRune(mob.getMobBaseID()));
|
||||
|
||||
// Additional powers may come from the contract ID. This is to support
|
||||
// powers for player guards irrespective of the mobbase used.
|
||||
|
||||
if (mob.isPlayerGuard()) {
|
||||
|
||||
ArrayList<RunePowerEntry> contractEntries = new ArrayList<>();
|
||||
|
||||
if (mob.contract != null)
|
||||
contractEntries = new ArrayList<>(PowersManager.getPowersForRune(mob.contractUUID));
|
||||
|
||||
if (mob.agentType.equals(Enum.AIAgentType.GUARDMINION))
|
||||
contractEntries = new ArrayList<>(PowersManager.getPowersForRune(mob.guardCaptain.contractUUID));
|
||||
|
||||
powerEntries.addAll(contractEntries);
|
||||
|
||||
}
|
||||
|
||||
for (RunePowerEntry runePowerEntry : powerEntries)
|
||||
output += PowersManager.getPowerByToken(runePowerEntry.token).getName() + newline;
|
||||
|
||||
// List outlaws defined for this player guard's city
|
||||
|
||||
if (mob.isPlayerGuard()) {
|
||||
|
||||
ArrayList<Integer> outlaws = new ArrayList(mob.guardedCity.cityOutlaws);
|
||||
|
||||
if (outlaws.isEmpty() == false)
|
||||
output += "Outlaws: " + newline;
|
||||
|
||||
for (Integer outlawUUID : outlaws)
|
||||
output += outlawUUID + newline;
|
||||
}
|
||||
for (int token : mob.mobPowers.keySet())
|
||||
output += token + newline;
|
||||
|
||||
throwbackInfo(playerCharacter, output);
|
||||
}
|
||||
|
||||
+87
@@ -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 |
|
||||
+63
@@ -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 |
|
||||
+73
@@ -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`)
|
||||
+119
@@ -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
|
||||
|
||||
+43
@@ -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 |
|
||||
+98
@@ -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 |
|
||||
+61
@@ -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 |
|
||||
+77
@@ -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 |
|
||||
+71
@@ -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 |
|
||||
+63
@@ -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 |
|
||||
+71
@@ -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 |
|
||||
+97
@@ -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 |
|
||||
+82
@@ -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 |
|
||||
+57
@@ -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 |
|
||||
+40
@@ -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 |
|
||||
+46
@@ -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 |
|
||||
+118
@@ -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 |
|
||||
+42
@@ -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 |
|
||||
+71
@@ -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 |
|
||||
+64
@@ -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 |
|
||||
+91
@@ -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 |
|
||||
+49
@@ -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 |
|
||||
+83
@@ -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 |
|
||||
+66
@@ -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 |
|
||||
+72
@@ -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 |
|
||||
+149
@@ -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 |
|
||||
+81
@@ -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
|
||||
+77
@@ -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
|
||||
+45
@@ -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 |
|
||||
+78
@@ -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
|
||||
+69
@@ -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
|
||||
+77
@@ -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
|
||||
+77
@@ -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
|
||||
+76
@@ -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
|
||||
+78
@@ -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
|
||||
+78
@@ -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
|
||||
+81
@@ -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
|
||||
+75
@@ -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
|
||||
+72
@@ -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
|
||||
+83
@@ -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/`
|
||||
@@ -308,72 +308,6 @@ public enum BuildingManager {
|
||||
|
||||
}
|
||||
|
||||
public static void removeHireling(Building building, AbstractCharacter hireling) {
|
||||
|
||||
if (hireling.getObjectType().equals(GameObjectType.Mob)) {
|
||||
|
||||
Mob guardCaptain = (Mob) hireling;
|
||||
|
||||
// Clear minions from database if a guard captain
|
||||
|
||||
if (guardCaptain.agentType.equals(Enum.AIAgentType.GUARDCAPTAIN))
|
||||
DbManager.MobQueries.REMOVE_ALL_MINIONS(hireling.getObjectUUID());
|
||||
}
|
||||
|
||||
// Clear minions from world
|
||||
|
||||
for (Integer minionUUID : hireling.minions) {
|
||||
Mob minionMob = Mob.getMob(minionUUID);
|
||||
DbManager.removeFromCache(minionMob);
|
||||
WorldGrid.RemoveWorldObject(minionMob);
|
||||
WorldGrid.unloadObject(minionMob);
|
||||
|
||||
if (minionMob.getParentZone() != null)
|
||||
minionMob.getParentZone().zoneMobSet.remove(minionMob);
|
||||
}
|
||||
|
||||
// Remove hireling from building
|
||||
|
||||
building.getHirelings().remove(hireling);
|
||||
|
||||
// Remove from zone mob set
|
||||
|
||||
if (hireling.getObjectType().equals(GameObjectType.Mob)) {
|
||||
|
||||
Mob hirelingMob = (Mob) hireling;
|
||||
|
||||
if (hirelingMob.getParentZone() != null)
|
||||
if (hirelingMob.getParentZone().zoneMobSet.contains(hirelingMob))
|
||||
hirelingMob.getParentZone().zoneMobSet.remove(hireling);
|
||||
|
||||
}
|
||||
|
||||
if (hireling.getObjectType().equals(GameObjectType.NPC)) {
|
||||
|
||||
NPC hirelingNPC = (NPC) hireling;
|
||||
|
||||
if (hirelingNPC.getParentZone() != null)
|
||||
if (hirelingNPC.getParentZone().zoneNPCSet.contains(hirelingNPC))
|
||||
hirelingNPC.getParentZone().zoneNPCSet.remove(hireling);
|
||||
|
||||
}
|
||||
|
||||
// Unload hireling from world
|
||||
|
||||
DbManager.removeFromCache(hireling);
|
||||
WorldGrid.RemoveWorldObject(hireling);
|
||||
WorldGrid.removeObject(hireling);
|
||||
|
||||
// Delete hireling from database
|
||||
|
||||
if (hireling.getObjectType().equals(GameObjectType.Mob))
|
||||
DbManager.MobQueries.DELETE_MOB((Mob) hireling);
|
||||
else
|
||||
DbManager.NPCQueries.DELETE_NPC((NPC) hireling);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void cleanupHirelings(Building building) {
|
||||
|
||||
// Early exit: Cannot have hirelings in a building
|
||||
@@ -386,18 +320,42 @@ public enum BuildingManager {
|
||||
|
||||
if (building.getRank() < 1) {
|
||||
|
||||
for (AbstractCharacter slottedNPC : building.getHirelings().keySet())
|
||||
BuildingManager.removeHireling(building, slottedNPC);
|
||||
for (AbstractCharacter slottedNPC : building.getHirelings().keySet()) {
|
||||
|
||||
if (slottedNPC.getObjectType() == Enum.GameObjectType.NPC)
|
||||
((NPC) slottedNPC).remove();
|
||||
else if (slottedNPC.getObjectType() == Enum.GameObjectType.Mob)
|
||||
NPCManager.removeMobileFromBuilding(((Mob) slottedNPC), building);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete hireling if building has deranked.
|
||||
|
||||
for (AbstractCharacter hireling : building.getHirelings().keySet()) {
|
||||
|
||||
NPC npc = null;
|
||||
Mob mob = null;
|
||||
|
||||
if (hireling.getObjectType() == Enum.GameObjectType.NPC)
|
||||
npc = (NPC) hireling;
|
||||
else if (hireling.getObjectType() == Enum.GameObjectType.Mob)
|
||||
mob = (Mob) hireling;
|
||||
|
||||
if (building.getHirelings().get(hireling) > building.getBlueprint().getSlotsForRank(building.getRank()))
|
||||
BuildingManager.removeHireling(building, hireling);
|
||||
|
||||
if (npc != null) {
|
||||
if (!npc.remove())
|
||||
Logger.error("Failed to remove npc " + npc.getObjectUUID()
|
||||
+ "from Building " + building.getObjectUUID());
|
||||
else
|
||||
building.getHirelings().remove(npc);
|
||||
} else if (mob != null) {
|
||||
if (!NPCManager.removeMobileFromBuilding(mob, building))
|
||||
Logger.error("Failed to remove npc " + npc.getObjectUUID()
|
||||
+ "from Building " + building.getObjectUUID());
|
||||
else
|
||||
building.getHirelings().remove(npc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -572,63 +530,41 @@ public enum BuildingManager {
|
||||
else
|
||||
rank = 10;
|
||||
|
||||
Mob mobile;
|
||||
Mob mob;
|
||||
NPC npc;
|
||||
|
||||
if (NPC.ISWallArcher(contract)) {
|
||||
|
||||
mobile = Mob.createMob(contract.getMobbaseID(), Vector3fImmutable.ZERO, contractOwner.getGuild(), zone, building, contract, pirateName, rank, Enum.AIAgentType.GUARDWALLARCHER);
|
||||
mob = Mob.createMob(contract.getMobbaseID(), Vector3fImmutable.ZERO, contractOwner.getGuild(), true, zone, building, contract.getContractID(), pirateName, rank);
|
||||
|
||||
if (mobile == null)
|
||||
if (mob == null)
|
||||
return false;
|
||||
|
||||
// Configure AI and write new mobile to disk
|
||||
|
||||
mobile.behaviourType = Enum.MobBehaviourType.GuardWallArcher;
|
||||
mobile = DbManager.MobQueries.PERSIST(mobile);
|
||||
|
||||
// Spawn new mobile
|
||||
|
||||
mobile.setLoc(mobile.getLoc());
|
||||
mob.setLoc(mob.getLoc());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NPC.ISGuardCaptain(contract.getContractID())) {
|
||||
|
||||
mobile = Mob.createMob(contract.getMobbaseID(), Vector3fImmutable.ZERO, contractOwner.getGuild(), zone, building, contract, pirateName, rank, Enum.AIAgentType.GUARDCAPTAIN);
|
||||
mob = Mob.createMob(contract.getMobbaseID(), Vector3fImmutable.ZERO, contractOwner.getGuild(), true, zone, building, contract.getContractID(), pirateName, rank);
|
||||
|
||||
if (mobile == null)
|
||||
if (mob == null)
|
||||
return false;
|
||||
|
||||
// Configure AI and write new mobile to disk
|
||||
|
||||
mobile.behaviourType = Enum.MobBehaviourType.GuardCaptain;
|
||||
mobile = DbManager.MobQueries.PERSIST(mobile);
|
||||
|
||||
// Spawn new mobile
|
||||
|
||||
mobile.setLoc(mobile.getLoc());
|
||||
mob.setLoc(mob.getLoc());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (contract.getContractID() == 910) {
|
||||
|
||||
//guard dog
|
||||
mobile = Mob.createMob(contract.getMobbaseID(), Vector3fImmutable.ZERO, contractOwner.getGuild(), zone, building, contract, pirateName, rank, Enum.AIAgentType.GUARDCAPTAIN);
|
||||
mob = Mob.createMob(contract.getMobbaseID(), Vector3fImmutable.ZERO, contractOwner.getGuild(), true, zone, building, contract.getContractID(), pirateName, rank);
|
||||
|
||||
if (mobile == null)
|
||||
if (mob == null)
|
||||
return false;
|
||||
|
||||
// Configure AI and write new mobile to disk
|
||||
|
||||
mobile.behaviourType = Enum.MobBehaviourType.GuardCaptain;
|
||||
mobile = DbManager.MobQueries.PERSIST(mobile);
|
||||
|
||||
// Spawn new mobile
|
||||
|
||||
mobile.setLoc(mobile.getLoc());
|
||||
mob.setLoc(mob.getLoc());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -788,7 +788,7 @@ public enum ChatManager {
|
||||
it.remove();
|
||||
else {
|
||||
PlayerCharacter pcc = (PlayerCharacter) awo;
|
||||
if (pcc.getSeeInvis() < pc.hidden)
|
||||
if (pcc.getSeeInvis() < pc.getHidden())
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ import java.util.HashSet;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
import static engine.math.FastMath.sqr;
|
||||
|
||||
public enum CombatManager {
|
||||
|
||||
COMBATMANAGER;
|
||||
@@ -39,6 +41,63 @@ public enum CombatManager {
|
||||
/**
|
||||
* Message sent by player to attack something.
|
||||
*/
|
||||
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 == GameObjectType.PlayerCharacter.ordinal()) {
|
||||
target = PlayerCharacter.getFromCache(msg.getTargetID());
|
||||
} else if (targetType == GameObjectType.Building.ordinal()) {
|
||||
target = BuildingManager.getBuildingFromCache(msg.getTargetID());
|
||||
} else if (targetType == 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);
|
||||
|
||||
//put in combat if not already
|
||||
|
||||
if (!player.isCombat())
|
||||
toggleCombat(true, origin);
|
||||
|
||||
//make character stand if sitting
|
||||
|
||||
if (player.isSit())
|
||||
toggleSit(false, origin);
|
||||
|
||||
AttackTarget(player, target);
|
||||
|
||||
}
|
||||
|
||||
public static void AttackTarget(PlayerCharacter playerCharacter, AbstractWorldObject target) {
|
||||
|
||||
@@ -82,6 +141,11 @@ public enum CombatManager {
|
||||
if (off == null)
|
||||
CombatManager.createTimer(playerCharacter, MBServerStatics.SLOT_OFFHAND, 1, true); // attack in 0.1 of a second
|
||||
}
|
||||
|
||||
City playerCity = ZoneManager.getCityAtLocation(playerCharacter.getLoc());
|
||||
|
||||
if (playerCity != null && playerCity.getGuild().getNation().equals(playerCharacter.getGuild().getNation()) == false && playerCity.cityOutlaws.contains(playerCharacter.getObjectUUID()) == false)
|
||||
playerCity.cityOutlaws.add(playerCharacter.getObjectUUID());
|
||||
}
|
||||
|
||||
public static void setAttackTarget(PetAttackMsg msg, ClientConnection origin) throws MsgSendException {
|
||||
@@ -459,7 +523,7 @@ public enum CombatManager {
|
||||
/**
|
||||
* Attempt to attack target
|
||||
*/
|
||||
private static void attack(AbstractCharacter attacker, AbstractWorldObject target, Item weapon, ItemBase wb, boolean mainHand) {
|
||||
private static void attack(AbstractCharacter ac, AbstractWorldObject target, Item weapon, ItemBase wb, boolean mainHand) {
|
||||
|
||||
float atr;
|
||||
int minDamage, maxDamage;
|
||||
@@ -467,20 +531,20 @@ public enum CombatManager {
|
||||
|
||||
try {
|
||||
|
||||
if (attacker == null)
|
||||
if (ac == null)
|
||||
return;
|
||||
|
||||
if (target == null)
|
||||
return;
|
||||
|
||||
if (mainHand) {
|
||||
atr = attacker.getAtrHandOne();
|
||||
minDamage = attacker.getMinDamageHandOne();
|
||||
maxDamage = attacker.getMaxDamageHandOne();
|
||||
atr = ac.getAtrHandOne();
|
||||
minDamage = ac.getMinDamageHandOne();
|
||||
maxDamage = ac.getMaxDamageHandOne();
|
||||
} else {
|
||||
atr = attacker.getAtrHandTwo();
|
||||
minDamage = attacker.getMinDamageHandTwo();
|
||||
maxDamage = attacker.getMaxDamageHandTwo();
|
||||
atr = ac.getAtrHandTwo();
|
||||
minDamage = ac.getMinDamageHandTwo();
|
||||
maxDamage = ac.getMaxDamageHandTwo();
|
||||
}
|
||||
|
||||
boolean tarIsRat = false;
|
||||
@@ -499,9 +563,9 @@ public enum CombatManager {
|
||||
//Dont think we need to do this anymore.
|
||||
|
||||
if (tarIsRat)
|
||||
if (attacker.getBonuses().getFloatPercentAll(ModType.Slay, SourceType.Rat) != 0) { //strip away current % dmg buffs then add with rat %
|
||||
if (ac.getBonuses().getFloatPercentAll(ModType.Slay, SourceType.Rat) != 0) { //strip away current % dmg buffs then add with rat %
|
||||
|
||||
float percent = 1 + attacker.getBonuses().getFloatPercentAll(ModType.Slay, SourceType.Rat);
|
||||
float percent = 1 + ac.getBonuses().getFloatPercentAll(ModType.Slay, SourceType.Rat);
|
||||
|
||||
minDamage *= percent;
|
||||
maxDamage *= percent;
|
||||
@@ -512,24 +576,24 @@ public enum CombatManager {
|
||||
//subtract stamina
|
||||
|
||||
if (wb == null)
|
||||
attacker.modifyStamina(-0.5f, attacker, true);
|
||||
ac.modifyStamina(-0.5f, ac, true);
|
||||
else {
|
||||
float stam = wb.getWeight() / 3;
|
||||
stam = (stam < 1) ? 1 : stam;
|
||||
attacker.modifyStamina(-(stam), attacker, true);
|
||||
ac.modifyStamina(-(stam), ac, true);
|
||||
}
|
||||
|
||||
attacker.cancelOnAttackSwing();
|
||||
ac.cancelOnAttackSwing();
|
||||
|
||||
errorTrack = 2;
|
||||
|
||||
//set last time this player has attacked something.
|
||||
|
||||
if (target.getObjectType().equals(GameObjectType.PlayerCharacter) && target.getObjectUUID() != attacker.getObjectUUID() && attacker.getObjectType() == GameObjectType.PlayerCharacter) {
|
||||
attacker.setTimeStamp("LastCombatPlayer", System.currentTimeMillis());
|
||||
if (target.getObjectType().equals(GameObjectType.PlayerCharacter) && target.getObjectUUID() != ac.getObjectUUID() && ac.getObjectType() == GameObjectType.PlayerCharacter) {
|
||||
ac.setTimeStamp("LastCombatPlayer", System.currentTimeMillis());
|
||||
((PlayerCharacter) target).setTimeStamp("LastCombatPlayer", System.currentTimeMillis());
|
||||
} else
|
||||
attacker.setTimeStamp("LastCombatMob", System.currentTimeMillis());
|
||||
ac.setTimeStamp("LastCombatMob", System.currentTimeMillis());
|
||||
|
||||
errorTrack = 3;
|
||||
|
||||
@@ -540,16 +604,42 @@ public enum CombatManager {
|
||||
if (target.getObjectType().equals(GameObjectType.Building)) {
|
||||
|
||||
if (BuildingManager.getBuildingFromCache(target.getObjectUUID()) == null) {
|
||||
attacker.setCombatTarget(null);
|
||||
ac.setCombatTarget(null);
|
||||
return;
|
||||
}
|
||||
|
||||
defense = 0;
|
||||
|
||||
Building building = (Building) target;
|
||||
|
||||
if (building.getParentZone() != null && building.getParentZone().isPlayerCity()) {
|
||||
|
||||
if (System.currentTimeMillis() > building.getTimeStamp("CallForHelp")) {
|
||||
|
||||
building.getTimestamps().put("CallForHelp", System.currentTimeMillis() + 15000);
|
||||
|
||||
for (Mob mob : building.getParentZone().zoneMobSet) {
|
||||
if (!mob.isPlayerGuard())
|
||||
continue;
|
||||
|
||||
if (mob.getCombatTarget() != null)
|
||||
continue;
|
||||
|
||||
if (mob.getGuild() != null && building.getGuild() != null)
|
||||
if (!Guild.sameGuild(mob.getGuild().getNation(), building.getGuild().getNation()))
|
||||
continue;
|
||||
|
||||
if (mob.getLoc().distanceSquared2D(building.getLoc()) > sqr(300))
|
||||
continue;
|
||||
|
||||
mob.setCombatTarget(ac);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
AbstractCharacter tar = (AbstractCharacter) target;
|
||||
defense = tar.getDefenseRating();
|
||||
handleRetaliate(tar, attacker); //Handle target attacking back if in combat and has no other target
|
||||
handleRetaliate(tar, ac); //Handle target attacking back if in combat and has no other target
|
||||
}
|
||||
|
||||
errorTrack = 4;
|
||||
@@ -575,11 +665,11 @@ public enum CombatManager {
|
||||
|
||||
if (roll < chance) {
|
||||
|
||||
if (attacker.getObjectType().equals(GameObjectType.PlayerCharacter))
|
||||
updateAttackTimers((PlayerCharacter) attacker, target, true);
|
||||
if (ac.getObjectType().equals(GameObjectType.PlayerCharacter))
|
||||
updateAttackTimers((PlayerCharacter) ac, target, true);
|
||||
|
||||
boolean skipPassives = false;
|
||||
PlayerBonuses bonuses = attacker.getBonuses();
|
||||
PlayerBonuses bonuses = ac.getBonuses();
|
||||
|
||||
if (bonuses != null && bonuses.getBool(ModType.IgnorePassiveDefense, SourceType.None))
|
||||
skipPassives = true;
|
||||
@@ -594,26 +684,26 @@ public enum CombatManager {
|
||||
// Apply Weapon power effect if any. don't try to apply twice if
|
||||
// dual wielding. Perform after passive test for sync purposes.
|
||||
|
||||
if (attacker.getObjectType().equals(GameObjectType.PlayerCharacter) && (mainHand || wb.isTwoHanded())) {
|
||||
if (ac.getObjectType().equals(GameObjectType.PlayerCharacter) && (mainHand || wb.isTwoHanded())) {
|
||||
|
||||
dpj = ((PlayerCharacter) attacker).getWeaponPower();
|
||||
dpj = ((PlayerCharacter) ac).getWeaponPower();
|
||||
|
||||
if (dpj != null) {
|
||||
|
||||
PlayerBonuses bonus = attacker.getBonuses();
|
||||
PlayerBonuses bonus = ac.getBonuses();
|
||||
float attackRange = getWeaponRange(wb, bonus);
|
||||
dpj.attack(target, attackRange);
|
||||
|
||||
if (dpj.getPower() != null && (dpj.getPowerToken() == -1851459567 || dpj.getPowerToken() == -1851489518))
|
||||
((PlayerCharacter) attacker).setWeaponPower(dpj);
|
||||
((PlayerCharacter) ac).setWeaponPower(dpj);
|
||||
}
|
||||
}
|
||||
|
||||
//check to apply second backstab.
|
||||
|
||||
if (attacker.getObjectType().equals(GameObjectType.PlayerCharacter) && !mainHand) {
|
||||
if (ac.getObjectType().equals(GameObjectType.PlayerCharacter) && !mainHand) {
|
||||
|
||||
dpj = ((PlayerCharacter) attacker).getWeaponPower();
|
||||
dpj = ((PlayerCharacter) ac).getWeaponPower();
|
||||
|
||||
if (dpj != null && dpj.getPower() != null && (dpj.getPowerToken() == -1851459567 || dpj.getPowerToken() == -1851489518)) {
|
||||
float attackRange = getWeaponRange(wb, bonuses);
|
||||
@@ -633,24 +723,24 @@ public enum CombatManager {
|
||||
|
||||
//Handle Block passive
|
||||
|
||||
if (testPassive(attacker, tarAc, "Block") && canTestBlock(attacker, target)) {
|
||||
if (testPassive(ac, tarAc, "Block") && canTestBlock(ac, target)) {
|
||||
|
||||
if (!target.isAlive())
|
||||
return;
|
||||
|
||||
sendPassiveDefenseMessage(attacker, wb, target, MBServerStatics.COMBAT_SEND_BLOCK, dpj, mainHand);
|
||||
sendPassiveDefenseMessage(ac, wb, target, MBServerStatics.COMBAT_SEND_BLOCK, dpj, mainHand);
|
||||
passiveFired = true;
|
||||
}
|
||||
|
||||
//Handle Parry passive
|
||||
|
||||
if (!passiveFired)
|
||||
if (canTestParry(attacker, target) && testPassive(attacker, tarAc, "Parry")) {
|
||||
if (canTestParry(ac, target) && testPassive(ac, tarAc, "Parry")) {
|
||||
|
||||
if (!target.isAlive())
|
||||
return;
|
||||
|
||||
sendPassiveDefenseMessage(attacker, wb, target, MBServerStatics.COMBAT_SEND_PARRY, dpj, mainHand);
|
||||
sendPassiveDefenseMessage(ac, wb, target, MBServerStatics.COMBAT_SEND_PARRY, dpj, mainHand);
|
||||
passiveFired = true;
|
||||
}
|
||||
|
||||
@@ -661,12 +751,12 @@ public enum CombatManager {
|
||||
//Handle Dodge passive
|
||||
|
||||
if (!passiveFired)
|
||||
if (testPassive(attacker, tarAc, "Dodge")) {
|
||||
if (testPassive(ac, tarAc, "Dodge")) {
|
||||
|
||||
if (!target.isAlive())
|
||||
return;
|
||||
|
||||
sendPassiveDefenseMessage(attacker, wb, target, MBServerStatics.COMBAT_SEND_DODGE, dpj, mainHand);
|
||||
sendPassiveDefenseMessage(ac, wb, target, MBServerStatics.COMBAT_SEND_DODGE, dpj, mainHand);
|
||||
passiveFired = true;
|
||||
}
|
||||
}
|
||||
@@ -682,7 +772,7 @@ public enum CombatManager {
|
||||
//if target is player, set last attack timestamp
|
||||
|
||||
if (target.getObjectType().equals(GameObjectType.PlayerCharacter))
|
||||
updateAttackTimers((PlayerCharacter) target, attacker, false);
|
||||
updateAttackTimers((PlayerCharacter) target, ac, false);
|
||||
|
||||
//Get damage Type
|
||||
|
||||
@@ -690,7 +780,7 @@ public enum CombatManager {
|
||||
|
||||
if (wb != null)
|
||||
damageType = wb.getDamageType();
|
||||
else if (attacker.getObjectType().equals(GameObjectType.Mob) && ((Mob) attacker).isSiege())
|
||||
else if (ac.getObjectType().equals(GameObjectType.Mob) && ((Mob) ac).isSiege())
|
||||
damageType = DamageType.Siege;
|
||||
else
|
||||
damageType = DamageType.Crush;
|
||||
@@ -709,7 +799,7 @@ public enum CombatManager {
|
||||
//make sure target is not immune to damage type;
|
||||
|
||||
if (resists != null && resists.immuneTo(damageType)) {
|
||||
sendCombatMessage(attacker, target, 0f, wb, dpj, mainHand);
|
||||
sendCombatMessage(ac, target, 0f, wb, dpj, mainHand);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -720,9 +810,9 @@ public enum CombatManager {
|
||||
float damage;
|
||||
|
||||
if (wb != null)
|
||||
damage = calculateDamage(attacker, tarAc, minDamage, maxDamage, damageType, resists);
|
||||
damage = calculateDamage(ac, tarAc, minDamage, maxDamage, damageType, resists);
|
||||
else
|
||||
damage = calculateDamage(attacker, tarAc, minDamage, maxDamage, damageType, resists);
|
||||
damage = calculateDamage(ac, tarAc, minDamage, maxDamage, damageType, resists);
|
||||
|
||||
float d = 0f;
|
||||
|
||||
@@ -735,35 +825,40 @@ public enum CombatManager {
|
||||
if (tarAc.isSit())
|
||||
damage *= 2.5f; //increase damage if sitting
|
||||
|
||||
if (tarAc.getObjectType() == GameObjectType.Mob) {
|
||||
ac.setHateValue(damage * MBServerStatics.PLAYER_COMBAT_HATE_MODIFIER);
|
||||
((Mob) tarAc).handleDirectAggro(ac);
|
||||
}
|
||||
|
||||
if (tarAc.getHealth() > 0)
|
||||
d = tarAc.modifyHealth(-damage, attacker, false);
|
||||
d = tarAc.modifyHealth(-damage, ac, false);
|
||||
|
||||
} else if (target.getObjectType().equals(GameObjectType.Building)) {
|
||||
|
||||
if (BuildingManager.getBuildingFromCache(target.getObjectUUID()) == null) {
|
||||
attacker.setCombatTarget(null);
|
||||
ac.setCombatTarget(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (target.getHealth() > 0)
|
||||
d = ((Building) target).modifyHealth(-damage, attacker);
|
||||
d = ((Building) target).modifyHealth(-damage, ac);
|
||||
}
|
||||
|
||||
errorTrack = 13;
|
||||
|
||||
//Test to see if any damage needs done to weapon or armor
|
||||
|
||||
testItemDamage(attacker, target, weapon, wb);
|
||||
testItemDamage(ac, target, weapon, wb);
|
||||
|
||||
// if target is dead, we got the killing blow, remove attack timers on our weapons
|
||||
|
||||
if (tarAc != null && !tarAc.isAlive())
|
||||
removeAttackTimers(attacker);
|
||||
removeAttackTimers(ac);
|
||||
|
||||
//test double death fix
|
||||
|
||||
if (d != 0)
|
||||
sendCombatMessage(attacker, target, damage, wb, dpj, mainHand); //send damage message
|
||||
sendCombatMessage(ac, target, damage, wb, dpj, mainHand); //send damage message
|
||||
|
||||
errorTrack = 14;
|
||||
|
||||
@@ -790,7 +885,7 @@ public enum CombatManager {
|
||||
int procChance = ThreadLocalRandom.current().nextInt(100);
|
||||
|
||||
if (procChance < MBServerStatics.PROC_CHANCE)
|
||||
((WeaponProcEffectModifier) aem).applyProc(attacker, target);
|
||||
((WeaponProcEffectModifier) aem).applyProc(ac, target);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -802,52 +897,52 @@ public enum CombatManager {
|
||||
|
||||
//handle damage shields
|
||||
|
||||
if (attacker.isAlive() && tarAc != null && tarAc.isAlive())
|
||||
handleDamageShields(attacker, tarAc, damage);
|
||||
if (ac.isAlive() && tarAc != null && tarAc.isAlive())
|
||||
handleDamageShields(ac, tarAc, damage);
|
||||
|
||||
} else {
|
||||
|
||||
// Apply Weapon power effect if any.
|
||||
// don't try to apply twice if dual wielding.
|
||||
|
||||
if (attacker.getObjectType().equals(GameObjectType.PlayerCharacter) && (mainHand || wb.isTwoHanded())) {
|
||||
dpj = ((PlayerCharacter) attacker).getWeaponPower();
|
||||
if (ac.getObjectType().equals(GameObjectType.PlayerCharacter) && (mainHand || wb.isTwoHanded())) {
|
||||
dpj = ((PlayerCharacter) ac).getWeaponPower();
|
||||
|
||||
if (dpj != null) {
|
||||
|
||||
PowersBase wp = dpj.getPower();
|
||||
|
||||
if (wp.requiresHitRoll() == false) {
|
||||
PlayerBonuses bonus = attacker.getBonuses();
|
||||
PlayerBonuses bonus = ac.getBonuses();
|
||||
float attackRange = getWeaponRange(wb, bonus);
|
||||
dpj.attack(target, attackRange);
|
||||
} else
|
||||
((PlayerCharacter) attacker).setWeaponPower(null);
|
||||
((PlayerCharacter) ac).setWeaponPower(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (target.getObjectType() == GameObjectType.Mob)
|
||||
((Mob) target).handleDirectAggro(attacker);
|
||||
((Mob) target).handleDirectAggro(ac);
|
||||
|
||||
errorTrack = 17;
|
||||
|
||||
//miss, Send miss message
|
||||
|
||||
sendCombatMessage(attacker, target, 0f, wb, dpj, mainHand);
|
||||
sendCombatMessage(ac, target, 0f, wb, dpj, mainHand);
|
||||
|
||||
//if attacker is player, set last attack timestamp
|
||||
|
||||
if (attacker.getObjectType().equals(GameObjectType.PlayerCharacter))
|
||||
updateAttackTimers((PlayerCharacter) attacker, target, true);
|
||||
if (ac.getObjectType().equals(GameObjectType.PlayerCharacter))
|
||||
updateAttackTimers((PlayerCharacter) ac, target, true);
|
||||
}
|
||||
|
||||
errorTrack = 18;
|
||||
|
||||
//cancel effects that break on attack or attackSwing
|
||||
attacker.cancelOnAttack();
|
||||
ac.cancelOnAttack();
|
||||
|
||||
} catch (Exception e) {
|
||||
Logger.error(attacker.getName() + ' ' + errorTrack + ' ' + e);
|
||||
Logger.error(ac.getName() + ' ' + errorTrack + ' ' + e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1125,7 +1220,7 @@ public enum CombatManager {
|
||||
toggleCombat(msg.getToggle(), origin);
|
||||
}
|
||||
|
||||
public static void toggleCombat(boolean toggle, ClientConnection origin) {
|
||||
private static void toggleCombat(boolean toggle, ClientConnection origin) {
|
||||
|
||||
PlayerCharacter pc = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
@@ -1142,7 +1237,7 @@ 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);
|
||||
|
||||
@@ -1172,69 +1267,61 @@ public enum CombatManager {
|
||||
}
|
||||
|
||||
//Called when character takes damage.
|
||||
public static void handleRetaliate(AbstractCharacter target, AbstractCharacter attacker) {
|
||||
public static void handleRetaliate(AbstractCharacter tarAc, AbstractCharacter ac) {
|
||||
|
||||
if (attacker == null || target == null)
|
||||
if (ac == null || tarAc == null)
|
||||
return;
|
||||
|
||||
if (attacker.equals(target))
|
||||
if (ac.equals(tarAc))
|
||||
return;
|
||||
|
||||
if (target.isMoving() && target.getObjectType().equals(GameObjectType.PlayerCharacter))
|
||||
if (tarAc.isMoving() && tarAc.getObjectType().equals(GameObjectType.PlayerCharacter))
|
||||
return;
|
||||
|
||||
if (!target.isAlive() || !attacker.isAlive())
|
||||
if (!tarAc.isAlive() || !ac.isAlive())
|
||||
return;
|
||||
|
||||
boolean isCombat = target.isCombat();
|
||||
boolean isCombat = tarAc.isCombat();
|
||||
|
||||
//If target in combat and has no target, then attack back
|
||||
|
||||
AbstractWorldObject awoCombTar = target.getCombatTarget();
|
||||
AbstractWorldObject awoCombTar = tarAc.getCombatTarget();
|
||||
|
||||
if ((target.isCombat() && awoCombTar == null) || (isCombat && awoCombTar != null && (!awoCombTar.isAlive() || target.isCombat() && NotInRange(target, awoCombTar, target.getRange()))) || (target != null && target.getObjectType() == GameObjectType.Mob && ((Mob) target).isSiege()))
|
||||
if (target.getObjectType().equals(GameObjectType.PlayerCharacter)) { // we are in combat with no valid target
|
||||
if ((tarAc.isCombat() && awoCombTar == null) || (isCombat && awoCombTar != null && (!awoCombTar.isAlive() || tarAc.isCombat() && NotInRange(tarAc, awoCombTar, tarAc.getRange()))) || (tarAc != null && tarAc.getObjectType() == GameObjectType.Mob && ((Mob) tarAc).isSiege()))
|
||||
if (tarAc.getObjectType().equals(GameObjectType.PlayerCharacter)) { // we are in combat with no valid target
|
||||
|
||||
PlayerCharacter pc = (PlayerCharacter) target;
|
||||
target.setCombatTarget(attacker);
|
||||
pc.setLastTarget(attacker.getObjectType(), attacker.getObjectUUID());
|
||||
PlayerCharacter pc = (PlayerCharacter) tarAc;
|
||||
tarAc.setCombatTarget(ac);
|
||||
pc.setLastTarget(ac.getObjectType(), ac.getObjectUUID());
|
||||
|
||||
if (target.getTimers() != null)
|
||||
if (!target.getTimers().containsKey("Attack" + MBServerStatics.SLOT_MAINHAND))
|
||||
CombatManager.AttackTarget((PlayerCharacter) target, target.getCombatTarget());
|
||||
if (tarAc.getTimers() != null)
|
||||
if (!tarAc.getTimers().containsKey("Attack" + MBServerStatics.SLOT_MAINHAND))
|
||||
CombatManager.AttackTarget((PlayerCharacter) tarAc, tarAc.getCombatTarget());
|
||||
}
|
||||
|
||||
//Handle pet retaliate if assist is on and pet doesn't have a target.
|
||||
|
||||
if (target.getObjectType().equals(GameObjectType.PlayerCharacter)) {
|
||||
if (tarAc.getObjectType().equals(GameObjectType.PlayerCharacter)) {
|
||||
|
||||
Mob pet = ((PlayerCharacter) target).getPet();
|
||||
Mob pet = ((PlayerCharacter) tarAc).getPet();
|
||||
|
||||
if (pet != null && pet.assist && pet.getCombatTarget() == null)
|
||||
pet.setCombatTarget(attacker);
|
||||
pet.setCombatTarget(ac);
|
||||
}
|
||||
|
||||
//Handle Mob Retaliate.
|
||||
|
||||
if (target.getObjectType() == GameObjectType.Mob) {
|
||||
|
||||
Mob attackedMobile = (Mob) target;
|
||||
|
||||
//handle minion informing his captain of an attack
|
||||
if (tarAc.getObjectType() == GameObjectType.Mob) {
|
||||
|
||||
if (attackedMobile.agentType.equals(AIAgentType.GUARDMINION) && attackedMobile.guardCaptain != null && attackedMobile.guardCaptain.isAlive()) {
|
||||
Mob retaliater = (Mob) tarAc;
|
||||
|
||||
if (attackedMobile.guardCaptain.combatTarget == null)
|
||||
attackedMobile.guardCaptain.setCombatTarget(attacker);
|
||||
|
||||
}
|
||||
|
||||
// Mobile already has a target; don't switch.
|
||||
if (retaliater.getCombatTarget() != null && !retaliater.isSiege())
|
||||
return;
|
||||
|
||||
if (attackedMobile.getCombatTarget() != null && !attackedMobile.isSiege())
|
||||
if (ac.getObjectType() == GameObjectType.Mob && retaliater.isSiege())
|
||||
return;
|
||||
|
||||
attackedMobile.setCombatTarget(attacker);
|
||||
retaliater.setCombatTarget(ac);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,6 +128,7 @@ public enum DevCmdManager {
|
||||
DevCmdManager.registerDevCmd(new SetForceRenameCityCmd());
|
||||
DevCmdManager.registerDevCmd(new GotoObj());
|
||||
DevCmdManager.registerDevCmd(new convertLoc());
|
||||
DevCmdManager.registerDevCmd(new AuditHeightMapCmd());
|
||||
DevCmdManager.registerDevCmd(new UnloadFurnitureCmd());
|
||||
DevCmdManager.registerDevCmd(new SetNpcEquipSetCmd());
|
||||
DevCmdManager.registerDevCmd(new SetBuildingAltitudeCmd());
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package engine.gameManager;
|
||||
|
||||
import engine.loot.WorkOrder;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.DelayQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public enum ForgeManager implements Runnable {
|
||||
|
||||
FORGE_MANAGER;
|
||||
|
||||
private final BlockingQueue<WorkOrder> workQueue = new DelayQueue();
|
||||
public static final AtomicInteger workOrder = new AtomicInteger(0);
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
while (true) {
|
||||
|
||||
try {
|
||||
|
||||
WorkOrder workOrder = workQueue.take();
|
||||
|
||||
// Fulfill workOrder
|
||||
|
||||
for (int i = 0; i < workOrder.slotCount; ++i) {
|
||||
|
||||
// Create workOrder items; one for each slot
|
||||
// assigned to this workOrder.
|
||||
|
||||
// if Prefix and suffix are null random roll item
|
||||
// otherwise roll what was asked for
|
||||
|
||||
workOrder.itemCount = workOrder.itemCount - 1;
|
||||
|
||||
}
|
||||
|
||||
if (workOrder.itemCount == 0) {
|
||||
|
||||
workOrder.runCompleted = true;
|
||||
|
||||
// Remove this workOrder from any slots on vendor
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Resubmit workOrder
|
||||
|
||||
workOrder.completionTime = System.currentTimeMillis() + 10000;
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -116,8 +116,8 @@ public enum MovementManager {
|
||||
|
||||
// if inside a building, convert both locations from the building local reference frame to the world reference frame
|
||||
|
||||
if (msg.getInBuildingUUID() > 0) {
|
||||
Building building = BuildingManager.getBuildingFromCache(msg.getInBuildingUUID());
|
||||
if (msg.getTargetID() > 0) {
|
||||
Building building = BuildingManager.getBuildingFromCache(msg.getTargetID());
|
||||
if (building != null) {
|
||||
|
||||
Vector3fImmutable convertLocEnd = new Vector3fImmutable(ZoneManager.convertLocalToWorld(building, endLocation));
|
||||
@@ -128,8 +128,8 @@ public enum MovementManager {
|
||||
// }
|
||||
// else {
|
||||
toMove.setInBuilding(msg.getInBuilding());
|
||||
toMove.setInFloorID(msg.getInBuildingFloor());
|
||||
toMove.setInBuildingID(msg.getInBuildingUUID());
|
||||
toMove.setInFloorID(msg.getUnknown01());
|
||||
toMove.setInBuildingID(msg.getTargetID());
|
||||
msg.setStartCoord(ZoneManager.convertWorldToLocal(building, toMove.getLoc()));
|
||||
|
||||
if (toMove.getObjectType() == GameObjectType.PlayerCharacter) {
|
||||
@@ -174,9 +174,9 @@ public enum MovementManager {
|
||||
msg.setStartCoord(ZoneManager.convertWorldToLocal(Regions.GetBuildingForRegion(toMove.region), toMove.getLoc()));
|
||||
msg.setEndCoord(ZoneManager.convertWorldToLocal(regionBuilding, endLocation));
|
||||
msg.setInBuilding(toMove.region.level);
|
||||
msg.setInBuildingFloor(toMove.region.room);
|
||||
msg.setStartLocType(GameObjectType.Building.ordinal());
|
||||
msg.setInBuildingUUID(regionBuilding.getObjectUUID());
|
||||
msg.setUnknown01(toMove.region.room);
|
||||
msg.setTargetType(GameObjectType.Building.ordinal());
|
||||
msg.setTargetID(regionBuilding.getObjectUUID());
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -185,8 +185,8 @@ public enum MovementManager {
|
||||
toMove.setInBuilding(-1);
|
||||
msg.setStartCoord(toMove.getLoc());
|
||||
msg.setEndCoord(endLocation);
|
||||
msg.setStartLocType(0);
|
||||
msg.setInBuildingUUID(0);
|
||||
msg.setTargetType(0);
|
||||
msg.setTargetID(0);
|
||||
}
|
||||
|
||||
//checks sync between character and server, if out of sync, teleport player to original position and return.
|
||||
@@ -233,7 +233,7 @@ public enum MovementManager {
|
||||
toMove.cancelOnMove();
|
||||
|
||||
//cancel any attacks for manual move.
|
||||
if ((toMove.getObjectType() == GameObjectType.PlayerCharacter) && msg.getInitiatedFromAttack() == 0)
|
||||
if ((toMove.getObjectType() == GameObjectType.PlayerCharacter) && msg.getUnknown02() == 0)
|
||||
toMove.setCombatTarget(null);
|
||||
|
||||
|
||||
|
||||
@@ -5,17 +5,13 @@ import engine.InterestManagement.WorldGrid;
|
||||
import engine.math.Quaternion;
|
||||
import engine.math.Vector3f;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.mobileAI.MobAI;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.msg.PetMsg;
|
||||
import engine.objects.*;
|
||||
import engine.powers.EffectsBase;
|
||||
import engine.powers.PowersBase;
|
||||
import engine.powers.RuneSkillAdjustEntry;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import javax.smartcardio.ATR;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
@@ -27,6 +23,92 @@ public enum NPCManager {
|
||||
NPC_MANAGER;
|
||||
public static HashMap<Integer, ArrayList<Integer>> _runeSetMap = new HashMap<>();
|
||||
|
||||
public static void LoadAllRuneSets() {
|
||||
_runeSetMap = DbManager.ItemBaseQueries.LOAD_RUNES_FOR_NPC_AND_MOBS();
|
||||
}
|
||||
|
||||
public static void LoadAllBootySets() {
|
||||
LootManager._bootySetMap = DbManager.LootQueries.LOAD_BOOTY_TABLES();
|
||||
}
|
||||
|
||||
public static void applyRuneSetEffects(Mob mob) {
|
||||
|
||||
// Early exit
|
||||
|
||||
if (mob.runeSet == 0)
|
||||
return;
|
||||
|
||||
//Apply all rune effects.
|
||||
|
||||
if (NPCManager._runeSetMap.get(mob.runeSet).contains(252623)) {
|
||||
mob.isPlayerGuard = true;
|
||||
}
|
||||
|
||||
// Only captains have contracts
|
||||
|
||||
if (mob.contract != null || mob.isPlayerGuard)
|
||||
applyEffectsForRune(mob, 252621);
|
||||
|
||||
|
||||
// Apply effects from RuneSet
|
||||
|
||||
if (mob.runeSet != 0)
|
||||
for (int runeID : _runeSetMap.get(mob.runeSet))
|
||||
applyEffectsForRune(mob, runeID);
|
||||
|
||||
// Not sure why but apply Warrior effects for some reason?
|
||||
|
||||
applyEffectsForRune(mob, 2518);
|
||||
}
|
||||
|
||||
public static void applyEffectsForRune(AbstractCharacter character, int runeID) {
|
||||
|
||||
EffectsBase effectsBase;
|
||||
RuneBase sourceRune = RuneBase.getRuneBase(runeID);
|
||||
|
||||
// Race runes are in the runeset but not in runebase for some reason
|
||||
|
||||
if (sourceRune == null)
|
||||
return;
|
||||
|
||||
for (MobBaseEffects mbe : sourceRune.getEffectsList()) {
|
||||
|
||||
effectsBase = PowersManager.getEffectByToken(mbe.getToken());
|
||||
|
||||
if (effectsBase == null) {
|
||||
Logger.info("Mob: " + character.getObjectUUID() + " EffectsBase Null for Token " + mbe.getToken());
|
||||
continue;
|
||||
}
|
||||
|
||||
//check to upgrade effects if needed.
|
||||
if (character.effects.containsKey(Integer.toString(effectsBase.getUUID()))) {
|
||||
|
||||
if (mbe.getReqLvl() > (int) character.level)
|
||||
continue;
|
||||
|
||||
Effect eff = character.effects.get(Integer.toString(effectsBase.getUUID()));
|
||||
|
||||
if (eff == null)
|
||||
continue;
|
||||
|
||||
//Current effect is a higher rank, dont apply.
|
||||
if (eff.getTrains() > mbe.getRank())
|
||||
continue;
|
||||
|
||||
//new effect is of a higher rank. remove old effect and apply new one.
|
||||
eff.cancelJob();
|
||||
character.addEffectNoTimer(Integer.toString(effectsBase.getUUID()), effectsBase, mbe.getRank(), true);
|
||||
} else {
|
||||
|
||||
if (mbe.getReqLvl() > (int) character.level)
|
||||
continue;
|
||||
|
||||
character.addEffectNoTimer(Integer.toString(effectsBase.getUUID()), effectsBase, mbe.getRank(), true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static void dismissNecroPet(Mob necroPet, boolean updateOwner) {
|
||||
|
||||
necroPet.setCombatTarget(null);
|
||||
@@ -45,12 +127,10 @@ public enum NPCManager {
|
||||
|
||||
DbManager.removeFromCache(necroPet);
|
||||
|
||||
|
||||
PlayerCharacter petOwner = (PlayerCharacter) necroPet.guardCaptain;
|
||||
PlayerCharacter petOwner = necroPet.getOwner();
|
||||
|
||||
if (petOwner != null) {
|
||||
|
||||
necroPet.guardCaptain = null;
|
||||
necroPet.setOwner(null);
|
||||
petOwner.setPet(null);
|
||||
|
||||
if (updateOwner == false)
|
||||
@@ -122,6 +202,78 @@ public enum NPCManager {
|
||||
playerCharacter.necroPets.clear();
|
||||
}
|
||||
|
||||
|
||||
public static void removeSiegeMinions(Mob mobile) {
|
||||
|
||||
for (Mob toRemove : mobile.siegeMinionMap.keySet()) {
|
||||
|
||||
if (mobile.isMoving()) {
|
||||
|
||||
mobile.stopMovement(mobile.getLoc());
|
||||
|
||||
if (toRemove.parentZone != null)
|
||||
toRemove.parentZone.zoneMobSet.remove(toRemove);
|
||||
}
|
||||
|
||||
try {
|
||||
toRemove.clearEffects();
|
||||
} catch (Exception e) {
|
||||
Logger.error(e.getMessage());
|
||||
}
|
||||
|
||||
if (toRemove.parentZone != null)
|
||||
toRemove.parentZone.zoneMobSet.remove(toRemove);
|
||||
|
||||
WorldGrid.RemoveWorldObject(toRemove);
|
||||
WorldGrid.removeObject(toRemove);
|
||||
DbManager.removeFromCache(toRemove);
|
||||
|
||||
PlayerCharacter petOwner = toRemove.getOwner();
|
||||
|
||||
if (petOwner != null) {
|
||||
|
||||
petOwner.setPet(null);
|
||||
toRemove.setOwner(null);
|
||||
|
||||
PetMsg petMsg = new PetMsg(5, null);
|
||||
Dispatch dispatch = Dispatch.borrow(petOwner, petMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean removeMobileFromBuilding(Mob mobile, Building building) {
|
||||
|
||||
// Remove npc from it's building
|
||||
|
||||
try {
|
||||
mobile.clearEffects();
|
||||
} catch (Exception e) {
|
||||
Logger.error(e.getMessage());
|
||||
}
|
||||
|
||||
if (mobile.parentZone != null)
|
||||
mobile.parentZone.zoneMobSet.remove(mobile);
|
||||
|
||||
if (building != null) {
|
||||
building.getHirelings().remove(mobile);
|
||||
removeSiegeMinions(mobile);
|
||||
}
|
||||
|
||||
// Delete npc from database
|
||||
|
||||
if (DbManager.MobQueries.DELETE_MOB(mobile) == 0)
|
||||
return false;
|
||||
|
||||
// Remove npc from the simulation
|
||||
|
||||
mobile.removeFromCache();
|
||||
DbManager.removeFromCache(mobile);
|
||||
WorldGrid.RemoveWorldObject(mobile);
|
||||
WorldGrid.removeObject(mobile);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void loadAllPirateNames() {
|
||||
|
||||
DbManager.NPCQueries.LOAD_PIRATE_NAMES();
|
||||
@@ -188,19 +340,10 @@ public enum NPCManager {
|
||||
else
|
||||
buildingSlot = BuildingManager.getAvailableSlot(abstractCharacter.building);
|
||||
|
||||
// Override slot for siege engines
|
||||
|
||||
if (abstractCharacter.getObjectType().equals(Enum.GameObjectType.Mob) && ((Mob) abstractCharacter).behaviourType.equals(Enum.MobBehaviourType.SiegeEngine)) {
|
||||
Mob siegeMobile = (Mob) abstractCharacter;
|
||||
buildingSlot = siegeMobile.guardCaptain.minions.size() + 2;
|
||||
}
|
||||
|
||||
if (buildingSlot == -1)
|
||||
Logger.error("No available slot for NPC: " + abstractCharacter.getObjectUUID());
|
||||
|
||||
// Pets are regular mobiles not hirelings (Siege engines)
|
||||
if (abstractCharacter.contract != null)
|
||||
abstractCharacter.building.getHirelings().put(abstractCharacter, buildingSlot);
|
||||
abstractCharacter.building.getHirelings().put(abstractCharacter, buildingSlot);
|
||||
|
||||
// Override bind and location for this npc derived
|
||||
// from BuildingManager slot location data.
|
||||
@@ -227,235 +370,4 @@ public enum NPCManager {
|
||||
|
||||
return buildingSlot;
|
||||
}
|
||||
|
||||
public static void AssignPatrolPoints(Mob mob) {
|
||||
mob.patrolPoints = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
float patrolRadius = mob.getSpawnRadius();
|
||||
|
||||
if (patrolRadius > 256)
|
||||
patrolRadius = 256;
|
||||
|
||||
if (patrolRadius < 60)
|
||||
patrolRadius = 60;
|
||||
|
||||
Vector3fImmutable newPatrolPoint = Vector3fImmutable.getRandomPointInCircle(mob.getBindLoc(), patrolRadius);
|
||||
mob.patrolPoints.add(newPatrolPoint);
|
||||
|
||||
if (i == 1) {
|
||||
mob.setLoc(newPatrolPoint);
|
||||
mob.endLoc = newPatrolPoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void applyGuardStanceModifiers(Mob guard){
|
||||
float damageModifier = 1;
|
||||
float attackRatingModifier = 1;
|
||||
float defenseModifier = 1;
|
||||
float attackSpeedModifier = 1;
|
||||
float powerDamageModifier = 1;
|
||||
//handle stance modifiers for guard mob
|
||||
if(guard.agentType.equals(Enum.AIAgentType.GUARDWALLARCHER)){
|
||||
//apply rogue bonuses
|
||||
attackRatingModifier += 0.5f;
|
||||
defenseModifier += 0.5f;
|
||||
damageModifier += 0.5f;
|
||||
attackSpeedModifier -= 0.36f;
|
||||
}else {
|
||||
Integer contractID;
|
||||
if (guard.agentType.equals(Enum.AIAgentType.GUARDMINION)) {
|
||||
contractID = guard.guardCaptain.contract.getContractID();
|
||||
} else{
|
||||
contractID = guard.contract.getContractID();
|
||||
}
|
||||
if (Enum.MinionType.ContractToMinionMap.get(contractID) != null && Enum.MinionType.ContractToMinionMap.get(contractID).isMage()){
|
||||
//apply mage offensive Stance
|
||||
powerDamageModifier += 0.5f;
|
||||
} else{
|
||||
//apply fighter offensive stance
|
||||
damageModifier += 0.5f;
|
||||
attackSpeedModifier -= 0.36f;
|
||||
}
|
||||
}
|
||||
guard.minDamageHandOne *= damageModifier;
|
||||
guard.minDamageHandTwo *= damageModifier;
|
||||
guard.maxDamageHandOne *= damageModifier;
|
||||
guard.maxDamageHandTwo *= damageModifier;
|
||||
guard.atrHandOne *= attackRatingModifier;
|
||||
guard.atrHandTwo *= attackRatingModifier;
|
||||
guard.defenseRating *= defenseModifier;
|
||||
guard.speedHandOne *= attackSpeedModifier;
|
||||
guard.speedHandTwo *= attackSpeedModifier;
|
||||
|
||||
//TODO figure out how to apply +50% powerdamage to mage guards
|
||||
}
|
||||
|
||||
public static void setDamageAndSpeedForGuard(Mob guard){
|
||||
|
||||
float rankModifier = 1 + (guard.getRank() * 0.1f);
|
||||
int primaryStat = 0;
|
||||
if(guard.equip == null) {
|
||||
guard.minDamageHandOne = (int)((guard.mobBase.getDamageMin()) * rankModifier);
|
||||
guard.maxDamageHandOne = (int)((guard.mobBase.getDamageMax()) * rankModifier);
|
||||
guard.speedHandOne = 30.0f;
|
||||
}else{
|
||||
if(guard.equip.containsKey(1)){
|
||||
//has main hand weapon
|
||||
ItemBase weapon = guard.equip.get(1).getItemBase();
|
||||
if(weapon.isStrBased())
|
||||
primaryStat = guard.getStatStrCurrent();
|
||||
else
|
||||
primaryStat = guard.getStatDexCurrent();
|
||||
guard.minDamageHandOne = (int)((guard.mobBase.getDamageMin() + weapon.getMinDamage()) * rankModifier) + primaryStat;
|
||||
guard.maxDamageHandOne = (int)((guard.mobBase.getDamageMax() + weapon.getMaxDamage()) * rankModifier) + primaryStat;
|
||||
guard.speedHandOne = weapon.getSpeed();
|
||||
guard.rangeHandOne = weapon.getRange();
|
||||
} else if(guard.equip.containsKey(2) && !guard.equip.get(2).getItemBase().isShield()){
|
||||
//has off hand weapon
|
||||
ItemBase weapon = guard.equip.get(2).getItemBase();
|
||||
if(weapon.isStrBased())
|
||||
primaryStat = guard.getStatStrCurrent();
|
||||
else
|
||||
primaryStat = guard.getStatDexCurrent();
|
||||
guard.minDamageHandTwo = (int)((guard.mobBase.getDamageMin() + weapon.getMinDamage()) * rankModifier) + primaryStat;
|
||||
guard.maxDamageHandTwo = (int)((guard.mobBase.getDamageMax() + weapon.getMaxDamage()) * rankModifier) + primaryStat;
|
||||
guard.speedHandTwo = weapon.getSpeed();
|
||||
guard.rangeHandTwo = weapon.getRange();
|
||||
} else {
|
||||
primaryStat = guard.getStatStrCurrent();
|
||||
guard.minDamageHandOne = (int)((guard.mobBase.getDamageMin()) * rankModifier) + primaryStat;
|
||||
guard.maxDamageHandOne = (int)((guard.mobBase.getDamageMax()) * rankModifier) + primaryStat;
|
||||
guard.speedHandOne = 30.0f;
|
||||
guard.rangeHandOne = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setDefenseForGuard(Mob guard){
|
||||
int dexterity = guard.getStatDexCurrent();
|
||||
if(dexterity < 1)
|
||||
dexterity = 1;
|
||||
int baseDef = guard.mobBase.getDefenseRating();
|
||||
int armorDefense = 0;
|
||||
for(MobEquipment equipped : guard.equip.values())
|
||||
if(equipped.getItemBase().isArmor() || equipped.getItemBase().isShield())
|
||||
armorDefense += equipped.getItemBase().getDefense();
|
||||
guard.defenseRating = dexterity + baseDef + armorDefense;
|
||||
}
|
||||
|
||||
public static void setAttackRatingForGuard(Mob guard) {
|
||||
int strength = guard.getStatStrCurrent();
|
||||
int baseAtr = guard.mobBase.getAttackRating();
|
||||
if (guard.equip.get(1) != null)
|
||||
guard.atrHandOne = baseAtr + (int) ((strength * 0.5f) + (guard.equip.get(1).getItemBase().getPercentRequired() * 4) + (guard.equip.get(1).getItemBase().getPercentRequired() * 3));
|
||||
else if (guard.equip.get(2) != null && !guard.equip.get(2).getItemBase().isShield())
|
||||
guard.atrHandTwo = baseAtr + (int) ((strength * 0.5f) + (guard.equip.get(2).getItemBase().getPercentRequired() * 4) + (guard.equip.get(2).getItemBase().getPercentRequired() * 3));
|
||||
else
|
||||
guard.atrHandOne = baseAtr;
|
||||
}
|
||||
|
||||
public static void setMaxHealthForGuard(Mob guard){
|
||||
//values derived fom reading memory address for health on client when selecting player guards
|
||||
switch(guard.getRank()){
|
||||
default:
|
||||
guard.healthMax = 750; //rank 1
|
||||
break;
|
||||
case 2:
|
||||
guard.healthMax = 2082;
|
||||
break;
|
||||
case 3:
|
||||
guard.healthMax = 2740;
|
||||
break;
|
||||
case 4:
|
||||
guard.healthMax = 3414;
|
||||
break;
|
||||
case 5:
|
||||
guard.healthMax = 4080;
|
||||
break;
|
||||
case 6:
|
||||
guard.healthMax = 4746;
|
||||
break;
|
||||
case 7:
|
||||
guard.healthMax = 5412;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void applyMobbaseEffects(Mob mob) {
|
||||
EffectsBase effectsBase;
|
||||
for (MobBaseEffects mbe : mob.mobBase.effectsList) {
|
||||
|
||||
effectsBase = PowersManager.getEffectByToken(mbe.getToken());
|
||||
|
||||
if (effectsBase == null) {
|
||||
Logger.info("Mob: " + mob.getObjectUUID() + " EffectsBase Null for Token " + mbe.getToken());
|
||||
continue;
|
||||
}
|
||||
|
||||
//check to upgrade effects if needed.
|
||||
if (mob.effects.containsKey(Integer.toString(effectsBase.getUUID()))) {
|
||||
|
||||
if (mbe.getReqLvl() > (int) mob.level)
|
||||
continue;
|
||||
|
||||
Effect eff = mob.effects.get(Integer.toString(effectsBase.getUUID()));
|
||||
|
||||
if (eff == null)
|
||||
continue;
|
||||
|
||||
//Current effect is a higher rank, dont apply.
|
||||
if (eff.getTrains() > mbe.getRank())
|
||||
continue;
|
||||
|
||||
//new effect is of a higher rank. remove old effect and apply new one.
|
||||
eff.cancelJob();
|
||||
mob.addEffectNoTimer(Integer.toString(effectsBase.getUUID()), effectsBase, mbe.getRank(), true);
|
||||
} else {
|
||||
|
||||
if (mbe.getReqLvl() > (int) mob.level)
|
||||
continue;
|
||||
|
||||
mob.addEffectNoTimer(Integer.toString(effectsBase.getUUID()), effectsBase, mbe.getRank(), true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static void applyEquipmentResists(Mob mob){
|
||||
if(mob.equip != null){
|
||||
for(MobEquipment equipped : mob.equip.values()){
|
||||
ItemBase itemBase = equipped.getItemBase();
|
||||
if(itemBase.isHeavyArmor() || itemBase.isLightArmor() || itemBase.isMediumArmor()){
|
||||
mob.resists.setResist(Enum.DamageType.Crush, mob.resists.getResist(Enum.DamageType.Crush,0) + itemBase.getCrushResist());
|
||||
mob.resists.setResist(Enum.DamageType.Slash, mob.resists.getResist(Enum.DamageType.Slash,0) + itemBase.getCrushResist());
|
||||
mob.resists.setResist(Enum.DamageType.Pierce, mob.resists.getResist(Enum.DamageType.Pierce,0) + itemBase.getCrushResist());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void applyMobbaseSkill(Mob mob) {
|
||||
SkillsBase baseSkill = DbManager.SkillsBaseQueries.GET_BASE_BY_TOKEN(mob.mobBase.getMobBaseStats().getBaseSkill());
|
||||
if(baseSkill != null)
|
||||
mob.getSkills().put(baseSkill.getName(),new CharacterSkill(baseSkill,mob,mob.mobBase.getMobBaseStats().getBaseSkillAmount()));
|
||||
}
|
||||
|
||||
public static void applyRuneSkills(Mob mob, int runeID){
|
||||
//load mob skill adjustments from mobbase rune
|
||||
if(PowersManager._allRuneSkillAdjusts.containsKey(runeID))
|
||||
for(RuneSkillAdjustEntry entry : PowersManager._allRuneSkillAdjusts.get(runeID)) {
|
||||
if(SkillsBase.getFromCache(entry.skill_type) == null)
|
||||
SkillsBase.putInCache(DbManager.SkillsBaseQueries.GET_BASE_BY_NAME(entry.skill_type));
|
||||
SkillsBase skillBase = SkillsBase.getFromCache(entry.skill_type);
|
||||
if(skillBase == null)
|
||||
continue;
|
||||
if (entry.level <= mob.level)
|
||||
if (mob.skills.containsKey(entry.name) == false)
|
||||
mob.skills.put(entry.skill_type, new CharacterSkill(skillBase, mob, entry.rank));
|
||||
else
|
||||
mob.skills.put(entry.skill_type, new CharacterSkill(skillBase, mob, entry.rank + mob.skills.get(entry.skill_type).getNumTrains()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,10 +53,13 @@ public enum PowersManager {
|
||||
public static HashMap<Integer, AbstractPowerAction> powerActionsByID = new HashMap<>();
|
||||
public static HashMap<String, Integer> ActionTokenByIDString = new HashMap<>();
|
||||
public static HashMap<String, Integer> AnimationOverrides = new HashMap<>();
|
||||
public static HashMap<Integer, ArrayList<RunePowerEntry>> _allRunePowers;
|
||||
public static HashMap<Integer, ArrayList<RuneSkillAdjustEntry>> _allRuneSkillAdjusts;
|
||||
public static HashMap<Integer, ArrayList<MobPowerEntry>> AllMobPowers;
|
||||
private static JobScheduler js;
|
||||
|
||||
private PowersManager() {
|
||||
|
||||
}
|
||||
|
||||
public static void initPowersManager(boolean fullPowersLoad) {
|
||||
|
||||
if (fullPowersLoad)
|
||||
@@ -100,16 +103,6 @@ public enum PowersManager {
|
||||
}
|
||||
}
|
||||
|
||||
public static ArrayList<RunePowerEntry> getPowersForRune(int rune_id) {
|
||||
|
||||
ArrayList<RunePowerEntry> powerEntries = PowersManager._allRunePowers.get(rune_id);
|
||||
|
||||
if (powerEntries == null)
|
||||
powerEntries = new ArrayList<>();
|
||||
|
||||
return powerEntries;
|
||||
}
|
||||
|
||||
// This pre-loads all powers and effects
|
||||
public static void InitializePowers() {
|
||||
|
||||
@@ -846,6 +839,8 @@ public enum PowersManager {
|
||||
return;
|
||||
}
|
||||
|
||||
playerCharacter.setHateValue(pb.getHateValue(trains));
|
||||
|
||||
//Send Cast Message.
|
||||
// PerformActionMsg castMsg = new PerformActionMsg(msg);
|
||||
// castMsg.setNumTrains(9999);
|
||||
@@ -896,6 +891,8 @@ public enum PowersManager {
|
||||
//Power is aiding a target, handle aggro if combat target is a Mob.
|
||||
if (!pb.isHarmful() && target.getObjectType() == GameObjectType.PlayerCharacter) {
|
||||
PlayerCharacter pcTarget = (PlayerCharacter) target;
|
||||
if (!pb.isHarmful())
|
||||
Mob.HandleAssistedAggro(playerCharacter, pcTarget);
|
||||
}
|
||||
|
||||
// update target of used power timer
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package engine.gameManager;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.InterestManagement.HeightMap;
|
||||
import engine.db.archive.CityRecord;
|
||||
import engine.db.archive.DataWarehouse;
|
||||
import engine.math.Bounds;
|
||||
@@ -454,31 +453,4 @@ public enum ZoneManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static float caclulateWorldAltitude(Zone zone) {
|
||||
|
||||
float worldAlttitude = MBServerStatics.SEA_FLOOR_ALTITUDE;
|
||||
|
||||
// Seafloor
|
||||
|
||||
if (zone.getParent() == null)
|
||||
return worldAlttitude;
|
||||
|
||||
Zone parentZone = zone.getParent();
|
||||
|
||||
// Children of seafloor
|
||||
|
||||
if (parentZone.getParent() == null)
|
||||
return worldAlttitude + zone.getYCoord();
|
||||
|
||||
// return height from heightmap engine at zone location
|
||||
|
||||
worldAlttitude = HeightMap.getWorldHeight(parentZone, zone.getLoc());
|
||||
|
||||
// Add zone offset to value
|
||||
|
||||
worldAlttitude += zone.getYCoord();
|
||||
|
||||
return worldAlttitude;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public class EndFearJob extends AbstractEffectJob {
|
||||
if (this.target == null || (!(this.target instanceof Mob)))
|
||||
return;
|
||||
|
||||
((Mob) this.target).fearedObject = null;
|
||||
((Mob) this.target).setFearedObject(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -40,6 +40,6 @@ public class EndFearJob extends AbstractEffectJob {
|
||||
if (this.target == null || (!(this.target instanceof Mob)))
|
||||
return;
|
||||
|
||||
((Mob) this.target).fearedObject = null;
|
||||
((Mob) this.target).setFearedObject(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package engine.loot;
|
||||
|
||||
import engine.gameManager.ForgeManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.concurrent.Delayed;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static java.lang.Math.toIntExact;
|
||||
|
||||
public class WorkOrder implements Delayed {
|
||||
|
||||
public int workOrder;
|
||||
public int npcUUID;
|
||||
public int slotCount;
|
||||
public int itemCount;
|
||||
public String prefix;
|
||||
public String suffix;
|
||||
public long completionTime;
|
||||
public boolean runCompleted;
|
||||
|
||||
public WorkOrder() {
|
||||
|
||||
this.workOrder = ForgeManager.workOrder.incrementAndGet();
|
||||
this.completionTime = System.currentTimeMillis() + 10000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDelay(TimeUnit unit) {
|
||||
|
||||
long timeRemaining = completionTime - System.currentTimeMillis();
|
||||
return unit.convert(timeRemaining, TimeUnit.MILLISECONDS);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull Delayed o) {
|
||||
return toIntExact(this.completionTime - ((WorkOrder) o).completionTime);
|
||||
}
|
||||
}
|
||||
+334
-256
@@ -23,7 +23,6 @@ import engine.net.client.msg.PowerProjectileMsg;
|
||||
import engine.objects.*;
|
||||
import engine.powers.ActionsBase;
|
||||
import engine.powers.PowersBase;
|
||||
import engine.powers.RunePowerEntry;
|
||||
import engine.server.MBServerStatics;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
@@ -50,19 +49,17 @@ public class MobAI {
|
||||
return;
|
||||
}
|
||||
|
||||
if (target.getObjectType().equals(Enum.GameObjectType.PlayerCharacter) &&
|
||||
!mob.canSee((AbstractCharacter) target)) {
|
||||
mob.setCombatTarget(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (target.getObjectType() == Enum.GameObjectType.PlayerCharacter && canCast(mob)) {
|
||||
|
||||
if (MobCast(mob)) {
|
||||
if (mob.isPlayerGuard() == false && MobCast(mob)) {
|
||||
mob.updateLocation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mob.isPlayerGuard() == true && GuardCast(mob)) {
|
||||
mob.updateLocation();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CombatUtilities.inRangeToAttack(mob, target))
|
||||
@@ -99,7 +96,7 @@ public class MobAI {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mob.behaviourType.callsForHelp)
|
||||
if (mob.BehaviourType.callsForHelp)
|
||||
MobCallForHelp(mob);
|
||||
|
||||
if (!MovementUtilities.inRangeDropAggro(mob, target)) {
|
||||
@@ -168,7 +165,7 @@ public class MobAI {
|
||||
|
||||
if (playercity != null)
|
||||
for (Mob guard : playercity.getParent().zoneMobSet)
|
||||
if (guard.agentType.equals(Enum.AIAgentType.GUARDCAPTAIN))
|
||||
if (guard.BehaviourType != null && guard.BehaviourType.ordinal() == Enum.MobBehaviourType.GuardCaptain.ordinal())
|
||||
if (guard.getCombatTarget() == null && !guard.getGuild().equals(mob.getGuild()))
|
||||
guard.setCombatTarget(mob);
|
||||
|
||||
@@ -252,58 +249,50 @@ public class MobAI {
|
||||
|
||||
try {
|
||||
|
||||
int patrolDelay = ThreadLocalRandom.current().nextInt((int) (MobAIThread.AI_PATROL_DIVISOR * 0.5f), MobAIThread.AI_PATROL_DIVISOR) + MobAIThread.AI_PATROL_DIVISOR;
|
||||
//make sure mob is out of combat stance
|
||||
|
||||
// early exit while waiting to patrol again.
|
||||
// Minions are force marched if captain is alive
|
||||
int patrolDelay = ThreadLocalRandom.current().nextInt((int) (MobAIThread.AI_PATROL_DIVISOR * 0.5f), MobAIThread.AI_PATROL_DIVISOR) + MobAIThread.AI_PATROL_DIVISOR;
|
||||
|
||||
boolean forced = mob.agentType.equals(Enum.AIAgentType.GUARDMINION) &&
|
||||
mob.guardCaptain.isAlive();
|
||||
//early exit while waiting to patrol again
|
||||
|
||||
if (mob.stopPatrolTime + (patrolDelay * 1000) > System.currentTimeMillis())
|
||||
if (!forced)
|
||||
return;
|
||||
return;
|
||||
|
||||
//guards inherit barracks patrol points dynamically
|
||||
//guard captains inherit barracks patrol points dynamically
|
||||
|
||||
if (mob.patrolPoints == null || mob.patrolPoints.isEmpty())
|
||||
if (mob.agentType.equals(Enum.AIAgentType.GUARDCAPTAIN) || mob.agentType.equals(Enum.AIAgentType.GUARDMINION)) {
|
||||
if (mob.BehaviourType.ordinal() == Enum.MobBehaviourType.GuardCaptain.ordinal()) {
|
||||
|
||||
Building barracks = mob.building;
|
||||
Building barracks = mob.building;
|
||||
|
||||
if (barracks != null && barracks.patrolPoints != null && !barracks.getPatrolPoints().isEmpty()) {
|
||||
mob.patrolPoints = barracks.patrolPoints;
|
||||
} else {
|
||||
randomGuardPatrolPoint(mob);
|
||||
return;
|
||||
}
|
||||
if (barracks != null && barracks.patrolPoints != null && !barracks.getPatrolPoints().isEmpty()) {
|
||||
mob.patrolPoints = barracks.patrolPoints;
|
||||
} else {
|
||||
randomGuardPatrolPoint(mob);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mob.lastPatrolPointIndex > mob.patrolPoints.size() - 1)
|
||||
mob.lastPatrolPointIndex = 0;
|
||||
|
||||
// Minions are given marching orders by the captain if he is alive
|
||||
mob.destination = mob.patrolPoints.get(mob.lastPatrolPointIndex);
|
||||
mob.lastPatrolPointIndex += 1;
|
||||
|
||||
if (mob.agentType.equals(Enum.AIAgentType.GUARDMINION)) {
|
||||
Mob captain = (Mob) mob.guardCaptain;
|
||||
mob.destination = captain.destination.add(Formation.getOffset(2, mob.guardCaptain.minions.indexOf(mob.getObjectUUID()) + 3));
|
||||
mob.lastPatrolPointIndex = captain.lastPatrolPointIndex;
|
||||
} else {
|
||||
mob.destination = mob.patrolPoints.get(mob.lastPatrolPointIndex);
|
||||
mob.lastPatrolPointIndex += 1;
|
||||
}
|
||||
|
||||
// Captain orders minions to patrol
|
||||
MovementUtilities.aiMove(mob, mob.destination, true);
|
||||
|
||||
if (mob.agentType.equals(Enum.AIAgentType.GUARDCAPTAIN))
|
||||
for (Integer minionUUID : mob.minions) {
|
||||
Mob minion = Mob.getMob(minionUUID);
|
||||
if (minion.isAlive() && minion.combatTarget == null)
|
||||
MobAI.Patrol(minion);
|
||||
}
|
||||
if (mob.BehaviourType.equals(Enum.MobBehaviourType.GuardCaptain))
|
||||
for (Entry<Mob, Integer> minion : mob.siegeMinionMap.entrySet())
|
||||
|
||||
MovementUtilities.aiMove(mob, mob.destination, true);
|
||||
//make sure mob is out of combat stance
|
||||
|
||||
if (minion.getKey().despawned == false) {
|
||||
if (MovementUtilities.canMove(minion.getKey())) {
|
||||
Vector3f minionOffset = Formation.getOffset(2, minion.getValue() + 3);
|
||||
minion.getKey().updateLocation();
|
||||
Vector3fImmutable formationPatrolPoint = new Vector3fImmutable(mob.destination.x + minionOffset.x, mob.destination.y, mob.destination.z + minionOffset.z);
|
||||
MovementUtilities.aiMove(minion.getKey(), formationPatrolPoint, true);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackTarget" + " " + e.getMessage());
|
||||
}
|
||||
@@ -311,8 +300,6 @@ public class MobAI {
|
||||
|
||||
public static boolean canCast(Mob mob) {
|
||||
|
||||
int contractID = 0;
|
||||
|
||||
try {
|
||||
|
||||
// Performs validation to determine if a
|
||||
@@ -321,27 +308,26 @@ public class MobAI {
|
||||
if (mob == null)
|
||||
return false;
|
||||
|
||||
if (mob.isPlayerGuard() == true) {
|
||||
if(mob.isPlayerGuard == true){
|
||||
|
||||
if(mob.agentType.equals(Enum.AIAgentType.GUARDWALLARCHER))
|
||||
return false; //wall archers don't cast
|
||||
if (mob.agentType.equals(Enum.AIAgentType.GUARDMINION))
|
||||
contractID = mob.guardCaptain.contract.getContractID();
|
||||
else
|
||||
contractID = mob.contract.getContractID();
|
||||
int contractID;
|
||||
|
||||
// exception allowing werewolf and werebear guard captains to cast
|
||||
if(mob.BehaviourType.equals(Enum.MobBehaviourType.GuardMinion))
|
||||
contractID = mob.npcOwner.contract.getContractID();
|
||||
else
|
||||
contractID = mob.contract.getContractID();
|
||||
|
||||
if (Enum.MinionType.ContractToMinionMap.get(contractID).isMage() == false && contractID != 980103 && contractID != 980104)
|
||||
if(Enum.MinionType.ContractToMinionMap.get(contractID).isMage() == false)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mobile has no powers defined in mobbase or contract..
|
||||
|
||||
if (PowersManager.getPowersForRune(mob.getMobBaseID()).isEmpty() &&
|
||||
PowersManager.getPowersForRune(contractID).isEmpty())
|
||||
if (mob.mobPowers.isEmpty())
|
||||
return false;
|
||||
|
||||
if (!mob.canSee((PlayerCharacter) mob.getCombatTarget())) {
|
||||
mob.setCombatTarget(null);
|
||||
return false;
|
||||
}
|
||||
if (mob.nextCastTime == 0)
|
||||
mob.nextCastTime = System.currentTimeMillis();
|
||||
|
||||
@@ -360,67 +346,164 @@ public class MobAI {
|
||||
// and casts it on the current target (or itself). Validation
|
||||
// (including empty lists) is done previously within canCast();
|
||||
|
||||
ArrayList<RunePowerEntry> powerEntries;
|
||||
ArrayList<RunePowerEntry> purgeEntries;
|
||||
ArrayList<Integer> powerTokens;
|
||||
ArrayList<Integer> purgeTokens;
|
||||
AbstractCharacter target = (AbstractCharacter) mob.getCombatTarget();
|
||||
|
||||
if (mob.behaviourType.callsForHelp)
|
||||
if (mob.BehaviourType.callsForHelp)
|
||||
MobCallForHelp(mob);
|
||||
|
||||
// Generate a list of tokens from the mob powers for this mobile.
|
||||
|
||||
powerEntries = new ArrayList<>(PowersManager.getPowersForRune(mob.getMobBaseID()));
|
||||
purgeEntries = new ArrayList<>();
|
||||
powerTokens = new ArrayList<>(mob.mobPowers.keySet());
|
||||
purgeTokens = new ArrayList<>();
|
||||
|
||||
// If player has this effect on them currently then remove
|
||||
// this token from our list.
|
||||
|
||||
for (int powerToken : powerTokens) {
|
||||
|
||||
// Additional powers may come from the contract ID. This is to support
|
||||
// powers for player guards irrespective of the mobbase used.
|
||||
PowersBase powerBase = PowersManager.getPowerByToken(powerToken);
|
||||
|
||||
if (mob.isPlayerGuard()) {
|
||||
for (ActionsBase actionBase : powerBase.getActions()) {
|
||||
|
||||
ArrayList<RunePowerEntry> contractEntries = new ArrayList<>();
|
||||
String stackType = actionBase.stackType;
|
||||
|
||||
if (mob.contract != null)
|
||||
contractEntries = PowersManager.getPowersForRune(mob.contractUUID);
|
||||
if (target.getEffects() != null && target.getEffects().containsKey(stackType))
|
||||
purgeTokens.add(powerToken);
|
||||
}
|
||||
}
|
||||
|
||||
if (mob.agentType.equals(Enum.AIAgentType.GUARDMINION))
|
||||
contractEntries = PowersManager.getPowersForRune(mob.guardCaptain.contractUUID);
|
||||
powerTokens.removeAll(purgeTokens);
|
||||
|
||||
// Sanity check
|
||||
|
||||
if (powerTokens.isEmpty())
|
||||
return false;
|
||||
|
||||
// Pick random spell from our list of powers
|
||||
|
||||
powerEntries.addAll(contractEntries);
|
||||
int powerToken = powerTokens.get(ThreadLocalRandom.current().nextInt(powerTokens.size()));
|
||||
int powerRank = mob.mobPowers.get(powerToken);
|
||||
|
||||
PowersBase mobPower = PowersManager.getPowerByToken(powerToken);
|
||||
|
||||
//check for hit-roll
|
||||
|
||||
if (mobPower.requiresHitRoll)
|
||||
if (CombatUtilities.triggerDefense(mob, mob.getCombatTarget()))
|
||||
return false;
|
||||
|
||||
// Cast the spell
|
||||
|
||||
if (CombatUtilities.inRange2D(mob, mob.getCombatTarget(), mobPower.getRange())) {
|
||||
|
||||
PerformActionMsg msg;
|
||||
|
||||
if (!mobPower.isHarmful() || mobPower.targetSelf) {
|
||||
PowersManager.useMobPower(mob, mob, mobPower, powerRank);
|
||||
msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, mob);
|
||||
} else {
|
||||
PowersManager.useMobPower(mob, target, mobPower, powerRank);
|
||||
msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target);
|
||||
}
|
||||
|
||||
msg.setUnknown04(2);
|
||||
|
||||
PowersManager.finishUseMobPower(msg, mob, 0, 0);
|
||||
long randomCooldown = (long)((ThreadLocalRandom.current().nextInt(10,15) * 1000) * MobAIThread.AI_CAST_FREQUENCY);
|
||||
|
||||
mob.nextCastTime = System.currentTimeMillis() + randomCooldown;
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: MobCast" + " " + e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean GuardCast(Mob mob) {
|
||||
|
||||
try {
|
||||
// Method picks a random spell from a mobile's list of powers
|
||||
// and casts it on the current target (or itself). Validation
|
||||
// (including empty lists) is done previously within canCast();
|
||||
|
||||
ArrayList<Integer> powerTokens;
|
||||
ArrayList<Integer> purgeTokens;
|
||||
AbstractCharacter target = (AbstractCharacter) mob.getCombatTarget();
|
||||
|
||||
if (mob.BehaviourType.callsForHelp)
|
||||
MobCallForHelp(mob);
|
||||
|
||||
// Generate a list of tokens from the mob powers for this mobile.
|
||||
|
||||
powerTokens = new ArrayList<>(mob.mobPowers.keySet());
|
||||
purgeTokens = new ArrayList<>();
|
||||
|
||||
// If player has this effect on them currently then remove
|
||||
// this token from our list.
|
||||
|
||||
for (RunePowerEntry runePowerEntry : powerEntries) {
|
||||
for (int powerToken : powerTokens) {
|
||||
|
||||
PowersBase powerBase = PowersManager.getPowerByToken(runePowerEntry.token);
|
||||
PowersBase powerBase = PowersManager.getPowerByToken(powerToken);
|
||||
|
||||
for (ActionsBase actionBase : powerBase.getActions()) {
|
||||
|
||||
String stackType = actionBase.stackType;
|
||||
|
||||
if (target.getEffects() != null && target.getEffects().containsKey(stackType))
|
||||
purgeEntries.add(runePowerEntry);
|
||||
purgeTokens.add(powerToken);
|
||||
}
|
||||
}
|
||||
|
||||
powerEntries.removeAll(purgeEntries);
|
||||
powerTokens.removeAll(purgeTokens);
|
||||
|
||||
// Sanity check
|
||||
|
||||
if (powerEntries.isEmpty())
|
||||
if (powerTokens.isEmpty())
|
||||
return false;
|
||||
|
||||
// Pick random spell from our list of powers
|
||||
int powerToken = 0;
|
||||
int nukeRoll = ThreadLocalRandom.current().nextInt(1,100);
|
||||
|
||||
if (nukeRoll < 55) {
|
||||
|
||||
RunePowerEntry runePowerEntry = powerEntries.get(ThreadLocalRandom.current().nextInt(powerEntries.size()));
|
||||
//use direct damage spell
|
||||
powerToken = powerTokens.get(powerTokens.size() - 1);
|
||||
|
||||
PowersBase mobPower = PowersManager.getPowerByToken(runePowerEntry.token);
|
||||
int powerRank = runePowerEntry.rank;
|
||||
} else {
|
||||
//use random spell
|
||||
powerToken = powerTokens.get(ThreadLocalRandom.current().nextInt(powerTokens.size()));
|
||||
}
|
||||
|
||||
if (mob.isPlayerGuard())
|
||||
powerRank = getGuardPowerRank(mob);
|
||||
int powerRank = 1;
|
||||
|
||||
switch(mob.getRank()){
|
||||
case 1:
|
||||
powerRank = 10;
|
||||
break;
|
||||
case 2:
|
||||
powerRank = 15;
|
||||
break;
|
||||
case 3:
|
||||
powerRank = 20;
|
||||
break;
|
||||
case 4:
|
||||
powerRank = 25;
|
||||
break;
|
||||
case 5:
|
||||
powerRank = 30;
|
||||
break;
|
||||
case 6:
|
||||
powerRank = 35;
|
||||
break;
|
||||
case 7:
|
||||
powerRank = 40;
|
||||
break;
|
||||
}
|
||||
|
||||
PowersBase mobPower = PowersManager.getPowerByToken(powerToken);
|
||||
|
||||
//check for hit-roll
|
||||
|
||||
@@ -435,8 +518,14 @@ public class MobAI {
|
||||
PerformActionMsg msg;
|
||||
|
||||
if (!mobPower.isHarmful() || mobPower.targetSelf) {
|
||||
PowersManager.useMobPower(mob, mob, mobPower, powerRank);
|
||||
msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, mob);
|
||||
|
||||
if (mobPower.category.equals("DISPEL")) {
|
||||
PowersManager.useMobPower(mob, target, mobPower, powerRank);
|
||||
msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target);
|
||||
} else {
|
||||
PowersManager.useMobPower(mob, mob, mobPower, powerRank);
|
||||
msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, mob);
|
||||
}
|
||||
} else {
|
||||
PowersManager.useMobPower(mob, target, mobPower, powerRank);
|
||||
msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target);
|
||||
@@ -445,8 +534,8 @@ public class MobAI {
|
||||
msg.setUnknown04(2);
|
||||
|
||||
PowersManager.finishUseMobPower(msg, mob, 0, 0);
|
||||
long randomCooldown = (long) ((ThreadLocalRandom.current().nextInt(10, 15) * 1000) * MobAIThread.AI_CAST_FREQUENCY);
|
||||
|
||||
long randomCooldown = (long)((ThreadLocalRandom.current().nextInt(10,15) * 1000) * MobAIThread.AI_CAST_FREQUENCY);
|
||||
mob.nextCastTime = System.currentTimeMillis() + randomCooldown;
|
||||
return true;
|
||||
}
|
||||
@@ -456,35 +545,6 @@ public class MobAI {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int getGuardPowerRank(Mob mob) {
|
||||
int powerRank = 1;
|
||||
|
||||
switch (mob.getRank()) {
|
||||
case 1:
|
||||
powerRank = 10;
|
||||
break;
|
||||
case 2:
|
||||
powerRank = 15;
|
||||
break;
|
||||
case 3:
|
||||
powerRank = 20;
|
||||
break;
|
||||
case 4:
|
||||
powerRank = 25;
|
||||
break;
|
||||
case 5:
|
||||
powerRank = 30;
|
||||
break;
|
||||
case 6:
|
||||
powerRank = 35;
|
||||
break;
|
||||
case 7:
|
||||
powerRank = 40;
|
||||
break;
|
||||
}
|
||||
return powerRank;
|
||||
}
|
||||
|
||||
public static void MobCallForHelp(Mob mob) {
|
||||
|
||||
try {
|
||||
@@ -504,7 +564,7 @@ public class MobAI {
|
||||
Zone mobCamp = mob.getParentZone();
|
||||
|
||||
for (Mob helper : mobCamp.zoneMobSet) {
|
||||
if (helper.behaviourType.respondsToCallForHelp && helper.behaviourType.BehaviourHelperType.equals(mob.behaviourType)) {
|
||||
if (helper.BehaviourType.respondsToCallForHelp && helper.BehaviourType.BehaviourHelperType.equals(mob.BehaviourType)) {
|
||||
helper.setCombatTarget(mob.getCombatTarget());
|
||||
callGotResponse = true;
|
||||
}
|
||||
@@ -546,10 +606,10 @@ public class MobAI {
|
||||
|
||||
//override for guards
|
||||
|
||||
if (mob.despawned && mob.isPlayerGuard()) {
|
||||
if (mob.despawned && mob.isPlayerGuard) {
|
||||
|
||||
if (mob.agentType.equals(Enum.AIAgentType.GUARDMINION)) {
|
||||
if (mob.guardCaptain.isAlive() == false || ((Mob) mob.guardCaptain).despawned == true) {
|
||||
if (mob.BehaviourType.ordinal() == Enum.MobBehaviourType.GuardMinion.ordinal()) {
|
||||
if (mob.npcOwner.isAlive() == false || ((Mob) mob.npcOwner).despawned == true) {
|
||||
|
||||
//minions don't respawn while guard captain is dead
|
||||
|
||||
@@ -565,7 +625,7 @@ public class MobAI {
|
||||
|
||||
//check to send mob home for player guards to prevent exploit of dragging guards away and then teleporting
|
||||
|
||||
if (!mob.agentType.equals(Enum.AIAgentType.PET))
|
||||
if (mob.BehaviourType.ordinal() != Enum.MobBehaviourType.Pet1.ordinal())
|
||||
CheckToSendMobHome(mob);
|
||||
|
||||
return;
|
||||
@@ -578,23 +638,15 @@ public class MobAI {
|
||||
return;
|
||||
}
|
||||
|
||||
//no players loaded, no need to proceed unless it's a player guard
|
||||
boolean bypassLoadedPlayerCheck = false;
|
||||
if(mob.isPlayerGuard() || mob.isSiege()) {
|
||||
bypassLoadedPlayerCheck = true;
|
||||
if(mob.combatTarget != null && mob.combatTarget.getObjectType().equals(Enum.GameObjectType.PlayerCharacter))
|
||||
if(mob.combatTarget.loc.distanceSquared(mob.loc) > 10000)
|
||||
mob.setCombatTarget(null);
|
||||
}
|
||||
//no players loaded, no need to proceed
|
||||
|
||||
if (mob.playerAgroMap.isEmpty() && !bypassLoadedPlayerCheck) {
|
||||
if (mob.getCombatTarget() != null)
|
||||
if (mob.playerAgroMap.isEmpty()) {
|
||||
if(mob.getCombatTarget() != null)
|
||||
mob.setCombatTarget(null);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (mob.agentType.equals(Enum.AIAgentType.PET) == false)
|
||||
if (mob.BehaviourType.ordinal() != Enum.MobBehaviourType.Pet1.ordinal())
|
||||
CheckToSendMobHome(mob);
|
||||
|
||||
if (mob.getCombatTarget() != null) {
|
||||
@@ -621,14 +673,17 @@ public class MobAI {
|
||||
}
|
||||
}
|
||||
|
||||
switch (mob.behaviourType) {
|
||||
switch (mob.BehaviourType) {
|
||||
case GuardCaptain:
|
||||
GuardCaptainLogic(mob);
|
||||
break;
|
||||
case GuardMinion:
|
||||
GuardMinionLogic(mob);
|
||||
break;
|
||||
case GuardWallArcher:
|
||||
GuardLogic(mob);
|
||||
GuardWallArcherLogic(mob);
|
||||
break;
|
||||
case Pet1:
|
||||
case SiegeEngine:
|
||||
PetLogic(mob);
|
||||
break;
|
||||
case HamletGuard:
|
||||
@@ -638,6 +693,8 @@ public class MobAI {
|
||||
DefaultLogic(mob);
|
||||
break;
|
||||
}
|
||||
if(mob.isAlive())
|
||||
RecoverHealth(mob);
|
||||
} catch (Exception e) {
|
||||
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: DetermineAction" + " " + e.getMessage());
|
||||
}
|
||||
@@ -652,7 +709,7 @@ public class MobAI {
|
||||
if (!aiAgent.isAlive())
|
||||
return;
|
||||
|
||||
ConcurrentHashMap<Integer, Float> loadedPlayers = aiAgent.playerAgroMap;
|
||||
ConcurrentHashMap<Integer, Boolean> loadedPlayers = aiAgent.playerAgroMap;
|
||||
|
||||
for (Entry playerEntry : loadedPlayers.entrySet()) {
|
||||
|
||||
@@ -692,6 +749,7 @@ public class MobAI {
|
||||
aiAgent.setCombatTarget(loadedPlayer);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (aiAgent.getCombatTarget() == null) {
|
||||
@@ -726,49 +784,52 @@ public class MobAI {
|
||||
|
||||
mob.updateLocation();
|
||||
|
||||
switch (mob.behaviourType) {
|
||||
switch (mob.BehaviourType) {
|
||||
|
||||
case Pet1:
|
||||
|
||||
if (mob.guardCaptain == null)
|
||||
if (mob.getOwner() == null)
|
||||
return;
|
||||
|
||||
//mob no longer has its owner loaded, translate pet to owner
|
||||
if (!mob.playerAgroMap.containsKey(mob.getOwner().getObjectUUID())) {
|
||||
|
||||
if (!mob.playerAgroMap.containsKey(mob.guardCaptain.getObjectUUID())) {
|
||||
MovementManager.translocate(mob, mob.guardCaptain.getLoc(), null);
|
||||
//mob no longer has its owner loaded, translocate pet to owner
|
||||
|
||||
MovementManager.translocate(mob, mob.getOwner().getLoc(), null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mob.getCombatTarget() == null) {
|
||||
|
||||
//move back to owner
|
||||
|
||||
if (CombatUtilities.inRange2D(mob, mob.guardCaptain, 6))
|
||||
if (CombatUtilities.inRange2D(mob, mob.getOwner(), 6))
|
||||
return;
|
||||
|
||||
mob.destination = mob.guardCaptain.getLoc();
|
||||
MovementUtilities.moveToLocation(mob, mob.destination, 5, false);
|
||||
mob.destination = mob.getOwner().getLoc();
|
||||
MovementUtilities.moveToLocation(mob, mob.destination, 5);
|
||||
} else
|
||||
chaseTarget(mob);
|
||||
break;
|
||||
case GuardMinion:
|
||||
if (!mob.npcOwner.isAlive() && mob.getCombatTarget() == null)
|
||||
randomGuardPatrolPoint(mob);
|
||||
else {
|
||||
if (mob.getCombatTarget() != null) {
|
||||
chaseTarget(mob);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (mob.getCombatTarget() == null) {
|
||||
|
||||
if (!mob.isMoving()) {
|
||||
|
||||
// Minions only patrol on their own if captain is dead.
|
||||
|
||||
if (mob.agentType.equals(Enum.AIAgentType.GUARDMINION) == false)
|
||||
Patrol(mob);
|
||||
else if (mob.guardCaptain.isAlive() == false)
|
||||
Patrol(mob);
|
||||
} else
|
||||
if (!mob.isMoving())
|
||||
Patrol(mob);
|
||||
else {
|
||||
mob.stopPatrolTime = System.currentTimeMillis();
|
||||
}
|
||||
} else {
|
||||
chaseTarget(mob);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckMobMovement" + " " + e.getMessage());
|
||||
@@ -835,8 +896,7 @@ public class MobAI {
|
||||
if (mob.getCombatTarget() == null)
|
||||
return;
|
||||
|
||||
if (mob.getCombatTarget().getObjectType().equals(Enum.GameObjectType.PlayerCharacter) && MovementUtilities.inRangeDropAggro(mob, (PlayerCharacter) mob.getCombatTarget()) == false &&
|
||||
mob.agentType.equals(Enum.AIAgentType.PET) == false) {
|
||||
if (mob.getCombatTarget().getObjectType().equals(Enum.GameObjectType.PlayerCharacter) && MovementUtilities.inRangeDropAggro(mob, (PlayerCharacter) mob.getCombatTarget()) == false && mob.BehaviourType.ordinal() != Enum.MobBehaviourType.Pet1.ordinal()) {
|
||||
|
||||
mob.setCombatTarget(null);
|
||||
return;
|
||||
@@ -852,6 +912,15 @@ public class MobAI {
|
||||
private static void CheckToSendMobHome(Mob mob) {
|
||||
|
||||
try {
|
||||
if (mob.BehaviourType.isAgressive) {
|
||||
|
||||
if (mob.isPlayerGuard()) {
|
||||
if (mob.BehaviourType.ordinal() == Enum.MobBehaviourType.GuardCaptain.ordinal())
|
||||
CheckForPlayerGuardAggro(mob);
|
||||
} else {
|
||||
CheckForAggro(mob);
|
||||
}
|
||||
}
|
||||
|
||||
if (mob.getCombatTarget() != null && CombatUtilities.inRange2D(mob, mob.getCombatTarget(), MobAIThread.AI_BASE_AGGRO_RANGE * 0.5f))
|
||||
return;
|
||||
@@ -866,15 +935,13 @@ public class MobAI {
|
||||
PowersManager.useMobPower(mob, mob, recall, 40);
|
||||
mob.setCombatTarget(null);
|
||||
|
||||
if (mob.agentType.equals(Enum.AIAgentType.GUARDCAPTAIN) && mob.isAlive()) {
|
||||
if (mob.BehaviourType.ordinal() == Enum.MobBehaviourType.GuardCaptain.ordinal() && mob.isAlive()) {
|
||||
|
||||
//guard captain pulls his minions home with him
|
||||
|
||||
for (Integer minionUUID : mob.minions) {
|
||||
Mob minion = Mob.getMob(minionUUID);
|
||||
|
||||
PowersManager.useMobPower(minion, minion, recall, 40);
|
||||
minion.setCombatTarget(null);
|
||||
for (Entry<Mob, Integer> minion : mob.siegeMinionMap.entrySet()) {
|
||||
PowersManager.useMobPower(minion.getKey(), minion.getKey(), recall, 40);
|
||||
minion.getKey().setCombatTarget(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -884,8 +951,8 @@ public class MobAI {
|
||||
PowersManager.useMobPower(mob, mob, recall, 40);
|
||||
mob.setCombatTarget(null);
|
||||
|
||||
for (Integer playerEntry : mob.playerAgroMap.keySet())
|
||||
mob.playerAgroMap.put(playerEntry, 0f);
|
||||
for (Entry playerEntry : mob.playerAgroMap.entrySet())
|
||||
PlayerCharacter.getFromCache((int) playerEntry.getKey()).setHateValue(0);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckToSendMobHome" + " " + e.getMessage());
|
||||
@@ -896,10 +963,16 @@ public class MobAI {
|
||||
|
||||
try {
|
||||
|
||||
if (CombatUtilities.inRange2D(mob, mob.getCombatTarget(), mob.getRange()) == false) {
|
||||
float rangeSquared = mob.getRange() * mob.getRange();
|
||||
float distanceSquared = mob.getLoc().distanceSquared2D(mob.getCombatTarget().getLoc());
|
||||
|
||||
if(mob.isMoving() == true && distanceSquared < rangeSquared - 50) {
|
||||
mob.destination = mob.getLoc();
|
||||
MovementUtilities.moveToLocation(mob, mob.destination, 0);
|
||||
} else if (CombatUtilities.inRange2D(mob, mob.getCombatTarget(), mob.getRange()) == false) {
|
||||
if (mob.getRange() > 15) {
|
||||
mob.destination = mob.getCombatTarget().getLoc();
|
||||
MovementUtilities.moveToLocation(mob, mob.destination, 0, false);
|
||||
MovementUtilities.moveToLocation(mob, mob.destination, 0);
|
||||
} else {
|
||||
|
||||
//check if building
|
||||
@@ -908,11 +981,11 @@ public class MobAI {
|
||||
case PlayerCharacter:
|
||||
case Mob:
|
||||
mob.destination = MovementUtilities.GetDestinationToCharacter(mob, (AbstractCharacter) mob.getCombatTarget());
|
||||
MovementUtilities.moveToLocation(mob, mob.destination, mob.getRange() + 1, false);
|
||||
MovementUtilities.moveToLocation(mob, mob.destination, mob.getRange() + 1);
|
||||
break;
|
||||
case Building:
|
||||
mob.destination = mob.getCombatTarget().getLoc();
|
||||
MovementUtilities.moveToLocation(mob, mob.getCombatTarget().getLoc(), 0, false);
|
||||
MovementUtilities.moveToLocation(mob, mob.getCombatTarget().getLoc(), 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -933,17 +1006,17 @@ public class MobAI {
|
||||
|
||||
//dont scan self.
|
||||
|
||||
if (mob.equals(awoMob) || (mob.agentType.equals(Enum.AIAgentType.GUARDCAPTAIN)) == true)
|
||||
if (mob.equals(awoMob) || (mob.agentType.equals(Enum.AIAgentType.GUARD)) == true)
|
||||
continue;
|
||||
|
||||
Mob aggroMob = (Mob) awoMob;
|
||||
|
||||
//don't attack other guards
|
||||
|
||||
if ((aggroMob.agentType.equals(Enum.AIAgentType.GUARDCAPTAIN)))
|
||||
if ((aggroMob.agentType.equals(Enum.AIAgentType.GUARD)))
|
||||
continue;
|
||||
|
||||
if (aggroMob.agentType.equals(Enum.AIAgentType.PET))
|
||||
if(aggroMob.BehaviourType.equals(Enum.MobBehaviourType.Pet1))
|
||||
continue;
|
||||
|
||||
if (mob.getLoc().distanceSquared2D(aggroMob.getLoc()) > sqr(50))
|
||||
@@ -956,33 +1029,59 @@ public class MobAI {
|
||||
}
|
||||
}
|
||||
|
||||
public static void GuardLogic(Mob mob) {
|
||||
public static void GuardCaptainLogic(Mob mob) {
|
||||
|
||||
try {
|
||||
if (mob.getCombatTarget() == null) {
|
||||
if (mob.getCombatTarget() == null)
|
||||
CheckForPlayerGuardAggro(mob);
|
||||
} else {
|
||||
//do not need to look to change target if target is already null
|
||||
AbstractWorldObject newTarget = ChangeTargetFromHateValue(mob);
|
||||
|
||||
if (newTarget != null) {
|
||||
AbstractWorldObject newTarget = ChangeTargetFromHateValue(mob);
|
||||
|
||||
if (newTarget.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) {
|
||||
if (GuardCanAggro(mob, (PlayerCharacter) newTarget))
|
||||
mob.setCombatTarget(newTarget);
|
||||
} else
|
||||
if (newTarget != null) {
|
||||
|
||||
if (newTarget.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) {
|
||||
if (GuardCanAggro(mob, (PlayerCharacter) newTarget))
|
||||
mob.setCombatTarget(newTarget);
|
||||
}
|
||||
} else
|
||||
mob.setCombatTarget(newTarget);
|
||||
|
||||
}
|
||||
CheckMobMovement(mob);
|
||||
CheckForAttack(mob);
|
||||
} catch (Exception e) {
|
||||
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: GuardCaptainLogic" + " " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if(mob.behaviourType.canRoam)
|
||||
CheckMobMovement(mob);//all guards that can move check to move
|
||||
public static void GuardMinionLogic(Mob mob) {
|
||||
|
||||
if(mob.combatTarget != null)
|
||||
CheckForAttack(mob); //only check to attack if combat target is not null
|
||||
try {
|
||||
boolean isComanded = mob.npcOwner.isAlive();
|
||||
if (!isComanded) {
|
||||
GuardCaptainLogic(mob);
|
||||
}else {
|
||||
if (mob.npcOwner.getCombatTarget() != null)
|
||||
mob.setCombatTarget(mob.npcOwner.getCombatTarget());
|
||||
else
|
||||
if (mob.getCombatTarget() != null)
|
||||
mob.setCombatTarget(null);
|
||||
}
|
||||
CheckMobMovement(mob);
|
||||
CheckForAttack(mob);
|
||||
} catch (Exception e) {
|
||||
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: GuardMinionLogic" + " " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static void GuardWallArcherLogic(Mob mob) {
|
||||
|
||||
try {
|
||||
if (mob.getCombatTarget() == null)
|
||||
CheckForPlayerGuardAggro(mob);
|
||||
else
|
||||
CheckForAttack(mob);
|
||||
} catch (Exception e) {
|
||||
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: GuardLogic" + " " + e.getMessage());
|
||||
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: GuardWallArcherLogic" + " " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -990,30 +1089,14 @@ public class MobAI {
|
||||
|
||||
try {
|
||||
|
||||
if (mob.guardCaptain == null && mob.isNecroPet() == false && mob.isSiege() == false)
|
||||
if (mob.getOwner() == null && mob.isNecroPet() == false && mob.isSiege() == false)
|
||||
if (ZoneManager.getSeaFloor().zoneMobSet.contains(mob))
|
||||
mob.killCharacter("no owner");
|
||||
|
||||
if (MovementUtilities.canMove(mob) && mob.behaviourType.canRoam)
|
||||
if (MovementUtilities.canMove(mob) && mob.BehaviourType.canRoam)
|
||||
CheckMobMovement(mob);
|
||||
|
||||
CheckForAttack(mob);
|
||||
|
||||
//recover health
|
||||
|
||||
if (mob.getTimestamps().containsKey("HEALTHRECOVERED") == false)
|
||||
mob.getTimestamps().put("HEALTHRECOVERED", System.currentTimeMillis());
|
||||
|
||||
if (mob.isSit() && mob.getTimeStamp("HEALTHRECOVERED") < System.currentTimeMillis() + 3000)
|
||||
if (mob.getHealth() < mob.getHealthMax()) {
|
||||
|
||||
float recoveredHealth = mob.getHealthMax() * ((1 + mob.getBonuses().getFloatPercentAll(Enum.ModType.HealthRecoverRate, Enum.SourceType.None)) * 0.01f);
|
||||
mob.setHealth(mob.getHealth() + recoveredHealth);
|
||||
mob.getTimestamps().put("HEALTHRECOVERED", System.currentTimeMillis());
|
||||
|
||||
if (mob.getHealth() > mob.getHealthMax())
|
||||
mob.setHealth(mob.getHealthMax());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: PetLogic" + " " + e.getMessage());
|
||||
}
|
||||
@@ -1044,7 +1127,7 @@ public class MobAI {
|
||||
if (mob.getCombatTarget() != null && mob.playerAgroMap.containsKey(mob.getCombatTarget().getObjectUUID()) == false)
|
||||
mob.setCombatTarget(null);
|
||||
|
||||
if (mob.behaviourType.isAgressive) {
|
||||
if (mob.BehaviourType.isAgressive) {
|
||||
|
||||
AbstractWorldObject newTarget = ChangeTargetFromHateValue(mob);
|
||||
|
||||
@@ -1052,7 +1135,7 @@ public class MobAI {
|
||||
mob.setCombatTarget(newTarget);
|
||||
else {
|
||||
if (mob.getCombatTarget() == null) {
|
||||
if (mob.behaviourType == Enum.MobBehaviourType.HamletGuard)
|
||||
if (mob.BehaviourType == Enum.MobBehaviourType.HamletGuard)
|
||||
SafeGuardAggro(mob); //safehold guard
|
||||
else
|
||||
CheckForAggro(mob); //normal aggro
|
||||
@@ -1062,12 +1145,12 @@ public class MobAI {
|
||||
|
||||
//check if mob can move for patrol or moving to target
|
||||
|
||||
if (mob.behaviourType.canRoam)
|
||||
if (mob.BehaviourType.canRoam)
|
||||
CheckMobMovement(mob);
|
||||
|
||||
//check if mob can attack if it isn't wimpy
|
||||
|
||||
if (!mob.behaviourType.isWimpy && mob.getCombatTarget() != null)
|
||||
if (!mob.BehaviourType.isWimpy && mob.getCombatTarget() != null)
|
||||
CheckForAttack(mob);
|
||||
|
||||
} catch (Exception e) {
|
||||
@@ -1084,16 +1167,7 @@ public class MobAI {
|
||||
if (!mob.isAlive())
|
||||
return;
|
||||
|
||||
// Defer to captain if possible for current target
|
||||
|
||||
if (mob.agentType.equals(Enum.AIAgentType.GUARDMINION) &&
|
||||
mob.guardCaptain.isAlive()
|
||||
&& mob.guardCaptain.combatTarget != null) {
|
||||
mob.setCombatTarget(mob.guardCaptain.combatTarget);
|
||||
return;
|
||||
}
|
||||
|
||||
ConcurrentHashMap<Integer, Float> loadedPlayers = mob.playerAgroMap;
|
||||
ConcurrentHashMap<Integer, Boolean> loadedPlayers = mob.playerAgroMap;
|
||||
|
||||
for (Entry playerEntry : loadedPlayers.entrySet()) {
|
||||
|
||||
@@ -1128,39 +1202,27 @@ public class MobAI {
|
||||
mob.setCombatTarget(loadedPlayer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mob.getCombatTarget() == null) {
|
||||
|
||||
//look for siege equipment to aggro if no players found to aggro
|
||||
|
||||
HashSet<AbstractWorldObject> awoList = WorldGrid.getObjectsInRangePartial(mob, MobAIThread.AI_BASE_AGGRO_RANGE, MBServerStatics.MASK_SIEGE);
|
||||
|
||||
for (AbstractWorldObject awoMob : awoList) {
|
||||
|
||||
|
||||
Mob aggroMob = (Mob) awoMob;
|
||||
if(GuardCanAggro(mob,aggroMob)) {
|
||||
mob.setCombatTarget(aggroMob);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckForPlayerGuardAggro" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static Boolean GuardCanAggro(Mob mob, AbstractCharacter target) {
|
||||
public static Boolean GuardCanAggro(Mob mob, PlayerCharacter target) {
|
||||
|
||||
try {
|
||||
|
||||
if (mob.guardedCity.cityOutlaws.contains(target.getObjectUUID()) == true)
|
||||
return true;
|
||||
|
||||
if (mob.getGuild().getNation().equals(target.getGuild().getNation()))
|
||||
return false;
|
||||
|
||||
if (mob.BehaviourType.ordinal() == Enum.MobBehaviourType.GuardMinion.ordinal()) {
|
||||
if (((Mob) mob.npcOwner).building.getCity().cityOutlaws.contains(target.getObjectUUID()) == true) {
|
||||
return true;
|
||||
}
|
||||
} else if (mob.building.getCity().cityOutlaws.contains(target.getObjectUUID()) == true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//first check condemn list for aggro allowed (allies button is checked)
|
||||
|
||||
if (ZoneManager.getCityAtLocation(mob.getLoc()).getTOL().reverseKOS) {
|
||||
@@ -1238,19 +1300,17 @@ public class MobAI {
|
||||
|
||||
MovementUtilities.aiMove(mob, mob.destination, true);
|
||||
|
||||
if (mob.agentType.equals(Enum.AIAgentType.GUARDCAPTAIN)) {
|
||||
for (Integer minionUUID : mob.minions) {
|
||||
|
||||
Mob minion = Mob.getMob(minionUUID);
|
||||
if (mob.BehaviourType.ordinal() == Enum.MobBehaviourType.GuardCaptain.ordinal()) {
|
||||
for (Entry<Mob, Integer> minion : mob.siegeMinionMap.entrySet()) {
|
||||
|
||||
//make sure mob is out of combat stance
|
||||
|
||||
if (minion.despawned == false) {
|
||||
if (MovementUtilities.canMove(minion)) {
|
||||
Vector3f minionOffset = Formation.getOffset(2, mob.minions.indexOf(minionUUID) + 3);
|
||||
minion.updateLocation();
|
||||
if (minion.getKey().despawned == false) {
|
||||
if (MovementUtilities.canMove(minion.getKey())) {
|
||||
Vector3f minionOffset = Formation.getOffset(2, minion.getValue() + 3);
|
||||
minion.getKey().updateLocation();
|
||||
Vector3fImmutable formationPatrolPoint = new Vector3fImmutable(mob.destination.x + minionOffset.x, mob.destination.y, mob.destination.z + minionOffset.z);
|
||||
MovementUtilities.aiMove(minion, formationPatrolPoint, true);
|
||||
MovementUtilities.aiMove(minion.getKey(), formationPatrolPoint, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1267,7 +1327,7 @@ public class MobAI {
|
||||
float CurrentHateValue = 0;
|
||||
|
||||
if (mob.getCombatTarget() != null && mob.getCombatTarget().getObjectType().equals(Enum.GameObjectType.PlayerCharacter))
|
||||
CurrentHateValue = mob.playerAgroMap.get(mob.combatTarget.getObjectUUID()).floatValue();
|
||||
CurrentHateValue = ((PlayerCharacter) mob.getCombatTarget()).getHateValue();
|
||||
|
||||
AbstractWorldObject mostHatedTarget = null;
|
||||
|
||||
@@ -1278,8 +1338,8 @@ public class MobAI {
|
||||
if (potentialTarget.equals(mob.getCombatTarget()))
|
||||
continue;
|
||||
|
||||
if (potentialTarget != null && mob.playerAgroMap.get(potentialTarget.getObjectUUID()).floatValue() > CurrentHateValue && MovementUtilities.inRangeToAggro(mob, potentialTarget)) {
|
||||
CurrentHateValue = mob.playerAgroMap.get(potentialTarget.getObjectUUID()).floatValue();
|
||||
if (potentialTarget != null && potentialTarget.getHateValue() > CurrentHateValue && MovementUtilities.inRangeToAggro(mob, potentialTarget)) {
|
||||
CurrentHateValue = potentialTarget.getHateValue();
|
||||
mostHatedTarget = potentialTarget;
|
||||
}
|
||||
|
||||
@@ -1290,4 +1350,22 @@ public class MobAI {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void RecoverHealth(Mob mob){
|
||||
//recover health
|
||||
|
||||
if (mob.getTimestamps().containsKey("HEALTHRECOVERED") == false)
|
||||
mob.getTimestamps().put("HEALTHRECOVERED", System.currentTimeMillis());
|
||||
|
||||
if (mob.isSit() && mob.getTimeStamp("HEALTHRECOVERED") < System.currentTimeMillis() + 3000)
|
||||
if (mob.getHealth() < mob.getHealthMax()) {
|
||||
|
||||
float recoveredHealth = mob.getHealthMax() * ((1 + mob.getBonuses().getFloatPercentAll(Enum.ModType.HealthRecoverRate, Enum.SourceType.None)) * 0.01f);
|
||||
mob.setHealth(mob.getHealth() + recoveredHealth);
|
||||
mob.getTimestamps().put("HEALTHRECOVERED", System.currentTimeMillis());
|
||||
|
||||
if (mob.getHealth() > mob.getHealthMax())
|
||||
mob.setHealth(mob.getHealthMax());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,11 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package engine.mobileAI.Threads;
|
||||
|
||||
import engine.gameManager.ConfigManager;
|
||||
import engine.gameManager.ZoneManager;
|
||||
import engine.mobileAI.MobAI;
|
||||
import engine.gameManager.ZoneManager;
|
||||
import engine.objects.Mob;
|
||||
import engine.objects.Zone;
|
||||
import engine.server.MBServerStatics;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
public class MobAIThread implements Runnable{
|
||||
@@ -21,27 +14,23 @@ public class MobAIThread implements Runnable{
|
||||
public static int AI_PULSE_MOB_THRESHOLD = 200;
|
||||
public static int AI_PATROL_DIVISOR = 15;
|
||||
public static float AI_CAST_FREQUENCY;
|
||||
|
||||
// Thread constructor
|
||||
|
||||
public MobAIThread() {
|
||||
|
||||
//cache config value for mobile casting delay
|
||||
|
||||
AI_CAST_FREQUENCY = Float.parseFloat(ConfigManager.MB_AI_CAST_FREQUENCY.getValue());
|
||||
AI_BASE_AGGRO_RANGE = (int) (60 * Float.parseFloat(ConfigManager.MB_AI_AGGRO_RANGE.getValue()));
|
||||
Logger.info(" MobAIThread thread has started!");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
Logger.info(" MobAIThread thread has started!");
|
||||
|
||||
//cache config value for mobile casting delay
|
||||
AI_CAST_FREQUENCY = Float.parseFloat(ConfigManager.MB_AI_CAST_FREQUENCY.getValue());
|
||||
AI_BASE_AGGRO_RANGE = (int)(60 * Float.parseFloat(ConfigManager.MB_AI_AGGRO_RANGE.getValue()));
|
||||
while (true) {
|
||||
for (Zone zone : ZoneManager.getAllZones()) {
|
||||
|
||||
for (Mob mob : zone.zoneMobSet) {
|
||||
|
||||
for (Zone zone : ZoneManager.getAllZones())
|
||||
for (Mob mob : zone.zoneMobSet)
|
||||
try {
|
||||
if (mob != null)
|
||||
MobAI.DetermineAction(mob);
|
||||
@@ -49,10 +38,10 @@ public class MobAIThread implements Runnable{
|
||||
Logger.error("Mob: " + mob.getName() + " UUID: " + mob.getObjectUUID() + " ERROR: " + e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void startAIThread() {
|
||||
Thread aiThread;
|
||||
aiThread = new Thread(new MobAIThread());
|
||||
|
||||
@@ -6,13 +6,23 @@
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package engine.mobileAI.Threads;
|
||||
|
||||
package engine.mobileAI.Threads;
|
||||
import engine.gameManager.ZoneManager;
|
||||
import engine.objects.Mob;
|
||||
import engine.objects.Zone;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
/**
|
||||
* Thread blocks until MagicBane dispatch messages are
|
||||
* enqueued then processes them in FIFO order. The collection
|
||||
* is thread safe.
|
||||
* <p>
|
||||
* Any large messages not time sensitive such as load object
|
||||
* sent to more than a single individual should be spawned
|
||||
* individually on a DispatchMessageThread.
|
||||
*/
|
||||
|
||||
public class MobRespawnThread implements Runnable {
|
||||
|
||||
|
||||
@@ -27,7 +37,8 @@ public class MobRespawnThread implements Runnable {
|
||||
while (true) {
|
||||
|
||||
try {
|
||||
for (Zone zone : ZoneManager.getAllZones())
|
||||
for (Zone zone : ZoneManager.getAllZones()) {
|
||||
|
||||
if (zone.respawnQue.isEmpty() == false && zone.lastRespawn + 100 < System.currentTimeMillis()) {
|
||||
|
||||
Mob respawner = zone.respawnQue.iterator().next();
|
||||
@@ -39,6 +50,7 @@ public class MobRespawnThread implements Runnable {
|
||||
zone.respawnQue.remove(respawner);
|
||||
zone.lastRespawn = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logger.error(e);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class CombatUtilities {
|
||||
}
|
||||
|
||||
public static boolean inRange2D(AbstractWorldObject entity1, AbstractWorldObject entity2, double range) {
|
||||
return entity1.getLoc().distanceSquared2D(entity2.getLoc()) < range * range;
|
||||
return entity1.getLoc().distance2D(entity2.getLoc()) < range;
|
||||
}
|
||||
|
||||
public static void swingIsBlock(Mob agent, AbstractWorldObject target, int animation) {
|
||||
@@ -264,9 +264,19 @@ public class CombatUtilities {
|
||||
swingIsBlock(agent, target, passiveAnim);
|
||||
return;
|
||||
}
|
||||
|
||||
swingIsDamage(agent, target, determineDamage(agent), anim);
|
||||
|
||||
if (agent.getEquip().get(1) != null && agent.getEquip().get(2) != null && agent.getEquip().get(2).getItemBase().isShield() == false) {
|
||||
//mob is duel wielding and should conduct an attack for each hand
|
||||
ItemBase weapon1 = agent.getEquip().get(1).getItemBase();
|
||||
double range1 = getMaxDmg(weapon1.getMinDamage(), agent, weapon1) - getMinDmg(weapon1.getMinDamage(), agent, weapon1);
|
||||
double damage1 = getMinDmg(weapon1.getMinDamage(), agent, weapon1) + ((ThreadLocalRandom.current().nextFloat() * range1) + (ThreadLocalRandom.current().nextFloat() * range1)) / 2;
|
||||
swingIsDamage(agent, target, (float) damage1, CombatManager.getSwingAnimation(weapon1, null, true));
|
||||
ItemBase weapon2 = agent.getEquip().get(2).getItemBase();
|
||||
double range2 = getMaxDmg(weapon2.getMinDamage(), agent, weapon2) - getMinDmg(weapon2.getMinDamage(), agent, weapon2);
|
||||
double damage2 = getMinDmg(weapon2.getMinDamage(), agent, weapon2) + ((ThreadLocalRandom.current().nextFloat() * range2) + (ThreadLocalRandom.current().nextFloat() * range2)) / 2;
|
||||
swingIsDamage(agent, target, (float) damage2, CombatManager.getSwingAnimation(weapon1, null, false));
|
||||
} else {
|
||||
swingIsDamage(agent, target, determineDamage(agent), anim);
|
||||
}
|
||||
|
||||
if (agent.getWeaponPower() != null)
|
||||
agent.getWeaponPower().attack(target, MBServerStatics.ONE_MINUTE);
|
||||
@@ -309,10 +319,19 @@ public class CombatUtilities {
|
||||
if (target == null)
|
||||
return 0;
|
||||
|
||||
int damage = 0;
|
||||
float damage = 0;
|
||||
|
||||
DamageType dt = getDamageType(agent);
|
||||
damage = ThreadLocalRandom.current().nextInt((int)getMinDmg(agent), (int)getMaxDmg(agent) + 1);
|
||||
if ((agent.agentType.equals(AIAgentType.PET)) == true || agent.isPet() == true || agent.isNecroPet() == true) {
|
||||
damage = calculatePetDamage(agent);
|
||||
} else if (agent.isPlayerGuard() == true) {
|
||||
//damage = calculateGuardDamage(agent);
|
||||
damage = calculateMobDamage(agent);
|
||||
} else if (agent.getLevel() > 80) {
|
||||
damage = calculateEpicDamage(agent);
|
||||
} else {
|
||||
damage = calculateMobDamage(agent);
|
||||
}
|
||||
if (AbstractWorldObject.IsAbstractCharacter(target)) {
|
||||
if (((AbstractCharacter) target).isSit()) {
|
||||
damage *= 2.5f; //increase damage if sitting
|
||||
@@ -338,16 +357,158 @@ public class CombatUtilities {
|
||||
return dt;
|
||||
}
|
||||
|
||||
public static double getMinDmg(Mob agent) {
|
||||
if(agent.equip.get(2) != null && !agent.equip.get(2).getItemBase().isShield())
|
||||
return agent.minDamageHandTwo;
|
||||
else return agent.minDamageHandOne;
|
||||
public static int calculatePetDamage(Mob agent) {
|
||||
//damage calc for pet
|
||||
float range;
|
||||
float damage;
|
||||
float min = 40;
|
||||
float max = 60;
|
||||
float dmgMultiplier = 1 + agent.getBonuses().getFloatPercentAll(ModType.MeleeDamageModifier, SourceType.None);
|
||||
double minDmg = getMinDmg(min, agent, null);
|
||||
double maxDmg = getMaxDmg(max, agent, null);
|
||||
dmgMultiplier += agent.getLevel() * 0.1f;
|
||||
range = (float) (maxDmg - minDmg);
|
||||
damage = min + ((ThreadLocalRandom.current().nextFloat() * range) + (ThreadLocalRandom.current().nextFloat() * range)) / 2;
|
||||
return (int) (damage * dmgMultiplier);
|
||||
}
|
||||
|
||||
public static int calculateGuardDamage(Mob agent) {
|
||||
//damage calc for guard
|
||||
ItemBase weapon = agent.getEquip().get(1).getItemBase();
|
||||
AbstractWorldObject target = agent.getCombatTarget();
|
||||
|
||||
float dmgMultiplier = 1 + agent.getBonuses().getFloatPercentAll(ModType.MeleeDamageModifier, SourceType.None);
|
||||
|
||||
double minDmg = weapon.getMinDamage();
|
||||
double maxDmg = weapon.getMaxDamage();
|
||||
double min = getMinDmg(minDmg, agent, weapon);
|
||||
double max = getMaxDmg(maxDmg, agent, weapon);
|
||||
|
||||
DamageType dt = weapon.getDamageType();
|
||||
|
||||
double range = max - min;
|
||||
double damage = min + ((ThreadLocalRandom.current().nextFloat() * range) + (ThreadLocalRandom.current().nextFloat() * range)) / 2;
|
||||
|
||||
if (AbstractWorldObject.IsAbstractCharacter(target))
|
||||
if (((AbstractCharacter) target).isSit())
|
||||
damage *= 2.5f; //increase damage if sitting
|
||||
if (AbstractWorldObject.IsAbstractCharacter(target))
|
||||
return (int) (((AbstractCharacter) target).getResists().getResistedDamage(agent, (AbstractCharacter) target, dt, (float) damage, 0) * dmgMultiplier);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int calculateEpicDamage(Mob agent) {
|
||||
//handle r8 mob damage
|
||||
DamageType dt = DamageType.Crush;
|
||||
AbstractWorldObject target = agent.getCombatTarget();
|
||||
float dmgMultiplier = 1 + agent.getBonuses().getFloatPercentAll(ModType.MeleeDamageModifier, SourceType.None);
|
||||
double min = agent.getMinDamageHandOne();
|
||||
double max = agent.getMaxDamageHandOne();
|
||||
if (agent.getEquip().get(1) != null) {
|
||||
if (agent.getEquip().get(1).getItemBase() != null) {
|
||||
dt = agent.getEquip().get(1).getItemBase().getDamageType();
|
||||
min = agent.getMinDamageHandOne();
|
||||
max = agent.getMaxDamageHandOne();
|
||||
} else if (agent.getEquip().get(2).getItemBase() != null && agent.getEquip().get(2).getItemBase().isShield() == false) {
|
||||
dt = agent.getEquip().get(2).getItemBase().getDamageType();
|
||||
min = agent.getMinDamageHandTwo();
|
||||
max = agent.getMaxDamageHandTwo();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double range = max - min;
|
||||
double damage = min + ((ThreadLocalRandom.current().nextFloat() * range) + (ThreadLocalRandom.current().nextFloat() * range)) / 2;
|
||||
return (int) (((AbstractCharacter) target).getResists().getResistedDamage(agent, (AbstractCharacter) target, dt, (float) damage, 0) * dmgMultiplier);
|
||||
}
|
||||
|
||||
public static int calculateMobDamage(Mob agent) {
|
||||
ItemBase weapon = null;
|
||||
double minDmg;
|
||||
double maxDmg;
|
||||
DamageType dt;
|
||||
|
||||
//main hand or offhand damage
|
||||
|
||||
if (agent.getEquip().get(1) != null)
|
||||
weapon = agent.getEquip().get(1).getItemBase();
|
||||
else if (agent.getEquip().get(2) != null)
|
||||
weapon = agent.getEquip().get(2).getItemBase();
|
||||
|
||||
if (weapon != null) {
|
||||
minDmg = getMinDmg(weapon.getMinDamage(), agent, weapon);
|
||||
maxDmg = getMaxDmg(weapon.getMaxDamage(), agent, weapon);
|
||||
dt = weapon.getDamageType();
|
||||
} else {
|
||||
minDmg = agent.getMobBase().getDamageMin();
|
||||
maxDmg = agent.getMobBase().getDamageMax();
|
||||
dt = DamageType.Crush;
|
||||
}
|
||||
|
||||
AbstractWorldObject target = agent.getCombatTarget();
|
||||
|
||||
float dmgMultiplier = 1 + agent.getBonuses().getFloatPercentAll(ModType.MeleeDamageModifier, SourceType.None);
|
||||
double range = maxDmg - minDmg;
|
||||
double damage = minDmg + ((ThreadLocalRandom.current().nextFloat() * range) + (ThreadLocalRandom.current().nextFloat() * range)) / 2;
|
||||
|
||||
if (AbstractWorldObject.IsAbstractCharacter(target))
|
||||
if (((AbstractCharacter) target).isSit())
|
||||
damage *= 2.5f; //increase damage if sitting
|
||||
if (AbstractWorldObject.IsAbstractCharacter(target))
|
||||
return (int) (((AbstractCharacter) target).getResists().getResistedDamage(agent, (AbstractCharacter) target, dt, (float) damage, 0) * dmgMultiplier);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static double getMaxDmg(Mob agent) {
|
||||
if(agent.equip.get(2) != null && !agent.equip.get(2).getItemBase().isShield())
|
||||
return agent.maxDamageHandTwo;
|
||||
else return agent.maxDamageHandOne;
|
||||
public static double getMinDmg(double min, Mob agent, ItemBase weapon) {
|
||||
|
||||
int primary = agent.getStatStrCurrent();
|
||||
int secondary = agent.getStatDexCurrent();
|
||||
int focusLevel = 0;
|
||||
int masteryLevel = 0;
|
||||
|
||||
if (weapon != null) {
|
||||
if (weapon.isStrBased() == true) {
|
||||
primary = agent.getStatStrCurrent();
|
||||
secondary = agent.getStatDexCurrent();
|
||||
} else {
|
||||
primary = agent.getStatDexCurrent();
|
||||
secondary = agent.getStatStrCurrent();
|
||||
if (agent.getSkills().containsKey(weapon.getSkillRequired())) {
|
||||
focusLevel = (int) agent.getSkills().get(weapon.getSkillRequired()).getModifiedAmount();
|
||||
}
|
||||
if (agent.getSkills().containsKey(weapon.getMastery())) {
|
||||
masteryLevel = (int) agent.getSkills().get(weapon.getMastery()).getModifiedAmount();
|
||||
}
|
||||
}
|
||||
}
|
||||
return min * (pow(0.0048 * primary + .049 * (primary - 0.75), 0.5) + pow(0.0066 * secondary + 0.064 * (secondary - 0.75), 0.5) + +0.01 * (focusLevel + masteryLevel));
|
||||
}
|
||||
|
||||
public static double getMaxDmg(double max, Mob agent, ItemBase weapon) {
|
||||
|
||||
int primary = agent.getStatStrCurrent();
|
||||
int secondary = agent.getStatDexCurrent();
|
||||
int focusLevel = 0;
|
||||
int masteryLevel = 0;
|
||||
|
||||
if (weapon != null) {
|
||||
|
||||
if (weapon.isStrBased() == true) {
|
||||
primary = agent.getStatStrCurrent();
|
||||
secondary = agent.getStatDexCurrent();
|
||||
} else {
|
||||
primary = agent.getStatDexCurrent();
|
||||
secondary = agent.getStatStrCurrent();
|
||||
}
|
||||
|
||||
if (agent.getSkills().containsKey(weapon.getSkillRequired()))
|
||||
focusLevel = (int) agent.getSkills().get(weapon.getSkillRequired()).getModifiedAmount();
|
||||
|
||||
if (agent.getSkills().containsKey(weapon.getSkillRequired()))
|
||||
masteryLevel = (int) agent.getSkills().get(weapon.getMastery()).getModifiedAmount();
|
||||
|
||||
}
|
||||
return max * (pow(0.0124 * primary + 0.118 * (primary - 0.75), 0.5) + pow(0.0022 * secondary + 0.028 * (secondary - 0.75), 0.5) + 0.0075 * (focusLevel + masteryLevel));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,10 +13,10 @@ import engine.Enum;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.Enum.ModType;
|
||||
import engine.Enum.SourceType;
|
||||
import engine.mobileAI.Threads.MobAIThread;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.MovementManager;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.mobileAI.Threads.MobAIThread;
|
||||
import engine.net.client.msg.MoveToPointMsg;
|
||||
import engine.objects.*;
|
||||
import org.pmw.tinylog.Logger;
|
||||
@@ -38,7 +38,7 @@ public class MovementUtilities {
|
||||
if (agent.getContract() != null)
|
||||
guardCaptain = agent;
|
||||
else
|
||||
guardCaptain = (Mob) agent.guardCaptain;
|
||||
guardCaptain = (Mob) agent.npcOwner;
|
||||
|
||||
if (guardCaptain != null) {
|
||||
Building barracks = guardCaptain.building;
|
||||
@@ -147,7 +147,7 @@ public class MovementUtilities {
|
||||
return aiAgent.getLoc().ClosestPointOnLine(aggroTarget.getLoc(), aggroTarget.getEndLoc());
|
||||
}
|
||||
|
||||
public static void moveToLocation(Mob agent, Vector3fImmutable newLocation, float offset, boolean isWalking) {
|
||||
public static void moveToLocation(Mob agent, Vector3fImmutable newLocation, float offset) {
|
||||
try {
|
||||
|
||||
//don't move farther than 30 units from player.
|
||||
@@ -158,7 +158,7 @@ public class MovementUtilities {
|
||||
|
||||
agent.setFaceDir(newLoc.subtract2D(agent.getLoc()).normalize());
|
||||
|
||||
aiMove(agent, newLoc, isWalking);
|
||||
aiMove(agent, newLoc, false);
|
||||
} catch (Exception e) {
|
||||
Logger.error(e.toString());
|
||||
}
|
||||
@@ -244,10 +244,10 @@ public class MovementUtilities {
|
||||
msg.setSourceID(agent.getObjectUUID());
|
||||
msg.setStartCoord(startLoc);
|
||||
msg.setEndCoord(endLoc);
|
||||
msg.setInBuildingFloor(-1);
|
||||
msg.setUnknown01(-1);
|
||||
msg.setInBuilding(-1);
|
||||
msg.setStartLocType(0);
|
||||
msg.setInBuildingUUID(0);
|
||||
msg.setTargetType(0);
|
||||
msg.setTargetID(0);
|
||||
|
||||
|
||||
try {
|
||||
|
||||
@@ -28,7 +28,7 @@ import static engine.net.MessageDispatcher.maxRecipients;
|
||||
|
||||
/*
|
||||
* Dispatch Message is the main interface to Magicbane's threaded
|
||||
* async message delivery system.
|
||||
* asynch message delivery system.
|
||||
*/
|
||||
|
||||
public class DispatchMessage {
|
||||
|
||||
@@ -643,7 +643,7 @@ public class ClientMessagePump implements NetMsgHandler {
|
||||
moveMsg.setStartCoord(sourcePlayer.getLoc());
|
||||
moveMsg.setEndCoord(sourcePlayer.getLoc());
|
||||
moveMsg.setInBuilding(-1);
|
||||
moveMsg.setInBuildingFloor(-1);
|
||||
moveMsg.setUnknown01(-1);
|
||||
|
||||
dispatch = Dispatch.borrow(sourcePlayer, moveMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
|
||||
@@ -1892,6 +1892,9 @@ public class ClientMessagePump implements NetMsgHandler {
|
||||
case POWER:
|
||||
PowersManager.usePower((PerformActionMsg) msg, origin, false);
|
||||
break;
|
||||
case REQUESTMELEEATTACK:
|
||||
CombatManager.setAttackTarget((AttackCmdMsg) msg, origin);
|
||||
break;
|
||||
case READYTOENTER:
|
||||
break;
|
||||
case OPENVAULT:
|
||||
|
||||
@@ -173,7 +173,7 @@ public enum Protocol {
|
||||
REPAIROBJECT(0x782219CE, RepairMsg.class, null), //Repair Window Req/Ack, RepairObject item Req/Ack
|
||||
REQUESTCONTENTS(0xA786B0A2, LootWindowRequestMsg.class, null), // MoveObjectToContainer Window Request
|
||||
REQUESTGUILDLIST(0x85DCC6D7, ReqGuildListMsg.class, RequestGuildListHandler.class),
|
||||
REQUESTMELEEATTACK(0x98C71545, AttackCmdMsg.class, AttackCmdMsgHandler.class), // Attack
|
||||
REQUESTMELEEATTACK(0x98C71545, AttackCmdMsg.class, null), // Attack
|
||||
REQUESTMEMBERLIST(0x3235E5EA, GuildControlMsg.class, GuildControlHandler.class), // Part of Promote/Demote, Also Player History
|
||||
REQUESTTOOPENBANK(0xF26E453F, null, null), // RequestToOpenBankMsg
|
||||
REQUESTTOTRADE(0x4D84259B, TradeRequestMsg.class, null), // Trade Request
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.CombatManager;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.AttackCmdMsg;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.TargetedActionMsg;
|
||||
import engine.objects.*;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which keeps
|
||||
* client's tcp connection open.
|
||||
*/
|
||||
|
||||
public class AttackCmdMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public AttackCmdMsgHandler() {
|
||||
super(AttackCmdMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter playerCharacter = origin.getPlayerCharacter();
|
||||
|
||||
// Member variable declaration
|
||||
|
||||
AttackCmdMsg msg;
|
||||
|
||||
// Member variable assignment
|
||||
|
||||
msg = (AttackCmdMsg) baseMsg;
|
||||
|
||||
if (TargetedActionMsg.un2cnt == 60 || TargetedActionMsg.un2cnt == 70)
|
||||
return true;
|
||||
|
||||
if (playerCharacter == null)
|
||||
return true;
|
||||
|
||||
AbstractWorldObject target = null;
|
||||
Enum.GameObjectType targetType;
|
||||
|
||||
targetType = Enum.GameObjectType.values()[msg.getTargetType()];
|
||||
|
||||
switch(targetType){
|
||||
case Mob:
|
||||
target = Mob.getMob(msg.getTargetID());
|
||||
break;
|
||||
case PlayerCharacter:
|
||||
target = PlayerCharacter.getPlayerCharacter(msg.getTargetID());
|
||||
break;
|
||||
case Building:
|
||||
target = BuildingManager.getBuilding(msg.getTargetID());
|
||||
break;
|
||||
case NPC:
|
||||
target = NPC.getNPC(msg.getTargetID());
|
||||
break;
|
||||
}
|
||||
if(target == null) {
|
||||
playerCharacter.setCombatTarget(null);
|
||||
return true; // cannot attack a null target
|
||||
}
|
||||
//set sources target
|
||||
|
||||
playerCharacter.setCombatTarget(target);
|
||||
|
||||
//put in combat if not already
|
||||
|
||||
if (!playerCharacter.isCombat())
|
||||
CombatManager.toggleCombat(true, origin);
|
||||
|
||||
//make character stand if sitting
|
||||
|
||||
if (playerCharacter.isSit())
|
||||
CombatManager.toggleSit(false, origin);
|
||||
|
||||
CombatManager.AttackTarget(playerCharacter, target);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.NPCManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
@@ -15,6 +16,9 @@ import engine.net.client.msg.*;
|
||||
import engine.objects.*;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which
|
||||
@@ -23,6 +27,8 @@ import org.pmw.tinylog.Logger;
|
||||
|
||||
public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public static HashMap<Integer, ArrayList<Integer>> _minionsByCaptain = null;
|
||||
|
||||
public MinionTrainingMsgHandler() {
|
||||
super(MinionTrainingMessage.class);
|
||||
}
|
||||
@@ -32,9 +38,9 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
MinionTrainingMessage minionMsg = (MinionTrainingMessage) baseMsg;
|
||||
|
||||
PlayerCharacter playerCharacter = SessionManager.getPlayerCharacter(origin);
|
||||
PlayerCharacter player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (playerCharacter == null)
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
if (minionMsg.getNpcType() == Enum.GameObjectType.NPC.ordinal()) {
|
||||
@@ -44,24 +50,23 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
|
||||
if (npc == null)
|
||||
return true;
|
||||
|
||||
Building building = BuildingManager.getBuildingFromCache(minionMsg.getBuildingID());
|
||||
Building b = BuildingManager.getBuildingFromCache(minionMsg.getBuildingID());
|
||||
|
||||
if (building == null)
|
||||
if (b == null)
|
||||
return true;
|
||||
|
||||
//clear minion
|
||||
|
||||
if (npc.minionLock.writeLock().tryLock()) {
|
||||
|
||||
try {
|
||||
if (minionMsg.getType() == 2) {
|
||||
|
||||
Mob toRemove = Mob.getFromCache(minionMsg.getUUID());
|
||||
|
||||
if (!npc.minions.contains(toRemove.getObjectUUID()))
|
||||
if (!npc.getSiegeMinionMap().containsKey(toRemove))
|
||||
return true;
|
||||
|
||||
npc.minions.remove(Integer.valueOf(toRemove.getObjectUUID()));
|
||||
npc.getSiegeMinionMap().remove(toRemove);
|
||||
|
||||
WorldGrid.RemoveWorldObject(toRemove);
|
||||
|
||||
@@ -69,35 +74,33 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
|
||||
toRemove.getParentZone().zoneMobSet.remove(toRemove);
|
||||
|
||||
DbManager.removeFromCache(toRemove);
|
||||
|
||||
if(toRemove.guardCaptain.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) {
|
||||
PlayerCharacter petOwner = (PlayerCharacter) toRemove.guardCaptain;
|
||||
|
||||
if (petOwner != null) {
|
||||
petOwner.setPet(null);
|
||||
|
||||
toRemove.guardCaptain = null;
|
||||
PetMsg petMsg = new PetMsg(5, null);
|
||||
Dispatch dispatch = Dispatch.borrow(petOwner, petMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
}
|
||||
PlayerCharacter petOwner = toRemove.getOwner();
|
||||
|
||||
if (petOwner != null) {
|
||||
petOwner.setPet(null);
|
||||
toRemove.setOwner(null);
|
||||
PetMsg petMsg = new PetMsg(5, null);
|
||||
Dispatch dispatch = Dispatch.borrow(petOwner, petMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
ManageCityAssetsMsg mca1 = new ManageCityAssetsMsg(playerCharacter, building);
|
||||
// we Found the move to remove, lets break the for loop so it doesnt look for more.
|
||||
|
||||
ManageCityAssetsMsg mca1 = new ManageCityAssetsMsg(player, b);
|
||||
mca1.actionType = 3;
|
||||
mca1.setTargetType(building.getObjectType().ordinal());
|
||||
mca1.setTargetID(building.getObjectUUID());
|
||||
mca1.setTargetType(b.getObjectType().ordinal());
|
||||
mca1.setTargetID(b.getObjectUUID());
|
||||
|
||||
mca1.setTargetType3(npc.getObjectType().ordinal());
|
||||
mca1.setTargetID3(npc.getObjectUUID());
|
||||
mca1.setAssetName1(building.getName());
|
||||
mca1.setAssetName1(b.getName());
|
||||
mca1.setUnknown54(1);
|
||||
|
||||
Dispatch dispatch = Dispatch.borrow(playerCharacter, mca1);
|
||||
Dispatch dispatch = Dispatch.borrow(player, mca1);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
ManageNPCMsg mnm = new ManageNPCMsg(npc);
|
||||
dispatch = Dispatch.borrow(playerCharacter, mnm);
|
||||
dispatch = Dispatch.borrow(player, mnm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
//Add Minion
|
||||
@@ -112,7 +115,7 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
|
||||
if (npc.getContractID() == 842)
|
||||
maxSlots = 1;
|
||||
|
||||
if (npc.minions.size() == maxSlots)
|
||||
if (npc.getSiegeMinionMap().size() == maxSlots)
|
||||
return true;
|
||||
|
||||
int mobBase;
|
||||
@@ -143,15 +146,47 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
|
||||
if (mobBase == 0)
|
||||
return true;
|
||||
|
||||
Mob siegeMob = Mob.createSiegeMinion(npc, mobBase);
|
||||
Mob siegeMob = Mob.createSiegeMob(npc, mobBase, npc.getGuild(), zone, b.getLoc(), (short) 1);
|
||||
|
||||
if (siegeMob == null)
|
||||
return true;
|
||||
|
||||
if (siegeMob != null) {
|
||||
|
||||
siegeMob.setSpawnTime(60 * 15);
|
||||
Building building = BuildingManager.getBuilding(((MinionTrainingMessage) baseMsg).getBuildingID());
|
||||
|
||||
siegeMob.building = building;
|
||||
siegeMob.parentZone = zone;
|
||||
|
||||
// Slot siege minion
|
||||
// Can be either corner tower or bulwark.
|
||||
|
||||
int slot;
|
||||
|
||||
if (building.getBlueprint().getBuildingGroup().equals(Enum.BuildingGroup.ARTYTOWER))
|
||||
slot = 2;
|
||||
else
|
||||
slot = ((NPC) siegeMob.npcOwner).getSiegeMinionMap().get(siegeMob) + 1; // First slot is for the captain
|
||||
|
||||
BuildingLocation slotLocation = BuildingManager._slotLocations.get(building.meshUUID).get(slot);
|
||||
siegeMob.bindLoc = building.getLoc().add(slotLocation.getLocation());
|
||||
|
||||
// Rotate slot position by the building rotation
|
||||
|
||||
siegeMob.bindLoc = Vector3fImmutable.rotateAroundPoint(building.getLoc(), siegeMob.bindLoc, building.getBounds().getQuaternion().angleY);
|
||||
|
||||
siegeMob.loc = new Vector3fImmutable(siegeMob.bindLoc);
|
||||
siegeMob.endLoc = new Vector3fImmutable(siegeMob.bindLoc);
|
||||
|
||||
zone.zoneMobSet.add(siegeMob);
|
||||
siegeMob.setLoc(siegeMob.bindLoc);
|
||||
}
|
||||
}
|
||||
|
||||
ManageNPCMsg mnm = new ManageNPCMsg(npc);
|
||||
mnm.setMessageType(1);
|
||||
Dispatch dispatch = Dispatch.borrow(playerCharacter, mnm);
|
||||
Dispatch dispatch = Dispatch.borrow(player, mnm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
} finally {
|
||||
@@ -179,13 +214,13 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
Mob toRemove = Mob.getFromCache(minionMsg.getUUID());
|
||||
|
||||
if (!npc.minions.contains(toRemove.getObjectUUID()))
|
||||
if (!npc.getSiegeMinionMap().containsKey(toRemove))
|
||||
return true;
|
||||
|
||||
if (!DbManager.MobQueries.REMOVE_GUARD_MINION(npc.getObjectUUID(), toRemove.firstName))
|
||||
if (!DbManager.MobQueries.REMOVE_FROM_GUARDS(npc.getObjectUUID(), toRemove.getMobBaseID(), npc.getSiegeMinionMap().get(toRemove)))
|
||||
return true;
|
||||
|
||||
npc.minions.remove(Integer.valueOf(toRemove.getObjectUUID()));
|
||||
npc.getSiegeMinionMap().remove(toRemove);
|
||||
|
||||
WorldGrid.RemoveWorldObject(toRemove);
|
||||
|
||||
@@ -193,22 +228,17 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
|
||||
toRemove.getParentZone().zoneMobSet.remove(toRemove);
|
||||
|
||||
DbManager.removeFromCache(toRemove);
|
||||
|
||||
if (toRemove.agentType.equals(Enum.AIAgentType.SIEGEENGINE)) {
|
||||
|
||||
PlayerCharacter trebOwner = (PlayerCharacter) toRemove.guardCaptain;
|
||||
|
||||
if (trebOwner != null) {
|
||||
trebOwner.setPet(null);
|
||||
|
||||
toRemove.guardCaptain = null;
|
||||
PetMsg petMsg = new PetMsg(5, null);
|
||||
Dispatch dispatch = Dispatch.borrow(trebOwner, petMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
}
|
||||
PlayerCharacter petOwner = toRemove.getOwner();
|
||||
|
||||
if (petOwner != null) {
|
||||
petOwner.setPet(null);
|
||||
toRemove.setOwner(null);
|
||||
PetMsg petMsg = new PetMsg(5, null);
|
||||
Dispatch dispatch = Dispatch.borrow(petOwner, petMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
ManageCityAssetsMsg mca1 = new ManageCityAssetsMsg(playerCharacter, building);
|
||||
ManageCityAssetsMsg mca1 = new ManageCityAssetsMsg(player, building);
|
||||
mca1.actionType = 3;
|
||||
mca1.setTargetType(building.getObjectType().ordinal());
|
||||
mca1.setTargetID(building.getObjectUUID());
|
||||
@@ -218,11 +248,11 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
|
||||
mca1.setAssetName1(building.getName());
|
||||
mca1.setUnknown54(1);
|
||||
|
||||
Dispatch dispatch = Dispatch.borrow(playerCharacter, mca1);
|
||||
Dispatch dispatch = Dispatch.borrow(player, mca1);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
ManageNPCMsg mnm = new ManageNPCMsg(npc);
|
||||
dispatch = Dispatch.borrow(playerCharacter, mnm);
|
||||
dispatch = Dispatch.borrow(player, mnm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
//Add Minion
|
||||
@@ -258,7 +288,7 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
|
||||
break;
|
||||
}
|
||||
|
||||
if (npc.minions.size() == maxSlots)
|
||||
if (npc.getSiegeMinionMap().size() == maxSlots)
|
||||
return true;
|
||||
|
||||
int mobBase = npc.getMobBaseID();
|
||||
@@ -268,12 +298,12 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
String pirateName = NPCManager.getPirateName(mobBase);
|
||||
|
||||
Mob toCreate = Mob.createGuardMinion(npc, npc.getLevel(), pirateName);
|
||||
|
||||
if (toCreate == null)
|
||||
if (!DbManager.MobQueries.ADD_TO_GUARDS(npc.getObjectUUID(), mobBase, pirateName, npc.getSiegeMinionMap().size() + 1))
|
||||
return true;
|
||||
|
||||
if (!DbManager.MobQueries.ADD_GUARD_MINION(npc.getObjectUUID(), pirateName))
|
||||
Mob toCreate = Mob.createGuardMob(npc, npc.getGuild(), zone, building.getLoc(), npc.getLevel(), pirateName);
|
||||
|
||||
if (toCreate == null)
|
||||
return true;
|
||||
|
||||
if (toCreate != null) {
|
||||
@@ -284,7 +314,7 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
ManageNPCMsg mnm = new ManageNPCMsg(npc);
|
||||
mnm.setMessageType(1);
|
||||
Dispatch dispatch = Dispatch.borrow(playerCharacter, mnm);
|
||||
Dispatch dispatch = Dispatch.borrow(player, mnm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -9,14 +9,12 @@
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.MovementManager;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.MoveToPointMsg;
|
||||
import engine.objects.*;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class MoveToPointHandler extends AbstractClientMsgHandler {
|
||||
|
||||
@@ -28,11 +26,13 @@ public class MoveToPointHandler extends AbstractClientMsgHandler {
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg,
|
||||
ClientConnection origin) throws MsgSendException {
|
||||
MoveToPointMsg msg = (MoveToPointMsg) baseMsg;
|
||||
PlayerCharacter pc = origin.getPlayerCharacter();
|
||||
if(pc == null)
|
||||
return true;
|
||||
|
||||
PlayerCharacter pc = (origin != null) ? (origin.getPlayerCharacter()) : null;
|
||||
if (pc == null)
|
||||
return false;
|
||||
|
||||
MovementManager.movement(msg, pc);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import engine.Enum.ProfitType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.NPCManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.math.FastMath;
|
||||
import engine.math.Vector3fImmutable;
|
||||
@@ -36,7 +37,7 @@ public class OrderNPCMsgHandler extends AbstractClientMsgHandler {
|
||||
super(OrderNPCMsg.class);
|
||||
}
|
||||
|
||||
public static void processRedeedHireling(AbstractCharacter hireling, Building building, ClientConnection origin) {
|
||||
public static void processRedeedMob(Mob mob, Building building, ClientConnection origin) {
|
||||
|
||||
PlayerCharacter player;
|
||||
Contract contract;
|
||||
@@ -47,28 +48,33 @@ public class OrderNPCMsgHandler extends AbstractClientMsgHandler {
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
itemMan = player.getCharItemManager();
|
||||
|
||||
contract = hireling.contract;
|
||||
contract = mob.getContract();
|
||||
|
||||
if (!player.getCharItemManager().hasRoomInventory((short) 1)) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 21);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!building.getHirelings().containsKey(hireling))
|
||||
if (!building.getHirelings().containsKey(mob))
|
||||
return;
|
||||
|
||||
BuildingManager.removeHireling(building, hireling);
|
||||
if (!NPCManager.removeMobileFromBuilding(mob, building)) {
|
||||
PlaceAssetMsg.sendPlaceAssetError(player.getClientConnection(), 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
||||
return;
|
||||
}
|
||||
|
||||
building.getHirelings().remove(mob);
|
||||
|
||||
itemBase = ItemBase.getItemBase(contract.getContractID());
|
||||
|
||||
if (itemBase == null) {
|
||||
Logger.error("Could not find Contract for npc: " + hireling.getObjectUUID());
|
||||
Logger.error("Could not find Contract for npc: " + mob.getObjectUUID());
|
||||
return;
|
||||
}
|
||||
|
||||
boolean itemWorked = false;
|
||||
|
||||
item = new Item(itemBase, player.getObjectUUID(), Enum.OwnerType.PlayerCharacter, (byte) ((byte) hireling.getRank() - 1), (byte) ((byte) hireling.getRank() - 1), (short) 1, (short) 1, true, false, Enum.ItemContainerType.INVENTORY, (byte) 0, new ArrayList<>(), "");
|
||||
item = new Item(itemBase, player.getObjectUUID(), Enum.OwnerType.PlayerCharacter, (byte) ((byte) mob.getRank() - 1), (byte) ((byte) mob.getRank() - 1), (short) 1, (short) 1, true, false, Enum.ItemContainerType.INVENTORY, (byte) 0, new ArrayList<>(), "");
|
||||
item.setNumOfItems(1);
|
||||
item.containerType = Enum.ItemContainerType.INVENTORY;
|
||||
|
||||
@@ -206,6 +212,10 @@ public class OrderNPCMsgHandler extends AbstractClientMsgHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
for (AbstractCharacter guard : building.getHirelings().keySet()) {
|
||||
if (guard.getObjectType() == GameObjectType.Mob)
|
||||
((Mob) guard).setPatrolPointIndex(0);
|
||||
}
|
||||
} else if (building.getPatrolPoints() != null)
|
||||
ClearPatrolPoints(building.getObjectUUID());
|
||||
|
||||
@@ -213,6 +223,10 @@ public class OrderNPCMsgHandler extends AbstractClientMsgHandler {
|
||||
AddSentryPoints(building.getObjectUUID(), orderNpcMsg.getSentryPoints());
|
||||
} else if (building.getSentryPoints() != null)
|
||||
ClearSentryPoints(building.getObjectUUID());
|
||||
|
||||
// Dispatch dispatch = Dispatch.borrow(pc, msg);
|
||||
// DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
}
|
||||
|
||||
private static void processUpgradeNPC(PlayerCharacter player, AbstractCharacter abstractCharacter) {
|
||||
@@ -276,6 +290,28 @@ public class OrderNPCMsgHandler extends AbstractClientMsgHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private static synchronized void processRedeedNPC(AbstractCharacter abstractCharacter, Building building, ClientConnection origin) {
|
||||
|
||||
// Member variable declaration
|
||||
|
||||
switch (abstractCharacter.getObjectType()) {
|
||||
case NPC:
|
||||
NPC npc = (NPC) abstractCharacter;
|
||||
|
||||
Building cityBuilding = npc.getBuilding();
|
||||
|
||||
if (cityBuilding == null)
|
||||
return;
|
||||
|
||||
BuildingManager.processRedeedNPC(npc, npc.building, origin);
|
||||
break;
|
||||
case Mob:
|
||||
Mob mob = (Mob) abstractCharacter;
|
||||
processRedeedMob(mob, mob.building, origin);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean AddPatrolPoints(int buildingID, ArrayList<Vector3fImmutable> patrolPoints) {
|
||||
|
||||
Building building = BuildingManager.getBuildingFromCache(buildingID);
|
||||
@@ -466,7 +502,7 @@ public class OrderNPCMsgHandler extends AbstractClientMsgHandler {
|
||||
if (BuildingManager.PlayerCanControlNotOwner(building, player) == false)
|
||||
return true;
|
||||
|
||||
processRedeedHireling(npc, building, origin);
|
||||
processRedeedNPC(npc, building, origin);
|
||||
return true;
|
||||
//MB TODO HANDLE all profits.
|
||||
case 7:
|
||||
@@ -505,7 +541,7 @@ public class OrderNPCMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
} else if (orderNPCMsg.getObjectType() == GameObjectType.Mob.ordinal()) {
|
||||
|
||||
mob = Mob.getMob(orderNPCMsg.getNpcUUID());
|
||||
mob = Mob.getFromCacheDBID(orderNPCMsg.getNpcUUID());
|
||||
|
||||
if (mob == null)
|
||||
return true;
|
||||
@@ -534,7 +570,10 @@ public class OrderNPCMsgHandler extends AbstractClientMsgHandler {
|
||||
if (building.getHirelings().containsKey(mob) == false)
|
||||
return true;
|
||||
|
||||
BuildingManager.removeHireling(building, mob);
|
||||
if (NPCManager.removeMobileFromBuilding(mob, building) == false) {
|
||||
PlaceAssetMsg.sendPlaceAssetError(player.getClientConnection(), 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
||||
return true;
|
||||
}
|
||||
|
||||
ManageCityAssetsMsg manageCityAssetsMsg = new ManageCityAssetsMsg();
|
||||
manageCityAssetsMsg.actionType = SVR_CLOSE_WINDOW;
|
||||
@@ -569,7 +608,7 @@ public class OrderNPCMsgHandler extends AbstractClientMsgHandler {
|
||||
if (BuildingManager.PlayerCanControlNotOwner(building, player) == false)
|
||||
return true;
|
||||
|
||||
processRedeedHireling(mob, building, origin);
|
||||
processRedeedNPC(mob, building, origin);
|
||||
return true;
|
||||
//MB TODO HANDLE all profits.
|
||||
case 7:
|
||||
|
||||
@@ -745,7 +745,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
}
|
||||
|
||||
Vector3fImmutable plantLoc = new Vector3fImmutable(treeInfo.getLoc().x,
|
||||
0,
|
||||
HeightMap.getWorldHeight(treeInfo.getLoc()),
|
||||
treeInfo.getLoc().z);
|
||||
|
||||
cityObjects = DbManager.CityQueries.CREATE_CITY(playerCharacter.getObjectUUID(), serverZone.getObjectUUID(),
|
||||
@@ -754,7 +754,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
plantLoc.z - serverZone.getAbsZ(), treeInfo.getRot().y, treeInfo.getW(), playerCharacter.getGuild().getName(), LocalDateTime.now());
|
||||
|
||||
// Uh oh!
|
||||
|
||||
if (cityObjects == null || cityObjects.isEmpty()) {
|
||||
PlaceAssetMsg.sendPlaceAssetError(origin, 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
||||
return false;
|
||||
@@ -768,7 +767,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
treeObject = (Building) cityObjectMap.get(GameObjectType.Building);
|
||||
treeObject.runAfterLoad();
|
||||
|
||||
;
|
||||
cityObject = (City) cityObjectMap.get(GameObjectType.City);
|
||||
zoneObject = (Zone) cityObjectMap.get(GameObjectType.Zone);
|
||||
|
||||
@@ -793,11 +792,10 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
ZoneManager.addPlayerCityZone(zoneObject);
|
||||
serverZone.addNode(zoneObject);
|
||||
|
||||
zoneObject.worldAltitude = ZoneManager.caclulateWorldAltitude(zoneObject);
|
||||
zoneObject.generateWorldAltitude();
|
||||
|
||||
cityObject.setParent(zoneObject);
|
||||
cityObject.setObjectTypeMask(MBServerStatics.MASK_CITY); // *** Refactor : should have it already
|
||||
|
||||
//Link the tree of life with the new zone
|
||||
|
||||
treeObject.setObjectTypeMask(MBServerStatics.MASK_BUILDING);
|
||||
@@ -819,6 +817,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
City.lastCityUpdate = System.currentTimeMillis();
|
||||
treeObject.setLoc(treeObject.getLoc());
|
||||
InterestManager.setObjectDirty(treeObject);
|
||||
// WorldGrid.addObject(treeObject, playerCharacter);
|
||||
|
||||
serverRealm.addCity(cityObject.getObjectUUID());
|
||||
playerNation.setCityUUID(cityObject.getObjectUUID());
|
||||
@@ -916,7 +915,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
// Early exit if something went horribly wrong
|
||||
// with locating the current realm and/or zone
|
||||
|
||||
if (serverZone == null)
|
||||
return false;
|
||||
|
||||
@@ -979,8 +977,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
City cityObject;
|
||||
PlacementInfo buildingList;
|
||||
|
||||
// Setup working variables
|
||||
|
||||
// Setup working variables we'll need
|
||||
buildingList = msg.getFirstPlacementInfo();
|
||||
|
||||
serverZone = ZoneManager.findSmallestZone(buildingList.getLoc());
|
||||
@@ -1093,6 +1090,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
placementCost = 0; // reset placement cost for fix bug with wall pieces somethings not taking gold out if forced an error.
|
||||
|
||||
|
||||
// Overlap check and wall deed verifications
|
||||
for (PlacementInfo wall : walls) {
|
||||
|
||||
@@ -1111,6 +1109,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
for (Building building : serverZone.zoneBuildingSet) {
|
||||
|
||||
|
||||
//TODO Clean up collision with placementInfo. don't need to create the same placementinfo bounds for collision checks on each building.
|
||||
if ((building.getBlueprintUUID() != 0) && (Bounds.collide(wall, building) == true)) {
|
||||
|
||||
@@ -1130,14 +1129,12 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
placementCost = PlaceAssetMsg.getWallCost(wall.getBlueprintUUID());
|
||||
|
||||
if (!itemMan.modifyInventoryGold(-placementCost)) {
|
||||
ChatManager.chatSystemInfo(player, player.getFirstName() + " can't has free moneys! no for real.. Thor.. seriously... I didnt fix it because you getting laid isnt important enough for me.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Attempt to place wall piece
|
||||
|
||||
wallPiece = createStructure(player, wall, serverZone);
|
||||
@@ -1148,12 +1145,14 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
}
|
||||
|
||||
// walls are auto protected
|
||||
|
||||
wallPiece.setProtectionState(ProtectionState.PROTECTED);
|
||||
PlaceAssetMsg.sendPlaceAssetConfirmWall(origin, serverZone);
|
||||
|
||||
}
|
||||
|
||||
// Deduct gold from character's inventory
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1173,7 +1172,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
}
|
||||
|
||||
// All siege buildings build in 15 minutes
|
||||
|
||||
if ((blueprint.getBuildingGroup().equals(BuildingGroup.SIEGETENT))
|
||||
|| (blueprint.getBuildingGroup().equals(BuildingGroup.BULWARK)))
|
||||
completionDate = DateTime.now().plusMinutes(15);
|
||||
@@ -1193,7 +1191,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
completionDate, blueprint.getMeshForRank(0), vendorRotation, buildingRotation);
|
||||
|
||||
// Make sure we have a valid mesh
|
||||
|
||||
if (newMesh == null) {
|
||||
Logger.error("CreateStructure: DB returned null object.");
|
||||
return null;
|
||||
@@ -1365,16 +1362,15 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
newMesh = (Building) ago;
|
||||
newMesh.setObjectTypeMask(MBServerStatics.MASK_BUILDING);
|
||||
MaintenanceManager.setMaintDateTime(newMesh, LocalDateTime.now().plusDays(7));
|
||||
// WorldGrid.addObject(newMesh, player);
|
||||
newMesh.setLoc(newMesh.getLoc());
|
||||
InterestManager.setObjectDirty(newMesh);
|
||||
newMesh.runAfterLoad();
|
||||
} else if (ago.getObjectType() == GameObjectType.Warehouse) {
|
||||
Warehouse warehouse = (Warehouse) ago;
|
||||
City city = City.getCity(currentZone.getPlayerCityUUID());
|
||||
|
||||
if (city == null)
|
||||
return true;
|
||||
|
||||
city.setWarehouseBuildingID(newMesh.getObjectUUID());
|
||||
Warehouse.warehouseByBuildingUUID.put(newMesh.getObjectUUID(), warehouse);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.pmw.tinylog.Logger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -95,7 +96,7 @@ public class ManageNPCMsg extends ClientNetMsg {
|
||||
writer.putString("A weapon suited to laying siege");
|
||||
}
|
||||
|
||||
private static void serializeGuardList(ByteBufferWriter writer, int minion, Mob captain) {
|
||||
private static void serializeGuardList(ByteBufferWriter writer, int minion) {
|
||||
|
||||
writer.putInt(1);
|
||||
|
||||
@@ -105,7 +106,7 @@ public class ManageNPCMsg extends ClientNetMsg {
|
||||
writer.putInt(minion);
|
||||
writer.putInt(1);
|
||||
writer.putInt(minion);
|
||||
writer.putInt(captain.getRank());//minion rank
|
||||
writer.putInt(1);
|
||||
writer.put((byte) 0);
|
||||
|
||||
writer.putInt(600); //roll time
|
||||
@@ -342,17 +343,14 @@ public class ManageNPCMsg extends ClientNetMsg {
|
||||
writer.putInt(0); //runemaster list
|
||||
|
||||
//artillery captain list
|
||||
|
||||
writer.putInt(1 + npc.minions.size());
|
||||
ConcurrentHashMap<Mob, Integer> siegeMinions = npc.getSiegeMinionMap();
|
||||
writer.putInt(1 + siegeMinions.size());
|
||||
serializeBulwarkList(writer, 1); //Trebuchet
|
||||
//serializeBulwarkList(writer, 2); //Ballista
|
||||
|
||||
if (npc.minions != null && npc.minions.size() > 0)
|
||||
|
||||
for (Integer minionUUID : npc.minions) {
|
||||
|
||||
Mob mob = Mob.getMob(minionUUID);
|
||||
if (siegeMinions != null && siegeMinions.size() > 0)
|
||||
|
||||
for (Mob mob : siegeMinions.keySet()) {
|
||||
this.unknown83 = mob.getObjectUUID();
|
||||
writer.putInt(2);
|
||||
writer.putInt(mob.getObjectType().ordinal());
|
||||
@@ -368,7 +366,7 @@ public class ManageNPCMsg extends ClientNetMsg {
|
||||
long timeLife = upgradeTime - curTime;
|
||||
|
||||
if (upgradeTime * 1000 > System.currentTimeMillis()) {
|
||||
if (mob.guardCaptain.isAlive()) {
|
||||
if (mob.npcOwner.isAlive()) {
|
||||
writer.put((byte) 0);//shows respawning timer
|
||||
writer.putInt(mob.spawnTime);
|
||||
writer.putInt(mob.spawnTime);
|
||||
@@ -559,7 +557,7 @@ public class ManageNPCMsg extends ClientNetMsg {
|
||||
|
||||
} else if (this.targetType == GameObjectType.Mob.ordinal()) {
|
||||
|
||||
mobA = Mob.getMob(this.targetID);
|
||||
mobA = Mob.getFromCacheDBID(this.targetID);
|
||||
|
||||
if (mobA == null) {
|
||||
Logger.error("Missing Mob of ID " + this.targetID);
|
||||
@@ -668,15 +666,14 @@ public class ManageNPCMsg extends ClientNetMsg {
|
||||
writer.putInt(0); //runemaster list
|
||||
|
||||
//artillery captain list
|
||||
ConcurrentHashMap<Mob, Integer> siegeMinions = mobA.getSiegeMinionMap();
|
||||
|
||||
writer.putInt(mobA.minions.size() + 1);
|
||||
|
||||
serializeGuardList(writer, mobA.getContract().getContractID(), mobA); //Guard
|
||||
writer.putInt(siegeMinions.size() + 1);
|
||||
serializeGuardList(writer, mobA.getContract().getContractID()); //Guard
|
||||
|
||||
if (mobA.minions != null && mobA.minions.size() > 0)
|
||||
if (siegeMinions != null && siegeMinions.size() > 0)
|
||||
|
||||
for (Integer minionUUID : mobA.minions) {
|
||||
Mob mob = Mob.getMob(minionUUID);
|
||||
for (Mob mob : siegeMinions.keySet()) {
|
||||
this.unknown83 = mob.getObjectUUID();
|
||||
writer.putInt(2);
|
||||
writer.putInt(mob.getObjectType().ordinal());
|
||||
@@ -692,7 +689,7 @@ public class ManageNPCMsg extends ClientNetMsg {
|
||||
long timeLife = upgradeTime - curTime;
|
||||
|
||||
if (upgradeTime * 1000 > System.currentTimeMillis()) {
|
||||
if (mob.guardCaptain.isAlive()) {
|
||||
if (mob.npcOwner.isAlive()) {
|
||||
writer.put((byte) 0);//shows respawning timer
|
||||
writer.putInt(mob.spawnTime);
|
||||
writer.putInt(mob.spawnTime);
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
package engine.net.client.msg;
|
||||
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.ZoneManager;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.net.AbstractConnection;
|
||||
@@ -22,19 +21,19 @@ import engine.objects.Building;
|
||||
|
||||
public class MoveToPointMsg extends ClientNetMsg {
|
||||
|
||||
private int sourceType; //ordinal of the character type that sent this message 54=PlayerCharacter
|
||||
private int sourceID; // uuid of the source character of this message
|
||||
private float startLat; //start loc of move message (offset if inside a building not world loc)
|
||||
private float startLon; //start loc of move message (offset if inside a building not world loc)
|
||||
private float startAlt; //start loc of move message (offset if inside a building not world loc)
|
||||
private float endLat; //end loc of move message (offset if inside a building not world loc)
|
||||
private float endLon; //end loc of move message (offset if inside a building not world loc)
|
||||
private float endAlt; //end loc of move message (offset if inside a building not world loc)
|
||||
private int startLocType; // enum ordinal of the object player is inside 0=nothing 8=building
|
||||
private int inBuildingUUID; // uuid of the building character is currently inside
|
||||
private int inBuilding; // is inside a building 0=true -1=false
|
||||
private int inBuildingFloor; // floor of building character is currently in -1=not inside building 0/1/2/3 = floor number
|
||||
private byte initiatedByAttack; // move message sent as a result of move to target to attack 0=false 1=true
|
||||
private int sourceType;
|
||||
private int sourceID;
|
||||
private float startLat;
|
||||
private float startLon;
|
||||
private float startAlt;
|
||||
private float endLat;
|
||||
private float endLon;
|
||||
private float endAlt;
|
||||
private int targetType;
|
||||
private int targetID;
|
||||
private int inBuilding; // 0=true, -1=false 0/1/2 = floor you are on
|
||||
private int unknown01;
|
||||
private byte unknown02;
|
||||
private byte unknown03;
|
||||
|
||||
/**
|
||||
@@ -55,11 +54,11 @@ public class MoveToPointMsg extends ClientNetMsg {
|
||||
this.endLat = msg.endLat;
|
||||
this.endLon = msg.endLon;
|
||||
this.endAlt = msg.endAlt;
|
||||
this.startLocType = msg.startLocType;
|
||||
this.inBuildingUUID = msg.inBuildingUUID;
|
||||
this.targetType = msg.targetType;
|
||||
this.targetID = msg.targetID;
|
||||
this.inBuilding = msg.inBuilding;
|
||||
this.inBuildingFloor = msg.inBuildingFloor;
|
||||
this.initiatedByAttack = msg.initiatedByAttack;
|
||||
this.unknown01 = msg.unknown01;
|
||||
this.unknown02 = msg.unknown02;
|
||||
this.unknown03 = msg.unknown03;
|
||||
}
|
||||
|
||||
@@ -74,11 +73,11 @@ public class MoveToPointMsg extends ClientNetMsg {
|
||||
this.endLat = building.getLoc().x;
|
||||
this.endLon = building.getLoc().z;
|
||||
this.endAlt = building.getLoc().y;
|
||||
this.startLocType = 0;
|
||||
this.inBuildingUUID = 0;
|
||||
this.targetType = 0;
|
||||
this.targetID = 0;
|
||||
this.inBuilding = -1;
|
||||
this.inBuildingFloor = -1;
|
||||
this.initiatedByAttack = 0;
|
||||
this.unknown01 = -1;
|
||||
this.unknown02 = 0;
|
||||
this.unknown03 = 0;
|
||||
}
|
||||
|
||||
@@ -109,11 +108,11 @@ public class MoveToPointMsg extends ClientNetMsg {
|
||||
writer.putFloat(this.endAlt);
|
||||
writer.putFloat(this.endLon);
|
||||
|
||||
writer.putInt(this.startLocType);
|
||||
writer.putInt(this.inBuildingUUID);
|
||||
writer.putInt(this.targetType);
|
||||
writer.putInt(this.targetID);
|
||||
|
||||
writer.putInt(this.inBuilding);
|
||||
writer.putInt(this.inBuildingFloor);
|
||||
writer.putInt(this.unknown01);
|
||||
|
||||
writer.put((byte) 0);
|
||||
writer.put((byte) 0);
|
||||
@@ -136,13 +135,13 @@ public class MoveToPointMsg extends ClientNetMsg {
|
||||
this.endAlt = reader.getFloat();
|
||||
this.endLon = reader.getFloat();
|
||||
|
||||
this.startLocType = reader.getInt();
|
||||
this.inBuildingUUID = reader.getInt();
|
||||
this.targetType = reader.getInt();
|
||||
this.targetID = reader.getInt();
|
||||
|
||||
this.inBuilding = reader.getInt();
|
||||
this.inBuildingFloor = reader.getInt();
|
||||
this.unknown01 = reader.getInt();
|
||||
|
||||
this.initiatedByAttack = reader.get();
|
||||
this.unknown02 = reader.get();
|
||||
this.unknown03 = reader.get();
|
||||
}
|
||||
|
||||
@@ -210,20 +209,20 @@ public class MoveToPointMsg extends ClientNetMsg {
|
||||
this.endAlt = value;
|
||||
}
|
||||
|
||||
public int getStartLocType() {
|
||||
return this.startLocType;
|
||||
public int getTargetType() {
|
||||
return this.targetType;
|
||||
}
|
||||
|
||||
public void setStartLocType(int value) {
|
||||
this.startLocType = value;
|
||||
public void setTargetType(int value) {
|
||||
this.targetType = value;
|
||||
}
|
||||
|
||||
public int getInBuildingUUID() {
|
||||
return this.inBuildingUUID;
|
||||
public int getTargetID() {
|
||||
return this.targetID;
|
||||
}
|
||||
|
||||
public void setInBuildingUUID(int value) {
|
||||
this.inBuildingUUID = value;
|
||||
public void setTargetID(int value) {
|
||||
this.targetID = value;
|
||||
}
|
||||
|
||||
public int getInBuilding() {
|
||||
@@ -234,8 +233,12 @@ public class MoveToPointMsg extends ClientNetMsg {
|
||||
this.inBuilding = value;
|
||||
}
|
||||
|
||||
public void setInBuildingFloor(int value) {
|
||||
this.inBuildingFloor = value;
|
||||
public int getUnknown01() {
|
||||
return this.unknown01;
|
||||
}
|
||||
|
||||
public void setUnknown01(int value) {
|
||||
this.unknown01 = value;
|
||||
}
|
||||
|
||||
public void setStartCoord(Vector3fImmutable value) {
|
||||
@@ -251,8 +254,8 @@ public class MoveToPointMsg extends ClientNetMsg {
|
||||
}
|
||||
|
||||
public void clearTarget() {
|
||||
this.startLocType = 0;
|
||||
this.inBuildingUUID = 0;
|
||||
this.targetType = 0;
|
||||
this.targetID = 0;
|
||||
}
|
||||
|
||||
public void setPlayer(AbstractCharacter ac) {
|
||||
@@ -260,10 +263,10 @@ public class MoveToPointMsg extends ClientNetMsg {
|
||||
this.sourceID = ac.getObjectUUID();
|
||||
this.setStartCoord(ac.getLoc());
|
||||
this.setEndCoord(ac.getEndLoc());
|
||||
this.startLocType = 0;
|
||||
this.inBuildingUUID = 0;
|
||||
this.targetType = 0;
|
||||
this.targetID = 0;
|
||||
this.inBuilding = ac.getInBuilding();
|
||||
this.inBuildingFloor = ac.getInFloorID();
|
||||
this.unknown01 = ac.getInFloorID();
|
||||
|
||||
}
|
||||
|
||||
@@ -271,10 +274,10 @@ public class MoveToPointMsg extends ClientNetMsg {
|
||||
if (target == null) {
|
||||
this.setStartCoord(ac.getLoc());
|
||||
this.setEndCoord(ac.getEndLoc());
|
||||
this.startLocType = 0;
|
||||
this.inBuildingUUID = 0;
|
||||
this.targetType = 0;
|
||||
this.targetID = 0;
|
||||
this.inBuilding = -1;
|
||||
this.inBuildingFloor = -1;
|
||||
this.unknown01 = -1;
|
||||
} else {
|
||||
Vector3fImmutable convertLocStart = ZoneManager.convertWorldToLocal(target, ac.getLoc());
|
||||
Vector3fImmutable convertLocEnd = convertLocStart;
|
||||
@@ -283,10 +286,10 @@ public class MoveToPointMsg extends ClientNetMsg {
|
||||
|
||||
this.setStartCoord(convertLocStart);
|
||||
this.setEndCoord(convertLocEnd);
|
||||
this.startLocType = GameObjectType.Building.ordinal();
|
||||
this.inBuildingUUID = target.getObjectUUID();
|
||||
this.targetType = GameObjectType.Building.ordinal();
|
||||
this.targetID = target.getObjectUUID();
|
||||
this.inBuilding = ac.getInBuilding();
|
||||
this.inBuildingFloor = ac.getInFloorID();
|
||||
this.unknown01 = ac.getInFloorID();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -295,11 +298,7 @@ public class MoveToPointMsg extends ClientNetMsg {
|
||||
return unknown03;
|
||||
}
|
||||
|
||||
public int getInitiatedFromAttack() {
|
||||
return initiatedByAttack;
|
||||
}
|
||||
|
||||
public int getInBuildingFloor() {
|
||||
return this.inBuildingFloor;
|
||||
public int getUnknown02() {
|
||||
return unknown02;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,10 @@ import engine.Enum.*;
|
||||
import engine.InterestManagement.InterestManager;
|
||||
import engine.InterestManagement.WorldGrid;
|
||||
import engine.exception.SerializationException;
|
||||
import engine.gameManager.*;
|
||||
import engine.gameManager.CombatManager;
|
||||
import engine.gameManager.ConfigManager;
|
||||
import engine.gameManager.MovementManager;
|
||||
import engine.gameManager.PowersManager;
|
||||
import engine.job.AbstractJob;
|
||||
import engine.job.JobContainer;
|
||||
import engine.job.JobScheduler;
|
||||
@@ -36,7 +39,6 @@ import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
@@ -50,8 +52,8 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
|
||||
public int contractUUID;
|
||||
public Contract contract;
|
||||
|
||||
public String firstName;
|
||||
public String lastName;
|
||||
protected String firstName;
|
||||
protected String lastName;
|
||||
protected short statStrCurrent;
|
||||
protected short statDexCurrent;
|
||||
protected short statConCurrent;
|
||||
@@ -69,7 +71,7 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
|
||||
public Guild guild;
|
||||
protected byte runningTrains;
|
||||
protected ConcurrentHashMap<Integer, CharacterPower> powers;
|
||||
public ConcurrentHashMap<String, CharacterSkill> skills;
|
||||
protected ConcurrentHashMap<String, CharacterSkill> skills;
|
||||
// Variables NOT to be stored in db
|
||||
protected boolean sit = false;
|
||||
protected boolean walkMode;
|
||||
@@ -86,20 +88,20 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
|
||||
protected AtomicFloat mana = new AtomicFloat();
|
||||
protected float manaMax; // Health/Mana/Stamina
|
||||
protected AtomicBoolean isAlive = new AtomicBoolean(true);
|
||||
public Resists resists = new Resists("Genric");
|
||||
protected Resists resists = new Resists("Genric");
|
||||
protected ConcurrentHashMap<String, JobContainer> timers;
|
||||
protected ConcurrentHashMap<String, Long> timestamps;
|
||||
public int atrHandOne;
|
||||
public int atrHandTwo;
|
||||
public int minDamageHandOne;
|
||||
public int maxDamageHandOne;
|
||||
public int minDamageHandTwo;
|
||||
public int maxDamageHandTwo;
|
||||
public float rangeHandOne;
|
||||
public float rangeHandTwo;
|
||||
public float speedHandOne;
|
||||
public float speedHandTwo;
|
||||
public int defenseRating;
|
||||
protected int atrHandOne;
|
||||
protected int atrHandTwo;
|
||||
protected int minDamageHandOne;
|
||||
protected int maxDamageHandOne;
|
||||
protected int minDamageHandTwo;
|
||||
protected int maxDamageHandTwo;
|
||||
protected float rangeHandOne;
|
||||
protected float rangeHandTwo;
|
||||
protected float speedHandOne;
|
||||
protected float speedHandTwo;
|
||||
protected int defenseRating;
|
||||
protected boolean isActive; // <-Do not use this for deleting character!
|
||||
protected float altitude = 0; // 0=on terrain, 1=tier 1, 2=tier 2, etc.
|
||||
protected ConcurrentHashMap<Integer, JobContainer> recycleTimers;
|
||||
@@ -115,35 +117,16 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
|
||||
protected boolean movingUp = false;
|
||||
private float desiredAltitude = 0;
|
||||
private long takeOffTime = 0;
|
||||
private float hateValue = 0;
|
||||
private long lastHateUpdate = 0;
|
||||
private boolean collided = false;
|
||||
private byte aoecntr = 0;
|
||||
|
||||
public int hidden = 0; // current rank of hide/sneak/invis
|
||||
public CopyOnWriteArrayList<Integer> minions = new CopyOnWriteArrayList();
|
||||
|
||||
public AbstractCharacter() {
|
||||
super();
|
||||
this.firstName = "";
|
||||
this.lastName = "";
|
||||
|
||||
this.statStrCurrent = (short) 0;
|
||||
this.statDexCurrent = (short) 0;
|
||||
this.statConCurrent = (short) 0;
|
||||
this.statIntCurrent = (short) 0;
|
||||
this.statSpiCurrent = (short) 0;
|
||||
|
||||
this.unusedStatPoints = (short) 0;
|
||||
|
||||
this.level = (short) 0; // TODO get this from MobsBase later
|
||||
this.exp = 1;
|
||||
this.walkMode = true;
|
||||
this.bindLoc = Vector3fImmutable.ZERO;
|
||||
this.faceDir = Vector3fImmutable.ZERO;
|
||||
|
||||
this.runningTrains = (byte) 0;
|
||||
|
||||
this.skills = new ConcurrentHashMap<>();
|
||||
this.powers = new ConcurrentHashMap<>();
|
||||
this.powers = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
|
||||
this.skills = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
|
||||
this.initializeCharacter();
|
||||
|
||||
}
|
||||
@@ -231,6 +214,8 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
|
||||
this.skills = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
|
||||
this.initializeCharacter();
|
||||
|
||||
// Dangerous to use THIS in a constructor!!!
|
||||
this.charItemManager = new CharacterItemManager(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,6 +258,8 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
|
||||
this.powers = new ConcurrentHashMap<>();
|
||||
this.initializeCharacter();
|
||||
|
||||
// Dangerous to use THIS in a constructor!!!
|
||||
this.charItemManager = new CharacterItemManager(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -304,6 +291,8 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
|
||||
this.powers = new ConcurrentHashMap<>();
|
||||
initializeCharacter();
|
||||
|
||||
// Dangerous to use THIS in a constructor!!!
|
||||
this.charItemManager = new CharacterItemManager(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -353,6 +342,9 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
|
||||
this.powers = new ConcurrentHashMap<>();
|
||||
|
||||
this.initializeCharacter();
|
||||
|
||||
// Dangerous to use THIS in a constructor!!!
|
||||
this.charItemManager = new CharacterItemManager(this);
|
||||
}
|
||||
|
||||
public static int getBankCapacity() {
|
||||
@@ -1104,7 +1096,6 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
|
||||
}
|
||||
|
||||
public final void setCombatTarget(final AbstractWorldObject value) {
|
||||
|
||||
if(this.getObjectTypeMask() == 2050) {//MOB?
|
||||
if (value == null) {
|
||||
if (this.isCombat()) {
|
||||
@@ -1122,9 +1113,7 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.combatTarget = value;
|
||||
|
||||
}
|
||||
|
||||
public final ConcurrentHashMap<String, JobContainer> getTimers() {
|
||||
@@ -1241,29 +1230,11 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
|
||||
CombatManager.handleRetaliate(this, attacker);
|
||||
}
|
||||
|
||||
if(this.getObjectType().equals(GameObjectType.Mob)){
|
||||
//handle hate value addition
|
||||
Mob target = (Mob)this;
|
||||
if (attacker.getObjectType().equals(GameObjectType.PlayerCharacter)) {
|
||||
target.playerAgroMap.put(attacker.getObjectUUID(), target.playerAgroMap.get(attacker.getObjectUUID()) + value);
|
||||
if (target.isPlayerGuard()){
|
||||
if(target.guardedCity != null && target.guardedCity.cityOutlaws.contains(attacker.getObjectUUID()) == false)
|
||||
target.guardedCity.cityOutlaws.add(attacker.getObjectUUID());
|
||||
}
|
||||
}
|
||||
} else if(this.getObjectType().equals(GameObjectType.PlayerCharacter)){
|
||||
City playerCity = ZoneManager.getCityAtLocation(this.loc);
|
||||
if(playerCity != null){
|
||||
if(!attacker.getGuild().getNation().equals(playerCity.getGuild().getNation()))
|
||||
if(!playerCity.getGuild().getNation().getAllyList().contains(attacker.getGuild().getNation()))
|
||||
if(!playerCity.cityOutlaws.contains(attacker.getObjectUUID()))
|
||||
playerCity.cityOutlaws.add(attacker.getObjectUUID());
|
||||
}
|
||||
}
|
||||
return newHealth - oldHealth;
|
||||
} finally {
|
||||
this.healthLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
@@ -1787,6 +1758,29 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
|
||||
this.inBuildingID = inBuildingID;
|
||||
}
|
||||
|
||||
public float getHateValue() {
|
||||
if (this.hateValue <= 0) {
|
||||
this.hateValue = 0;
|
||||
return hateValue;
|
||||
}
|
||||
|
||||
if (this.lastHateUpdate == 0) {
|
||||
this.lastHateUpdate = System.currentTimeMillis();
|
||||
return this.hateValue;
|
||||
}
|
||||
long duration = System.currentTimeMillis() - this.lastHateUpdate;
|
||||
//convert duration to seconds and multiply Hate Delimiter.
|
||||
float modAmount = duration / 1000 * MBServerStatics.PLAYER_HATE_DELIMITER;
|
||||
this.hateValue -= modAmount;
|
||||
this.lastHateUpdate = System.currentTimeMillis();
|
||||
return this.hateValue;
|
||||
}
|
||||
|
||||
public void setHateValue(float hateValue) {
|
||||
this.lastHateUpdate = System.currentTimeMillis();
|
||||
this.hateValue = hateValue;
|
||||
}
|
||||
|
||||
public int getInFloorID() {
|
||||
return inFloorID;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
package engine.objects;
|
||||
|
||||
import ch.claude_martin.enumbitset.EnumBitSet;
|
||||
import engine.Enum;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.Enum.ModType;
|
||||
@@ -33,19 +32,6 @@ public abstract class AbstractIntelligenceAgent extends AbstractCharacter {
|
||||
public boolean assist = false;
|
||||
public Enum.AIAgentType agentType = Enum.AIAgentType.MOBILE;
|
||||
|
||||
public AbstractCharacter guardCaptain;
|
||||
public EnumBitSet<Enum.MonsterType> notEnemy = EnumBitSet.noneOf(Enum.MonsterType.class);
|
||||
public EnumBitSet<Enum.MonsterType> enemy = EnumBitSet.noneOf(Enum.MonsterType.class);
|
||||
;
|
||||
public Enum.MobBehaviourType behaviourType;
|
||||
public ArrayList<Vector3fImmutable> patrolPoints;
|
||||
public int lastPatrolPointIndex = 0;
|
||||
public long stopPatrolTime = 0;
|
||||
public City guardedCity;
|
||||
|
||||
public AbstractIntelligenceAgent() {
|
||||
super();
|
||||
}
|
||||
|
||||
public AbstractIntelligenceAgent(ResultSet rs) throws SQLException {
|
||||
super(rs);
|
||||
@@ -101,8 +87,7 @@ public abstract class AbstractIntelligenceAgent extends AbstractCharacter {
|
||||
this.agentType = Enum.AIAgentType.CHARMED;
|
||||
|
||||
if (this.getObjectType().equals(GameObjectType.Mob)) {
|
||||
|
||||
((Mob) this).guardCaptain = owner;
|
||||
((Mob) this).setOwner(owner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +110,14 @@ public abstract class AbstractIntelligenceAgent extends AbstractCharacter {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public PlayerCharacter getOwner() {
|
||||
|
||||
if (this.getObjectType().equals(GameObjectType.Mob))
|
||||
return this.getOwner();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean getSafeZone() {
|
||||
|
||||
ArrayList<Zone> allIn = ZoneManager.getAllZonesIn(this.getLoc());
|
||||
@@ -163,11 +156,9 @@ public abstract class AbstractIntelligenceAgent extends AbstractCharacter {
|
||||
this.setCombatTarget(null);
|
||||
}
|
||||
|
||||
// clear owner and set not alive
|
||||
|
||||
this.isAlive.set(false);
|
||||
//clear owner
|
||||
|
||||
PlayerCharacter owner = (PlayerCharacter) this.guardCaptain;
|
||||
PlayerCharacter owner = this.getOwner();
|
||||
|
||||
//close pet window
|
||||
|
||||
@@ -183,7 +174,7 @@ public abstract class AbstractIntelligenceAgent extends AbstractCharacter {
|
||||
owner.setPet(null);
|
||||
|
||||
if (this.getObjectType().equals(GameObjectType.Mob))
|
||||
this.guardCaptain = null;
|
||||
((Mob) this).setOwner(null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -357,9 +357,7 @@ public abstract class AbstractWorldObject extends AbstractGameObject {
|
||||
Mob mob = (Mob) this;
|
||||
if (mob.isSiege()) {
|
||||
if (mob.isPet()) {
|
||||
|
||||
|
||||
PlayerCharacter petOwner = (PlayerCharacter) mob.guardCaptain;
|
||||
PlayerCharacter petOwner = mob.getOwner();
|
||||
if (petOwner != null && source.equals(EffectSourceType.Effect)) {
|
||||
petOwner.dismissPet();
|
||||
return;
|
||||
@@ -502,7 +500,7 @@ public abstract class AbstractWorldObject extends AbstractGameObject {
|
||||
return;
|
||||
this.lastLoc = new Vector3fImmutable(this.loc);
|
||||
this.loc = loc;
|
||||
this.loc = this.loc.setY(HeightMap.getWorldHeight(this.getLoc()) + this.getAltitude());
|
||||
this.loc = this.loc.setY(HeightMap.getWorldHeight(this) + this.getAltitude());
|
||||
|
||||
//lets not add mob to world grid if he is currently despawned.
|
||||
if (this.getObjectType().equals(GameObjectType.Mob) && ((Mob) this).despawned)
|
||||
|
||||
@@ -537,18 +537,6 @@ public class Building extends AbstractWorldObject {
|
||||
if (value < 0)
|
||||
Mine.SendMineAttackMessage(this);
|
||||
|
||||
City playerCity = ZoneManager.getCityAtLocation(this.loc);
|
||||
if(playerCity != null){
|
||||
if(this.getGuild().getNation().equals(playerCity.getTOL().getGuild().getNation())){
|
||||
//friendly building has been attacked, add attacker to city outlaw list
|
||||
if(!playerCity.cityOutlaws.contains(attacker.getObjectUUID()) && attacker.getObjectType().equals(GameObjectType.PlayerCharacter))
|
||||
playerCity.cityOutlaws.add(attacker.getObjectUUID());
|
||||
for(Mob guard : playerCity.getParent().zoneMobSet)
|
||||
if(guard.combatTarget == null)
|
||||
guard.setCombatTarget(attacker);
|
||||
}
|
||||
}
|
||||
|
||||
return newHealth - oldHealth;
|
||||
|
||||
|
||||
|
||||
@@ -223,7 +223,7 @@ public class CharacterSkill extends AbstractGameObject {
|
||||
this.numTrains.set(0);
|
||||
this.ownerUID = pc.getObjectUUID();
|
||||
calculateBaseAmount();
|
||||
calculateModifiedAmount(false);
|
||||
calculateModifiedAmount();
|
||||
this.skillType = CharacterSkills.GetCharacterSkillByToken(this.skillsBase.getToken());
|
||||
}
|
||||
|
||||
@@ -238,7 +238,7 @@ public class CharacterSkill extends AbstractGameObject {
|
||||
this.ownerUID = pc.getObjectUUID();
|
||||
this.trained = true;
|
||||
calculateBaseAmount();
|
||||
calculateModifiedAmount(false);
|
||||
calculateModifiedAmount();
|
||||
this.skillType = CharacterSkills.GetCharacterSkillByToken(this.skillsBase.getToken());
|
||||
|
||||
}
|
||||
@@ -254,7 +254,7 @@ public class CharacterSkill extends AbstractGameObject {
|
||||
this.numTrains.set(rs.getShort("trains"));
|
||||
this.ownerUID = pc.getObjectUUID();
|
||||
calculateBaseAmount();
|
||||
calculateModifiedAmount(false);
|
||||
calculateModifiedAmount();
|
||||
this.skillType = CharacterSkills.GetCharacterSkillByToken(this.skillsBase.getToken());
|
||||
}
|
||||
|
||||
@@ -264,9 +264,8 @@ public class CharacterSkill extends AbstractGameObject {
|
||||
this.numTrains.set(trains);
|
||||
this.ownerUID = mob.getObjectUUID();
|
||||
this.isMobOwner = true;
|
||||
boolean isGuard = mob.agentType.equals(Enum.AIAgentType.GUARDCAPTAIN) || mob.agentType.equals(Enum.AIAgentType.GUARDMINION);
|
||||
calculateMobBaseAmount(isGuard);
|
||||
calculateModifiedAmount(isGuard);
|
||||
calculateMobBaseAmount();
|
||||
calculateModifiedAmount();
|
||||
this.skillType = CharacterSkills.GetCharacterSkillByToken(this.skillsBase.getToken());
|
||||
}
|
||||
|
||||
@@ -278,7 +277,7 @@ public class CharacterSkill extends AbstractGameObject {
|
||||
this.ownerUID = rs.getInt("CharacterID");
|
||||
// this.owner = DbManager.PlayerCharacterQueries.GET_PLAYER_CHARACTER(rs.getInt("CharacterID"));
|
||||
calculateBaseAmount();
|
||||
calculateModifiedAmount(false);
|
||||
calculateModifiedAmount();
|
||||
this.skillType = CharacterSkills.GetCharacterSkillByToken(this.skillsBase.getToken());
|
||||
}
|
||||
|
||||
@@ -371,7 +370,7 @@ public class CharacterSkill extends AbstractGameObject {
|
||||
String name = it.next();
|
||||
CharacterSkill cs = skills.get(name);
|
||||
if (cs != null)
|
||||
cs.calculateModifiedAmount(false);
|
||||
cs.calculateModifiedAmount();
|
||||
|
||||
}
|
||||
|
||||
@@ -757,7 +756,7 @@ public class CharacterSkill extends AbstractGameObject {
|
||||
|
||||
//recalculate this skill
|
||||
calculateBaseAmount();
|
||||
calculateModifiedAmount(false);
|
||||
calculateModifiedAmount();
|
||||
|
||||
//see if any new skills or powers granted
|
||||
pc.calculateSkills();
|
||||
@@ -849,7 +848,7 @@ public class CharacterSkill extends AbstractGameObject {
|
||||
if (recalculate) {
|
||||
//recalculate this skill
|
||||
calculateBaseAmount();
|
||||
calculateModifiedAmount(false);
|
||||
calculateModifiedAmount();
|
||||
|
||||
//see if any skills or powers removed
|
||||
pc.calculateSkills();
|
||||
@@ -888,7 +887,7 @@ public class CharacterSkill extends AbstractGameObject {
|
||||
if (recalculate) {
|
||||
//recalculate this skill
|
||||
calculateBaseAmount();
|
||||
calculateModifiedAmount(false);
|
||||
calculateModifiedAmount();
|
||||
|
||||
//see if any skills or powers removed
|
||||
pc.calculateSkills();
|
||||
@@ -1017,34 +1016,33 @@ public class CharacterSkill extends AbstractGameObject {
|
||||
this.modifiedAmountBeforeMods = Math.round(this.baseAmountBeforeMods + calculateAmountAfterTrains());
|
||||
}
|
||||
|
||||
public void calculateMobBaseAmount(boolean isGuard) {
|
||||
if(!isGuard) {
|
||||
if (CharacterSkill.GetOwner(this) == null) {
|
||||
Logger.error("owner not found for owner uuid : " + this.ownerUID);
|
||||
this.baseAmount = 1;
|
||||
this.modifiedAmount = 1;
|
||||
return;
|
||||
}
|
||||
public void calculateMobBaseAmount() {
|
||||
if (CharacterSkill.GetOwner(this) == null) {
|
||||
Logger.error("owner not found for owner uuid : " + this.ownerUID);
|
||||
this.baseAmount = 1;
|
||||
this.modifiedAmount = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.skillsBase == null) {
|
||||
Logger.error("SkillsBase not found for skill " + this.getObjectUUID());
|
||||
this.baseAmount = 1;
|
||||
this.modifiedAmount = 1;
|
||||
return;
|
||||
}
|
||||
if (this.skillsBase == null) {
|
||||
Logger.error("SkillsBase not found for skill " + this.getObjectUUID());
|
||||
this.baseAmount = 1;
|
||||
this.modifiedAmount = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
//Get any rune bonus
|
||||
float bonus = 0f;
|
||||
//TODO SKILLS RUNES
|
||||
float base = 7f;
|
||||
float statMod = 0.5f;
|
||||
if (CharacterSkill.GetOwner(this) != null && CharacterSkill.GetOwner(this).getBonuses() != null) {
|
||||
|
||||
if (CharacterSkill.GetOwner(this).getBonuses() != null) {
|
||||
//Get bonuses from runes
|
||||
bonus = CharacterSkill.GetOwner(this).getBonuses().getSkillBonus(this.skillsBase.sourceType);
|
||||
}
|
||||
|
||||
//Get Base skill for unmodified stats
|
||||
|
||||
|
||||
float base = 7f;
|
||||
float statMod = 0.5f;
|
||||
if (this.skillsBase.getStrMod() > 0)
|
||||
statMod += (float) this.skillsBase.getStrMod() * (float) ((Mob) CharacterSkill.GetOwner(this)).getMobBase().getMobBaseStats().getBaseStr() / 100f;
|
||||
if (this.skillsBase.getDexMod() > 0)
|
||||
@@ -1059,7 +1057,6 @@ public class CharacterSkill extends AbstractGameObject {
|
||||
statMod = 1f;
|
||||
else if (statMod > 600)
|
||||
statMod = 600f;
|
||||
}
|
||||
base += CharacterSkill.baseSkillValues[(int) statMod];
|
||||
|
||||
if (base + bonus < 1f)
|
||||
@@ -1069,48 +1066,45 @@ public class CharacterSkill extends AbstractGameObject {
|
||||
this.modifiedAmountBeforeMods = (int) (this.baseAmountBeforeMods + calculateAmountAfterTrains());
|
||||
}
|
||||
|
||||
public void calculateModifiedAmount(boolean isGuard) {
|
||||
if(!isGuard) {
|
||||
if (CharacterSkill.GetOwner(this) == null || this.skillsBase == null) {
|
||||
Logger.error("owner or SkillsBase not found for skill " + this.getObjectUUID());
|
||||
this.baseAmount = 1;
|
||||
this.modifiedAmount = 1;
|
||||
return;
|
||||
}
|
||||
public void calculateModifiedAmount() {
|
||||
if (CharacterSkill.GetOwner(this) == null || this.skillsBase == null) {
|
||||
Logger.error("owner or SkillsBase not found for skill " + this.getObjectUUID());
|
||||
this.baseAmount = 1;
|
||||
this.modifiedAmount = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
//Get any rune bonus
|
||||
float bonus = 0f;
|
||||
float base = 7f;
|
||||
float statMod = 0.5f;
|
||||
if (CharacterSkill.GetOwner(this) != null && CharacterSkill.GetOwner(this).getBonuses() != null) {
|
||||
if (CharacterSkill.GetOwner(this).getBonuses() != null) {
|
||||
//Get bonuses from runes
|
||||
bonus = CharacterSkill.GetOwner(this).getBonuses().getSkillBonus(this.skillsBase.sourceType);
|
||||
|
||||
|
||||
//Get Base skill for modified stats
|
||||
//TODO this fomula needs verified
|
||||
|
||||
if (this.skillsBase.getStrMod() > 0)
|
||||
statMod += (float) this.skillsBase.getStrMod() * (float) CharacterSkill.GetOwner(this).getStatStrCurrent() / 100f;
|
||||
if (this.skillsBase.getDexMod() > 0)
|
||||
statMod += (float) this.skillsBase.getDexMod() * (float) CharacterSkill.GetOwner(this).getStatDexCurrent() / 100f;
|
||||
if (this.skillsBase.getConMod() > 0)
|
||||
statMod += (float) this.skillsBase.getConMod() * (float) CharacterSkill.GetOwner(this).getStatConCurrent() / 100f;
|
||||
if (this.skillsBase.getIntMod() > 0)
|
||||
statMod += (float) this.skillsBase.getIntMod() * (float) CharacterSkill.GetOwner(this).getStatIntCurrent() / 100f;
|
||||
if (this.skillsBase.getSpiMod() > 0)
|
||||
statMod += (float) this.skillsBase.getSpiMod() * (float) CharacterSkill.GetOwner(this).getStatSpiCurrent() / 100f;
|
||||
if (statMod < 1)
|
||||
statMod = 1f;
|
||||
else if (statMod > 600)
|
||||
statMod = 600f;
|
||||
}
|
||||
|
||||
//Get Base skill for modified stats
|
||||
//TODO this fomula needs verified
|
||||
float base = 7f;
|
||||
float statMod = 0.5f;
|
||||
if (this.skillsBase.getStrMod() > 0)
|
||||
statMod += (float) this.skillsBase.getStrMod() * (float) CharacterSkill.GetOwner(this).getStatStrCurrent() / 100f;
|
||||
if (this.skillsBase.getDexMod() > 0)
|
||||
statMod += (float) this.skillsBase.getDexMod() * (float) CharacterSkill.GetOwner(this).getStatDexCurrent() / 100f;
|
||||
if (this.skillsBase.getConMod() > 0)
|
||||
statMod += (float) this.skillsBase.getConMod() * (float) CharacterSkill.GetOwner(this).getStatConCurrent() / 100f;
|
||||
if (this.skillsBase.getIntMod() > 0)
|
||||
statMod += (float) this.skillsBase.getIntMod() * (float) CharacterSkill.GetOwner(this).getStatIntCurrent() / 100f;
|
||||
if (this.skillsBase.getSpiMod() > 0)
|
||||
statMod += (float) this.skillsBase.getSpiMod() * (float) CharacterSkill.GetOwner(this).getStatSpiCurrent() / 100f;
|
||||
if (statMod < 1)
|
||||
statMod = 1f;
|
||||
else if (statMod > 600)
|
||||
statMod = 600f;
|
||||
base += CharacterSkill.baseSkillValues[(int) statMod];
|
||||
SourceType sourceType = SourceType.GetSourceType(this.skillsBase.getNameNoSpace());
|
||||
|
||||
//Get any rune, effect and item bonus
|
||||
|
||||
if (CharacterSkill.GetOwner(this) != null && CharacterSkill.GetOwner(this).getBonuses() != null) {
|
||||
if (CharacterSkill.GetOwner(this).getBonuses() != null) {
|
||||
//add bonuses from effects/items and runes
|
||||
base += bonus + CharacterSkill.GetOwner(this).getBonuses().getFloat(ModType.Skill, sourceType);
|
||||
}
|
||||
@@ -1122,7 +1116,7 @@ public class CharacterSkill extends AbstractGameObject {
|
||||
|
||||
float modAmount = this.baseAmount + calculateAmountAfterTrains();
|
||||
|
||||
if (CharacterSkill.GetOwner(this) != null && CharacterSkill.GetOwner(this).getBonuses() != null) {
|
||||
if (CharacterSkill.GetOwner(this).getBonuses() != null) {
|
||||
//Multiply any percent bonuses
|
||||
modAmount *= (1 + CharacterSkill.GetOwner(this).getBonuses().getFloatPercentAll(ModType.Skill, sourceType));
|
||||
}
|
||||
|
||||
+137
-58
@@ -66,6 +66,9 @@ public class City extends AbstractWorldObject {
|
||||
private int realmID;
|
||||
private int radiusType;
|
||||
private float bindRadius;
|
||||
private float statLat;
|
||||
private float statAlt;
|
||||
private float statLon;
|
||||
private float bindX;
|
||||
private float bindZ;
|
||||
private byte isNpc; //aka Safehold
|
||||
@@ -74,7 +77,7 @@ public class City extends AbstractWorldObject {
|
||||
private boolean forceRename = false;
|
||||
private boolean noTeleport = false; //used by npc cities
|
||||
private boolean noRepledge = false; //used by npc cities
|
||||
private final boolean isOpen = false;
|
||||
private boolean isOpen = false;
|
||||
private int treeOfLifeID;
|
||||
private Vector3fImmutable location = Vector3fImmutable.ZERO;
|
||||
|
||||
@@ -110,7 +113,10 @@ public class City extends AbstractWorldObject {
|
||||
if (establishedTimeStamp != null)
|
||||
this.established = java.time.LocalDateTime.ofInstant(establishedTimeStamp.toInstant(), ZoneId.systemDefault());
|
||||
|
||||
this.location = Vector3fImmutable.ZERO;
|
||||
this.location = new Vector3fImmutable(rs.getFloat("xCoord"), rs.getFloat("yCoord"), rs.getFloat("zCoord"));
|
||||
this.statLat = rs.getFloat("xCoord");
|
||||
this.statAlt = rs.getFloat("yCoord");
|
||||
this.statLon = rs.getFloat("zCoord");
|
||||
|
||||
java.sql.Timestamp realmTaxTimeStamp = rs.getTimestamp("realmTaxDate");
|
||||
|
||||
@@ -153,6 +159,11 @@ public class City extends AbstractWorldObject {
|
||||
this.motto = guild.getMotto();
|
||||
}
|
||||
|
||||
|
||||
//Disabled till i finish.
|
||||
// this.reverseKOS = rs.getInt("kos") == 1;
|
||||
|
||||
|
||||
Zone zone = ZoneManager.getZoneByUUID(rs.getInt("parent"));
|
||||
|
||||
if (zone != null)
|
||||
@@ -160,12 +171,18 @@ public class City extends AbstractWorldObject {
|
||||
|
||||
//npc cities without heightmaps except swampstone are specials.
|
||||
|
||||
|
||||
this.realmID = rs.getInt("realmID");
|
||||
|
||||
} catch (Exception e) {
|
||||
Logger.error(e);
|
||||
}
|
||||
|
||||
// *** Refactor: Is this working? Intended to supress
|
||||
// login server errors from attempting to
|
||||
// load cities/realms along with players
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -191,6 +208,7 @@ public class City extends AbstractWorldObject {
|
||||
Logger.error("NULL TOL FOR " + city.cityName);
|
||||
}
|
||||
|
||||
|
||||
// Assign city owner
|
||||
|
||||
if (city.getTOL() != null)
|
||||
@@ -208,8 +226,7 @@ public class City extends AbstractWorldObject {
|
||||
|
||||
rulingNation = rulingGuild.getNation();
|
||||
|
||||
// Begin Serializing sovereign guild data
|
||||
|
||||
// Begin Serialzing soverign guild data
|
||||
writer.putInt(city.getObjectType().ordinal());
|
||||
writer.putInt(city.getObjectUUID());
|
||||
writer.putString(city.cityName);
|
||||
@@ -264,6 +281,7 @@ public class City extends AbstractWorldObject {
|
||||
writer.putInt(rulingNation.getObjectUUID());
|
||||
}
|
||||
|
||||
|
||||
// Serialize nation name
|
||||
|
||||
if (rulingNation.isEmptyGuild())
|
||||
@@ -285,8 +303,16 @@ public class City extends AbstractWorldObject {
|
||||
else
|
||||
writer.putString(Guild.GetGL(rulingNation).getFirstName() + ' ' + Guild.GetGL(rulingNation).getLastName());
|
||||
|
||||
|
||||
writer.putLocalDateTime(city.established);
|
||||
|
||||
// writer.put((byte) city.established.getDayOfMonth());
|
||||
// writer.put((byte) city.established.minusMonths(1).getMonth().getValue());
|
||||
// writer.putInt((int) years);
|
||||
// writer.put((byte) hours);
|
||||
// writer.put((byte) minutes);
|
||||
// writer.put((byte) seconds);
|
||||
|
||||
writer.putFloat(city.location.x);
|
||||
writer.putFloat(city.location.y);
|
||||
writer.putFloat(city.location.z);
|
||||
@@ -325,7 +351,6 @@ public class City extends AbstractWorldObject {
|
||||
ConcurrentHashMap<Integer, AbstractGameObject> worldCities = DbManager.getMap(Enum.GameObjectType.City);
|
||||
|
||||
//add npc cities
|
||||
|
||||
for (AbstractGameObject ago : worldCities.values()) {
|
||||
|
||||
if (ago.getObjectType().equals(GameObjectType.City)) {
|
||||
@@ -342,7 +367,6 @@ public class City extends AbstractWorldObject {
|
||||
//list Player cities
|
||||
|
||||
//open city, just list
|
||||
|
||||
if (city.open && city.getTOL() != null && city.getTOL().getRank() > 4) {
|
||||
|
||||
if (!BuildingManager.IsPlayerHostile(city.getTOL(), pc))
|
||||
@@ -352,9 +376,7 @@ public class City extends AbstractWorldObject {
|
||||
|
||||
|
||||
} else if (city.isNpc == 1) {
|
||||
|
||||
//list NPC cities
|
||||
|
||||
Guild g = city.getGuild();
|
||||
if (g == null) {
|
||||
if (city.isNpc == 1)
|
||||
@@ -364,34 +386,32 @@ public class City extends AbstractWorldObject {
|
||||
} else if (pc.getLevel() > 9)
|
||||
cities.add(city);
|
||||
|
||||
} else if (pc.getLevel() >= g.getTeleportMin() && pc.getLevel() <= g.getTeleportMax())
|
||||
} else if (pc.getLevel() >= g.getTeleportMin() && pc.getLevel() <= g.getTeleportMax()) {
|
||||
|
||||
|
||||
cities.add(city);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return cities;
|
||||
}
|
||||
|
||||
public static ArrayList<City> getCitiesToRepledgeTo(PlayerCharacter playerCharacter) {
|
||||
|
||||
public static ArrayList<City> getCitiesToRepledgeTo(PlayerCharacter pc) {
|
||||
ArrayList<City> cities = new ArrayList<>();
|
||||
|
||||
if (playerCharacter == null)
|
||||
if (pc == null)
|
||||
return cities;
|
||||
|
||||
Guild pcG = playerCharacter.getGuild();
|
||||
Guild pcG = pc.getGuild();
|
||||
|
||||
ConcurrentHashMap<Integer, AbstractGameObject> worldCities = DbManager.getMap(Enum.GameObjectType.City);
|
||||
|
||||
//add npc cities
|
||||
|
||||
for (AbstractGameObject ago : worldCities.values()) {
|
||||
if (ago.getObjectType().equals(GameObjectType.City)) {
|
||||
|
||||
City city = (City) ago;
|
||||
|
||||
if (city.noRepledge)
|
||||
continue;
|
||||
|
||||
@@ -399,12 +419,11 @@ public class City extends AbstractWorldObject {
|
||||
|
||||
//list Player cities
|
||||
//open city, just list
|
||||
|
||||
if (playerCharacter.getAccount().status.equals(AccountStatus.ADMIN)) {
|
||||
if (pc.getAccount().status.equals(AccountStatus.ADMIN)) {
|
||||
cities.add(city);
|
||||
} else if (city.open && city.getTOL() != null && city.getTOL().getRank() > 4) {
|
||||
|
||||
if (!BuildingManager.IsPlayerHostile(city.getTOL(), playerCharacter))
|
||||
if (!BuildingManager.IsPlayerHostile(city.getTOL(), pc))
|
||||
cities.add(city); //verify nation or guild is same
|
||||
} else if (Guild.sameNationExcludeErrant(city.getGuild(), pcG))
|
||||
cities.add(city);
|
||||
@@ -412,16 +431,15 @@ public class City extends AbstractWorldObject {
|
||||
} else if (city.isNpc == 1) {
|
||||
//list NPC cities
|
||||
|
||||
Guild guild = city.getGuild();
|
||||
|
||||
if (guild == null) {
|
||||
Guild g = city.getGuild();
|
||||
if (g == null) {
|
||||
if (city.isNpc == 1)
|
||||
if (city.isNoobIsle == 1) {
|
||||
if (playerCharacter.getLevel() < 21)
|
||||
if (pc.getLevel() < 21)
|
||||
cities.add(city);
|
||||
} else if (playerCharacter.getLevel() > 9)
|
||||
} else if (pc.getLevel() > 9)
|
||||
cities.add(city);
|
||||
} else if (playerCharacter.getLevel() >= guild.getRepledgeMin() && playerCharacter.getLevel() <= guild.getRepledgeMax()) {
|
||||
} else if (pc.getLevel() >= g.getRepledgeMin() && pc.getLevel() <= g.getRepledgeMax()) {
|
||||
|
||||
cities.add(city);
|
||||
}
|
||||
@@ -437,7 +455,6 @@ public class City extends AbstractWorldObject {
|
||||
return null;
|
||||
|
||||
City city = (City) DbManager.getFromCache(Enum.GameObjectType.City, cityId);
|
||||
|
||||
if (city != null)
|
||||
return city;
|
||||
|
||||
@@ -454,10 +471,8 @@ public class City extends AbstractWorldObject {
|
||||
}
|
||||
|
||||
public boolean renameCity(String cityName) {
|
||||
|
||||
if (!DbManager.CityQueries.renameCity(this, cityName))
|
||||
return false;
|
||||
|
||||
if (!DbManager.CityQueries.updateforceRename(this, false))
|
||||
return false;
|
||||
|
||||
@@ -467,22 +482,17 @@ public class City extends AbstractWorldObject {
|
||||
}
|
||||
|
||||
public boolean updateTOL(Building tol) {
|
||||
|
||||
if (tol == null)
|
||||
return false;
|
||||
|
||||
if (!DbManager.CityQueries.updateTOL(this, tol.getObjectUUID()))
|
||||
return false;
|
||||
|
||||
this.treeOfLifeID = tol.getObjectUUID();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean renameCityForNewPlant(String cityName) {
|
||||
|
||||
if (!DbManager.CityQueries.renameCity(this, cityName))
|
||||
return false;
|
||||
|
||||
if (!DbManager.CityQueries.updateforceRename(this, true))
|
||||
return false;
|
||||
|
||||
@@ -505,11 +515,19 @@ public class City extends AbstractWorldObject {
|
||||
}
|
||||
|
||||
public Building getTOL() {
|
||||
|
||||
if (this.treeOfLifeID == 0)
|
||||
return null;
|
||||
|
||||
return BuildingManager.getBuildingFromCache(this.treeOfLifeID);
|
||||
|
||||
}
|
||||
|
||||
public int getIsNoobIsle() {
|
||||
return isNoobIsle;
|
||||
}
|
||||
|
||||
public int getPopulation() {
|
||||
return population;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -539,6 +557,14 @@ public class City extends AbstractWorldObject {
|
||||
Logger.error("Error when writing to database for cityUUID: " + this.getObjectUUID());
|
||||
}
|
||||
|
||||
public float getLatitude() {
|
||||
return this.location.x;
|
||||
}
|
||||
|
||||
public float getLongitude() {
|
||||
return this.location.z;
|
||||
}
|
||||
|
||||
public float getAltitude() {
|
||||
return this.location.y;
|
||||
}
|
||||
@@ -548,10 +574,34 @@ public class City extends AbstractWorldObject {
|
||||
return this.location;
|
||||
}
|
||||
|
||||
public byte getIsNpcOwned() {
|
||||
return isNpc;
|
||||
}
|
||||
|
||||
public byte getIsSafeHold() {
|
||||
return this.isSafeHold;
|
||||
}
|
||||
|
||||
public boolean isSafeHold() {
|
||||
return (this.isSafeHold == (byte) 1);
|
||||
}
|
||||
|
||||
public byte getIsCapital() {
|
||||
return isCapital;
|
||||
}
|
||||
|
||||
public void setIsCapital(boolean state) {
|
||||
this.isCapital = (state) ? (byte) 1 : (byte) 0;
|
||||
}
|
||||
|
||||
public int getRadiusType() {
|
||||
return this.radiusType;
|
||||
}
|
||||
|
||||
public float getBindRadius() {
|
||||
return this.bindRadius;
|
||||
}
|
||||
|
||||
public int getRank() {
|
||||
return (this.getTOL() == null) ? 0 : this.getTOL().getRank();
|
||||
}
|
||||
@@ -574,7 +624,7 @@ public class City extends AbstractWorldObject {
|
||||
|
||||
|
||||
this.parentZone = zone;
|
||||
this.location = new Vector3fImmutable(zone.absX, zone.absY, zone.absZ);
|
||||
this.location = new Vector3fImmutable(zone.absX + statLat, zone.absY + statAlt, zone.absZ + statLon);
|
||||
this.bindLoc = new Vector3fImmutable(this.location.x + this.bindX,
|
||||
this.location.y,
|
||||
this.location.z + this.bindZ);
|
||||
@@ -596,6 +646,15 @@ public class City extends AbstractWorldObject {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isCityZone(Zone zone) {
|
||||
|
||||
if (zone == null || this.parentZone == null)
|
||||
return false;
|
||||
|
||||
return zone.getObjectUUID() == this.parentZone.getObjectUUID();
|
||||
|
||||
}
|
||||
|
||||
public AbstractCharacter getOwner() {
|
||||
|
||||
if (this.getTOL() == null)
|
||||
@@ -617,13 +676,13 @@ public class City extends AbstractWorldObject {
|
||||
if (this.getTOL() == null)
|
||||
return null;
|
||||
|
||||
|
||||
if (this.isNpc == 1) {
|
||||
|
||||
if (this.getTOL().getOwner() == null)
|
||||
return null;
|
||||
return this.getTOL().getOwner().getGuild();
|
||||
} else {
|
||||
|
||||
if (this.getTOL().getOwner() == null)
|
||||
return null;
|
||||
return this.getTOL().getOwner().getGuild();
|
||||
@@ -631,16 +690,13 @@ public class City extends AbstractWorldObject {
|
||||
}
|
||||
|
||||
public boolean openCity(boolean open) {
|
||||
|
||||
if (!DbManager.CityQueries.updateOpenCity(this, open))
|
||||
return false;
|
||||
|
||||
this.open = open;
|
||||
return true;
|
||||
}
|
||||
|
||||
public Vector3fImmutable getBindLoc() {
|
||||
|
||||
Vector3fImmutable treeLoc = null;
|
||||
|
||||
if (this.getTOL() != null && this.getTOL().getRank() == 8)
|
||||
@@ -650,9 +706,7 @@ public class City extends AbstractWorldObject {
|
||||
return treeLoc;
|
||||
|
||||
if (this.radiusType == 1 && this.bindRadius > 0f) {
|
||||
|
||||
//square radius
|
||||
|
||||
float x = this.bindLoc.getX();
|
||||
float z = this.bindLoc.getZ();
|
||||
float offset = ((ThreadLocalRandom.current().nextFloat() * 2) - 1) * this.bindRadius;
|
||||
@@ -773,6 +827,7 @@ public class City extends AbstractWorldObject {
|
||||
try {
|
||||
this.getTOL().addEffectBit((1 << 16));
|
||||
this.getBane().getStone().addEffectBit((1 << 19));
|
||||
;
|
||||
} catch (Exception e) {
|
||||
Logger.info("Failed ao add bane effects on city." + e.getMessage());
|
||||
}
|
||||
@@ -797,7 +852,6 @@ public class City extends AbstractWorldObject {
|
||||
|
||||
if (playerObject == null)
|
||||
continue;
|
||||
|
||||
if (!this.isLocationWithinSiegeBounds(playerObject.getLoc()))
|
||||
continue;
|
||||
|
||||
@@ -814,7 +868,8 @@ public class City extends AbstractWorldObject {
|
||||
|
||||
// Remove the city effect from the ago's internal collection
|
||||
|
||||
this.getEffects().remove(Integer.toString(effectBase.getUUID()));
|
||||
if (this.getEffects().containsKey(Integer.toString(effectBase.getUUID())))
|
||||
this.getEffects().remove(Integer.toString(effectBase.getUUID()));
|
||||
|
||||
// Any players currently in the zone will not be processed by the heartbeat
|
||||
// so we do it here manually
|
||||
@@ -823,7 +878,6 @@ public class City extends AbstractWorldObject {
|
||||
for (Integer playerID : this._playerMemory) {
|
||||
|
||||
player = PlayerCharacter.getFromCache(playerID);
|
||||
|
||||
if (player == null)
|
||||
continue;
|
||||
|
||||
@@ -839,10 +893,8 @@ public class City extends AbstractWorldObject {
|
||||
}
|
||||
|
||||
public Warehouse getWarehouse() {
|
||||
|
||||
if (this.warehouseBuildingID == 0)
|
||||
return null;
|
||||
|
||||
return Warehouse.warehouseByBuildingUUID.get(this.warehouseBuildingID);
|
||||
}
|
||||
|
||||
@@ -1014,7 +1066,8 @@ public class City extends AbstractWorldObject {
|
||||
|
||||
_playerMemory.removeAll(toRemove);
|
||||
for (Integer removalUUID : toRemove) {
|
||||
this.cityOutlaws.remove(removalUUID);
|
||||
if (this.cityOutlaws.contains(removalUUID))
|
||||
this.cityOutlaws.remove(removalUUID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1030,7 +1083,7 @@ public class City extends AbstractWorldObject {
|
||||
|
||||
Thread destroyCityThread = new Thread(new DestroyCityThread(this));
|
||||
|
||||
destroyCityThread.setName("destroyCity:" + this.getName());
|
||||
destroyCityThread.setName("deestroyCity:" + this.getName());
|
||||
destroyCityThread.start();
|
||||
}
|
||||
|
||||
@@ -1115,7 +1168,6 @@ public class City extends AbstractWorldObject {
|
||||
|
||||
// All protection contracts are void upon transfer of a city
|
||||
//Dont forget to not Flip protection on Banestones and siege Equipment... Noob.
|
||||
|
||||
if (cityBuilding.getBlueprint() != null && !cityBuilding.getBlueprint().isSiegeEquip()
|
||||
&& cityBuilding.getBlueprint().getBuildingGroup() != BuildingGroup.BANESTONE)
|
||||
cityBuilding.setProtectionState(ProtectionState.NONE);
|
||||
@@ -1147,6 +1199,7 @@ public class City extends AbstractWorldObject {
|
||||
Zone cityZone;
|
||||
sourceGuild = sourcePlayer.getGuild();
|
||||
|
||||
|
||||
if (sourceGuild == null)
|
||||
return false;
|
||||
|
||||
@@ -1202,6 +1255,14 @@ public class City extends AbstractWorldObject {
|
||||
this.forceRename = forceRename;
|
||||
}
|
||||
|
||||
public boolean isReverseKOS() {
|
||||
return reverseKOS;
|
||||
}
|
||||
|
||||
public void setReverseKOS(boolean reverseKOS) {
|
||||
this.reverseKOS = reverseKOS;
|
||||
}
|
||||
|
||||
public String getHash() {
|
||||
return hash;
|
||||
}
|
||||
@@ -1229,6 +1290,26 @@ public class City extends AbstractWorldObject {
|
||||
|
||||
}
|
||||
|
||||
//TODO use this for taxing later.
|
||||
// public boolean isAfterTaxPeriod(LocalDateTime dateTime,PlayerCharacter player){
|
||||
// if (dateTime.isBefore(realmTaxDate)){
|
||||
// String wait = "";
|
||||
// float hours = 1000*60*60;
|
||||
// float seconds = 1000;
|
||||
// float hoursUntil = realmTaxDate.minus(dateTime.get).getMillis() /hours;
|
||||
// int secondsUntil = (int) (realmTaxDate.minus(dateTime.getMillis()).getMillis() /seconds);
|
||||
// if (hoursUntil < 1)
|
||||
// wait = "You must wait " + secondsUntil + " seconds before taxing this city again!";
|
||||
// else
|
||||
// wait = "You must wait " + hoursUntil + " hours before taxing this city again!";
|
||||
// ErrorPopupMsg.sendErrorMsg(player, wait);
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
|
||||
|
||||
public synchronized boolean TaxWarehouse(TaxResourcesMsg msg, PlayerCharacter player) {
|
||||
|
||||
// Member variable declaration
|
||||
@@ -1241,12 +1322,12 @@ public class City extends AbstractWorldObject {
|
||||
}
|
||||
|
||||
City city = building.getCity();
|
||||
|
||||
if (city == null) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "This building does not belong to a city.");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (playerGuild == null || playerGuild.isEmptyGuild()) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You must belong to a guild to do that!");
|
||||
return true;
|
||||
@@ -1271,7 +1352,6 @@ public class City extends AbstractWorldObject {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot find realm for your city!");
|
||||
return true;
|
||||
}
|
||||
|
||||
Realm targetRealm = RealmMap.getRealmForCity(city);
|
||||
|
||||
if (targetRealm == null) {
|
||||
@@ -1300,32 +1380,31 @@ public class City extends AbstractWorldObject {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (this.realmTaxDate.isAfter(LocalDateTime.now()))
|
||||
return true;
|
||||
|
||||
if (msg.getResources().size() == 0)
|
||||
return true;
|
||||
|
||||
if (city.getWarehouse() == null)
|
||||
return true;
|
||||
|
||||
Warehouse ruledWarehouse = playerGuild.getOwnedCity().getWarehouse();
|
||||
|
||||
if (ruledWarehouse == null)
|
||||
return true;
|
||||
|
||||
|
||||
ItemBase.getItemHashIDMap();
|
||||
|
||||
ArrayList<Integer> resources = new ArrayList<>();
|
||||
|
||||
float taxPercent = msg.getTaxPercent();
|
||||
|
||||
if (taxPercent > 20)
|
||||
taxPercent = .20f;
|
||||
|
||||
for (int resourceHash : msg.getResources().keySet()) {
|
||||
if (ItemBase.getItemHashIDMap().get(resourceHash) != null)
|
||||
resources.add(ItemBase.getItemHashIDMap().get(resourceHash));
|
||||
|
||||
}
|
||||
|
||||
for (Integer itemBaseID : resources) {
|
||||
@@ -1343,7 +1422,6 @@ public class City extends AbstractWorldObject {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Failed to Update next Tax Date due to internal Error. City was not charged taxes this time.");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
city.getWarehouse().transferResources(player, msg, resources, taxPercent, ruledWarehouse);
|
||||
} catch (Exception e) {
|
||||
@@ -1361,5 +1439,6 @@ public class City extends AbstractWorldObject {
|
||||
dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -914,21 +914,4 @@ public class ItemBase {
|
||||
public void setAutoID(boolean autoID) {
|
||||
this.autoID = autoID;
|
||||
}
|
||||
|
||||
public boolean isArmor(){
|
||||
|
||||
if(this.isHeavyArmor())
|
||||
return true;
|
||||
|
||||
if(this.isMediumArmor())
|
||||
return true;
|
||||
|
||||
if(this.isLightArmor())
|
||||
return true;
|
||||
|
||||
if(this.isClothArmor())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+843
-458
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,6 @@ public class MobBase extends AbstractGameObject {
|
||||
private final String firstName;
|
||||
private final byte level;
|
||||
private final float scale;
|
||||
public final ArrayList<MobBaseEffects> effectsList;
|
||||
public int bootySet;
|
||||
public Enum.MobBehaviourType fsm;
|
||||
public EnumBitSet<Enum.MonsterType> notEnemy;
|
||||
@@ -43,6 +42,10 @@ public class MobBase extends AbstractGameObject {
|
||||
private int goldMod;
|
||||
private int seeInvis;
|
||||
private int spawnTime = 0;
|
||||
private int defense = 0;
|
||||
private int atr = 0;
|
||||
private float minDmg = 0;
|
||||
private float maxDmg = 0;
|
||||
private float attackRange;
|
||||
private boolean isNecroPet = false;
|
||||
private MobBaseStats mobBaseStats;
|
||||
@@ -105,8 +108,6 @@ public class MobBase extends AbstractGameObject {
|
||||
|
||||
this.mobBaseStats = DbManager.MobBaseQueries.LOAD_STATS(this.loadID);
|
||||
DbManager.MobBaseQueries.LOAD_ALL_MOBBASE_SPEEDS(this);
|
||||
//load effects for mobbase
|
||||
this.effectsList = DbManager.MobBaseQueries.GET_RUNEBASE_EFFECTS(this.loadID);
|
||||
|
||||
}
|
||||
|
||||
@@ -244,6 +245,30 @@ public class MobBase extends AbstractGameObject {
|
||||
return mobBaseStats;
|
||||
}
|
||||
|
||||
public float getMaxDmg() {
|
||||
return maxDmg;
|
||||
}
|
||||
|
||||
public float getMinDmg() {
|
||||
return minDmg;
|
||||
}
|
||||
|
||||
public int getAtr() {
|
||||
return atr;
|
||||
}
|
||||
|
||||
public void setAtr(int atr) {
|
||||
this.atr = atr;
|
||||
}
|
||||
|
||||
public int getDefense() {
|
||||
return defense;
|
||||
}
|
||||
|
||||
public void setDefense(int defense) {
|
||||
this.defense = defense;
|
||||
}
|
||||
|
||||
public float getAttackRange() {
|
||||
return attackRange;
|
||||
}
|
||||
|
||||
@@ -21,9 +21,6 @@ public class MobBaseStats {
|
||||
private final int baseSpi;
|
||||
private final int baseDex;
|
||||
|
||||
private final int mobbaseSkill;
|
||||
private final int mobbaseSkillAmount;
|
||||
|
||||
|
||||
/**
|
||||
* ResultSet Constructor
|
||||
@@ -34,8 +31,6 @@ public class MobBaseStats {
|
||||
this.baseCon = rs.getInt("Constitution");
|
||||
this.baseSpi = rs.getInt("Spirit");
|
||||
this.baseDex = rs.getInt("Dexterity");
|
||||
this.mobbaseSkill = rs.getInt("baseSkills");
|
||||
this.mobbaseSkillAmount = rs.getInt("skillAmount");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,8 +43,6 @@ public class MobBaseStats {
|
||||
this.baseCon = 0;
|
||||
this.baseSpi = 0;
|
||||
this.baseDex = 0;
|
||||
this.mobbaseSkill = 0;
|
||||
this.mobbaseSkillAmount = 0;
|
||||
}
|
||||
|
||||
public static MobBaseStats GetGenericStats() {
|
||||
@@ -79,8 +72,5 @@ public class MobBaseStats {
|
||||
return baseDex;
|
||||
}
|
||||
|
||||
public int getBaseSkill(){return mobbaseSkill;}
|
||||
|
||||
public int getBaseSkillAmount(){return mobbaseSkillAmount;}
|
||||
|
||||
}
|
||||
|
||||
+17
-17
@@ -50,6 +50,7 @@ public class NPC extends AbstractCharacter {
|
||||
// Used for thread safety
|
||||
public final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
private final ArrayList<MobLoot> rolling = new ArrayList<>();
|
||||
private final ConcurrentHashMap<Mob, Integer> siegeMinionMap = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
|
||||
public ReentrantReadWriteLock minionLock = new ReentrantReadWriteLock();
|
||||
public ArrayList<ProducedItem> forgedItems = new ArrayList<>();
|
||||
public HashMap<Integer, MobEquipment> equip = null;
|
||||
@@ -85,7 +86,6 @@ public class NPC extends AbstractCharacter {
|
||||
|
||||
public NPC() {
|
||||
|
||||
super();
|
||||
this.dbID = MBServerStatics.NO_DB_ROW_ASSIGNED_YET;
|
||||
this.currentID = MBServerStatics.NO_DB_ROW_ASSIGNED_YET;
|
||||
}
|
||||
@@ -640,31 +640,26 @@ public class NPC extends AbstractCharacter {
|
||||
|
||||
public void removeMinions() {
|
||||
|
||||
|
||||
for (Integer minionUUID : this.minions) {
|
||||
|
||||
Mob minionMob = Mob.getMob(minionUUID);
|
||||
for (Mob toRemove : this.siegeMinionMap.keySet()) {
|
||||
|
||||
try {
|
||||
minionMob.clearEffects();
|
||||
toRemove.clearEffects();
|
||||
} catch (Exception e) {
|
||||
Logger.error(e.getMessage());
|
||||
}
|
||||
|
||||
if (minionMob.getParentZone() != null)
|
||||
minionMob.getParentZone().zoneMobSet.remove(minionMob);
|
||||
|
||||
WorldGrid.RemoveWorldObject(minionMob);
|
||||
DbManager.removeFromCache(minionMob);
|
||||
if (toRemove.getParentZone() != null)
|
||||
toRemove.getParentZone().zoneMobSet.remove(toRemove);
|
||||
|
||||
WorldGrid.RemoveWorldObject(toRemove);
|
||||
DbManager.removeFromCache(toRemove);
|
||||
|
||||
PlayerCharacter petOwner = (PlayerCharacter) minionMob.guardCaptain;
|
||||
PlayerCharacter petOwner = toRemove.getOwner();
|
||||
|
||||
if (petOwner != null) {
|
||||
|
||||
petOwner.setPet(null);
|
||||
|
||||
minionMob.guardCaptain = null;
|
||||
toRemove.setOwner(null);
|
||||
|
||||
PetMsg petMsg = new PetMsg(5, null);
|
||||
Dispatch dispatch = Dispatch.borrow(petOwner, petMsg);
|
||||
@@ -672,7 +667,6 @@ public class NPC extends AbstractCharacter {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -811,8 +805,6 @@ public class NPC extends AbstractCharacter {
|
||||
@Override
|
||||
public void runAfterLoad() {
|
||||
|
||||
this.charItemManager = new CharacterItemManager(this);
|
||||
|
||||
if (ConfigManager.serverType.equals(ServerType.LOGINSERVER))
|
||||
return;
|
||||
|
||||
@@ -854,6 +846,10 @@ public class NPC extends AbstractCharacter {
|
||||
if (wordCount(this.name) < 2 && this.contract != null)
|
||||
this.name += " the " + this.contract.getName();
|
||||
|
||||
// Initialize inventory
|
||||
|
||||
this.charItemManager = new CharacterItemManager(this);
|
||||
|
||||
// Configure parent zone adding this NPC to the
|
||||
// zone collection
|
||||
|
||||
@@ -1107,6 +1103,10 @@ public class NPC extends AbstractCharacter {
|
||||
return (int) time;
|
||||
}
|
||||
|
||||
public ConcurrentHashMap<Mob, Integer> getSiegeMinionMap() {
|
||||
return siegeMinionMap;
|
||||
}
|
||||
|
||||
public boolean remove() {
|
||||
|
||||
Building building;
|
||||
|
||||
@@ -135,6 +135,7 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
private Vector3fImmutable lastStaticLoc = new Vector3fImmutable(0.0f, 0.0f, 0.0f);
|
||||
private GameObjectType lastTargetType;
|
||||
private int lastTargetID;
|
||||
private int hidden = 0; // current rank of hide/sneak/invis
|
||||
private int seeInvis = 0; // current rank of see invis
|
||||
private float speedMod;
|
||||
private boolean teleportMode = false; // Teleport on MoveToPoint
|
||||
@@ -143,6 +144,7 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
private long lastUpdateTime = System.currentTimeMillis();
|
||||
private long lastStamUpdateTime = System.currentTimeMillis();
|
||||
private boolean safeZone = false;
|
||||
private int bindBuildingID;
|
||||
|
||||
/*
|
||||
DataWarehouse based kill/death tracking.
|
||||
@@ -203,18 +205,15 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
this.spiMod.set(spiMod);
|
||||
|
||||
this.guildStatus = new AtomicInteger(0);
|
||||
this.buildingUUID = -1;
|
||||
this.bindBuildingID = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* ResultSet Constructor
|
||||
*/
|
||||
public PlayerCharacter(ResultSet rs) throws SQLException {
|
||||
|
||||
super(rs, true);
|
||||
|
||||
this.charItemManager = new CharacterItemManager(this);
|
||||
|
||||
this.runes = DbManager.CharacterRuneQueries.GET_RUNES_FOR_CHARACTER(this.getObjectUUID());
|
||||
int accountID = rs.getInt("parent");
|
||||
this.account = DbManager.AccountQueries.GET_ACCOUNT(accountID);
|
||||
@@ -266,7 +265,7 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
this.intMod.set(rs.getShort("char_intMod"));
|
||||
this.spiMod.set(rs.getShort("char_spiMod"));
|
||||
|
||||
this.buildingUUID = rs.getInt("char_bindBuilding");
|
||||
this.bindBuildingID = rs.getInt("char_bindBuilding");
|
||||
|
||||
this.hash = rs.getString("hash");
|
||||
|
||||
@@ -2722,12 +2721,12 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
*/
|
||||
|
||||
public synchronized int getBindBuildingID() {
|
||||
return this.buildingUUID;
|
||||
return this.bindBuildingID;
|
||||
}
|
||||
|
||||
public synchronized void setBindBuildingID(int value) {
|
||||
DbManager.PlayerCharacterQueries.SET_BIND_BUILDING(this, value);
|
||||
this.buildingUUID = value;
|
||||
this.bindBuildingID = value;
|
||||
}
|
||||
|
||||
public AbstractGameObject getLastTarget() {
|
||||
@@ -2773,6 +2772,10 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
this.lastStaticLoc = value;
|
||||
}
|
||||
|
||||
public int getHidden() {
|
||||
return this.hidden;
|
||||
}
|
||||
|
||||
public void setHidden(int value) {
|
||||
this.hidden = value;
|
||||
}
|
||||
@@ -4558,6 +4561,10 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
@Override
|
||||
public void runAfterLoad() {
|
||||
|
||||
// Init inventory
|
||||
|
||||
this.charItemManager = new CharacterItemManager(this);
|
||||
|
||||
Bounds playerBounds = Bounds.borrow();
|
||||
playerBounds.setBounds(this.getLoc());
|
||||
this.setBounds(playerBounds);
|
||||
@@ -4685,8 +4692,7 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
|
||||
} else if (currentPet.isSiege()) {
|
||||
currentPet.agentType = AIAgentType.MOBILE;
|
||||
|
||||
currentPet.guardCaptain = null;
|
||||
currentPet.setOwner(null);
|
||||
currentPet.setCombatTarget(null);
|
||||
if (currentPet.isAlive())
|
||||
WorldGrid.updateObject(currentPet);
|
||||
@@ -4834,7 +4840,7 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
} else
|
||||
this.altitude = this.getDesiredAltitude();
|
||||
|
||||
this.loc = this.loc.setY(HeightMap.getWorldHeight(this.getLoc()) + this.getAltitude());
|
||||
this.loc = this.loc.setY(HeightMap.getWorldHeight(this) + this.getAltitude());
|
||||
|
||||
this.setTakeOffTime(0);
|
||||
MovementManager.finishChangeAltitude(this, this.getDesiredAltitude());
|
||||
@@ -4842,7 +4848,7 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loc = this.loc.setY(HeightMap.getWorldHeight(this.getLoc()) + this.getAltitude());
|
||||
this.loc = this.loc.setY(HeightMap.getWorldHeight(this) + this.getAltitude());
|
||||
}
|
||||
|
||||
public boolean hasBoon() {
|
||||
@@ -5353,7 +5359,7 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
moveToMsg.setStartCoord(this.getLoc());
|
||||
moveToMsg.setEndCoord(endLoc);
|
||||
moveToMsg.setInBuilding(-1);
|
||||
moveToMsg.setInBuildingFloor(-1);
|
||||
moveToMsg.setUnknown01(-1);
|
||||
moveToMsg.setSourceType(GameObjectType.PlayerCharacter.ordinal());
|
||||
moveToMsg.setSourceID(this.getObjectUUID());
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user