forked from MagicBane/Server
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
631 lines
13 KiB
631 lines
13 KiB
3 years ago
|
package engine.objects;
|
||
|
|
||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||
|
// Magicbane Emulator Project © 2013 - 2022
|
||
|
// www.magicbane.com
|
||
|
|
||
|
|
||
|
|
||
|
import engine.Enum.BuildingGroup;
|
||
|
import engine.gameManager.DbManager;
|
||
|
import engine.math.Vector2f;
|
||
|
import org.pmw.tinylog.Logger;
|
||
|
|
||
|
import java.sql.ResultSet;
|
||
|
import java.sql.SQLException;
|
||
|
import java.util.HashMap;
|
||
|
|
||
|
/* @Summary - Blueprint class is used for determining
|
||
|
characteristics of instanced player owned
|
||
|
structures such as available slots, upgrade
|
||
|
cost/time and the target window symbol icon.
|
||
|
*/
|
||
|
public class Blueprint {
|
||
|
|
||
|
public final static Vector2f IrikieForgeExtents = new Vector2f(32, 32);
|
||
|
public final static Vector2f IrikieBarracksExtents = new Vector2f(32, 32);
|
||
|
|
||
|
private static HashMap<Integer, Blueprint> _blueprints = new HashMap<>();
|
||
|
private static HashMap<Integer, Integer> _doorNumbers = new HashMap<>();
|
||
|
public static HashMap<Integer, Blueprint> _meshLookup = new HashMap<>();
|
||
|
|
||
|
private final int blueprintUUID;
|
||
|
private final String name;
|
||
|
private final BuildingGroup buildingGroup;
|
||
|
private final int icon;
|
||
|
private final int maxRank;
|
||
|
private final int maxSlots;
|
||
|
private final int rank1UUID;
|
||
|
private final int rank3UUID;
|
||
|
private final int rank7UUID;
|
||
|
private final int destroyedUUID;
|
||
|
|
||
|
private Blueprint() {
|
||
|
this.blueprintUUID = 0;
|
||
|
this.name = "";
|
||
|
this.icon = 0;
|
||
|
this.buildingGroup = BuildingGroup.BANESTONE;
|
||
|
this.maxRank = 0;
|
||
|
this.maxSlots = 0;
|
||
|
this.rank1UUID = 0;
|
||
|
this.rank3UUID = 0;
|
||
|
this.rank7UUID = 0;
|
||
|
this.destroyedUUID = 0;
|
||
|
}
|
||
|
|
||
|
public Blueprint(ResultSet rs) throws SQLException {
|
||
|
|
||
|
this.blueprintUUID = rs.getInt("Rank0UUID");
|
||
|
this.name = rs.getString("MeshName");
|
||
|
this.icon = rs.getInt("Icon");
|
||
|
this.buildingGroup = BuildingGroup.valueOf(rs.getString("BuildingGroup"));
|
||
|
this.maxRank = rs.getInt("MaxRank");
|
||
|
this.maxSlots = rs.getInt("MaxSlots");
|
||
|
this.rank1UUID = rs.getInt("Rank1UUID");
|
||
|
this.rank3UUID = rs.getInt("Rank3UUID");
|
||
|
this.rank7UUID = rs.getInt("Rank7UUID");
|
||
|
this.destroyedUUID = rs.getInt("DestroyedUUID");
|
||
|
|
||
|
}
|
||
|
|
||
|
// Accessors
|
||
|
|
||
|
public static Blueprint getBlueprint(int blueprintUUID) {
|
||
|
|
||
|
return _blueprints.get(blueprintUUID);
|
||
|
|
||
|
}
|
||
|
|
||
|
public static BuildingGroup getBuildingGroup(int blueprintUUID) {
|
||
|
|
||
|
Blueprint blueprint;
|
||
|
|
||
|
blueprint = _blueprints.get(blueprintUUID);
|
||
|
|
||
|
return blueprint.buildingGroup;
|
||
|
}
|
||
|
|
||
|
public static int getMaxShrines(int treeRank) {
|
||
|
|
||
|
// Returns the number of allowed spires/shrines
|
||
|
// for a given rank.
|
||
|
|
||
|
int maxShrines;
|
||
|
|
||
|
switch (treeRank) {
|
||
|
case 0:
|
||
|
case 1:
|
||
|
case 2:
|
||
|
maxShrines = 0;
|
||
|
break;
|
||
|
case 3:
|
||
|
case 4:
|
||
|
maxShrines = 1;
|
||
|
break;
|
||
|
case 5:
|
||
|
case 6:
|
||
|
maxShrines = 2;
|
||
|
break;
|
||
|
case 7:
|
||
|
case 8:
|
||
|
maxShrines = 3;
|
||
|
break;
|
||
|
default:
|
||
|
maxShrines = 0;
|
||
|
|
||
|
}
|
||
|
|
||
|
return maxShrines;
|
||
|
}
|
||
|
|
||
|
public static void loadAllBlueprints() {
|
||
|
|
||
|
_blueprints = DbManager.BlueprintQueries.LOAD_ALL_BLUEPRINTS();
|
||
|
|
||
|
}
|
||
|
|
||
|
// Method returns a blueprint based on a blueprintUUID
|
||
|
|
||
|
public static void loadAllDoorNumbers() {
|
||
|
|
||
|
_doorNumbers = DbManager.BlueprintQueries.LOAD_ALL_DOOR_NUMBERS();
|
||
|
|
||
|
}
|
||
|
|
||
|
public static int getDoorNumberbyMesh(int doorMeshUUID) {
|
||
|
|
||
|
if (_doorNumbers.containsKey(doorMeshUUID))
|
||
|
return _doorNumbers.get(doorMeshUUID);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
public static boolean isMeshWallPiece(int meshUUID) {
|
||
|
|
||
|
Blueprint buildingBlueprint = Blueprint.getBlueprint(meshUUID);
|
||
|
|
||
|
if (buildingBlueprint == null)
|
||
|
return false;
|
||
|
|
||
|
switch (buildingBlueprint.buildingGroup) {
|
||
|
case WALLSTRAIGHT:
|
||
|
case ARTYTOWER:
|
||
|
case WALLCORNER:
|
||
|
case SMALLGATE:
|
||
|
case WALLSTAIRS:
|
||
|
return true;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
return false;
|
||
|
|
||
|
}
|
||
|
|
||
|
// Method calculates available vendor slots
|
||
|
// based upon the building's current rank
|
||
|
|
||
|
public static int getNpcMaintCost(int rank) {
|
||
|
int maintCost = Integer.MAX_VALUE;
|
||
|
|
||
|
maintCost = (9730 * rank) + 1890;
|
||
|
|
||
|
return maintCost;
|
||
|
}
|
||
|
|
||
|
public int getMaxRank() {
|
||
|
return maxRank;
|
||
|
}
|
||
|
|
||
|
public int getMaxSlots() {
|
||
|
if (this.buildingGroup != null && this.buildingGroup.equals(BuildingGroup.BARRACK))
|
||
|
return 1;
|
||
|
return maxSlots;
|
||
|
}
|
||
|
|
||
|
// Method returns a mesh UUID for this blueprint
|
||
|
// based upon a given rank.
|
||
|
|
||
|
public BuildingGroup getBuildingGroup() {
|
||
|
return this.buildingGroup;
|
||
|
}
|
||
|
|
||
|
// Method returns a cost to upgrade a building to a given rank
|
||
|
// based upon this blueprint's maintenance group
|
||
|
|
||
|
public int getMaxHealth(int currentRank) {
|
||
|
|
||
|
int maxHealth;
|
||
|
|
||
|
// Return 0 health for a destroyed building
|
||
|
// or 1 for a destroyed mine (cleint looting restriction)
|
||
|
|
||
|
if (currentRank == -1) {
|
||
|
|
||
|
return this.buildingGroup == BuildingGroup.MINE ? 1 : 0;
|
||
|
}
|
||
|
|
||
|
// Return 15k for a constructing mesh
|
||
|
|
||
|
if (currentRank == 0)
|
||
|
return 15000;
|
||
|
|
||
|
switch (this.buildingGroup) {
|
||
|
|
||
|
case TOL:
|
||
|
maxHealth = (70000 * currentRank) + 10000;
|
||
|
break;
|
||
|
case BARRACK:
|
||
|
maxHealth = (35000 * currentRank) + 5000;
|
||
|
break;
|
||
|
case BANESTONE:
|
||
|
maxHealth = (170000 * currentRank) - 120000;
|
||
|
break;
|
||
|
case CHURCH:
|
||
|
maxHealth = (28000 * currentRank) + 4000;
|
||
|
break;
|
||
|
case MAGICSHOP:
|
||
|
case FORGE:
|
||
|
case INN:
|
||
|
case TAILOR:
|
||
|
maxHealth = (17500 * currentRank) + 2500;
|
||
|
break;
|
||
|
case VILLA:
|
||
|
case ESTATE:
|
||
|
case FORTRESS:
|
||
|
maxHealth = 300000;
|
||
|
break;
|
||
|
case CITADEL:
|
||
|
maxHealth = 500000;
|
||
|
break;
|
||
|
case SPIRE:
|
||
|
maxHealth = (37000 * currentRank) - 9000;
|
||
|
break;
|
||
|
case GENERICNOUPGRADE:
|
||
|
case SHACK:
|
||
|
case SIEGETENT:
|
||
|
maxHealth = 40000;
|
||
|
break;
|
||
|
case BULWARK:
|
||
|
if (currentRank == 1)
|
||
|
maxHealth = 110000;
|
||
|
else
|
||
|
maxHealth = 40000;
|
||
|
break;
|
||
|
case WALLSTRAIGHT:
|
||
|
case WALLSTRAIGHTTOWER:
|
||
|
case WALLSTAIRS:
|
||
|
maxHealth = 1000000;
|
||
|
break;
|
||
|
case WALLCORNER:
|
||
|
case ARTYTOWER:
|
||
|
maxHealth = 900000;
|
||
|
break;
|
||
|
case SMALLGATE:
|
||
|
maxHealth = 1100000;
|
||
|
break;
|
||
|
case AMAZONHALL:
|
||
|
case CATHEDRAL:
|
||
|
case GREATHALL:
|
||
|
case KEEP:
|
||
|
case THIEFHALL:
|
||
|
case TEMPLEHALL:
|
||
|
case WIZARDHALL:
|
||
|
case ELVENHALL:
|
||
|
case ELVENSANCTUM:
|
||
|
case IREKEIHALL:
|
||
|
case FORESTHALL:
|
||
|
maxHealth = (28000 * currentRank) + 4000;
|
||
|
break;
|
||
|
case MINE:
|
||
|
maxHealth = 125000;
|
||
|
break;
|
||
|
case RUNEGATE:
|
||
|
maxHealth = 100000;
|
||
|
break;
|
||
|
case SHRINE:
|
||
|
maxHealth = 100000;
|
||
|
break;
|
||
|
case WAREHOUSE:
|
||
|
maxHealth = 40000;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
maxHealth = 40000;
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
return maxHealth;
|
||
|
}
|
||
|
|
||
|
// Returns number of vendor slots available
|
||
|
// for the building's current rank.
|
||
|
|
||
|
public int getSlotsForRank(int currentRank) {
|
||
|
|
||
|
int availableSlots;
|
||
|
|
||
|
// Early exit for buildings not yet constructed
|
||
|
|
||
|
if (currentRank == 0)
|
||
|
return 0;
|
||
|
|
||
|
// Early exit for buildings with single or no slots
|
||
|
|
||
|
if (this.maxSlots <= 1)
|
||
|
return maxSlots;
|
||
|
|
||
|
if (this.maxRank == 1 && currentRank == 1)
|
||
|
return getMaxSlots();
|
||
|
|
||
|
switch (currentRank) {
|
||
|
|
||
|
case 1:
|
||
|
case 2:
|
||
|
availableSlots = 1;
|
||
|
break;
|
||
|
case 3:
|
||
|
case 4:
|
||
|
case 5:
|
||
|
case 6:
|
||
|
availableSlots = 2;
|
||
|
break;
|
||
|
case 7:
|
||
|
availableSlots = 3;
|
||
|
break;
|
||
|
case 8:
|
||
|
availableSlots = 1;
|
||
|
break;
|
||
|
default:
|
||
|
availableSlots = 0;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return availableSlots;
|
||
|
}
|
||
|
|
||
|
// Returns the half extents of this blueprint's
|
||
|
// bounding box, based upon it's buildinggroup
|
||
|
|
||
|
public int getIcon() {
|
||
|
return this.icon;
|
||
|
}
|
||
|
|
||
|
public String getName() {
|
||
|
return this.name;
|
||
|
}
|
||
|
|
||
|
public int getMeshForRank(int targetRank) {
|
||
|
|
||
|
int targetMesh = this.blueprintUUID;
|
||
|
|
||
|
// The Blueprint UUID is the 'constructing' mesh so
|
||
|
// we return that value if the rank passed is 0.
|
||
|
|
||
|
if ((maxRank == 1) && (this.rank1UUID == 0)) {
|
||
|
return blueprintUUID;
|
||
|
}
|
||
|
|
||
|
// Set the return value to the proper mesh UID for rank
|
||
|
|
||
|
switch (targetRank) {
|
||
|
|
||
|
case -1:
|
||
|
targetMesh = this.destroyedUUID; // -1 Rank is a destroyed mesh
|
||
|
break;
|
||
|
case 0:
|
||
|
targetMesh = this.blueprintUUID; // Rank 0 is the 'constructing' mesh
|
||
|
break;
|
||
|
case 1:
|
||
|
case 2:
|
||
|
targetMesh = this.rank1UUID;
|
||
|
break;
|
||
|
case 3:
|
||
|
case 4:
|
||
|
case 5:
|
||
|
case 6:
|
||
|
targetMesh = this.rank3UUID;
|
||
|
break;
|
||
|
case 7:
|
||
|
case 8:
|
||
|
targetMesh = this.rank7UUID;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return targetMesh;
|
||
|
}
|
||
|
|
||
|
public int getRankCost(int targetRank) {
|
||
|
|
||
|
// Set a MAXINT rankcost in case something goes wrong
|
||
|
|
||
|
int rankCost = Integer.MAX_VALUE;
|
||
|
|
||
|
// Sanity chack for retrieving a rankcost outside proper range
|
||
|
|
||
|
if ((targetRank > maxRank) || (targetRank < 0)) {
|
||
|
Logger.error( "Attempt to retrieve rankcost for rank of" + targetRank);
|
||
|
return rankCost;
|
||
|
}
|
||
|
|
||
|
// Select linear equation for rank cost based upon the
|
||
|
// buildings current Maintenance BuildingGroup.
|
||
|
|
||
|
switch (this.buildingGroup) {
|
||
|
|
||
|
case GENERICNOUPGRADE:
|
||
|
case WALLSTRAIGHT:
|
||
|
case WALLSTAIRS:
|
||
|
case WALLCORNER:
|
||
|
case SMALLGATE:
|
||
|
case ARTYTOWER:
|
||
|
case SIEGETENT:
|
||
|
case BULWARK:
|
||
|
case BANESTONE:
|
||
|
case SHACK:
|
||
|
break; // This set cannot be upgraded. Returns max integer.
|
||
|
|
||
|
case TOL:
|
||
|
rankCost = (880000 * targetRank) - 440000;
|
||
|
break;
|
||
|
case BARRACK:
|
||
|
case VILLA:
|
||
|
case ESTATE:
|
||
|
case FORTRESS:
|
||
|
case CITADEL:
|
||
|
rankCost = (451000 * targetRank) - 308000;
|
||
|
break;
|
||
|
case CHURCH:
|
||
|
rankCost = (682000 * targetRank) - 110000;
|
||
|
break;
|
||
|
case FORGE:
|
||
|
case INN:
|
||
|
case TAILOR:
|
||
|
case MAGICSHOP:
|
||
|
rankCost = (440000 * targetRank) - 550000;
|
||
|
break;
|
||
|
case SPIRE:
|
||
|
rankCost = (176000 * targetRank) - 88000;
|
||
|
break;
|
||
|
case AMAZONHALL:
|
||
|
case CATHEDRAL:
|
||
|
case GREATHALL:
|
||
|
case KEEP:
|
||
|
case THIEFHALL:
|
||
|
case TEMPLEHALL:
|
||
|
case WIZARDHALL:
|
||
|
case ELVENHALL:
|
||
|
case ELVENSANCTUM:
|
||
|
case IREKEIHALL:
|
||
|
case FORESTHALL:
|
||
|
rankCost = (682000 * targetRank) - 110000;
|
||
|
break;
|
||
|
default:
|
||
|
Logger.error("Attempt to retrieve rankcost without MaintGroup for " + this.buildingGroup.name());
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return rankCost;
|
||
|
}
|
||
|
|
||
|
public int getRankTime(int targetRank) {
|
||
|
|
||
|
// Set a very long rankTime in case something goes wrong
|
||
|
|
||
|
int rankTime = (Integer.MAX_VALUE / 2);
|
||
|
|
||
|
// Set all initial construction to a default of 4 hours.
|
||
|
|
||
|
if (targetRank == 1)
|
||
|
return 4;
|
||
|
|
||
|
// Sanity chack for retrieving a ranktime outside proper range
|
||
|
|
||
|
if ((targetRank > maxRank) || (targetRank < 1)) {
|
||
|
Logger.error( "Attempt to retrieve ranktime for rank of" + targetRank);
|
||
|
return rankTime;
|
||
|
}
|
||
|
|
||
|
// Select equation for rank time based upon the
|
||
|
// buildings current Maintenance BuildingGroup. These values
|
||
|
// are expressed in hours
|
||
|
|
||
|
switch (this.buildingGroup) {
|
||
|
|
||
|
case GENERICNOUPGRADE:
|
||
|
break; // Cannot be upgraded
|
||
|
case VILLA:
|
||
|
case ESTATE:
|
||
|
case FORTRESS:
|
||
|
case CITADEL:
|
||
|
rankTime = (7 * targetRank) - 7;
|
||
|
break;
|
||
|
case TOL:
|
||
|
rankTime = (7 * targetRank) - 7;
|
||
|
break;
|
||
|
case BARRACK:
|
||
|
rankTime = (7 * targetRank) - 7;
|
||
|
break;
|
||
|
case CHURCH:
|
||
|
rankTime = (7 * targetRank) - 7;
|
||
|
break;
|
||
|
case FORGE:
|
||
|
case INN:
|
||
|
case TAILOR:
|
||
|
case MAGICSHOP:
|
||
|
rankTime = (7 * targetRank) - 7;
|
||
|
break;
|
||
|
case SPIRE:
|
||
|
rankTime = (4 * targetRank) + 4;
|
||
|
break;
|
||
|
case AMAZONHALL:
|
||
|
case CATHEDRAL:
|
||
|
case GREATHALL:
|
||
|
case KEEP:
|
||
|
case THIEFHALL:
|
||
|
case TEMPLEHALL:
|
||
|
case WIZARDHALL:
|
||
|
case ELVENHALL:
|
||
|
case ELVENSANCTUM:
|
||
|
case IREKEIHALL:
|
||
|
case FORESTHALL:
|
||
|
rankTime = (7 * targetRank) - 7;
|
||
|
break;
|
||
|
default:
|
||
|
Logger.error("Attempt to retrieve ranktime without MaintGroup");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return rankTime;
|
||
|
}
|
||
|
|
||
|
public Vector2f getExtents() {
|
||
|
|
||
|
if (blueprintUUID == 1302600)
|
||
|
return Blueprint.IrikieForgeExtents;
|
||
|
else if (blueprintUUID == 1300600)
|
||
|
return Blueprint.IrikieBarracksExtents;
|
||
|
|
||
|
return this.buildingGroup.getExtents();
|
||
|
|
||
|
}
|
||
|
|
||
|
public boolean isWallPiece() {
|
||
|
|
||
|
switch (this.buildingGroup) {
|
||
|
case WALLSTRAIGHT:
|
||
|
case WALLSTAIRS:
|
||
|
case ARTYTOWER:
|
||
|
case WALLCORNER:
|
||
|
case SMALLGATE:
|
||
|
return true;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public boolean isSiegeEquip() {
|
||
|
|
||
|
switch (this.buildingGroup) {
|
||
|
case BULWARK:
|
||
|
case SIEGETENT:
|
||
|
return true;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
return false;
|
||
|
|
||
|
}
|
||
|
|
||
|
public int getBlueprintUUID() {
|
||
|
return blueprintUUID;
|
||
|
}
|
||
|
|
||
|
|
||
|
@Override
|
||
|
public boolean equals(Object object) {
|
||
|
|
||
|
if ((object instanceof Blueprint) == false)
|
||
|
return false;
|
||
|
|
||
|
Blueprint blueprint = (Blueprint) object;
|
||
|
|
||
|
return this.blueprintUUID == blueprint.blueprintUUID;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int hashCode() {
|
||
|
|
||
|
return this.blueprintUUID ;
|
||
|
}
|
||
|
|
||
|
public int getMaintCost(int rank) {
|
||
|
|
||
|
int maintCost = Integer.MAX_VALUE;
|
||
|
|
||
|
switch (this.buildingGroup) {
|
||
|
case TOL:
|
||
|
case BARRACK:
|
||
|
maintCost = (61500 * rank) + 19500;
|
||
|
break;
|
||
|
case SPIRE:
|
||
|
maintCost = (4800 * rank) + 1200;
|
||
|
break;
|
||
|
default:
|
||
|
if (maxRank == 1)
|
||
|
maintCost = 22500;
|
||
|
else
|
||
|
maintCost = (15900 * rank) + 3300;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return maintCost;
|
||
|
}
|
||
|
}
|