759 lines
22 KiB
Java
759 lines
22 KiB
Java
package engine.gameManager;
|
|
|
|
import engine.Enum;
|
|
import engine.InterestManagement.WorldGrid;
|
|
import engine.exception.SerializationException;
|
|
import engine.math.Quaternion;
|
|
import engine.math.Vector3f;
|
|
import engine.math.Vector3fImmutable;
|
|
import engine.net.ByteBufferWriter;
|
|
import engine.net.Dispatch;
|
|
import engine.net.DispatchMessage;
|
|
import engine.net.client.msg.PetMsg;
|
|
import engine.objects.*;
|
|
import engine.powers.EffectsBase;
|
|
import engine.server.MBServerStatics;
|
|
import org.pmw.tinylog.Logger;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.concurrent.ThreadLocalRandom;
|
|
|
|
import static engine.math.FastMath.acos;
|
|
|
|
public enum NPCManager {
|
|
|
|
NPC_MANAGER;
|
|
public static HashMap<Integer, ArrayList<Integer>> _runeSetMap = new HashMap<>();
|
|
public static int SVR_CLOSE_WINDOW = 4;
|
|
public static HashMap<Integer, ArrayList<String>> _pirateNames = new HashMap<>();
|
|
|
|
public static void LoadAllRuneSets() {
|
|
_runeSetMap = DbManager.ItemBaseQueries.LOAD_RUNES_FOR_NPC_AND_MOBS();
|
|
}
|
|
|
|
public static void LoadAllBootySets() {
|
|
LootManager._bootySetMap = DbManager.LootQueries.LOAD_BOOTY_TABLES();
|
|
}
|
|
|
|
public static void applyRuneSetEffects(Mob mob) {
|
|
|
|
// Early exit
|
|
|
|
if (mob.runeSet == 0)
|
|
return;
|
|
|
|
//Apply all rune effects.
|
|
|
|
if (NPCManager._runeSetMap.get(mob.runeSet).contains(252623)) {
|
|
mob.isPlayerGuard = true;
|
|
}
|
|
|
|
// Only captains have contracts
|
|
|
|
if (mob.contract != null || mob.isPlayerGuard)
|
|
applyEffectsForRune(mob, 252621);
|
|
|
|
|
|
// Apply effects from RuneSet
|
|
|
|
if (mob.runeSet != 0)
|
|
for (int runeID : _runeSetMap.get(mob.runeSet))
|
|
applyEffectsForRune(mob, runeID);
|
|
|
|
// Not sure why but apply Warrior effects for some reason?
|
|
|
|
applyEffectsForRune(mob, 2518);
|
|
}
|
|
|
|
public static void applyEffectsForRune(AbstractCharacter character, int runeID) {
|
|
|
|
EffectsBase effectsBase;
|
|
RuneBase sourceRune = RuneBase.getRuneBase(runeID);
|
|
|
|
// Race runes are in the runeset but not in runebase for some reason
|
|
|
|
if (sourceRune == null)
|
|
return;
|
|
|
|
for (MobBaseEffects mbe : sourceRune.getEffectsList()) {
|
|
|
|
effectsBase = PowersManager.getEffectByToken(mbe.getToken());
|
|
|
|
if (effectsBase == null) {
|
|
Logger.info("Mob: " + character.getObjectUUID() + " EffectsBase Null for Token " + mbe.getToken());
|
|
continue;
|
|
}
|
|
|
|
//check to upgrade effects if needed.
|
|
if (character.effects.containsKey(Integer.toString(effectsBase.getUUID()))) {
|
|
|
|
if (mbe.getReqLvl() > (int) character.level)
|
|
continue;
|
|
|
|
Effect eff = character.effects.get(Integer.toString(effectsBase.getUUID()));
|
|
|
|
if (eff == null)
|
|
continue;
|
|
|
|
//Current effect is a higher rank, dont apply.
|
|
if (eff.getTrains() > mbe.getRank())
|
|
continue;
|
|
|
|
//new effect is of a higher rank. remove old effect and apply new one.
|
|
eff.cancelJob();
|
|
character.addEffectNoTimer(Integer.toString(effectsBase.getUUID()), effectsBase, mbe.getRank(), true);
|
|
} else {
|
|
|
|
if (mbe.getReqLvl() > (int) character.level)
|
|
continue;
|
|
|
|
character.addEffectNoTimer(Integer.toString(effectsBase.getUUID()), effectsBase, mbe.getRank(), true);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
public static void dismissNecroPet(Mob necroPet, boolean updateOwner) {
|
|
|
|
necroPet.setCombatTarget(null);
|
|
necroPet.hasLoot = false;
|
|
|
|
if (necroPet.parentZone != null)
|
|
necroPet.parentZone.zoneMobSet.remove(necroPet);
|
|
|
|
try {
|
|
necroPet.clearEffects();
|
|
} catch (Exception e) {
|
|
Logger.error(e.getMessage());
|
|
}
|
|
necroPet.playerAgroMap.clear();
|
|
WorldGrid.RemoveWorldObject(necroPet);
|
|
|
|
DbManager.removeFromCache(necroPet);
|
|
|
|
PlayerCharacter petOwner = necroPet.getOwner();
|
|
|
|
if (petOwner != null) {
|
|
necroPet.setOwner(null);
|
|
petOwner.setPet(null);
|
|
|
|
if (updateOwner == false)
|
|
return;
|
|
|
|
PetMsg petMsg = new PetMsg(5, null);
|
|
Dispatch dispatch = Dispatch.borrow(petOwner, petMsg);
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
|
|
}
|
|
}
|
|
|
|
public static void auditNecroPets(PlayerCharacter player) {
|
|
int removeIndex = 0;
|
|
while (player.necroPets.size() >= 10) {
|
|
|
|
|
|
if (removeIndex == player.necroPets.size())
|
|
break;
|
|
|
|
Mob necroPet = player.necroPets.get(removeIndex);
|
|
|
|
if (necroPet == null) {
|
|
removeIndex++;
|
|
continue;
|
|
}
|
|
dismissNecroPet(necroPet, true);
|
|
player.necroPets.remove(necroPet);
|
|
removeIndex++;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
public static void resetNecroPets(PlayerCharacter player) {
|
|
|
|
for (Mob necroPet : player.necroPets)
|
|
if (necroPet.isPet())
|
|
necroPet.agentType = Enum.AIAgentType.MOBILE;
|
|
}
|
|
|
|
public static void spawnNecroPet(PlayerCharacter playerCharacter, Mob mob) {
|
|
|
|
if (mob == null)
|
|
return;
|
|
|
|
if (mob.getMobBaseID() != 12021 && mob.getMobBaseID() != 12022)
|
|
return;
|
|
|
|
auditNecroPets(playerCharacter);
|
|
resetNecroPets(playerCharacter);
|
|
|
|
playerCharacter.necroPets.add(mob);
|
|
}
|
|
|
|
public static void dismissNecroPets(PlayerCharacter playerCharacter) {
|
|
|
|
|
|
if (playerCharacter.necroPets.isEmpty())
|
|
return;
|
|
|
|
for (Mob necroPet : playerCharacter.necroPets) {
|
|
|
|
try {
|
|
dismissNecroPet(necroPet, true);
|
|
} catch (Exception e) {
|
|
Logger.error(e);
|
|
}
|
|
}
|
|
playerCharacter.necroPets.clear();
|
|
}
|
|
|
|
|
|
public static void removeSiegeMinions(Mob mobile) {
|
|
|
|
for (Mob toRemove : mobile.siegeMinionMap.keySet()) {
|
|
|
|
if (mobile.isMoving()) {
|
|
|
|
mobile.stopMovement(mobile.getLoc());
|
|
|
|
if (toRemove.parentZone != null)
|
|
toRemove.parentZone.zoneMobSet.remove(toRemove);
|
|
}
|
|
|
|
try {
|
|
toRemove.clearEffects();
|
|
} catch (Exception e) {
|
|
Logger.error(e.getMessage());
|
|
}
|
|
|
|
if (toRemove.parentZone != null)
|
|
toRemove.parentZone.zoneMobSet.remove(toRemove);
|
|
|
|
WorldGrid.RemoveWorldObject(toRemove);
|
|
WorldGrid.removeObject(toRemove);
|
|
DbManager.removeFromCache(toRemove);
|
|
|
|
PlayerCharacter petOwner = toRemove.getOwner();
|
|
|
|
if (petOwner != null) {
|
|
|
|
petOwner.setPet(null);
|
|
toRemove.setOwner(null);
|
|
|
|
PetMsg petMsg = new PetMsg(5, null);
|
|
Dispatch dispatch = Dispatch.borrow(petOwner, petMsg);
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static boolean removeMobileFromBuilding(Mob mobile, Building building) {
|
|
|
|
// Remove npc from it's building
|
|
|
|
try {
|
|
mobile.clearEffects();
|
|
} catch (Exception e) {
|
|
Logger.error(e.getMessage());
|
|
}
|
|
|
|
if (mobile.parentZone != null)
|
|
mobile.parentZone.zoneMobSet.remove(mobile);
|
|
|
|
if (building != null) {
|
|
building.getHirelings().remove(mobile);
|
|
removeSiegeMinions(mobile);
|
|
}
|
|
|
|
// Delete npc from database
|
|
|
|
if (DbManager.MobQueries.DELETE_MOB(mobile) == 0)
|
|
return false;
|
|
|
|
// Remove npc from the simulation
|
|
|
|
mobile.removeFromCache();
|
|
DbManager.removeFromCache(mobile);
|
|
WorldGrid.RemoveWorldObject(mobile);
|
|
WorldGrid.removeObject(mobile);
|
|
return true;
|
|
}
|
|
|
|
public static void loadAllPirateNames() {
|
|
|
|
DbManager.NPCQueries.LOAD_PIRATE_NAMES();
|
|
}
|
|
|
|
public static String getPirateName(int mobBaseID) {
|
|
|
|
ArrayList<String> nameList = null;
|
|
|
|
// If we cannot find name for this mobbase then
|
|
// fallback to human male
|
|
|
|
if (_pirateNames.containsKey(mobBaseID))
|
|
nameList = _pirateNames.get(mobBaseID);
|
|
else
|
|
nameList = _pirateNames.get(2111);
|
|
|
|
if (nameList == null) {
|
|
Logger.error("Null name list for 2111!");
|
|
}
|
|
|
|
return nameList.get(ThreadLocalRandom.current().nextInt(nameList.size()));
|
|
|
|
}
|
|
|
|
public static ArrayList<Building> getProtectedBuildings(NPC npc) {
|
|
|
|
ArrayList<Building> protectedBuildings = new ArrayList<>();
|
|
|
|
if (npc.building == null)
|
|
return protectedBuildings;
|
|
|
|
if (npc.building.getCity() == null)
|
|
return protectedBuildings;
|
|
|
|
for (Building b : npc.building.getCity().getParent().zoneBuildingSet) {
|
|
|
|
if (b.getBlueprint() == null)
|
|
continue;
|
|
|
|
if (b.getProtectionState().equals(Enum.ProtectionState.CONTRACT))
|
|
protectedBuildings.add(b);
|
|
|
|
if (b.getProtectionState().equals(Enum.ProtectionState.PENDING))
|
|
protectedBuildings.add(b);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
public static boolean ISWallArcher(Contract contract) {
|
|
|
|
if (contract == null)
|
|
return false;
|
|
|
|
//838, 950, 1051, 1181, 1251, 1351, 1451, 1501, 1526, 1551, 980101,
|
|
|
|
return contract.getAllowedBuildings().contains(Enum.BuildingGroup.WALLCORNER) ||
|
|
contract.getAllowedBuildings().contains(Enum.BuildingGroup.WALLSTRAIGHTTOWER);
|
|
}
|
|
|
|
public static NPC getFromCache(int id) {
|
|
return (NPC) DbManager.getFromCache(Enum.GameObjectType.NPC, id);
|
|
}
|
|
|
|
public static boolean UpdateName(NPC npc, String value) {
|
|
|
|
if (!DbManager.NPCQueries.UPDATE_NAME(npc, value))
|
|
return false;
|
|
|
|
npc.setName(value);
|
|
return true;
|
|
|
|
}
|
|
|
|
public static void serializeNpcForClientMsgOtherPlayer(NPC npc, ByteBufferWriter writer, boolean hideAsciiLastName)
|
|
throws SerializationException {
|
|
serializeForClientMsgOtherPlayer(npc, writer);
|
|
}
|
|
|
|
public static void serializeForClientMsgOtherPlayer(NPC npc, ByteBufferWriter writer)
|
|
throws SerializationException {
|
|
|
|
writer.putInt(0);
|
|
writer.putInt(0);
|
|
|
|
//num Runes
|
|
int cnt = 3;
|
|
boolean isVamp = false, isHealer = false, isArcher = false, isTrainer = false;
|
|
int contractID = 0, classID = 0;
|
|
int extraRune = 0;
|
|
|
|
if (npc.contract != null) {
|
|
contractID = npc.contract.getContractID();
|
|
classID = npc.contract.getClassID();
|
|
extraRune = npc.contract.getExtraRune();
|
|
|
|
if (extraRune == contractID)
|
|
extraRune = 0;
|
|
|
|
}
|
|
|
|
if ((contractID > 252642 && contractID < 252647) || contractID == 252652) {
|
|
isVamp = true;
|
|
cnt++;
|
|
}
|
|
|
|
if (contractID == 252582 || contractID == 252579 || contractID == 252581
|
|
|| contractID == 252584 || contractID == 252597 || contractID == 252598
|
|
|| contractID == 252628 || extraRune == 252582 || extraRune == 252579
|
|
|| extraRune == 252581 || extraRune == 252584 || extraRune == 252597
|
|
|| extraRune == 252598 || extraRune == 252628) {
|
|
isHealer = true;
|
|
cnt++;
|
|
}
|
|
|
|
if (contractID == 252570) {
|
|
isArcher = true;
|
|
cnt++;
|
|
}
|
|
|
|
if (classID != 0)
|
|
cnt++;
|
|
|
|
if (extraRune != 0 && extraRune != contractID)
|
|
cnt++;
|
|
|
|
writer.putInt(cnt);
|
|
|
|
//Race
|
|
writer.putInt(1);
|
|
writer.putInt(0);
|
|
|
|
if (npc.getMobBase() != null)
|
|
writer.putInt(npc.getMobBase().getLoadID());
|
|
else
|
|
writer.putInt(2011);
|
|
|
|
writer.putInt(Enum.GameObjectType.NPCRaceRune.ordinal());
|
|
writer.putInt(npc.currentID);
|
|
|
|
//Class/Trainer/Whatever
|
|
writer.putInt(5);
|
|
writer.putInt(0);
|
|
|
|
if (npc.contract != null)
|
|
writer.putInt(contractID);
|
|
else
|
|
writer.putInt(2500);
|
|
|
|
writer.putInt(Enum.GameObjectType.NPCClassRune.ordinal());
|
|
writer.putInt(npc.currentID);
|
|
|
|
//vampire trainer
|
|
cnt = 0;
|
|
|
|
if (extraRune != 0)
|
|
cnt = serializeExtraRune(npc, extraRune, cnt, writer);
|
|
if (isVamp)
|
|
cnt = serializeExtraRune(npc, 252647, cnt, writer);
|
|
|
|
//Healer trainer
|
|
if (isHealer)
|
|
cnt = serializeExtraRune(npc, 252592, cnt, writer);
|
|
|
|
if (classID != 0) {
|
|
writer.putInt(4);
|
|
writer.putInt(0);
|
|
writer.putInt(classID);
|
|
writer.putInt(Enum.GameObjectType.NPCExtraRune.ordinal());
|
|
writer.putInt(npc.currentID);
|
|
}
|
|
|
|
//Scout trainer
|
|
if (isArcher)
|
|
cnt = serializeExtraRune(npc, 252654, cnt, writer);
|
|
|
|
//Shopkeeper
|
|
writer.putInt(5);
|
|
writer.putInt(0);
|
|
writer.putInt(0x3DACC);
|
|
writer.putInt(Enum.GameObjectType.NPCShopkeeperRune.ordinal());
|
|
writer.putInt(npc.currentID);
|
|
|
|
//Send Stats
|
|
writer.putInt(5);
|
|
writer.putInt(0x8AC3C0E6); //Str
|
|
writer.putInt(0);
|
|
writer.putInt(0xACB82E33); //Dex
|
|
writer.putInt(0);
|
|
writer.putInt(0xB15DC77E); //Con
|
|
writer.putInt(0);
|
|
writer.putInt(0xE07B3336); //Int
|
|
writer.putInt(0);
|
|
writer.putInt(0xFF665EC3); //Spi
|
|
writer.putInt(0);
|
|
|
|
writer.putString(npc.getName());
|
|
writer.putString("");
|
|
|
|
writer.putInt(0);
|
|
writer.putInt(0);
|
|
writer.putInt(0);
|
|
writer.putInt(0);
|
|
|
|
writer.put((byte) 0);
|
|
writer.putInt(npc.getObjectType().ordinal());
|
|
writer.putInt(npc.currentID);
|
|
|
|
writer.putFloat(1.0f);
|
|
writer.putFloat(1.0f);
|
|
writer.putFloat(1.0f);
|
|
|
|
if (npc.region != null)
|
|
writer.putVector3f(ZoneManager.convertWorldToLocal(npc.building, npc.getLoc()));
|
|
else
|
|
writer.putVector3f(npc.getLoc());
|
|
|
|
//Rotation
|
|
float radians = (float) Math.acos(npc.getRot().y) * 2;
|
|
|
|
if (npc.building != null)
|
|
if (npc.building.getBounds() != null && npc.building.getBounds().getQuaternion() != null)
|
|
radians += (npc.building.getBounds().getQuaternion()).angleY;
|
|
|
|
writer.putFloat(radians);
|
|
|
|
//Running Speed
|
|
writer.putInt(0);
|
|
|
|
// get a copy of the equipped items.
|
|
|
|
if (npc.equip != null) {
|
|
writer.putInt(npc.equip.size());
|
|
|
|
for (MobEquipment me : npc.equip.values())
|
|
MobEquipment.serializeForClientMsg(me, writer);
|
|
} else
|
|
writer.putInt(0);
|
|
|
|
writer.putInt((npc.level / 10));
|
|
writer.putInt(npc.level);
|
|
writer.putInt(npc.getIsSittingAsInt()); //Standing
|
|
writer.putInt(npc.getIsWalkingAsInt()); //Walking
|
|
writer.putInt(npc.getIsCombatAsInt()); //Combat
|
|
writer.putInt(2); //Unknown
|
|
writer.putInt(1); //Unknown - Headlights?
|
|
writer.putInt(0);
|
|
|
|
if (npc.building != null && npc.region != null) {
|
|
writer.putInt(npc.building.getObjectType().ordinal());
|
|
writer.putInt(npc.building.getObjectUUID());
|
|
} else {
|
|
writer.putInt(0); //<-Building Object Type
|
|
writer.putInt(0); //<-Building Object ID
|
|
}
|
|
writer.put((byte) 0);
|
|
writer.put((byte) 0);
|
|
writer.put((byte) 0);
|
|
|
|
//npc dialog menus from contracts
|
|
|
|
if (npc.contract != null) {
|
|
ArrayList<Integer> npcMenuOptions = npc.contract.getNPCMenuOptions();
|
|
writer.putInt(npcMenuOptions.size());
|
|
for (Integer val : npcMenuOptions) {
|
|
writer.putInt(val);
|
|
}
|
|
|
|
} else
|
|
writer.putInt(0);
|
|
|
|
writer.put((byte) 1);
|
|
|
|
if (npc.building != null) {
|
|
writer.putInt(Enum.GameObjectType.StrongBox.ordinal());
|
|
writer.putInt(npc.currentID);
|
|
writer.putInt(Enum.GameObjectType.StrongBox.ordinal());
|
|
writer.putInt(npc.building.getObjectUUID());
|
|
} else {
|
|
writer.putLong(0);
|
|
writer.putLong(0);
|
|
}
|
|
|
|
if (npc.contract != null)
|
|
writer.putInt(npc.contract.getIconID());
|
|
else
|
|
writer.putInt(0); //npc icon ID
|
|
|
|
writer.putInt(0);
|
|
writer.putShort((short) 0);
|
|
|
|
if (npc.contract != null && npc.contract.isTrainer()) {
|
|
writer.putInt(classID);
|
|
} else {
|
|
writer.putInt(0);
|
|
}
|
|
|
|
if (npc.contract != null && npc.contract.isTrainer())
|
|
writer.putInt(classID);
|
|
else
|
|
writer.putInt(0);
|
|
|
|
writer.putInt(0);
|
|
writer.putInt(0);
|
|
|
|
writer.putFloat(4);
|
|
writer.putInt(0);
|
|
writer.putInt(0);
|
|
writer.putInt(0);
|
|
writer.put((byte) 0);
|
|
|
|
//Pull guild info from building if linked to one
|
|
|
|
Guild.serializeForClientMsg(npc.guild, writer, null, true);
|
|
|
|
writer.putInt(1);
|
|
writer.putInt(0x8A2E);
|
|
writer.putInt(0);
|
|
writer.putInt(0);
|
|
|
|
//TODO Guard
|
|
writer.put((byte) 0); //Is guard..
|
|
|
|
writer.putFloat(1500f); //npc.healthMax
|
|
writer.putFloat(1500f); //npc.health
|
|
|
|
//TODO Peace Zone
|
|
writer.put((byte) 1); //0=show tags, 1=don't
|
|
writer.putInt(0);
|
|
writer.put((byte) 0);
|
|
}
|
|
|
|
private static int serializeExtraRune(NPC npc, int runeID, int cnt, ByteBufferWriter writer) {
|
|
|
|
writer.putInt(5);
|
|
writer.putInt(0);
|
|
writer.putInt(runeID);
|
|
|
|
if (cnt == 0)
|
|
writer.putInt(Enum.GameObjectType.NPCClassRuneTwo.ordinal());
|
|
else
|
|
writer.putInt(Enum.GameObjectType.NPCClassRuneThree.ordinal());
|
|
|
|
writer.putInt(npc.currentID);
|
|
return cnt + 1;
|
|
}
|
|
|
|
public static NPC createNPC(String name, int contractID, Vector3fImmutable spawn, Guild guild, Zone parent, short level, Building building) {
|
|
|
|
NPC newNPC = new NPC();
|
|
|
|
newNPC.setName(name);
|
|
newNPC.contractUUID = contractID;
|
|
|
|
if (building == null)
|
|
newNPC.bindLoc = spawn;
|
|
else
|
|
newNPC.bindLoc = Vector3fImmutable.ZERO;
|
|
|
|
newNPC.parentZoneUUID = parent.getObjectUUID();
|
|
newNPC.guildUUID = guild.getObjectUUID();
|
|
|
|
if (building == null)
|
|
newNPC.buildingUUID = 0;
|
|
else
|
|
newNPC.buildingUUID = building.getObjectUUID();
|
|
|
|
newNPC.level = level;
|
|
|
|
newNPC.buyPercent = .33f;
|
|
newNPC.sellPercent = 1;
|
|
|
|
NPC npc;
|
|
|
|
try {
|
|
npc = DbManager.NPCQueries.PERSIST(newNPC);
|
|
npc.setObjectTypeMask(MBServerStatics.MASK_NPC);
|
|
} catch (Exception e) {
|
|
Logger.error(e);
|
|
npc = null;
|
|
}
|
|
|
|
return npc;
|
|
}
|
|
|
|
public static NPC getNPC(int id) {
|
|
|
|
if (id == 0)
|
|
return null;
|
|
|
|
NPC npc = (NPC) DbManager.getFromCache(Enum.GameObjectType.NPC, id);
|
|
|
|
if (npc != null)
|
|
return npc;
|
|
|
|
return DbManager.NPCQueries.GET_NPC(id);
|
|
}
|
|
|
|
public static boolean ISGuardCaptain(int contractID) {
|
|
return Enum.MinionType.ContractToMinionMap.containsKey(contractID);
|
|
}
|
|
|
|
public static boolean UpdateEquipSetID(NPC npc, int equipSetID) {
|
|
|
|
if (!LootManager._bootySetMap.containsKey(equipSetID))
|
|
return false;
|
|
|
|
if (!DbManager.NPCQueries.UPDATE_EQUIPSET(npc, equipSetID))
|
|
return false;
|
|
|
|
npc.equipmentSetID = equipSetID;
|
|
|
|
return true;
|
|
}
|
|
|
|
public static boolean UpdateRaceID(NPC npc, int raceID) {
|
|
|
|
if (!DbManager.NPCQueries.UPDATE_MOBBASE(npc, raceID))
|
|
return false;
|
|
|
|
npc.loadID = raceID;
|
|
npc.mobBase = MobBase.getMobBase(npc.loadID);
|
|
return true;
|
|
}
|
|
|
|
public static NPCProfits GetNPCProfits(NPC npc) {
|
|
return NPCProfits.ProfitCache.get(npc.currentID);
|
|
}
|
|
}
|