Files
prestonbane/src/engine/gameManager/BuildingManager.java
T

868 lines
28 KiB
Java
Raw Normal View History

2022-04-30 09:41:17 -04:00
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.gameManager;
2023-08-20 19:07:26 -04:00
import engine.InterestManagement.InterestManager;
2022-04-30 09:41:17 -04:00
import engine.InterestManagement.WorldGrid;
import engine.job.JobContainer;
import engine.job.JobScheduler;
import engine.jobs.UpgradeBuildingJob;
2024-05-11 07:51:56 -04:00
import engine.loot.WorkOrder;
2022-04-30 09:41:17 -04:00
import engine.math.Bounds;
import engine.math.Vector3fImmutable;
import engine.mbEnums;
import engine.mbEnums.BuildingGroup;
import engine.mbEnums.GameObjectType;
2022-04-30 09:41:17 -04:00
import engine.net.client.msg.ErrorPopupMsg;
import engine.objects.*;
2023-08-20 17:23:50 -04:00
import engine.server.MBServerStatics;
2022-04-30 09:41:17 -04:00
import org.pmw.tinylog.Logger;
import java.time.LocalDateTime;
import java.time.ZoneId;
2023-04-24 15:37:30 -04:00
import java.util.ArrayList;
2024-03-15 10:01:22 -04:00
import java.util.EnumSet;
2023-04-24 15:37:30 -04:00
import java.util.HashMap;
2023-10-18 12:24:32 -04:00
import java.util.concurrent.ConcurrentHashMap;
2022-04-30 09:41:17 -04:00
import java.util.concurrent.ThreadLocalRandom;
public enum BuildingManager {
BUILDINGMANAGER;
2023-04-24 16:49:41 -04:00
public static HashMap<Integer, ArrayList<BuildingLocation>> _stuckLocations = new HashMap<>();
public static HashMap<Integer, ArrayList<BuildingLocation>> _slotLocations = new HashMap<>();
2023-04-24 15:37:30 -04:00
2023-10-18 12:24:32 -04:00
public static HashMap<Integer, ConcurrentHashMap<Integer, BuildingFriends>> _buildingFriends = new HashMap<>();
public static HashMap<Integer, ConcurrentHashMap<Integer, Condemned>> _buildingCondemned = new HashMap<>();
2023-10-19 16:20:43 -04:00
public static HashMap<Integer, ArrayList<Vector3fImmutable>> _buildingPatrolPoints = new HashMap<>();
2024-03-24 09:42:27 -04:00
2023-04-24 16:17:55 -04:00
public static int getAvailableSlot(Building building) {
2023-04-30 08:37:08 -04:00
ArrayList<BuildingLocation> slotLocations = _slotLocations.get(building.meshUUID);
// Some meshes might not have slot locations assigned.
2024-05-11 07:51:56 -04:00
if (slotLocations == null || slotLocations.isEmpty())
2023-04-30 08:37:08 -04:00
return -1;
2023-04-24 16:17:55 -04:00
int numOfSlots = _slotLocations.get(building.meshUUID).size();
2023-04-29 08:10:59 -04:00
for (int i = 1; i <= numOfSlots; i++) {
2023-05-02 14:44:22 -04:00
2023-04-24 16:17:55 -04:00
if (!building.getHirelings().containsValue(i))
2023-04-29 08:10:59 -04:00
return i;
2023-04-24 16:17:55 -04:00
}
return -1;
}
2023-08-12 06:16:12 -04:00
public static int getLastAvailableSlot(Building building) {
ArrayList<BuildingLocation> slotLocations = _slotLocations.get(building.meshUUID);
// Some meshes might not have slot locations assigned.
2024-05-11 07:51:56 -04:00
if (slotLocations == null || slotLocations.isEmpty())
2023-08-12 06:16:12 -04:00
return -1;
int numOfSlots = _slotLocations.get(building.meshUUID).size();
2024-05-11 08:02:19 -04:00
for (int i = numOfSlots; i > 0; i--)
2023-08-12 06:16:12 -04:00
if (!building.getHirelings().containsValue(i))
return i;
2024-05-11 08:02:19 -04:00
2023-08-12 06:16:12 -04:00
return -1;
}
public static BuildingLocation getSlotLocation(Building building, int slot) {
BuildingLocation buildingLocation = new BuildingLocation();
2023-04-29 08:17:05 -04:00
if (slot == -1)
return buildingLocation;
2023-04-29 08:17:05 -04:00
2023-04-29 09:07:48 -04:00
buildingLocation = _slotLocations.get(building.meshUUID).get(slot - 1); // array index
2023-04-29 08:17:05 -04:00
2024-05-11 08:02:19 -04:00
if (buildingLocation == null)
2023-04-29 08:17:05 -04:00
Logger.error("Invalid slot for building: " + building.getObjectUUID());
return buildingLocation;
}
2022-04-30 09:41:17 -04:00
public static boolean playerCanManage(PlayerCharacter player, Building building) {
if (player == null)
return false;
if (building == null)
return false;
//cannot access destroyed buildings
2022-04-30 09:41:17 -04:00
if (building.getRank() == -1)
return false;
//admin characters can always access buildings
2022-04-30 09:41:17 -04:00
if (player.isCSR())
return true;
//owner can always access their own building
2022-04-30 09:41:17 -04:00
if (IsOwner(building, player))
return true;
//check for default IC access if building belongs to same guild
if(player.guild.equals(building.getGuild())) {
if (building.getBlueprint() != null && building.getBlueprint().getBuildingGroup() != null) {
switch (building.getBlueprint().getBuildingGroup()) {
case TOL:
case BARRACK:
case SPIRE:
case SHRINE:
case BANESTONE:
case MINE:
case WAREHOUSE:
case BULWARK:
case SIEGETENT:
if (GuildStatusController.isInnerCouncil(player.getGuildStatus()))
return true;
if (GuildStatusController.isGuildLeader(player.getGuildStatus()))
return true;
break;
}
}
}
2022-04-30 09:41:17 -04:00
//check against friends list entries if any present
if (building.getFriends() != null) {
//check individuals
if (building.getFriends().get(player.getObjectUUID()) != null)
return true;
if (building.getFriends().get(player.guild.objectUUID) != null) {
//check friend type for guild related access
switch (building.getFriends().get(player.guild.objectUUID).friendType) {
case 8: //full member
if (GuildStatusController.isFullMember(player.getGuildStatus()))
return true;
break;
case 9: //Inner Council
if (GuildStatusController.isInnerCouncil(player.getGuildStatus()))
return true;
if (GuildStatusController.isGuildLeader(player.getGuildStatus()))
return true;
break;
}
}
}
//did not meet access grant criteria, deny access
2022-04-30 09:41:17 -04:00
return false;
}
public static synchronized boolean lootBuilding(PlayerCharacter player, Building building) {
if (building == null)
return false;
if (player == null)
return false;
if (building.getRank() != -1)
return false;
if (building.getBlueprintUUID() == 0)
return false;
switch (building.getBlueprint().getBuildingGroup()) {
case SHRINE:
Shrine shrine = Shrine.shrinesByBuildingUUID.get(building.getObjectUUID());
if (shrine == null)
return false;
int amount = shrine.getFavors();
//no more favors too loot!
if (amount == 0) {
try {
ErrorPopupMsg.sendErrorPopup(player, 166);
} catch (Exception e) {
}
return false;
}
2024-03-16 07:57:17 -04:00
ItemTemplate template = ItemTemplate.templates.get(1705032); // Elan Stone
2022-04-30 09:41:17 -04:00
2024-03-18 10:01:29 -04:00
if (!player.charItemManager.hasRoomInventory(template.item_wt))
2022-04-30 09:41:17 -04:00
return false;
2024-04-02 12:00:59 -04:00
if (!ItemManager.MakeItemForPlayer(template.template_id, player, amount))
2022-04-30 09:41:17 -04:00
return false;
shrine.setFavors(0);
break;
case WAREHOUSE:
2024-03-17 09:47:00 -04:00
City city = building.getCity();
if (city == null)
return true;
Warehouse warehouse = city.warehouse;
2022-04-30 09:41:17 -04:00
if (warehouse == null)
return false;
for (mbEnums.ResourceType resourceType : EnumSet.allOf(mbEnums.ResourceType.class)) {
2024-03-03 15:06:44 -05:00
2024-03-18 10:01:29 -04:00
if (!player.charItemManager.hasRoomInventory(resourceType.template.item_wt)) {
2022-04-30 09:41:17 -04:00
ChatManager.chatSystemInfo(player, "You can not carry any more of that item.");
return false;
}
2024-03-15 10:01:22 -04:00
if (warehouse.resources.get(resourceType) == null)
2022-04-30 09:41:17 -04:00
continue;
2024-03-15 10:01:22 -04:00
int resourceAmount = warehouse.resources.get(resourceType);
2022-04-30 09:41:17 -04:00
if (resourceAmount <= 0)
continue;
2024-03-15 10:01:22 -04:00
if (Warehouse.loot(warehouse, player, resourceType, resourceAmount, true)) {
ChatManager.chatInfoInfo(player, "You have looted " + resourceAmount + ' ' + resourceType.name());
2024-02-28 16:31:09 -05:00
}
2022-04-30 09:41:17 -04:00
}
break;
}
//Everything was looted, Maybe we should
return true;
}
//This method restarts an upgrade timer when a building is loaded from the database.
// Submit upgrade job for this building based upon it's current upgradeDateTime
public static void submitUpgradeJob(Building building) {
if (building == null)
return;
if (building.getUpgradeDateTime() == null) {
Logger.error("Attempt to submit upgrade job for non-ranking building");
return;
}
// Submit upgrade job for future date or current instant
if (building.getUpgradeDateTime().isAfter(LocalDateTime.now())) {
2024-05-11 07:51:56 -04:00
JobContainer jc = JobScheduler.getInstance().scheduleJob(new UpgradeBuildingJob(building), building.getUpgradeDateTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
2022-04-30 09:41:17 -04:00
} else
JobScheduler.getInstance().scheduleJob(new UpgradeBuildingJob(building), 0);
}
public static void setUpgradeDateTime(Building building, LocalDateTime upgradeDateTime, int rankCost) {
if (building == null)
return;
if (!DbManager.BuildingQueries.updateBuildingUpgradeTime(upgradeDateTime, building, rankCost)) {
Logger.error("Failed to set upgradeTime for building " + building.getObjectUUID());
return;
}
building.upgradeDateTime = upgradeDateTime;
}
// Method transfers ownership of all hirelings in a building
public static void refreshHirelings(Building building) {
if (building == null)
return;
Guild newGuild;
if (building.getOwner() == null)
newGuild = Guild.getErrantGuild();
else
newGuild = building.getOwner().getGuild();
for (AbstractCharacter hireling : building.getHirelings().keySet()) {
hireling.setGuild(newGuild);
WorldGrid.updateObject(hireling);
}
}
2023-09-09 08:28:03 -04:00
public static void removeHireling(Building building, AbstractCharacter hireling) {
if (hireling.getObjectType().equals(GameObjectType.Mob)) {
2023-09-09 08:34:09 -04:00
Mob guardCaptain = (Mob) hireling;
2023-09-09 08:28:03 -04:00
// Clear minions from database if a guard captain
if (guardCaptain.agentType.equals(mbEnums.AIAgentType.GUARDCAPTAIN))
2023-09-09 08:28:03 -04:00
DbManager.MobQueries.REMOVE_ALL_MINIONS(hireling.getObjectUUID());
}
// Clear minions from world
for (Integer minionUUID : hireling.minions) {
Mob minionMob = Mob.getMob(minionUUID);
DbManager.removeFromCache(minionMob);
WorldGrid.RemoveWorldObject(minionMob);
WorldGrid.unloadObject(minionMob);
2024-05-11 07:51:56 -04:00
if (minionMob.parentZone != null)
minionMob.parentZone.zoneMobSet.remove(minionMob);
2023-09-09 08:28:03 -04:00
}
2024-05-11 07:51:56 -04:00
// Clear all workorders for this hireling
2024-05-11 08:49:44 -04:00
if (hireling.getObjectType().equals(GameObjectType.NPC)) {
NPC hirelingNPC = (NPC) hireling;
if (ForgeManager.vendorWorkOrderLookup.get(hirelingNPC) != null)
2024-05-11 09:25:57 -04:00
2024-05-11 08:49:44 -04:00
for (WorkOrder workOrder : ForgeManager.vendorWorkOrderLookup.get(hirelingNPC)) {
2024-05-11 09:15:11 -04:00
workOrder.runCompleted.set(true);
2024-05-11 08:51:41 -04:00
workOrder.vendor = null;
2024-05-11 09:25:57 -04:00
// Remove any cooking items from collections
// to ensure we don't leak memory.
2024-05-11 09:37:23 -04:00
for (Item item : workOrder.cooking) {
DbManager.removeFromCache(item);
2024-05-11 09:25:57 -04:00
ForgeManager.itemWorkOrderLookup.remove(item);
2024-05-11 09:37:23 -04:00
}
2024-05-11 09:25:57 -04:00
2024-05-11 07:51:56 -04:00
DbManager.WarehouseQueries.DELETE_WORKORDER(workOrder);
2024-05-11 08:07:04 -04:00
}
2024-05-11 09:25:57 -04:00
// Finally remove the NPC from ForgeManager
ForgeManager.vendorWorkOrderLookup.remove(hirelingNPC);
2024-05-11 08:49:44 -04:00
}
2024-05-11 09:25:57 -04:00
2023-09-09 08:28:03 -04:00
// Remove hireling from building
building.getHirelings().remove(hireling);
2023-09-09 10:16:36 -04:00
// Remove from zone mob set
if (hireling.getObjectType().equals(GameObjectType.Mob)) {
Mob hirelingMob = (Mob) hireling;
2024-05-11 08:02:19 -04:00
if (hirelingMob.parentZone != null)
if (hirelingMob.parentZone.zoneMobSet.contains(hirelingMob))
2024-05-11 07:51:56 -04:00
hirelingMob.parentZone.zoneMobSet.remove(hireling);
2023-09-09 10:16:36 -04:00
}
if (hireling.getObjectType().equals(GameObjectType.NPC)) {
NPC hirelingNPC = (NPC) hireling;
if (hirelingNPC.getParentZone() != null)
2023-09-09 10:20:20 -04:00
if (hirelingNPC.getParentZone().zoneNPCSet.contains(hirelingNPC))
hirelingNPC.getParentZone().zoneNPCSet.remove(hireling);
2023-09-09 10:16:36 -04:00
}
2023-09-09 08:34:09 -04:00
// Unload hireling from world
DbManager.removeFromCache(hireling);
WorldGrid.RemoveWorldObject(hireling);
WorldGrid.removeObject(hireling);
2023-09-09 08:28:03 -04:00
// Delete hireling from database
if (hireling.getObjectType().equals(GameObjectType.Mob))
DbManager.MobQueries.DELETE_MOB((Mob) hireling);
else
DbManager.NPCQueries.DELETE_NPC((NPC) hireling);
}
2022-04-30 09:41:17 -04:00
public static void cleanupHirelings(Building building) {
// Early exit: Cannot have hirelings in a building
// without a blueprint.
if (building.getBlueprintUUID() == 0)
return;
// Remove all hirelings for destroyed buildings
if (building.getRank() < 1) {
2023-09-09 08:38:00 -04:00
for (AbstractCharacter slottedNPC : building.getHirelings().keySet())
BuildingManager.removeHireling(building, slottedNPC);
2022-04-30 09:41:17 -04:00
return;
}
// Delete hireling if building has deranked.
2024-05-11 08:02:19 -04:00
for (AbstractCharacter hireling : building.getHirelings().keySet())
2022-04-30 09:41:17 -04:00
if (building.getHirelings().get(hireling) > building.getBlueprint().getSlotsForRank(building.getRank()))
2023-09-09 08:38:00 -04:00
BuildingManager.removeHireling(building, hireling);
2022-04-30 09:41:17 -04:00
refreshHirelings(building);
}
public static Building getBuilding(int id) {
if (id == 0)
return null;
Building building;
building = (Building) DbManager.getFromCache(mbEnums.GameObjectType.Building, id);
2022-04-30 09:41:17 -04:00
if (building != null)
return building;
return DbManager.BuildingQueries.GET_BUILDINGBYUUID(id);
}
public static boolean PlayerCanControlNotOwner(Building building, PlayerCharacter player) {
if (player == null)
return false;
if (building == null)
return false;
if (building.getOwner() == null)
return false;
//lets pass true if player is owner anyway.
2024-05-11 08:02:19 -04:00
2022-04-30 09:41:17 -04:00
if (building.getOwner().equals(player))
return true;
if (player.getGuild().isEmptyGuild())
2022-04-30 09:41:17 -04:00
return false;
if (building.getGuild().isGuildLeader(player.getObjectUUID()))
return true;
if (!Guild.sameGuild(building.getGuild(), player.getGuild()))
return false;
2024-05-11 07:51:56 -04:00
return GuildStatusController.isGuildLeader(player.getGuildStatus()) || GuildStatusController.isInnerCouncil(player.getGuildStatus());
2022-04-30 09:41:17 -04:00
}
public static boolean IsPlayerHostile(Building building, PlayerCharacter player) {
if (Guild.sameNationExcludeErrant(building.getGuild(), player.getGuild()))
return false;
2024-06-26 20:07:37 -05:00
if(building.enforceKOS) {
if (building.getCity() != null) {
Building TOL = building.getCity().getTOL();
if (TOL != null) {
building = TOL;
}
}
}
2022-04-30 09:41:17 -04:00
if (!building.reverseKOS) {
Condemned condemn = building.getCondemned().get(player.getObjectUUID());
if (condemn != null && condemn.active)
2022-04-30 09:41:17 -04:00
return true;
if (player.getGuild() != null) {
Condemned guildCondemn = building.getCondemned().get(player.getGuild().getObjectUUID());
if (guildCondemn != null && guildCondemn.active)
2022-04-30 09:41:17 -04:00
return true;
Condemned nationCondemn = building.getCondemned().get(player.getGuild().getNation().getObjectUUID());
return nationCondemn != null && nationCondemn.active && nationCondemn.friendType == Condemned.NATION;
2022-04-30 09:41:17 -04:00
} else {
//TODO ADD ERRANT KOS CHECK
}
} else {
Condemned condemn = building.getCondemned().get(player.getObjectUUID());
if (condemn != null && condemn.active)
2022-04-30 09:41:17 -04:00
return false;
if (player.getGuild() != null) {
Condemned guildCondemn = building.getCondemned().get(player.getGuild().getObjectUUID());
if (guildCondemn != null && guildCondemn.active)
2022-04-30 09:41:17 -04:00
return false;
Condemned nationCondemn = building.getCondemned().get(player.getGuild().getNation().getObjectUUID());
return nationCondemn == null || !nationCondemn.active || nationCondemn.friendType != Condemned.NATION;
2022-04-30 09:41:17 -04:00
} else {
//TODO ADD ERRANT KOS CHECK
}
return true;
}
//When we get to here, This means The building was not reverse KOS
//and passed the hostile test.
return false;
}
public static final synchronized boolean addHirelingForWorld(Building building, PlayerCharacter contractOwner, Vector3fImmutable NpcLoc, Zone zone, Contract NpcID, int rank) {
String pirateName = NPCManager.getPirateName(NpcID.getMobbaseID());
2022-04-30 09:41:17 -04:00
2024-05-11 08:02:19 -04:00
NPC npc;
2022-04-30 09:41:17 -04:00
2024-01-28 10:01:01 -05:00
npc = NPC.createNPC(pirateName, NpcID.getObjectUUID(), NpcLoc, building.getGuild(), zone, (short) rank, building);
2022-04-30 09:41:17 -04:00
if (npc == null)
return false;
2023-08-20 17:23:50 -04:00
npc.setObjectTypeMask(MBServerStatics.MASK_NPC);
2023-08-20 17:16:18 -04:00
npc.setLoc(npc.bindLoc);
2023-08-20 19:07:26 -04:00
InterestManager.setObjectDirty(npc);
2022-04-30 09:41:17 -04:00
return true;
}
public static synchronized boolean addHireling(Building building, PlayerCharacter contractOwner, Zone zone, Contract contract, Item item) {
2022-04-30 09:41:17 -04:00
2024-05-11 08:02:19 -04:00
int rank;
2022-04-30 09:41:17 -04:00
if (building.getBlueprintUUID() == 0)
return false;
if (building.getBlueprint().getMaxSlots() == building.getHirelings().size())
return false;
String pirateName = NPCManager.getPirateName(contract.getMobbaseID());
2022-04-30 09:41:17 -04:00
2024-03-01 21:32:51 -05:00
if ((byte) item.chargesRemaining > 0)
rank = (byte) item.chargesRemaining * 10;
2023-07-15 09:23:48 -04:00
else
rank = 10;
2022-04-30 09:41:17 -04:00
Mob mobile;
2023-04-23 10:01:18 -04:00
NPC npc;
2023-04-24 09:22:01 -04:00
if (NPC.ISWallArcher(contract)) {
2022-04-30 09:41:17 -04:00
mobile = Mob.createMob(contract.getMobbaseID(), Vector3fImmutable.ZERO, contractOwner.getGuild(), zone, building, contract, pirateName, rank, mbEnums.AIAgentType.GUARDWALLARCHER);
2022-04-30 09:41:17 -04:00
if (mobile == null)
2022-04-30 09:41:17 -04:00
return false;
2023-08-31 08:58:55 -04:00
// Configure AI and write new mobile to disk
mobile.behaviourType = mbEnums.MobBehaviourType.GuardWallArcher;
2023-08-31 08:58:55 -04:00
mobile = DbManager.MobQueries.PERSIST(mobile);
2023-08-31 08:58:55 -04:00
// Spawn new mobile
mobile.setLoc(mobile.getLoc());
2023-04-29 16:06:05 -04:00
2022-04-30 09:41:17 -04:00
return true;
2023-04-04 10:31:59 -04:00
}
2023-04-24 09:22:01 -04:00
if (NPC.ISGuardCaptain(contract.getContractID())) {
2023-04-18 20:47:49 -05:00
mobile = Mob.createMob(contract.getMobbaseID(), Vector3fImmutable.ZERO, contractOwner.getGuild(), zone, building, contract, pirateName, rank, mbEnums.AIAgentType.GUARDCAPTAIN);
2023-04-18 20:47:49 -05:00
if (mobile == null)
2023-04-18 20:47:49 -05:00
return false;
2023-08-31 08:58:55 -04:00
// Configure AI and write new mobile to disk
mobile.behaviourType = mbEnums.MobBehaviourType.GuardCaptain;
2023-08-31 08:58:55 -04:00
mobile = DbManager.MobQueries.PERSIST(mobile);
2023-08-31 08:58:55 -04:00
// Spawn new mobile
mobile.setLoc(mobile.getLoc());
2023-04-29 16:06:05 -04:00
2023-04-18 20:47:49 -05:00
return true;
}
2023-06-25 21:32:36 -05:00
if (contract.getContractID() == 910) {
2023-07-21 12:50:52 -04:00
2023-06-25 21:32:36 -05:00
//guard dog
2024-05-11 08:02:19 -04:00
mobile = Mob.createMob(contract.getMobbaseID(), Vector3fImmutable.ZERO, contractOwner.getGuild(), zone, building, contract, pirateName, rank, mbEnums.AIAgentType.GUARDCAPTAIN);
2023-06-25 21:32:36 -05:00
if (mobile == null)
2023-06-25 21:32:36 -05:00
return false;
2023-04-29 10:30:53 -04:00
2023-08-31 08:58:55 -04:00
// Configure AI and write new mobile to disk
mobile.behaviourType = mbEnums.MobBehaviourType.GuardCaptain;
2023-08-31 08:58:55 -04:00
mobile = DbManager.MobQueries.PERSIST(mobile);
// Spawn new mobile
mobile.setLoc(mobile.getLoc());
2023-06-25 21:32:36 -05:00
return true;
}
2023-07-21 12:50:52 -04:00
2023-08-21 14:11:22 -04:00
npc = NPC.createNPC(pirateName, contract.getObjectUUID(), Vector3fImmutable.ZERO, contractOwner.getGuild(), zone, (short) rank, building);
2022-04-30 09:41:17 -04:00
2023-04-04 10:31:59 -04:00
if (npc == null)
return false;
2022-04-30 09:41:17 -04:00
2023-08-20 20:02:16 -04:00
npc.setObjectTypeMask(MBServerStatics.MASK_NPC);
npc.setLoc(npc.bindLoc);
InterestManager.setObjectDirty(npc);
2023-04-04 10:31:59 -04:00
return true;
2022-04-30 09:41:17 -04:00
}
public static boolean IsWallPiece(Building building) {
if (building.getBlueprint() == null)
return false;
BuildingGroup buildingGroup = building.getBlueprint().getBuildingGroup();
switch (buildingGroup) {
case WALLSTRAIGHT:
case WALLCORNER:
case SMALLGATE:
case ARTYTOWER:
case WALLSTRAIGHTTOWER:
case WALLSTAIRS:
return true;
default:
return false;
}
}
public static Building getBuildingFromCache(int id) {
return (Building) DbManager.getFromCache(GameObjectType.Building, id);
}
public static boolean IsOwner(Building building, PlayerCharacter player) {
if (building == null || player == null)
return false;
2023-07-15 09:23:48 -04:00
2022-04-30 09:41:17 -04:00
if (building.getOwner() == null)
2023-07-15 09:23:48 -04:00
return false;
2022-04-30 09:41:17 -04:00
return building.getOwner().getObjectUUID() == player.getObjectUUID();
}
public static float GetMissingHealth(Building building) {
return building.healthMax - building.getCurrentHitpoints();
}
public static int GetRepairCost(Building building) {
return (int) (GetMissingHealth(building) * .10f);
}
public static Regions GetRegion(Building building, float x, float y, float z) {
2024-05-11 08:02:19 -04:00
2022-04-30 09:41:17 -04:00
if (building.getBounds() == null)
return null;
if (building.getBounds().getRegions() == null)
return null;
Regions currentRegion = null;
2024-05-11 08:02:19 -04:00
for (Regions region : building.getBounds().getRegions()) {
if (region.isPointInPolygon(new Vector3fImmutable(x, y, z)))
2022-04-30 09:41:17 -04:00
if (y > (region.highLerp.y - 5))
currentRegion = region;
}
2024-05-11 08:02:19 -04:00
2022-04-30 09:41:17 -04:00
return currentRegion;
}
public static Regions GetRegion(Building building, int room, int level, float x, float z) {
2024-05-11 08:02:19 -04:00
2022-04-30 09:41:17 -04:00
if (building.getBounds() == null)
return null;
if (building.getBounds().getRegions() == null)
return null;
for (Regions region : building.getBounds().getRegions()) {
if (region.getLevel() != level)
continue;
2024-05-11 08:02:19 -04:00
2022-04-30 09:41:17 -04:00
if (region.getRoom() != room)
continue;
2024-05-11 08:02:19 -04:00
if (region.isPointInPolygon(new Vector3fImmutable(x, 0, z)))
2022-04-30 09:41:17 -04:00
return region;
}
return null;
}
2023-07-15 09:23:48 -04:00
public static Vector3fImmutable GetBindLocationForBuilding(Building building) {
Vector3fImmutable bindLoc = null;
if (building == null)
return mbEnums.Ruins.getRandomRuin().getLocation();
2023-07-15 09:23:48 -04:00
bindLoc = building.getLoc();
float radius = Bounds.meshBoundsCache.get(building.getMeshUUID()).radius;
2024-05-11 08:02:19 -04:00
2023-07-15 09:23:48 -04:00
if (building.getRank() == 8) {
bindLoc = building.getStuckLocation();
if (bindLoc != null)
return bindLoc;
}
float x = bindLoc.getX();
float z = bindLoc.getZ();
float offset = ((ThreadLocalRandom.current().nextFloat() * 2) - 1) * radius;
int direction = ThreadLocalRandom.current().nextInt(4);
switch (direction) {
case 0:
x += radius;
z += offset;
break;
case 1:
x += offset;
z -= radius;
break;
case 2:
x -= radius;
z += offset;
break;
case 3:
x += offset;
z += radius;
break;
}
bindLoc = new Vector3fImmutable(x, bindLoc.getY(), z);
return bindLoc;
2022-04-30 09:41:17 -04:00
}
public static void rebuildMine(Building mineBuilding) {
2023-10-18 11:30:22 -04:00
setRank(mineBuilding, 1);
mineBuilding.meshUUID = mineBuilding.getBlueprint().getMeshForRank(mineBuilding.rank);
// New rank mean new max hit points.
mineBuilding.healthMax = mineBuilding.getBlueprint().getMaxHealth(mineBuilding.rank);
mineBuilding.setCurrentHitPoints(mineBuilding.healthMax);
mineBuilding.getBounds().setBounds(mineBuilding);
}
2023-10-18 11:30:22 -04:00
public static void setRank(Building building, int rank) {
int newMeshUUID;
boolean success;
// If this building has no blueprint then set rank and exit immediatly.
if (building.blueprintUUID == 0 || building.getBlueprint() != null && building.getBlueprint().getBuildingGroup().equals(BuildingGroup.MINE)) {
building.rank = rank;
DbManager.BuildingQueries.CHANGE_RANK(building.getObjectUUID(), rank);
return;
}
// Delete any upgrade jobs before doing anything else. It won't quite work
// if in a few lines we happen to delete this building.
2024-05-11 08:02:19 -04:00
JobContainer jobContainer = building.getTimers().get("UPGRADE");
2023-10-18 11:30:22 -04:00
2024-05-11 08:02:19 -04:00
if (jobContainer != null) {
if (!JobScheduler.getInstance().cancelScheduledJob(jobContainer))
2023-10-18 11:30:22 -04:00
Logger.error("failed to cancel existing upgrade job.");
}
2024-05-11 08:02:19 -04:00
// Attempt to write to database or delete the building
2023-10-18 11:30:22 -04:00
// if we are destroying it.
2024-08-25 16:23:28 -04:00
if (rank < 0)
2023-10-18 11:30:22 -04:00
success = DbManager.BuildingQueries.DELETE_FROM_DATABASE(building);
else
success = DbManager.BuildingQueries.updateBuildingRank(building, rank);
2024-05-11 07:51:56 -04:00
if (!success) {
2023-10-18 11:30:22 -04:00
Logger.error("Error writing to database UUID: " + building.getObjectUUID());
return;
}
building.isDeranking.compareAndSet(false, true);
// Change the building's rank
building.rank = rank;
// New rank means new mesh
newMeshUUID = building.getBlueprint().getMeshForRank(building.rank);
2024-02-10 22:14:52 -06:00
2024-03-24 09:42:27 -04:00
if ((building.getBlueprint().getBuildingGroup() == BuildingGroup.TOL) && (building.rank == 8))
2024-02-10 22:14:52 -06:00
newMeshUUID = Realm.getRealmMesh(building.getCity());
2023-10-18 11:30:22 -04:00
building.meshUUID = newMeshUUID;
// New rank mean new max hitpoints.
building.healthMax = building.getBlueprint().getMaxHealth(building.rank);
building.setCurrentHitPoints(building.healthMax);
if (building.getUpgradeDateTime() != null)
setUpgradeDateTime(building, null, 0);
// If we destroyed this building make sure to turn off
// protection
if (building.rank == -1)
building.protectionState = mbEnums.ProtectionState.NONE;
2023-10-18 11:30:22 -04:00
// update object to clients
building.refresh(true);
if (building.getBounds() != null)
building.getBounds().setBounds(building);
// Cleanup hirelings resulting from rank change
cleanupHirelings(building);
building.isDeranking.compareAndSet(true, false);
}
public static Building getBuildingAtLocation(Vector3fImmutable loc) {
for (AbstractWorldObject awo : WorldGrid.getObjectsInRangePartial(loc, 64, MBServerStatics.MASK_BUILDING)) {
Building building = (Building) awo;
if (building == null)
2023-10-18 18:23:14 -05:00
continue;
2023-10-19 08:15:22 -04:00
if (Bounds.collide(loc, building.getBounds()))
2023-10-18 18:23:14 -05:00
return building;
}
return null;
}
2022-04-30 09:41:17 -04:00
}