Compare commits
7 Commits
Author | SHA1 | Date |
---|---|---|
|
3649c629b7 | 1 year ago |
|
1c31070fc8 | 1 year ago |
|
bff41967db | 2 years ago |
|
d3692d0fb7 | 2 years ago |
|
074a799d01 | 2 years ago |
|
36ffd08a72 | 2 years ago |
|
58f828b3cd | 2 years ago |
685 changed files with 28375 additions and 18941 deletions
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,706 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2022
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
package engine.InterestManagement; |
||||||
|
|
||||||
|
import engine.Enum; |
||||||
|
import engine.gameManager.ConfigManager; |
||||||
|
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; |
||||||
|
import java.awt.*; |
||||||
|
import java.awt.image.BufferedImage; |
||||||
|
import java.io.File; |
||||||
|
import java.io.IOException; |
||||||
|
import java.sql.ResultSet; |
||||||
|
import java.sql.SQLException; |
||||||
|
import java.util.HashMap; |
||||||
|
|
||||||
|
public class HeightMap { |
||||||
|
|
||||||
|
// Class variables
|
||||||
|
|
||||||
|
// Heightmap data for all zones.
|
||||||
|
|
||||||
|
public static final HashMap<Integer, HeightMap> heightmapByLoadNum = new HashMap<>(); |
||||||
|
|
||||||
|
// Bootstrap Tracking
|
||||||
|
|
||||||
|
public static int heightMapsCreated = 0; |
||||||
|
public static HeightMap PlayerCityHeightMap; |
||||||
|
|
||||||
|
// Heightmap data for this heightmap
|
||||||
|
|
||||||
|
public BufferedImage heightmapImage; |
||||||
|
|
||||||
|
private int heightMapID; |
||||||
|
private int maxHeight; |
||||||
|
private int fullExtentsX; |
||||||
|
private int fullExtentsY; |
||||||
|
|
||||||
|
private float bucketWidthX; |
||||||
|
private float bucketWidthY; |
||||||
|
private int zoneLoadID; |
||||||
|
private float seaLevel = 0; |
||||||
|
private float outsetX; |
||||||
|
private float outsetZ; |
||||||
|
private int[][] pixelColorValues; |
||||||
|
|
||||||
|
public HeightMap(ResultSet rs) throws SQLException { |
||||||
|
|
||||||
|
this.heightMapID = rs.getInt("heightMapID"); |
||||||
|
this.maxHeight = rs.getInt("maxHeight"); |
||||||
|
int halfExtentsX = rs.getInt("xRadius"); |
||||||
|
int halfExtentsY = rs.getInt("zRadius"); |
||||||
|
this.zoneLoadID = rs.getInt("zoneLoadID"); |
||||||
|
this.seaLevel = rs.getFloat("seaLevel"); |
||||||
|
this.outsetX = rs.getFloat("outsetX"); |
||||||
|
this.outsetZ = rs.getFloat("outsetZ"); |
||||||
|
|
||||||
|
|
||||||
|
// Cache the full extents to avoid the calculation
|
||||||
|
|
||||||
|
this.fullExtentsX = halfExtentsX * 2; |
||||||
|
this.fullExtentsY = halfExtentsY * 2; |
||||||
|
|
||||||
|
this.heightmapImage = null; |
||||||
|
File imageFile = new File(ConfigManager.DEFAULT_DATA_DIR + "heightmaps/" + this.heightMapID + ".bmp"); |
||||||
|
|
||||||
|
// early exit if no image file was found. Will log in caller.
|
||||||
|
|
||||||
|
if (!imageFile.exists()) |
||||||
|
return; |
||||||
|
|
||||||
|
// load the heightmap image.
|
||||||
|
|
||||||
|
try { |
||||||
|
this.heightmapImage = ImageIO.read(imageFile); |
||||||
|
} catch (IOException e) { |
||||||
|
Logger.error("***Error loading heightmap data for heightmap " + this.heightMapID + e.toString()); |
||||||
|
} |
||||||
|
|
||||||
|
// We needed to flip the image as OpenGL and Shadowbane both use the bottom left corner as origin.
|
||||||
|
|
||||||
|
this.heightmapImage = MapLoader.flipImage(this.heightmapImage); |
||||||
|
|
||||||
|
// Calculate the data we do not load from table
|
||||||
|
|
||||||
|
float numOfBuckets = this.heightmapImage.getWidth() - 1; |
||||||
|
float calculatedWidth = this.fullExtentsX / numOfBuckets; |
||||||
|
this.bucketWidthX = calculatedWidth; |
||||||
|
this.bucketWidthY = this.bucketWidthX; // This makes no sense.
|
||||||
|
|
||||||
|
// Generate pixel array from image data
|
||||||
|
|
||||||
|
generatePixelData(); |
||||||
|
|
||||||
|
HeightMap.heightmapByLoadNum.put(this.zoneLoadID, this); |
||||||
|
|
||||||
|
heightMapsCreated++; |
||||||
|
} |
||||||
|
|
||||||
|
//Created for PlayerCities
|
||||||
|
public HeightMap() { |
||||||
|
|
||||||
|
this.heightMapID = 999999; |
||||||
|
this.maxHeight = 5; // for real...
|
||||||
|
int halfExtentsX = (int) Enum.CityBoundsType.ZONE.extents; |
||||||
|
int halfExtentsY = (int) Enum.CityBoundsType.ZONE.extents; |
||||||
|
this.zoneLoadID = 0; |
||||||
|
this.seaLevel = 0; |
||||||
|
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 = 1; |
||||||
|
this.bucketWidthY = 1; |
||||||
|
|
||||||
|
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] = 255; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
HeightMap.heightmapByLoadNum.put(this.zoneLoadID, this); |
||||||
|
} |
||||||
|
|
||||||
|
public HeightMap(Zone zone) { |
||||||
|
|
||||||
|
this.heightMapID = 999999; |
||||||
|
this.maxHeight = 0; |
||||||
|
int halfExtentsX = (int) zone.getBounds().getHalfExtents().x; |
||||||
|
int halfExtentsY = (int) zone.getBounds().getHalfExtents().y; |
||||||
|
this.zoneLoadID = 0; |
||||||
|
this.seaLevel = 0; |
||||||
|
this.outsetX = 0; |
||||||
|
this.outsetZ = 0; |
||||||
|
|
||||||
|
// Cache the full extents to avoid the calculation
|
||||||
|
|
||||||
|
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 = 1; |
||||||
|
this.bucketWidthY = 1; |
||||||
|
|
||||||
|
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] = 255; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
HeightMap.heightmapByLoadNum.put(this.zoneLoadID, this); |
||||||
|
} |
||||||
|
|
||||||
|
public static void GeneratePlayerCityHeightMap() { |
||||||
|
|
||||||
|
HeightMap.PlayerCityHeightMap = new HeightMap(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public static void GenerateCustomHeightMap(Zone zone) { |
||||||
|
|
||||||
|
HeightMap heightMap = new HeightMap(zone); |
||||||
|
|
||||||
|
HeightMap.heightmapByLoadNum.put(zone.getLoadNum(), heightMap); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public static Zone getNextZoneWithTerrain(Zone zone) { |
||||||
|
|
||||||
|
Zone nextZone = zone; |
||||||
|
|
||||||
|
if (zone.getHeightMap() != null) |
||||||
|
return zone; |
||||||
|
|
||||||
|
if (zone.equals(ZoneManager.getSeaFloor())) |
||||||
|
return zone; |
||||||
|
|
||||||
|
while (nextZone.getHeightMap() == null) |
||||||
|
nextZone = nextZone.getParent(); |
||||||
|
|
||||||
|
return nextZone; |
||||||
|
} |
||||||
|
|
||||||
|
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; |
||||||
|
|
||||||
|
currentZone = getNextZoneWithTerrain(currentZone); |
||||||
|
|
||||||
|
if (currentZone == ZoneManager.getSeaFloor()) |
||||||
|
return currentZone.getAbsY(); |
||||||
|
|
||||||
|
Zone parentZone = getNextZoneWithTerrain(currentZone.getParent()); |
||||||
|
HeightMap heightMap = currentZone.getHeightMap(); |
||||||
|
|
||||||
|
if ((heightMap == null) || (currentZone == ZoneManager.getSeaFloor())) |
||||||
|
return currentZone.getAbsY(); |
||||||
|
|
||||||
|
Vector2f zoneLoc = ZoneManager.worldToZoneSpace(worldLoc, currentZone); |
||||||
|
Vector3fImmutable localLocFromCenter = ZoneManager.worldToLocal(worldLoc, currentZone); |
||||||
|
|
||||||
|
if ((parentZone != null) && (parentZone.getHeightMap() != null)) |
||||||
|
parentLoc = ZoneManager.worldToZoneSpace(worldLoc, parentZone); |
||||||
|
|
||||||
|
float interaltitude = currentZone.getHeightMap().getInterpolatedTerrainHeight(zoneLoc); |
||||||
|
|
||||||
|
float worldAltitude = currentZone.getWorldAltitude(); |
||||||
|
|
||||||
|
float realWorldAltitude = interaltitude + worldAltitude; |
||||||
|
|
||||||
|
//OUTSET
|
||||||
|
|
||||||
|
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; |
||||||
|
|
||||||
|
float offsetX = Math.abs((localLocFromCenter.x / parentXRadius)); |
||||||
|
float offsetZ = Math.abs((localLocFromCenter.z / parentZRadius)); |
||||||
|
|
||||||
|
float bucketScaleX = heightMap.outsetX / parentXRadius; |
||||||
|
float bucketScaleZ = heightMap.outsetZ / 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().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 getOutsetHeight(float interpolatedAltitude, Zone zone, Vector3fImmutable worldLocation) { |
||||||
|
|
||||||
|
Vector2f parentLoc; |
||||||
|
float outsetALt = 0; |
||||||
|
|
||||||
|
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); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public static void loadAlHeightMaps() { |
||||||
|
|
||||||
|
// Load the heightmaps into staging hashmap keyed by HashMapID
|
||||||
|
|
||||||
|
DbManager.HeightMapQueries.LOAD_ALL_HEIGHTMAPS(); |
||||||
|
|
||||||
|
//generate static player city heightmap.
|
||||||
|
|
||||||
|
HeightMap.GeneratePlayerCityHeightMap(); |
||||||
|
|
||||||
|
|
||||||
|
// Clear all heightmap image data as it's no longer needed.
|
||||||
|
|
||||||
|
for (HeightMap heightMap : HeightMap.heightmapByLoadNum.values()) { |
||||||
|
heightMap.heightmapImage = null; |
||||||
|
} |
||||||
|
|
||||||
|
Logger.info(HeightMap.heightmapByLoadNum.size() + " Heightmaps cached."); |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean isLocUnderwater(Vector3fImmutable currentLoc) { |
||||||
|
|
||||||
|
float localAltitude = HeightMap.getWorldHeight(currentLoc); |
||||||
|
Zone zone = ZoneManager.findSmallestZone(currentLoc); |
||||||
|
|
||||||
|
if (localAltitude < zone.getSeaLevel()) |
||||||
|
return true; |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public Vector2f getGridSquare(Vector2f zoneLoc) { |
||||||
|
|
||||||
|
if (zoneLoc.x < 0) |
||||||
|
zoneLoc.setX(0); |
||||||
|
|
||||||
|
if (zoneLoc.x > this.fullExtentsX - 1) |
||||||
|
zoneLoc.setX((this.fullExtentsX - 1) + .9999999f); |
||||||
|
|
||||||
|
if (zoneLoc.y < 0) |
||||||
|
zoneLoc.setY(0); |
||||||
|
|
||||||
|
if (zoneLoc.y > this.fullExtentsY - 1) |
||||||
|
zoneLoc.setY((this.fullExtentsY - 1) + .9999999f); |
||||||
|
|
||||||
|
float xBucket = (zoneLoc.x / this.bucketWidthX); |
||||||
|
float yBucket = (zoneLoc.y / this.bucketWidthY); |
||||||
|
|
||||||
|
return new Vector2f(xBucket, yBucket); |
||||||
|
} |
||||||
|
|
||||||
|
public float getInterpolatedTerrainHeight(Vector2f zoneLoc) { |
||||||
|
|
||||||
|
Vector2f gridSquare; |
||||||
|
|
||||||
|
if (zoneLoc.x < 0 || zoneLoc.x > this.fullExtentsX) |
||||||
|
return -1; |
||||||
|
|
||||||
|
if (zoneLoc.y < 0 || zoneLoc.y > this.fullExtentsY) |
||||||
|
return -1; |
||||||
|
|
||||||
|
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); |
||||||
|
|
||||||
|
if (gridX > maxX) |
||||||
|
gridX = maxX; |
||||||
|
if (gridY > maxY) |
||||||
|
gridY = maxY; |
||||||
|
|
||||||
|
float offsetX = (gridSquare.x - gridX); |
||||||
|
float offsetY = gridSquare.y - gridY; |
||||||
|
|
||||||
|
//get height of the 4 vertices.
|
||||||
|
|
||||||
|
float topLeftHeight = 0; |
||||||
|
float topRightHeight = 0; |
||||||
|
float bottomLeftHeight = 0; |
||||||
|
float bottomRightHeight = 0; |
||||||
|
|
||||||
|
int nextY = gridY + 1; |
||||||
|
int nextX = gridX + 1; |
||||||
|
|
||||||
|
if (nextY > maxY) |
||||||
|
nextY = gridY; |
||||||
|
|
||||||
|
if (nextX > maxX) |
||||||
|
nextX = gridX; |
||||||
|
|
||||||
|
topLeftHeight = pixelColorValues[gridX][gridY]; |
||||||
|
topRightHeight = pixelColorValues[nextX][gridY]; |
||||||
|
bottomLeftHeight = pixelColorValues[gridX][nextY]; |
||||||
|
bottomRightHeight = pixelColorValues[nextX][nextY]; |
||||||
|
|
||||||
|
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; |
||||||
|
} |
||||||
|
|
||||||
|
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; |
||||||
|
|
||||||
|
// Generate altitude lookup table for this heightmap
|
||||||
|
|
||||||
|
this.pixelColorValues = new int[this.heightmapImage.getWidth()][this.heightmapImage.getHeight()]; |
||||||
|
|
||||||
|
for (int y = 0; y < this.heightmapImage.getHeight(); y++) { |
||||||
|
for (int x = 0; x < this.heightmapImage.getWidth(); x++) { |
||||||
|
|
||||||
|
color = new Color(this.heightmapImage.getRGB(x, y)); |
||||||
|
pixelColorValues[x][y] = color.getRed(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public float getScaledHeightForColor(float color) { |
||||||
|
|
||||||
|
return (color / 256) * this.maxHeight; |
||||||
|
} |
||||||
|
|
||||||
|
public float getBucketWidthX() { |
||||||
|
return bucketWidthX; |
||||||
|
} |
||||||
|
|
||||||
|
public float getBucketWidthY() { |
||||||
|
return bucketWidthY; |
||||||
|
} |
||||||
|
|
||||||
|
public int getHeightMapID() { |
||||||
|
return heightMapID; |
||||||
|
} |
||||||
|
|
||||||
|
public BufferedImage getHeightmapImage() { |
||||||
|
return heightmapImage; |
||||||
|
} |
||||||
|
|
||||||
|
public float getSeaLevel() { |
||||||
|
return seaLevel; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -1,238 +0,0 @@ |
|||||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
|
||||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
|
||||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
|
||||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
|
||||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
|
||||||
// Magicbane Emulator Project © 2013 - 2022
|
|
||||||
// www.magicbane.com
|
|
||||||
|
|
||||||
package engine.InterestManagement; |
|
||||||
|
|
||||||
import engine.gameManager.ZoneManager; |
|
||||||
import engine.math.Vector2f; |
|
||||||
import engine.math.Vector3fImmutable; |
|
||||||
import engine.objects.Zone; |
|
||||||
import org.pmw.tinylog.Logger; |
|
||||||
|
|
||||||
import java.util.HashMap; |
|
||||||
|
|
||||||
import static java.lang.Math.PI; |
|
||||||
|
|
||||||
|
|
||||||
// MB Dev Notes:
|
|
||||||
// The Terrain class handles lookups into the Heightmap data.
|
|
||||||
// It supports all current maps along with the differences in
|
|
||||||
// their parenting configuration.
|
|
||||||
//
|
|
||||||
// Heightmap images are stored on disk in /mb.data/heightmaps/
|
|
||||||
|
|
||||||
public class Terrain { |
|
||||||
public static final HashMap<Integer, short[][]> _heightmap_pixel_cache = new HashMap<>(); |
|
||||||
public short[][] terrain_pixel_data; |
|
||||||
public Vector2f terrain_size = new Vector2f(); |
|
||||||
public Vector2f cell_size = new Vector2f(); |
|
||||||
public Vector2f cell_count = new Vector2f(); |
|
||||||
public float terrain_scale; |
|
||||||
public Vector2f blend_values = new Vector2f(); |
|
||||||
public Vector2f blend_ratio = new Vector2f(); |
|
||||||
public int heightmap; |
|
||||||
Zone zone; |
|
||||||
|
|
||||||
public Terrain(Zone zone) { |
|
||||||
|
|
||||||
this.zone = zone; |
|
||||||
this.heightmap = this.zone.template.terrain_image; |
|
||||||
|
|
||||||
// Configure PLANAR zones to use the same 16x16 pixel image
|
|
||||||
// that all similar terrains share. (See JSON)
|
|
||||||
|
|
||||||
if (this.zone.template.terrain_type.equals("PLANAR")) |
|
||||||
this.heightmap = 1006300; // all 0
|
|
||||||
|
|
||||||
// Load pixel data for this terrain from cache
|
|
||||||
|
|
||||||
this.terrain_pixel_data = Terrain._heightmap_pixel_cache.get(heightmap); |
|
||||||
|
|
||||||
if (terrain_pixel_data == null) |
|
||||||
Logger.error("Pixel map empty for zone: " + this.zone.getObjectUUID() + ":" + this.zone.zoneName); |
|
||||||
|
|
||||||
// Configure terrain based on zone properties
|
|
||||||
|
|
||||||
this.terrain_size.x = this.zone.major_radius * 2; |
|
||||||
this.terrain_size.y = this.zone.minor_radius * 2; |
|
||||||
|
|
||||||
this.cell_count.x = this.terrain_pixel_data.length - 1; |
|
||||||
this.cell_count.y = this.terrain_pixel_data[0].length - 1; |
|
||||||
|
|
||||||
this.cell_size.x = terrain_size.x / this.cell_count.x; |
|
||||||
this.cell_size.y = terrain_size.y / this.cell_count.y; |
|
||||||
|
|
||||||
// Blending configuration. These ratios are used to calculate
|
|
||||||
// the blending area between child and parent terrains when
|
|
||||||
// they are stitched together.
|
|
||||||
|
|
||||||
this.blend_values.x = this.zone.template.max_blend; |
|
||||||
this.blend_values.y = this.zone.template.min_blend; |
|
||||||
|
|
||||||
Vector2f major_blend = new Vector2f(this.blend_values.x / this.zone.major_radius, |
|
||||||
this.blend_values.y / this.zone.major_radius); |
|
||||||
|
|
||||||
Vector2f minor_blend = new Vector2f(this.blend_values.x / this.zone.minor_radius, |
|
||||||
this.blend_values.y / this.zone.minor_radius); |
|
||||||
|
|
||||||
if (major_blend.y > 0.4f) |
|
||||||
blend_ratio.x = major_blend.y; |
|
||||||
else |
|
||||||
blend_ratio.x = Math.min(major_blend.x, 0.4f); |
|
||||||
|
|
||||||
if (minor_blend.y > 0.4f) |
|
||||||
blend_ratio.y = minor_blend.y; |
|
||||||
else |
|
||||||
blend_ratio.y = Math.min(minor_blend.x, 0.4f); |
|
||||||
|
|
||||||
// Scale coefficient for this terrain
|
|
||||||
|
|
||||||
this.terrain_scale = this.zone.template.terrain_max_y / 255f; |
|
||||||
} |
|
||||||
|
|
||||||
public static Zone getNextZoneWithTerrain(Zone zone) { |
|
||||||
|
|
||||||
// Not all zones have a terrain. Some are for display only
|
|
||||||
// and heights returned are from the parent heightmap. This
|
|
||||||
// is controlled in the JSON via the has_terrain_gen field.
|
|
||||||
|
|
||||||
Zone terrain_zone = zone; |
|
||||||
|
|
||||||
if (zone == null) |
|
||||||
return ZoneManager.seaFloor; |
|
||||||
|
|
||||||
if (zone.terrain != null) |
|
||||||
return zone; |
|
||||||
|
|
||||||
if (zone.equals(ZoneManager.seaFloor)) |
|
||||||
return zone; |
|
||||||
|
|
||||||
while (terrain_zone.terrain == null) |
|
||||||
terrain_zone = terrain_zone.parent; |
|
||||||
|
|
||||||
return terrain_zone; |
|
||||||
} |
|
||||||
|
|
||||||
public static float getWorldHeight(Zone zone, Vector3fImmutable world_loc) { |
|
||||||
|
|
||||||
// Retrieve the next zone up in the tree with a terrain defined.
|
|
||||||
|
|
||||||
Zone terrainZone = getNextZoneWithTerrain(zone); |
|
||||||
Zone parentZone = getNextZoneWithTerrain(zone.parent); |
|
||||||
|
|
||||||
// Transform world loc into zone space coordinate system
|
|
||||||
|
|
||||||
Vector2f terrainLoc = ZoneManager.worldToTerrainSpace(world_loc, terrainZone); |
|
||||||
Vector2f parentLoc = ZoneManager.worldToTerrainSpace(world_loc, parentZone); |
|
||||||
|
|
||||||
// Offset from origin needed for blending function
|
|
||||||
|
|
||||||
Vector2f terrainOffset = ZoneManager.worldToZoneOffset(world_loc, terrainZone); |
|
||||||
|
|
||||||
// Interpolate height for this position in both terrains
|
|
||||||
|
|
||||||
float interpolatedChildHeight = terrainZone.terrain.getInterpolatedTerrainHeight(terrainLoc); |
|
||||||
interpolatedChildHeight += terrainZone.global_height; |
|
||||||
|
|
||||||
float interpolatedParentTerrainHeight = parentZone.terrain.getInterpolatedTerrainHeight(parentLoc); |
|
||||||
interpolatedParentTerrainHeight += parentZone.global_height; |
|
||||||
|
|
||||||
// Blend between terrains
|
|
||||||
|
|
||||||
float blendCoefficient = terrainZone.terrain.getTerrainBlendCoefficient(terrainOffset); |
|
||||||
|
|
||||||
float terrainHeight = interpolatedChildHeight * blendCoefficient; |
|
||||||
terrainHeight += interpolatedParentTerrainHeight * (1 - blendCoefficient); |
|
||||||
|
|
||||||
return terrainHeight; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
public static float getWorldHeight(Vector3fImmutable world_loc) { |
|
||||||
|
|
||||||
Zone currentZone = ZoneManager.findSmallestZone(world_loc); |
|
||||||
|
|
||||||
return getWorldHeight(currentZone, world_loc); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
public Vector2f getTerrainCell(Vector2f terrain_loc) { |
|
||||||
|
|
||||||
// Calculate terrain cell with offset
|
|
||||||
|
|
||||||
Vector2f terrain_cell = new Vector2f(terrain_loc.x / this.cell_size.x, terrain_loc.y / this.cell_size.y); |
|
||||||
|
|
||||||
// Clamp values when standing directly on pole
|
|
||||||
|
|
||||||
terrain_cell.x = Math.max(0, Math.min(this.cell_count.x - 1, terrain_cell.x)); |
|
||||||
terrain_cell.y = Math.max(0, Math.min(this.cell_count.y - 1, terrain_cell.y)); |
|
||||||
|
|
||||||
return terrain_cell; |
|
||||||
} |
|
||||||
|
|
||||||
public float getInterpolatedTerrainHeight(Vector2f terrain_loc) { |
|
||||||
|
|
||||||
float interpolatedHeight; |
|
||||||
|
|
||||||
// Early exit for guild zones
|
|
||||||
|
|
||||||
if (this.zone.guild_zone) |
|
||||||
return 5.0f; |
|
||||||
|
|
||||||
// Determine terrain and offset from top left vertex
|
|
||||||
|
|
||||||
Vector2f terrain_cell = getTerrainCell(terrain_loc); |
|
||||||
|
|
||||||
int pixel_x = (int) Math.floor(terrain_cell.x); |
|
||||||
int pixel_y = (int) Math.floor(terrain_cell.y); |
|
||||||
|
|
||||||
Vector2f pixel_offset = new Vector2f(terrain_cell.x % 1, terrain_cell.y % 1); |
|
||||||
|
|
||||||
// 4 surrounding vertices from the pixel array.
|
|
||||||
|
|
||||||
short top_left_pixel = terrain_pixel_data[pixel_x][pixel_y]; |
|
||||||
short top_right_pixel = terrain_pixel_data[pixel_x + 1][pixel_y]; |
|
||||||
short bottom_left_pixel = terrain_pixel_data[pixel_x][pixel_y + 1]; |
|
||||||
short bottom_right_pixel = terrain_pixel_data[pixel_x + 1][pixel_y + 1]; |
|
||||||
|
|
||||||
// Interpolate between the 4 vertices
|
|
||||||
|
|
||||||
interpolatedHeight = top_left_pixel * (1 - pixel_offset.x) * (1 - pixel_offset.y); |
|
||||||
interpolatedHeight += top_right_pixel * (1 - pixel_offset.y) * (pixel_offset.x); |
|
||||||
interpolatedHeight += (bottom_left_pixel * (1 - pixel_offset.x) * pixel_offset.y); |
|
||||||
interpolatedHeight += (bottom_right_pixel * pixel_offset.y * pixel_offset.x); |
|
||||||
|
|
||||||
interpolatedHeight *= this.terrain_scale; // Scale height
|
|
||||||
|
|
||||||
return interpolatedHeight; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
public float getTerrainBlendCoefficient(Vector2f zone_offset) { |
|
||||||
|
|
||||||
// Normalize terrain offset
|
|
||||||
|
|
||||||
Vector2f normalizedOffset = new Vector2f(Math.abs(zone_offset.x) / this.zone.template.major_radius, |
|
||||||
Math.abs(zone_offset.y) / this.zone.template.minor_radius); |
|
||||||
|
|
||||||
float blendCoefficient; |
|
||||||
|
|
||||||
if (normalizedOffset.x <= 1 - blend_ratio.x || normalizedOffset.x <= normalizedOffset.y) { |
|
||||||
|
|
||||||
if (normalizedOffset.y < 1 - blend_ratio.y) |
|
||||||
return 1; |
|
||||||
|
|
||||||
blendCoefficient = (normalizedOffset.y - (1 - blend_ratio.y)) / blend_ratio.y; |
|
||||||
} else |
|
||||||
blendCoefficient = (normalizedOffset.x - (1 - blend_ratio.x)) / blend_ratio.x; |
|
||||||
|
|
||||||
blendCoefficient = (float) Math.atan((0.5f - blendCoefficient) * PI); |
|
||||||
|
|
||||||
return (blendCoefficient + 1) * 0.5f; |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,51 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2022
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
|
||||||
|
package engine.db.handlers; |
||||||
|
|
||||||
|
import engine.gameManager.DbManager; |
||||||
|
import engine.objects.Boon; |
||||||
|
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; |
||||||
|
|
||||||
|
public class dbBoonHandler extends dbHandlerBase { |
||||||
|
|
||||||
|
public dbBoonHandler() { |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public ArrayList<Boon> GET_BOON_AMOUNTS_FOR_ITEMBASE(int itemBaseUUID) { |
||||||
|
|
||||||
|
ArrayList<Boon> boons = new ArrayList<>(); |
||||||
|
Boon thisBoon; |
||||||
|
|
||||||
|
try (Connection connection = DbManager.getConnection(); |
||||||
|
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `static_item_boons` WHERE `itemBaseID` = ?")) { |
||||||
|
|
||||||
|
preparedStatement.setInt(1, itemBaseUUID); |
||||||
|
|
||||||
|
ResultSet rs = preparedStatement.executeQuery(); |
||||||
|
|
||||||
|
while (rs.next()) { |
||||||
|
thisBoon = new Boon(rs); |
||||||
|
boons.add(thisBoon); |
||||||
|
} |
||||||
|
|
||||||
|
} catch (SQLException e) { |
||||||
|
Logger.error(e); |
||||||
|
} |
||||||
|
|
||||||
|
return boons; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,43 @@ |
|||||||
|
package engine.db.handlers; |
||||||
|
|
||||||
|
import engine.InterestManagement.HeightMap; |
||||||
|
import engine.gameManager.DbManager; |
||||||
|
import org.pmw.tinylog.Logger; |
||||||
|
|
||||||
|
import java.sql.Connection; |
||||||
|
import java.sql.PreparedStatement; |
||||||
|
import java.sql.ResultSet; |
||||||
|
import java.sql.SQLException; |
||||||
|
|
||||||
|
public class dbHeightMapHandler extends dbHandlerBase { |
||||||
|
|
||||||
|
public dbHeightMapHandler() { |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public void LOAD_ALL_HEIGHTMAPS() { |
||||||
|
|
||||||
|
HeightMap thisHeightmap; |
||||||
|
HeightMap.heightMapsCreated = 0; |
||||||
|
|
||||||
|
try (Connection connection = DbManager.getConnection(); |
||||||
|
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM static_zone_heightmap INNER JOIN static_zone_size ON static_zone_size.loadNum = static_zone_heightmap.zoneLoadID")) { |
||||||
|
|
||||||
|
ResultSet rs = preparedStatement.executeQuery(); |
||||||
|
|
||||||
|
while (rs.next()) { |
||||||
|
thisHeightmap = new HeightMap(rs); |
||||||
|
|
||||||
|
if (thisHeightmap.getHeightmapImage() == null) { |
||||||
|
Logger.info("Imagemap for " + thisHeightmap.getHeightMapID() + " was null"); |
||||||
|
continue; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} catch (SQLException e) { |
||||||
|
Logger.error(e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,138 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2022
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
|
||||||
|
package engine.db.handlers; |
||||||
|
|
||||||
|
import engine.gameManager.DbManager; |
||||||
|
import engine.objects.ItemBase; |
||||||
|
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; |
||||||
|
|
||||||
|
public class dbItemBaseHandler extends dbHandlerBase { |
||||||
|
|
||||||
|
public dbItemBaseHandler() { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public void LOAD_BAKEDINSTATS(ItemBase itemBase) { |
||||||
|
|
||||||
|
try (Connection connection = DbManager.getConnection(); |
||||||
|
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `static_item_bakedinstat` WHERE `itemID` = ?")) { |
||||||
|
|
||||||
|
preparedStatement.setInt(1, itemBase.getUUID()); |
||||||
|
ResultSet rs = preparedStatement.executeQuery(); |
||||||
|
|
||||||
|
while (rs.next()) { |
||||||
|
if (rs.getBoolean("fromUse")) |
||||||
|
itemBase.getUsedStats().put(rs.getInt("token"), rs.getInt("numTrains")); |
||||||
|
else |
||||||
|
itemBase.getBakedInStats().put(rs.getInt("token"), rs.getInt("numTrains")); |
||||||
|
} |
||||||
|
} catch (SQLException e) { |
||||||
|
Logger.error(e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void LOAD_ANIMATIONS(ItemBase itemBase) { |
||||||
|
|
||||||
|
ArrayList<Integer> tempList = new ArrayList<>(); |
||||||
|
ArrayList<Integer> tempListOff = new ArrayList<>(); |
||||||
|
|
||||||
|
try (Connection connection = DbManager.getConnection(); |
||||||
|
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `static_itembase_animations` WHERE `itemBaseUUID` = ?")) { |
||||||
|
|
||||||
|
preparedStatement.setInt(1, itemBase.getUUID()); |
||||||
|
ResultSet rs = preparedStatement.executeQuery(); |
||||||
|
|
||||||
|
while (rs.next()) { |
||||||
|
int animation = rs.getInt("animation"); |
||||||
|
boolean rightHand = rs.getBoolean("rightHand"); |
||||||
|
|
||||||
|
if (rightHand) |
||||||
|
tempList.add(animation); |
||||||
|
else |
||||||
|
tempListOff.add(animation); |
||||||
|
} |
||||||
|
} catch (SQLException e) { |
||||||
|
Logger.error(e); |
||||||
|
} |
||||||
|
|
||||||
|
itemBase.setAnimations(tempList); |
||||||
|
itemBase.setOffHandAnimations(tempListOff); |
||||||
|
} |
||||||
|
|
||||||
|
public void LOAD_ALL_ITEMBASES() { |
||||||
|
|
||||||
|
ItemBase itemBase; |
||||||
|
int recordsRead = 0; |
||||||
|
|
||||||
|
try (Connection connection = DbManager.getConnection(); |
||||||
|
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM static_itembase")) { |
||||||
|
|
||||||
|
ResultSet rs = preparedStatement.executeQuery(); |
||||||
|
|
||||||
|
while (rs.next()) { |
||||||
|
recordsRead++; |
||||||
|
itemBase = new ItemBase(rs); |
||||||
|
ItemBase.addToCache(itemBase); |
||||||
|
} |
||||||
|
|
||||||
|
} catch (SQLException e) { |
||||||
|
Logger.error(e); |
||||||
|
} |
||||||
|
|
||||||
|
Logger.info("read: " + recordsRead + " cached: " + ItemBase.getUUIDCache().size()); |
||||||
|
} |
||||||
|
|
||||||
|
public HashMap<Integer, ArrayList<Integer>> LOAD_RUNES_FOR_NPC_AND_MOBS() { |
||||||
|
|
||||||
|
HashMap<Integer, ArrayList<Integer>> runeSets = new HashMap<>(); |
||||||
|
int runeSetID; |
||||||
|
int runeBaseID; |
||||||
|
int recordsRead = 0; |
||||||
|
|
||||||
|
try (Connection connection = DbManager.getConnection(); |
||||||
|
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM static_npc_runeSet")) { |
||||||
|
|
||||||
|
ResultSet rs = preparedStatement.executeQuery(); |
||||||
|
|
||||||
|
while (rs.next()) { |
||||||
|
|
||||||
|
recordsRead++; |
||||||
|
|
||||||
|
runeSetID = rs.getInt("runeSet"); |
||||||
|
runeBaseID = rs.getInt("runeBase"); |
||||||
|
|
||||||
|
if (runeSets.get(runeSetID) == null) { |
||||||
|
ArrayList<Integer> runeList = new ArrayList<>(); |
||||||
|
runeList.add(runeBaseID); |
||||||
|
runeSets.put(runeSetID, runeList); |
||||||
|
} else { |
||||||
|
ArrayList<Integer> runeList = runeSets.get(runeSetID); |
||||||
|
runeList.add(runeSetID); |
||||||
|
runeSets.put(runeSetID, runeList); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} catch (SQLException e) { |
||||||
|
Logger.error(e); |
||||||
|
return runeSets; |
||||||
|
} |
||||||
|
|
||||||
|
Logger.info("read: " + recordsRead + " cached: " + runeSets.size()); |
||||||
|
return runeSets; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,127 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2022
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
|
||||||
|
package engine.devcmd.cmds; |
||||||
|
|
||||||
|
import engine.Enum.ModType; |
||||||
|
import engine.devcmd.AbstractDevCmd; |
||||||
|
import engine.gameManager.PowersManager; |
||||||
|
import engine.net.ItemProductionManager; |
||||||
|
import engine.objects.*; |
||||||
|
import engine.powers.effectmodifiers.AbstractEffectModifier; |
||||||
|
import engine.powers.poweractions.AbstractPowerAction; |
||||||
|
import org.pmw.tinylog.Logger; |
||||||
|
|
||||||
|
public class AuditFailedItemsCmd extends AbstractDevCmd { |
||||||
|
|
||||||
|
public AuditFailedItemsCmd() { |
||||||
|
super("faileditems"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void _doCmd(PlayerCharacter pcSender, String[] words, |
||||||
|
AbstractGameObject target) { |
||||||
|
|
||||||
|
|
||||||
|
if (ItemProductionManager.FailedItems.isEmpty()) |
||||||
|
return; |
||||||
|
|
||||||
|
Logger.info("Auditing Item production Failed Items"); |
||||||
|
|
||||||
|
String newLine = "\r\n"; |
||||||
|
String auditFailedItem = "Failed Item Name | Prefix | Suffix | NPC | Contract | Player | "; |
||||||
|
|
||||||
|
for (ProducedItem failedItem : ItemProductionManager.FailedItems) { |
||||||
|
|
||||||
|
String npcName = ""; |
||||||
|
String playerName = ""; |
||||||
|
String contractName = ""; |
||||||
|
|
||||||
|
String prefix = ""; |
||||||
|
String suffix = ""; |
||||||
|
String itemName = ""; |
||||||
|
NPC npc = NPC.getFromCache(failedItem.getNpcUID()); |
||||||
|
|
||||||
|
if (npc == null) { |
||||||
|
npcName = "null"; |
||||||
|
contractName = "null"; |
||||||
|
} else { |
||||||
|
npcName = npc.getName(); |
||||||
|
if (npc.getContract() != null) |
||||||
|
contractName = npc.getContract().getName(); |
||||||
|
} |
||||||
|
|
||||||
|
PlayerCharacter roller = PlayerCharacter.getFromCache(failedItem.getPlayerID()); |
||||||
|
|
||||||
|
if (roller == null) |
||||||
|
playerName = "null"; |
||||||
|
else |
||||||
|
playerName = roller.getName(); |
||||||
|
|
||||||
|
ItemBase ib = ItemBase.getItemBase(failedItem.getItemBaseID()); |
||||||
|
|
||||||
|
if (ib != null) { |
||||||
|
itemName = ib.getName(); |
||||||
|
} |
||||||
|
|
||||||
|
if (failedItem.isRandom() == false) { |
||||||
|
if (failedItem.getPrefix().isEmpty() == false) { |
||||||
|
AbstractPowerAction pa = PowersManager.getPowerActionByIDString(failedItem.getPrefix()); |
||||||
|
if (pa != null) { |
||||||
|
for (AbstractEffectModifier aem : pa.getEffectsBase().getModifiers()) { |
||||||
|
if (aem.modType.equals(ModType.ItemName)) { |
||||||
|
prefix = aem.getString1(); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
if (failedItem.getSuffix().isEmpty() == false) { |
||||||
|
AbstractPowerAction pa = PowersManager.getPowerActionByIDString(failedItem.getSuffix()); |
||||||
|
if (pa != null) { |
||||||
|
for (AbstractEffectModifier aem : pa.getEffectsBase().getModifiers()) { |
||||||
|
if (aem.modType.equals(ModType.ItemName)) { |
||||||
|
suffix = aem.getString1(); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} else { |
||||||
|
prefix = "random"; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
auditFailedItem += newLine; |
||||||
|
auditFailedItem += itemName + " | " + prefix + " | " + suffix + " | " + failedItem.getNpcUID() + ":" + npcName + " | " + contractName + " | " + failedItem.getPlayerID() + ":" + playerName; |
||||||
|
|
||||||
|
} |
||||||
|
Logger.info(auditFailedItem); |
||||||
|
ItemProductionManager.FailedItems.clear(); |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getUsageString() { |
||||||
|
return "' /bounds'"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getHelpString() { |
||||||
|
return "Audits all the mobs in a zone."; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -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."; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,105 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2022
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
|
||||||
|
package engine.devcmd.cmds; |
||||||
|
|
||||||
|
import engine.devcmd.AbstractDevCmd; |
||||||
|
import engine.gameManager.ZoneManager; |
||||||
|
import engine.objects.AbstractGameObject; |
||||||
|
import engine.objects.PlayerCharacter; |
||||||
|
import engine.objects.Zone; |
||||||
|
|
||||||
|
public class AuditMobsCmd extends AbstractDevCmd { |
||||||
|
|
||||||
|
public AuditMobsCmd() { |
||||||
|
super("auditmobs"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void _doCmd(PlayerCharacter pcSender, String[] words, |
||||||
|
AbstractGameObject target) { |
||||||
|
if (pcSender == null) |
||||||
|
return; |
||||||
|
|
||||||
|
//get Zone to check mobs against
|
||||||
|
|
||||||
|
Zone zone; |
||||||
|
|
||||||
|
if (words.length == 2) { |
||||||
|
if (words[0].equals("all")) { |
||||||
|
int plusplus = 0; |
||||||
|
int count = Integer.parseInt(words[1]); |
||||||
|
for (Zone zoneMicro : ZoneManager.getAllZones()) { |
||||||
|
int size = zoneMicro.zoneMobSet.size(); |
||||||
|
|
||||||
|
if (size >= count) { |
||||||
|
plusplus++; |
||||||
|
throwbackInfo(pcSender, zoneMicro.getName() + " at location " + zoneMicro.getLoc().toString() + " has " + size + " mobs. "); |
||||||
|
System.out.println(zoneMicro.getName() + " at location " + zoneMicro.getLoc().toString() + " has " + size + " mobs. "); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
throwbackInfo(pcSender, " there are " + plusplus + " zones with at least " + count + " mobs in each."); |
||||||
|
} |
||||||
|
return; |
||||||
|
} |
||||||
|
if (words.length > 1) { |
||||||
|
this.sendUsage(pcSender); |
||||||
|
return; |
||||||
|
} else if (words.length == 1) { |
||||||
|
int uuid; |
||||||
|
try { |
||||||
|
uuid = Integer.parseInt(words[0]); |
||||||
|
zone = ZoneManager.getZoneByUUID(uuid); |
||||||
|
} catch (NumberFormatException e) { |
||||||
|
zone = ZoneManager.findSmallestZone(pcSender.getLoc()); |
||||||
|
} |
||||||
|
} else |
||||||
|
zone = ZoneManager.findSmallestZone(pcSender.getLoc()); |
||||||
|
|
||||||
|
if (zone == null) { |
||||||
|
throwbackError(pcSender, "Unable to find the zone"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
//get list of mobs for zone
|
||||||
|
|
||||||
|
if (zone.zoneMobSet.isEmpty()) { |
||||||
|
throwbackError(pcSender, "No mobs found for this zone."); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// ConcurrentHashMap<Integer, Mob> spawnMap = Mob.getSpawnMap();
|
||||||
|
//ConcurrentHashMap<Mob, Long> respawnMap = Mob.getRespawnMap();
|
||||||
|
// ConcurrentHashMap<Mob, Long> despawnMap = Mob.getDespawnMap();
|
||||||
|
|
||||||
|
throwbackInfo(pcSender, zone.getName() + ", numMobs: " + zone.zoneMobSet.size()); |
||||||
|
throwbackInfo(pcSender, "UUID, dbID, inRespawnMap, isAlive, activeAI, Loc"); |
||||||
|
|
||||||
|
|
||||||
|
//mob not found in spawn map, check respawn
|
||||||
|
boolean inRespawn = false; |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getUsageString() { |
||||||
|
return "' /auditmobs [zone.UUID]'"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getHelpString() { |
||||||
|
return "Audits all the mobs in a zone."; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,114 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2022
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
|
||||||
|
package engine.devcmd.cmds; |
||||||
|
|
||||||
|
import engine.devcmd.AbstractDevCmd; |
||||||
|
import engine.gameManager.DbManager; |
||||||
|
import engine.gameManager.SessionManager; |
||||||
|
import engine.math.Vector3fImmutable; |
||||||
|
import engine.objects.AbstractGameObject; |
||||||
|
import engine.objects.PlayerCharacter; |
||||||
|
import engine.util.MiscUtils; |
||||||
|
|
||||||
|
public class ChangeNameCmd extends AbstractDevCmd { |
||||||
|
|
||||||
|
public ChangeNameCmd() { |
||||||
|
super("changename"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void _doCmd(PlayerCharacter pc, String[] words, |
||||||
|
AbstractGameObject target) { |
||||||
|
Vector3fImmutable loc = null; |
||||||
|
|
||||||
|
// Arg Count Check
|
||||||
|
if (words.length < 2) { |
||||||
|
this.sendUsage(pc); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
String oldFirst = words[0]; |
||||||
|
String newFirst = words[1]; |
||||||
|
String newLast = ""; |
||||||
|
if (words.length > 2) { |
||||||
|
newLast = words[2]; |
||||||
|
for (int i = 3; i < words.length; i++) |
||||||
|
newLast += ' ' + words[i]; |
||||||
|
} |
||||||
|
|
||||||
|
//verify new name length
|
||||||
|
if (newFirst.length() < 3) { |
||||||
|
this.throwbackError(pc, "Error: First name is incorrect length. Must be between 3 and 15 characters"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
//verify old name length
|
||||||
|
if (newLast.length() > 50) { |
||||||
|
this.throwbackError(pc, "Error: Last name is incorrect length. Must be no more than 50 characters"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// Check if firstname is valid
|
||||||
|
if (MiscUtils.checkIfFirstNameInvalid(newFirst)) { |
||||||
|
this.throwbackError(pc, "Error: First name is not allowed"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//get the world ID we're modifying for
|
||||||
|
|
||||||
|
//test if first name is unique, unless new and old first name are equal.
|
||||||
|
if (!(oldFirst.equals(newFirst))) { |
||||||
|
if (!DbManager.PlayerCharacterQueries.IS_CHARACTER_NAME_UNIQUE(newFirst)) { |
||||||
|
this.throwbackError(pc, "Error: First name is not unique."); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//tests passed, update name in database
|
||||||
|
if (!DbManager.PlayerCharacterQueries.UPDATE_NAME(oldFirst, newFirst, newLast)) { |
||||||
|
this.throwbackError(pc, "Error: Database failed to update the name."); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
//Finally update player ingame
|
||||||
|
PlayerCharacter pcTar = null; |
||||||
|
try { |
||||||
|
pcTar = SessionManager |
||||||
|
.getPlayerCharacterByLowerCaseName(words[0]); |
||||||
|
pcTar.setFirstName(newFirst); |
||||||
|
pcTar.setLastName(newLast); |
||||||
|
this.setTarget(pcTar); //for logging
|
||||||
|
|
||||||
|
//specify if last name is ascii characters only
|
||||||
|
String lastAscii = newLast.replaceAll("[^\\p{ASCII}]", ""); |
||||||
|
pcTar.setAsciiLastName(lastAscii.equals(newLast)); |
||||||
|
} catch (Exception e) { |
||||||
|
this.throwbackError(pc, "Database was updated but ingame character failed to update."); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
String out = oldFirst + " was changed to " + newFirst + (newLast.isEmpty() ? "." : (' ' + newLast + '.')); |
||||||
|
this.throwbackInfo(pc, out); |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getHelpString() { |
||||||
|
return "Changes the name of a player"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getUsageString() { |
||||||
|
return "'./changename oldFirstName newFirstName newLastName'"; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,56 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2022
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
|
||||||
|
package engine.devcmd.cmds; |
||||||
|
|
||||||
|
import engine.devcmd.AbstractDevCmd; |
||||||
|
import engine.net.client.msg.TargetedActionMsg; |
||||||
|
import engine.objects.AbstractGameObject; |
||||||
|
import engine.objects.PlayerCharacter; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Eighty |
||||||
|
*/ |
||||||
|
public class CombatMessageCmd extends AbstractDevCmd { |
||||||
|
|
||||||
|
public CombatMessageCmd() { |
||||||
|
super("cm"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void _doCmd(PlayerCharacter pcSender, String[] args, |
||||||
|
AbstractGameObject target) { |
||||||
|
if (pcSender == null) |
||||||
|
return; |
||||||
|
if (args.length != 1) { |
||||||
|
this.sendUsage(pcSender); |
||||||
|
return; |
||||||
|
} |
||||||
|
int num = 0; |
||||||
|
try { |
||||||
|
num = Integer.parseInt(args[0]); |
||||||
|
} catch (NumberFormatException e) { |
||||||
|
throwbackError(pcSender, "Supplied message number " + args[0] + " failed to parse to an Integer"); |
||||||
|
return; |
||||||
|
} |
||||||
|
TargetedActionMsg.un2cnt = num; |
||||||
|
throwbackInfo(pcSender, "CombatMessage set to " + num); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getUsageString() { |
||||||
|
return "' /cm [cmNumber]'"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getHelpString() { |
||||||
|
return "Sets the combat message to the supplied integer value"; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,122 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2022
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
|
||||||
|
package engine.devcmd.cmds; |
||||||
|
|
||||||
|
import engine.devcmd.AbstractDevCmd; |
||||||
|
import engine.jobs.DebugTimerJob; |
||||||
|
import engine.objects.AbstractGameObject; |
||||||
|
import engine.objects.PlayerCharacter; |
||||||
|
|
||||||
|
public class DebugCmd extends AbstractDevCmd { |
||||||
|
|
||||||
|
|
||||||
|
public DebugCmd() { |
||||||
|
super("debug"); |
||||||
|
// super("debug", MBServerStatics.ACCESS_GROUP_ALL_TEAM, 0, false, false);
|
||||||
|
} |
||||||
|
|
||||||
|
private static void toggleDebugTimer(PlayerCharacter pc, String name, int num, int duration, boolean toggle) { |
||||||
|
if (toggle) { |
||||||
|
DebugTimerJob dtj = new DebugTimerJob(pc, name, num, duration); |
||||||
|
pc.renewTimer(name, dtj, duration); |
||||||
|
} else |
||||||
|
pc.cancelTimer(name); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void _doCmd(PlayerCharacter pc, String[] words, |
||||||
|
AbstractGameObject target) { |
||||||
|
if (words.length < 2) { |
||||||
|
this.sendUsage(pc); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (pc == null) |
||||||
|
return; |
||||||
|
|
||||||
|
//pc.setDebug must use bit sizes: 1, 2, 4, 8, 16, 32
|
||||||
|
|
||||||
|
String command = words[0].toLowerCase(); |
||||||
|
boolean toggle = (words[1].toLowerCase().equals("on")) ? true : false; |
||||||
|
|
||||||
|
switch (command) { |
||||||
|
case "magictrek": |
||||||
|
pc.RUN_MAGICTREK = toggle; |
||||||
|
|
||||||
|
break; |
||||||
|
case "combat": |
||||||
|
pc.setDebug(64, toggle); |
||||||
|
|
||||||
|
break; |
||||||
|
case "health": |
||||||
|
toggleDebugTimer(pc, "Debug_Health", 1, 1000, toggle); |
||||||
|
|
||||||
|
break; |
||||||
|
case "mana": |
||||||
|
toggleDebugTimer(pc, "Debug_Mana", 2, 1000, toggle); |
||||||
|
|
||||||
|
break; |
||||||
|
case "stamina": |
||||||
|
toggleDebugTimer(pc, "Debug_Stamina", 3, 500, toggle); |
||||||
|
|
||||||
|
break; |
||||||
|
case "spells": |
||||||
|
pc.setDebug(16, toggle); |
||||||
|
|
||||||
|
break; |
||||||
|
case "damageabsorber": |
||||||
|
pc.setDebug(2, toggle); |
||||||
|
|
||||||
|
break; |
||||||
|
case "recast": |
||||||
|
case "recycle": |
||||||
|
pc.setDebug(4, toggle); |
||||||
|
|
||||||
|
break; |
||||||
|
case "seeinvis": |
||||||
|
pc.setDebug(8, toggle); |
||||||
|
|
||||||
|
break; |
||||||
|
case "movement": |
||||||
|
pc.setDebug(1, toggle); |
||||||
|
|
||||||
|
break; |
||||||
|
case "noaggro": |
||||||
|
pc.setDebug(32, toggle); |
||||||
|
|
||||||
|
break; |
||||||
|
// case "loot":
|
||||||
|
// MBServerStatics.debugLoot = toggle;
|
||||||
|
// break;
|
||||||
|
|
||||||
|
default: |
||||||
|
String output = "Debug for " + command + " not found."; |
||||||
|
throwbackError(pc, output); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
setTarget(pc); //for logging
|
||||||
|
|
||||||
|
String output = "Debug for " + command + " turned " + ((toggle) ? "on." : "off."); |
||||||
|
throwbackInfo(pc, output); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getHelpString() { |
||||||
|
return "Runs debug commands"; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getUsageString() { |
||||||
|
return "'./Debug command on/off'"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,66 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2022
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
|
||||||
|
package engine.devcmd.cmds; |
||||||
|
|
||||||
|
import engine.Enum.GameObjectType; |
||||||
|
import engine.devcmd.AbstractDevCmd; |
||||||
|
import engine.objects.AbstractGameObject; |
||||||
|
import engine.objects.Mob; |
||||||
|
import engine.objects.PlayerCharacter; |
||||||
|
|
||||||
|
public class DespawnCmd extends AbstractDevCmd { |
||||||
|
|
||||||
|
public DespawnCmd() { |
||||||
|
super("debugmob"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void _doCmd(PlayerCharacter pc, String[] words, |
||||||
|
AbstractGameObject target) { |
||||||
|
|
||||||
|
|
||||||
|
if (pc == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
Mob mob = null; |
||||||
|
|
||||||
|
if (target != null && target.getObjectType().equals(GameObjectType.Mob)) |
||||||
|
mob = (Mob) target; |
||||||
|
|
||||||
|
if (mob == null) |
||||||
|
mob = Mob.getFromCache(Integer.parseInt(words[1])); |
||||||
|
|
||||||
|
if (mob == null) |
||||||
|
return; |
||||||
|
|
||||||
|
if (words[0].equalsIgnoreCase("respawn")) { |
||||||
|
mob.respawn(); |
||||||
|
this.throwbackInfo(pc, "Mob with ID " + mob.getObjectUUID() + " Respawned"); |
||||||
|
} else if (words[0].equalsIgnoreCase("despawn")) { |
||||||
|
mob.despawn(); |
||||||
|
this.throwbackInfo(pc, "Mob with ID " + mob.getObjectUUID() + " Despawned"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getHelpString() { |
||||||
|
return "Gets distance from a target."; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getUsageString() { |
||||||
|
return "' /distance'"; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,65 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2022
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
|
||||||
|
package engine.devcmd.cmds; |
||||||
|
|
||||||
|
import engine.devcmd.AbstractDevCmd; |
||||||
|
import engine.math.Vector3fImmutable; |
||||||
|
import engine.objects.AbstractGameObject; |
||||||
|
import engine.objects.AbstractWorldObject; |
||||||
|
import engine.objects.PlayerCharacter; |
||||||
|
|
||||||
|
public class DistanceCmd extends AbstractDevCmd { |
||||||
|
|
||||||
|
public DistanceCmd() { |
||||||
|
super("distance"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void _doCmd(PlayerCharacter pc, String[] words, |
||||||
|
AbstractGameObject target) { |
||||||
|
|
||||||
|
|
||||||
|
// Arg Count Check
|
||||||
|
if (words.length != 1) { |
||||||
|
this.sendUsage(pc); |
||||||
|
return; |
||||||
|
} |
||||||
|
if (pc == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (target == null || !(target instanceof AbstractWorldObject)) { |
||||||
|
throwbackError(pc, "No target found."); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
AbstractWorldObject awoTarget = (AbstractWorldObject) target; |
||||||
|
|
||||||
|
Vector3fImmutable pcLoc = pc.getLoc(); |
||||||
|
Vector3fImmutable tarLoc = awoTarget.getLoc(); |
||||||
|
String out = "Distance: " + pcLoc.distance(tarLoc) + |
||||||
|
"\r\nYour Loc: " + pcLoc.x + 'x' + pcLoc.y + 'x' + pcLoc.z + |
||||||
|
"\r\nTarget Loc: " + tarLoc.x + 'x' + tarLoc.y + 'x' + tarLoc.z; |
||||||
|
throwbackInfo(pc, out); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getHelpString() { |
||||||
|
return "Gets distance from a target."; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getUsageString() { |
||||||
|
return "' /distance'"; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,61 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2022
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
|
||||||
|
package engine.devcmd.cmds; |
||||||
|
|
||||||
|
import engine.devcmd.AbstractDevCmd; |
||||||
|
import engine.gameManager.ChatManager; |
||||||
|
import engine.gameManager.PowersManager; |
||||||
|
import engine.objects.AbstractGameObject; |
||||||
|
import engine.objects.PlayerCharacter; |
||||||
|
import engine.powers.EffectsBase; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Eighty |
||||||
|
*/ |
||||||
|
public class EffectCmd extends AbstractDevCmd { |
||||||
|
|
||||||
|
public EffectCmd() { |
||||||
|
super("effect"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void _doCmd(PlayerCharacter pcSender, String[] args, |
||||||
|
AbstractGameObject target) { |
||||||
|
int ID = 0; |
||||||
|
int token = 0; |
||||||
|
|
||||||
|
if (args.length != 2) { |
||||||
|
this.sendUsage(pcSender); |
||||||
|
return; |
||||||
|
} |
||||||
|
ID = Integer.parseInt(args[0]); |
||||||
|
token = Integer.parseInt(args[1]); |
||||||
|
|
||||||
|
EffectsBase eb = PowersManager.setEffectToken(ID, token); |
||||||
|
if (eb == null) { |
||||||
|
throwbackError(pcSender, "Unable to find EffectsBase " + ID |
||||||
|
+ " to modify."); |
||||||
|
return; |
||||||
|
} |
||||||
|
ChatManager.chatSayInfo(pcSender, |
||||||
|
"EffectsBase with ID " + ID + " changed token to " + token); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getUsageString() { |
||||||
|
return "' /effect EffectsBaseID Token'"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getHelpString() { |
||||||
|
return "Temporarily places the effect token with the corresponding EffectsBase on the server"; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,87 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2022
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
|
||||||
|
package engine.devcmd.cmds; |
||||||
|
|
||||||
|
import engine.devcmd.AbstractDevCmd; |
||||||
|
import engine.objects.*; |
||||||
|
|
||||||
|
public class EnchantCmd extends AbstractDevCmd { |
||||||
|
|
||||||
|
public EnchantCmd() { |
||||||
|
super("enchant"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void _doCmd(PlayerCharacter pc, String[] words, |
||||||
|
AbstractGameObject target) { |
||||||
|
int rank = 0; |
||||||
|
if (words.length < 1) { |
||||||
|
this.sendUsage(pc); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
try { |
||||||
|
rank = Integer.parseInt(words[0]); |
||||||
|
} catch (Exception e) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
Item item; |
||||||
|
if (target == null || target instanceof Item) |
||||||
|
item = (Item) target; |
||||||
|
else { |
||||||
|
throwbackError(pc, "Must have an item targeted"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
CharacterItemManager cim = pc.getCharItemManager(); |
||||||
|
if (cim == null) { |
||||||
|
throwbackError(pc, "Unable to find the character item manager for player " + pc.getFirstName() + '.'); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (words[0].equals("clear")) { |
||||||
|
item.clearEnchantments(); |
||||||
|
cim.updateInventory(); |
||||||
|
this.setResult(String.valueOf(item.getObjectUUID())); |
||||||
|
} else { |
||||||
|
int cnt = words.length; |
||||||
|
for (int i = 1; i < cnt; i++) { |
||||||
|
String enchant = words[i]; |
||||||
|
boolean valid = true; |
||||||
|
for (Effect eff : item.getEffects().values()) { |
||||||
|
if (eff.getEffectsBase().getIDString().equals(enchant)) { |
||||||
|
throwbackError(pc, "This item already has that enchantment"); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
if (valid) { |
||||||
|
item.addPermanentEnchantmentForDev(enchant, rank); |
||||||
|
this.setResult(String.valueOf(item.getObjectUUID())); |
||||||
|
} else |
||||||
|
throwbackError(pc, "Invalid Enchantment. Enchantment must consist of SUF-001 to SUF-328 or PRE-001 to PRE-334. Sent " + enchant + '.'); |
||||||
|
} |
||||||
|
cim.updateInventory(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getHelpString() { |
||||||
|
return "Enchants an item with a prefix and suffix"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getUsageString() { |
||||||
|
return "' /enchant clear/Enchant1 Enchant2 Enchant3 ...'"; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,84 @@ |
|||||||
|
package engine.devcmd.cmds; |
||||||
|
|
||||||
|
import engine.Enum.BuildingGroup; |
||||||
|
import engine.Enum.GameObjectType; |
||||||
|
import engine.devcmd.AbstractDevCmd; |
||||||
|
import engine.math.Vector3fImmutable; |
||||||
|
import engine.objects.*; |
||||||
|
|
||||||
|
public class GateInfoCmd extends AbstractDevCmd { |
||||||
|
|
||||||
|
public GateInfoCmd() { |
||||||
|
super("gateinfo"); |
||||||
|
} |
||||||
|
|
||||||
|
// AbstractDevCmd Overridden methods
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected void _doCmd(PlayerCharacter player, String[] args, |
||||||
|
AbstractGameObject target) { |
||||||
|
|
||||||
|
Building targetBuilding; |
||||||
|
String outString; |
||||||
|
Runegate runeGate; |
||||||
|
Blueprint blueprint; |
||||||
|
String newline = "\r\n "; |
||||||
|
targetBuilding = (Building) target; |
||||||
|
|
||||||
|
if (targetBuilding.getObjectType() != GameObjectType.Building) { |
||||||
|
throwbackInfo(player, "GateInfo: target must be a Building"); |
||||||
|
throwbackInfo(player, "Found" + targetBuilding.getObjectType().toString()); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
blueprint = Blueprint._meshLookup.get(targetBuilding.getMeshUUID()); |
||||||
|
|
||||||
|
if (blueprint == null || |
||||||
|
(blueprint.getBuildingGroup() != BuildingGroup.RUNEGATE)) { |
||||||
|
throwbackInfo(player, "showgate: target must be a Runegate"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
runeGate = Runegate._runegates.get(targetBuilding.getObjectUUID()); |
||||||
|
|
||||||
|
outString = "RungateType: " + runeGate.gateBuilding.getName(); |
||||||
|
outString += newline; |
||||||
|
|
||||||
|
outString += "Portal State:"; |
||||||
|
outString += newline; |
||||||
|
|
||||||
|
for (Portal portal : runeGate.getPortals()) { |
||||||
|
|
||||||
|
outString += "Portal: " + portal.portalType.name(); |
||||||
|
outString += " Active: " + portal.isActive(); |
||||||
|
outString += " Dest: " + portal.targetGate.getName(); |
||||||
|
outString += newline; |
||||||
|
outString += " Origin: " + portal.getPortalLocation().x + 'x'; |
||||||
|
outString += " " + portal.getPortalLocation().y + 'y'; |
||||||
|
outString += newline; |
||||||
|
|
||||||
|
Vector3fImmutable offset = portal.getPortalLocation().subtract(targetBuilding.getLoc()); |
||||||
|
outString += " Offset: " + offset.x + "x " + offset.z + 'y'; |
||||||
|
outString += newline; |
||||||
|
outString += newline; |
||||||
|
|
||||||
|
} |
||||||
|
outString += newline; |
||||||
|
throwbackInfo(player, outString); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getHelpString() { |
||||||
|
return "Displays a runegate's gate status"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getUsageString() { |
||||||
|
|
||||||
|
|
||||||
|
return "/gateinfo <target runegate> \n"; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,58 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2022
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
|
||||||
|
package engine.devcmd.cmds; |
||||||
|
|
||||||
|
import engine.devcmd.AbstractDevCmd; |
||||||
|
import engine.objects.AbstractGameObject; |
||||||
|
import engine.objects.PlayerCharacter; |
||||||
|
|
||||||
|
public class GetMemoryCmd extends AbstractDevCmd { |
||||||
|
|
||||||
|
public GetMemoryCmd() { |
||||||
|
super("getmemory"); |
||||||
|
} |
||||||
|
|
||||||
|
public static String getMemoryOutput(long memory) { |
||||||
|
String out = ""; |
||||||
|
if (memory > 1073741824) |
||||||
|
return (memory / 1073741824) + "GB"; |
||||||
|
else if (memory > 1048576) |
||||||
|
return (memory / 1048576) + "MB"; |
||||||
|
else if (memory > 1024) |
||||||
|
return (memory / 1048576) + "KB"; |
||||||
|
else |
||||||
|
return memory + "B"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void _doCmd(PlayerCharacter pcSender, String[] words, |
||||||
|
AbstractGameObject target) { |
||||||
|
if (pcSender == null) |
||||||
|
return; |
||||||
|
|
||||||
|
String hSize = getMemoryOutput(Runtime.getRuntime().totalMemory()); |
||||||
|
String mhSize = getMemoryOutput(Runtime.getRuntime().maxMemory()); |
||||||
|
String fhSize = getMemoryOutput(Runtime.getRuntime().freeMemory()); |
||||||
|
|
||||||
|
String out = "Heap Size: " + hSize + ", Max Heap Size: " + mhSize + ", Free Heap Size: " + fhSize; |
||||||
|
throwbackInfo(pcSender, out); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getUsageString() { |
||||||
|
return "' /getmemory'"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getHelpString() { |
||||||
|
return "lists memory usage"; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,67 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2022
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
|
||||||
|
package engine.devcmd.cmds; |
||||||
|
|
||||||
|
import engine.devcmd.AbstractDevCmd; |
||||||
|
import engine.gameManager.ZoneManager; |
||||||
|
import engine.objects.AbstractGameObject; |
||||||
|
import engine.objects.PlayerCharacter; |
||||||
|
import engine.objects.Zone; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
|
||||||
|
public class GetZoneCmd extends AbstractDevCmd { |
||||||
|
|
||||||
|
public GetZoneCmd() { |
||||||
|
super("getzone"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void _doCmd(PlayerCharacter pcSender, String[] words, |
||||||
|
AbstractGameObject target) { |
||||||
|
if (pcSender == null) |
||||||
|
return; |
||||||
|
|
||||||
|
if (words.length != 1) { |
||||||
|
this.sendUsage(pcSender); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
ArrayList<Zone> allIn = new ArrayList<>(); |
||||||
|
switch (words[0].toLowerCase()) { |
||||||
|
case "all": |
||||||
|
throwbackInfo(pcSender, "All zones currently in"); |
||||||
|
allIn = ZoneManager.getAllZonesIn(pcSender.getLoc()); |
||||||
|
break; |
||||||
|
case "smallest": |
||||||
|
throwbackInfo(pcSender, "Smallest zone currently in"); |
||||||
|
Zone zone = ZoneManager.findSmallestZone(pcSender.getLoc()); |
||||||
|
allIn.add(zone); |
||||||
|
break; |
||||||
|
default: |
||||||
|
this.sendUsage(pcSender); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
for (Zone zone : allIn) |
||||||
|
throwbackInfo(pcSender, zone.getName() + "; UUID: " + zone.getObjectUUID() + ", loadNum: " + zone.getLoadNum()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getUsageString() { |
||||||
|
return "' /getzone smallest/all'"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getHelpString() { |
||||||
|
return "lists what zones a player is in"; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,107 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2022
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
|
||||||
|
package engine.devcmd.cmds; |
||||||
|
|
||||||
|
import engine.Enum.GameObjectType; |
||||||
|
import engine.devcmd.AbstractDevCmd; |
||||||
|
import engine.math.Vector3fImmutable; |
||||||
|
import engine.objects.AbstractGameObject; |
||||||
|
import engine.objects.Building; |
||||||
|
import engine.objects.PlayerCharacter; |
||||||
|
|
||||||
|
public class GotoBoundsCmd extends AbstractDevCmd { |
||||||
|
|
||||||
|
public GotoBoundsCmd() { |
||||||
|
super("gotobounds"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void _doCmd(PlayerCharacter player, String[] words, |
||||||
|
AbstractGameObject target) { |
||||||
|
|
||||||
|
String corner = words[0]; |
||||||
|
Vector3fImmutable targetLoc = Vector3fImmutable.ZERO; |
||||||
|
|
||||||
|
if (target == null || !target.getObjectType().equals(GameObjectType.Building)) { |
||||||
|
this.throwbackError(player, "No Building Selected"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
Building building = (Building) target; |
||||||
|
|
||||||
|
if (building.getBounds() == null) { |
||||||
|
this.throwbackInfo(player, "No valid Bounds for building UUID " + building.getObjectUUID()); |
||||||
|
return; |
||||||
|
} |
||||||
|
float x = building.getBounds().getHalfExtents().x; |
||||||
|
float z = building.getBounds().getHalfExtents().y; |
||||||
|
|
||||||
|
if (building.getBlueprint() != null) { |
||||||
|
x = building.getBlueprint().getExtents().x; |
||||||
|
z = building.getBlueprint().getExtents().y; |
||||||
|
} |
||||||
|
|
||||||
|
float topLeftX = building.getLoc().x - x; |
||||||
|
float topLeftY = building.getLoc().z - z; |
||||||
|
|
||||||
|
float topRightX = building.getLoc().x + x; |
||||||
|
float topRightY = building.getLoc().z - z; |
||||||
|
|
||||||
|
float bottomLeftX = building.getLoc().x - x; |
||||||
|
float bottomLeftY = building.getLoc().z + z; |
||||||
|
|
||||||
|
float bottomRightX = building.getLoc().x + x; |
||||||
|
float bottomRightY = building.getLoc().z + z; |
||||||
|
|
||||||
|
|
||||||
|
switch (corner) { |
||||||
|
case "topleft": |
||||||
|
targetLoc = new Vector3fImmutable(topLeftX, 0, topLeftY); |
||||||
|
break; |
||||||
|
case "topright": |
||||||
|
targetLoc = new Vector3fImmutable(topRightX, 0, topRightY); |
||||||
|
break; |
||||||
|
case "bottomleft": |
||||||
|
targetLoc = new Vector3fImmutable(bottomLeftX, 0, bottomLeftY); |
||||||
|
break; |
||||||
|
case "bottomright": |
||||||
|
targetLoc = new Vector3fImmutable(bottomRightX, 0, bottomRightY); |
||||||
|
break; |
||||||
|
default: |
||||||
|
this.throwbackInfo(player, "wrong corner name. use topleft , topright , bottomleft , bottomright"); |
||||||
|
return; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
targetLoc = Vector3fImmutable.transform(building.getLoc(), targetLoc, building.getBounds().getRotationDegrees()); |
||||||
|
|
||||||
|
// Teleport player
|
||||||
|
|
||||||
|
if (targetLoc == Vector3fImmutable.ZERO) { |
||||||
|
this.throwbackError(player, "Failed to locate UUID"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
player.teleport(targetLoc); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getHelpString() { |
||||||
|
return "Teleports player to a UUID"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getUsageString() { |
||||||
|
return "' /gotoobj <UID>'"; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,212 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2022
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
|
||||||
|
package engine.devcmd.cmds; |
||||||
|
|
||||||
|
import engine.Enum.ProtectionState; |
||||||
|
import engine.InterestManagement.WorldGrid; |
||||||
|
import engine.devcmd.AbstractDevCmd; |
||||||
|
import engine.gameManager.BuildingManager; |
||||||
|
import engine.gameManager.ChatManager; |
||||||
|
import engine.gameManager.DbManager; |
||||||
|
import engine.gameManager.ZoneManager; |
||||||
|
import engine.math.Vector3f; |
||||||
|
import engine.math.Vector3fImmutable; |
||||||
|
import engine.objects.*; |
||||||
|
import org.pmw.tinylog.Logger; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Eighty |
||||||
|
*/ |
||||||
|
public class MakeBaneCmd extends AbstractDevCmd { |
||||||
|
|
||||||
|
public MakeBaneCmd() { |
||||||
|
super("makebane"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void _doCmd(PlayerCharacter pc, String[] words, |
||||||
|
AbstractGameObject target) { |
||||||
|
if (words.length < 1 || words.length > 2) { |
||||||
|
this.sendUsage(pc); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
int attackerID = 0; |
||||||
|
int rank = 8; |
||||||
|
|
||||||
|
if (words.length == 2) { |
||||||
|
try { |
||||||
|
attackerID = Integer.parseInt(words[0]); |
||||||
|
rank = Integer.parseInt(words[1]); |
||||||
|
} catch (NumberFormatException e) { |
||||||
|
throwbackError(pc, "AttackerGuildID must be a number, " + words[0] + " is invalid"); |
||||||
|
return; |
||||||
|
} |
||||||
|
} else if (words.length == 1) { |
||||||
|
if (target == null) { |
||||||
|
throwbackError(pc, "No target specified"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (!(target instanceof PlayerCharacter)) { |
||||||
|
throwbackError(pc, "Target is not a player"); |
||||||
|
return; |
||||||
|
} |
||||||
|
attackerID = target.getObjectUUID(); |
||||||
|
|
||||||
|
try { |
||||||
|
rank = Integer.parseInt(words[0]); |
||||||
|
} catch (NumberFormatException e) { |
||||||
|
throwbackError(pc, "Rank must be specified, 1 through 8"); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (rank < 1 || rank > 8) { |
||||||
|
throwbackError(pc, "Rank must be 1 through 8"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
PlayerCharacter player = PlayerCharacter.getPlayerCharacter(attackerID); |
||||||
|
|
||||||
|
|
||||||
|
if (player.getGuild().isEmptyGuild()) { |
||||||
|
throwbackError(pc, "Errant's can not place banes"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
AbstractCharacter attackerAGL = Guild.GetGL(player.getGuild()); |
||||||
|
|
||||||
|
if (attackerAGL == null) { |
||||||
|
throwbackError(pc, "No guild leader found for attacking guild."); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (!(attackerAGL instanceof PlayerCharacter)) { |
||||||
|
throwbackError(pc, "Attacking guild leader is an NPC."); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (player.getGuild().isNPCGuild()) { |
||||||
|
throwbackError(pc, "The guild used is an npc guild. They can not bane."); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// if (player.getGuild().getOwnedCity() != null) {
|
||||||
|
// throwbackError(pc, "The attacking guild already has a city.");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
Zone zone = ZoneManager.findSmallestZone(pc.getLoc()); |
||||||
|
|
||||||
|
if (zone == null) { |
||||||
|
throwbackError(pc, "Unable to find the zone you're in."); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (!zone.isPlayerCity()) { |
||||||
|
throwbackError(pc, "This is not a player city."); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
City city = City.getCity(zone.getPlayerCityUUID()); |
||||||
|
if (city == null) { |
||||||
|
throwbackError(pc, "Unable to find the city associated with this zone."); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (city.getTOL() == null) { |
||||||
|
throwbackError(pc, "Unable to find the tree of life for this city."); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (city.getBane() != null) { |
||||||
|
throwbackError(pc, "This city is already baned."); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (Bane.getBaneByAttackerGuild(player.getGuild()) != null) { |
||||||
|
throwbackError(pc, "This guild is already baning someone."); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
Blueprint blueprint = Blueprint.getBlueprint(24300); |
||||||
|
|
||||||
|
if (blueprint == null) { |
||||||
|
throwbackError(pc, "Unable to find building set for banestone."); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
Vector3f rot = new Vector3f(0, 0, 0); |
||||||
|
|
||||||
|
// *** Refactor : Overlap test goes here
|
||||||
|
|
||||||
|
//Let's drop a banestone!
|
||||||
|
Vector3fImmutable localLocation = ZoneManager.worldToLocal(pc.getLoc(), zone); |
||||||
|
|
||||||
|
if (localLocation == null) { |
||||||
|
ChatManager.chatSystemError(pc, "Failed to convert world location to zone location. Contact a CCR."); |
||||||
|
Logger.info("Failed to Convert World coordinates to local zone coordinates"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
Building stone = DbManager.BuildingQueries.CREATE_BUILDING( |
||||||
|
zone.getObjectUUID(), pc.getObjectUUID(), blueprint.getName(), blueprint.getBlueprintUUID(), |
||||||
|
localLocation, 1.0f, blueprint.getMaxHealth(rank), ProtectionState.PROTECTED, 0, rank, |
||||||
|
null, blueprint.getBlueprintUUID(), 1, 0.0f); |
||||||
|
|
||||||
|
if (stone == null) { |
||||||
|
ChatManager.chatSystemError(pc, "Failed to create banestone."); |
||||||
|
return; |
||||||
|
} |
||||||
|
stone.addEffectBit((1 << 19)); |
||||||
|
stone.setRank((byte) rank); |
||||||
|
stone.setMaxHitPoints(blueprint.getMaxHealth(stone.getRank())); |
||||||
|
stone.setCurrentHitPoints(stone.getMaxHitPoints()); |
||||||
|
BuildingManager.setUpgradeDateTime(stone, null, 0); |
||||||
|
|
||||||
|
//Make the bane
|
||||||
|
|
||||||
|
Bane bane = Bane.makeBane(player, city, stone); |
||||||
|
|
||||||
|
if (bane == null) { |
||||||
|
|
||||||
|
//delete bane stone, failed to make bane object
|
||||||
|
DbManager.BuildingQueries.DELETE_FROM_DATABASE(stone); |
||||||
|
|
||||||
|
throwbackError(pc, "Failed to create bane."); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
WorldGrid.addObject(stone, pc); |
||||||
|
|
||||||
|
//Add baned effect to TOL
|
||||||
|
city.getTOL().addEffectBit((1 << 16)); |
||||||
|
city.getTOL().updateEffects(); |
||||||
|
|
||||||
|
Vector3fImmutable movePlayerOutsideStone = player.getLoc(); |
||||||
|
movePlayerOutsideStone = movePlayerOutsideStone.setX(movePlayerOutsideStone.x + 10); |
||||||
|
movePlayerOutsideStone = movePlayerOutsideStone.setZ(movePlayerOutsideStone.z + 10); |
||||||
|
player.teleport(movePlayerOutsideStone); |
||||||
|
|
||||||
|
throwbackInfo(pc, "The city has been succesfully baned."); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getHelpString() { |
||||||
|
return "Creates an bane."; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String _getUsageString() { |
||||||
|
return "'./makebane playerUUID baneRank'"; |
||||||
|
} |
||||||
|
|
||||||
|
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue