diff --git a/src/engine/gameManager/NPCManager.java b/src/engine/gameManager/NPCManager.java index 6997b207..0ad83ecb 100644 --- a/src/engine/gameManager/NPCManager.java +++ b/src/engine/gameManager/NPCManager.java @@ -2,6 +2,9 @@ package engine.gameManager; import engine.Enum; import engine.InterestManagement.WorldGrid; +import engine.math.Quaternion; +import engine.math.Vector3f; +import engine.math.Vector3fImmutable; import engine.net.Dispatch; import engine.net.DispatchMessage; import engine.net.client.msg.PetMsg; @@ -13,6 +16,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.concurrent.ThreadLocalRandom; +import static engine.math.FastMath.acos; + public enum NPCManager { NPC_MANAGER; @@ -318,4 +323,51 @@ public enum NPCManager { return protectedBuildings; } + + public static int slotCharacterInBuilding(AbstractCharacter abstractCharacter) { + + int buildingSlot; + + if (abstractCharacter.building == null) + return -1; + + // Get next available slot for this NPC and use it + // to add the NPC to the building's hireling list + // Account for R8's having slots reversed. + + if (abstractCharacter.building.getBlueprint() != null && abstractCharacter.building.getBlueprint().getBuildingGroup().equals(Enum.BuildingGroup.TOL) && abstractCharacter.building.getRank() == 8) + buildingSlot = BuildingManager.getLastAvailableSlot(abstractCharacter.building); + else + buildingSlot = BuildingManager.getAvailableSlot(abstractCharacter.building); + + if (buildingSlot == -1) + Logger.error("No available slot for NPC: " + abstractCharacter.getObjectUUID()); + + abstractCharacter.building.getHirelings().put(abstractCharacter, buildingSlot); + + // Override bind and location for this npc derived + // from BuildingManager slot location data. + + Vector3fImmutable slotLocation = BuildingManager.getSlotLocation(abstractCharacter.building, buildingSlot).getLocation(); + + abstractCharacter.bindLoc = abstractCharacter.building.getLoc().add(slotLocation); + + // Rotate slot position by the building rotation + + abstractCharacter.bindLoc = Vector3fImmutable.rotateAroundPoint(abstractCharacter.building.getLoc(), abstractCharacter.bindLoc, abstractCharacter.building.getBounds().getQuaternion().angleY); + + abstractCharacter.loc = new Vector3fImmutable(abstractCharacter.bindLoc); + + // Rotate NPC rotation by the building's rotation + + Quaternion slotRotation = new Quaternion().fromAngles(0, acos(abstractCharacter.getRot().y) * 2, 0); + slotRotation = slotRotation.mult(abstractCharacter.building.getBounds().getQuaternion()); + abstractCharacter.setRot(new Vector3f(0, slotRotation.y, 0)); + + // Configure region and floor/level for this NPC + + abstractCharacter.region = BuildingManager.GetRegion(abstractCharacter.building, abstractCharacter.bindLoc.x, abstractCharacter.bindLoc.y, abstractCharacter.bindLoc.z); + + return buildingSlot; + } } diff --git a/src/engine/objects/AbstractCharacter.java b/src/engine/objects/AbstractCharacter.java index 8685d371..7b441f70 100644 --- a/src/engine/objects/AbstractCharacter.java +++ b/src/engine/objects/AbstractCharacter.java @@ -60,9 +60,14 @@ public abstract class AbstractCharacter extends AbstractWorldObject { protected short statSpiCurrent; protected short unusedStatPoints; protected int exp; + public int buildingUUID; + public Building building; + public Vector3fImmutable bindLoc; protected Vector3fImmutable faceDir; - protected Guild guild; + + public int guildUUID; + public Guild guild; protected byte runningTrains; protected ConcurrentHashMap powers; protected ConcurrentHashMap skills; diff --git a/src/engine/objects/NPC.java b/src/engine/objects/NPC.java index a407926e..ecf566c9 100644 --- a/src/engine/objects/NPC.java +++ b/src/engine/objects/NPC.java @@ -38,7 +38,6 @@ import java.util.HashSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantReadWriteLock; -import static engine.math.FastMath.acos; import static engine.net.client.msg.ErrorPopupMsg.sendErrorPopup; import static engine.objects.MobBase.loadEquipmentSet; import static engine.util.StringUtils.wordCount; @@ -51,8 +50,6 @@ public class NPC extends AbstractCharacter { // Used for thread safety public final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); private final ArrayList rolling = new ArrayList<>(); - private final ArrayList siegeMinions = new ArrayList<>(); - public Building building; public ReentrantReadWriteLock minionLock = new ReentrantReadWriteLock(); public ArrayList forgedItems = new ArrayList<>(); public HashMap equip = null; @@ -789,45 +786,8 @@ public class NPC extends AbstractCharacter { // Handle NPCs within buildings - if (this.building != null) { - - // Get next available slot for this NPC and use it - // to add the NPC to the building's hireling list - // Account for R8's having slots reversed. - - if (building.getBlueprint() != null && building.getBlueprint().getBuildingGroup().equals(BuildingGroup.TOL) && building.getRank() == 8) - slot = BuildingManager.getLastAvailableSlot(building); - else - slot = BuildingManager.getAvailableSlot(building); - - if (slot == -1) - Logger.error("No available slot for NPC: " + this.getObjectUUID()); - - building.getHirelings().put(this, slot); - - // Override bind and location for this npc derived - // from BuildingManager slot location data. - - slotLocation = BuildingManager.getSlotLocation(building, slot).getLocation(); - - this.bindLoc = building.getLoc().add(slotLocation); - - // Rotate slot position by the building rotation - - this.bindLoc = Vector3fImmutable.rotateAroundPoint(building.getLoc(), this.bindLoc, building.getBounds().getQuaternion().angleY); - - this.loc = new Vector3fImmutable(bindLoc); - - // Rotate NPC rotation by the building's rotation - - slotRotation = new Quaternion().fromAngles(0, acos(this.getRot().y) * 2, 0); - slotRotation = slotRotation.mult(building.getBounds().getQuaternion()); - this.setRot(new Vector3f(0, slotRotation.y, 0)); - - // Configure region and floor/level for this NPC - - this.region = BuildingManager.GetRegion(this.building, bindLoc.x, bindLoc.y, bindLoc.z); - } + if (this.building != null) + NPCManager.slotCharacterInBuilding(this); if (this.contract != null) { this.symbol = this.contract.getIconID();