Public Repository for the Magicbane Shadowbane Emulator
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.

2392 lines
91 KiB

package engine.gameManager;
import engine.Enum;
import engine.InterestManagement.InterestManager;
import engine.InterestManagement.WorldGrid;
import engine.exception.MsgSendException;
import engine.exception.SerializationException;
import engine.job.JobContainer;
import engine.job.JobScheduler;
import engine.jobs.FinishSpireEffectJob;
import engine.jobs.NoTimeJob;
import engine.math.Vector3fImmutable;
import engine.net.ByteBufferWriter;
import engine.net.Dispatch;
import engine.net.DispatchMessage;
import engine.net.client.ClientConnection;
import engine.net.client.msg.*;
import engine.net.client.msg.login.CommitNewCharacterMsg;
import engine.objects.*;
import engine.powers.EffectsBase;
import engine.server.MBServerStatics;
import engine.server.login.LoginServer;
import engine.server.login.LoginServerMsgHandler;
import engine.server.world.WorldServer;
import engine.util.MiscUtils;
import org.joda.time.DateTime;
import org.pmw.tinylog.Logger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class PlayerManager {
public static Building getUpdatedBindBuilding(PlayerCharacter player) {
Building returnBuilding = null;
//update bindBuilding based on Guild or nation TOL;
if (player.getBindBuildingID() == 0) {
returnBuilding = getBindBuildingForGuild(player);
if (returnBuilding != null)
player.setBindBuildingID(returnBuilding.getObjectUUID());
return returnBuilding;
}
returnBuilding = BuildingManager.getBuildingFromCache(player.getBindBuildingID());
if (returnBuilding == null) {
returnBuilding = getBindBuildingForGuild(player);
if (returnBuilding != null)
player.setBindBuildingID(returnBuilding.getObjectUUID());
}
return returnBuilding;
}
public static Building getBindBuildingForGuild(PlayerCharacter player) {
Building returnBuilding;
if (player.getGuild() == null || player.getGuild().isEmptyGuild())
return null;
if (player.getGuild().getOwnedCity() == null) {
if (player.getGuild().getNation().getOwnedCity() == null)
return null;
if (player.getGuild().getNation().getOwnedCity().getTOL() == null)
return null;
returnBuilding = player.getGuild().getNation().getOwnedCity().getTOL();
player.setBindBuildingID(returnBuilding.getObjectUUID());
return returnBuilding;
}
if (player.getGuild().getOwnedCity().getTOL() == null)
return null;
returnBuilding = player.getGuild().getOwnedCity().getTOL();
return returnBuilding;
}
public static void __serializeForClientMsg(PlayerCharacter playerCharacter, ByteBufferWriter writer) throws SerializationException {
serializeForClientCommon(playerCharacter, writer, true, false, false, false);
}
public static void serializeForClientMsgLogin(PlayerCharacter playerCharacter, ByteBufferWriter writer) throws SerializationException {
serializeForClientCommon(playerCharacter, writer, true, false, false, false);
}
public static void serializeForClientMsgCommit(PlayerCharacter playerCharacter, ByteBufferWriter writer) throws SerializationException {
serializeForClientCommon(playerCharacter, writer, true, true, false, false);
}
public static void serializeForClientMsgFull(PlayerCharacter playerCharacter, ByteBufferWriter writer) throws SerializationException {
serializeForClientCommon(playerCharacter, writer, false, false, false, false);
}
public static void serializeForClientMsgOtherPlayer(PlayerCharacter playerCharacter, ByteBufferWriter writer) throws SerializationException {
serializeForClientCommon(playerCharacter, writer, false, false, true, false);
}
public static void serializePlayerForClientMsgOtherPlayer(PlayerCharacter playerCharacter, ByteBufferWriter writer, boolean hideAsciiLastName) throws SerializationException {
serializeForClientCommon(playerCharacter, writer, false, false, true, hideAsciiLastName);
}
// TODO what is a Fresh Char?
private static void serializeForClientCommon(PlayerCharacter playerCharacter, ByteBufferWriter writer, boolean loginData, boolean freshChar, boolean otherPlayer, boolean hideAsciiLastName)
throws SerializationException {
/*
* RUNES
*/
// Handle Applied Runes
writer.putInt(0); // Pad
writer.putInt(0); // Pad
// Put number of runes
//We need to send all runes to everyone, otherwise playerCharacter will cause major issues
if (playerCharacter.getPromotionClass() != null)
writer.putInt(playerCharacter.getRunes().size() + 3);
else
writer.putInt(playerCharacter.getRunes().size() + 2);
// Cant forget that Race and baseClass are technically Runes :0
if (playerCharacter.getSubRaceID() != 0) {
writer.putInt(1); // For Race
writer.putInt(0); // Pad
writer.putInt(playerCharacter.getSubRaceID());
writer.putInt(Enum.GameObjectType.Race.ordinal());
writer.putInt(playerCharacter.getSubRaceID());
} else
playerCharacter.getRace().serializeForClientMsg(writer);
if (playerCharacter.getPromotionClass() != null) {
BaseClass.serializeForClientMsg(playerCharacter.getBaseClass(), writer, 2);
PromotionClass.serializeForClientMsg(playerCharacter.getPromotionClass(), writer);
} else
BaseClass.serializeForClientMsg(playerCharacter.getBaseClass(), writer, 3);
// Put runes.
for (CharacterRune rb : playerCharacter.getRunes()) {
CharacterRune.serializeForClientMsg(rb, writer);
}
/*
* STATS
*/
// Number of Stats to follow
writer.putInt(5);
writer.putInt(MBServerStatics.STAT_STR_ID); // Strength ID
writer.putInt(freshChar ? 0 : playerCharacter.getStrMod());
writer.putInt(MBServerStatics.STAT_SPI_ID); // Spirit ID
writer.putInt(freshChar ? 0 : playerCharacter.getSpiMod());
writer.putInt(MBServerStatics.STAT_CON_ID); // Constitution ID
writer.putInt(freshChar ? 0 : playerCharacter.getConMod());
writer.putInt(MBServerStatics.STAT_DEX_ID); // Dexterity ID
writer.putInt(freshChar ? 0 : playerCharacter.getDexMod());
writer.putInt(MBServerStatics.STAT_INT_ID); // Intelligence ID
writer.putInt(freshChar ? 0 : playerCharacter.getIntMod());
// Handle Info
playerCharacter.title._serializeFirstName(writer, playerCharacter.getFirstName());
playerCharacter.title._serializeLastName(writer, playerCharacter.getLastName(), hideAsciiLastName, playerCharacter.asciiLastName);
// Unknown
writer.putInt(0);
writer.putString(ConfigManager.MB_WORLD_NAME.getValue());
writer.putInt(WorldServer.worldMapID);
writer.put((byte) 1); // End Datablock byte
writer.putInt(0); // Unsure, Pad?
writer.putInt(playerCharacter.getObjectType().ordinal());
writer.putInt(playerCharacter.getObjectUUID());
// Perhaps playerCharacter is loc and the next 3 are Facing dir?
writer.putFloat(1); // Unknown
writer.putFloat(playerCharacter.getRace().getRaceType().getScaleHeight()); // Unknown
writer.putFloat(1); // Unknown
writer.putVector3f(playerCharacter.getLoc());
writer.putFloat(playerCharacter.getFaceDir().getRotation()); // Rotation, direction
// facing
// Running trains.
if (otherPlayer) {
CharacterSkill runSkill = playerCharacter.getSkills().get("Running");
if (runSkill == null)
// Logger.log.log(
// LogEventType.WARNING,
// "Failed to find the 'Running Skill' when serializing PlayerCharacter '"
// + playerCharacter.getCombinedName() + "'");
// TODO put int=0 for now.
writer.putInt(0);
else
writer.putInt(runSkill.getNumTrains());
} else
writer.putInt(0);
ArrayList<Item> equipped = playerCharacter.getCharItemManager().getEquippedList();
writer.putInt(equipped.size());
for (Item item : equipped) {
Item._serializeForClientMsg(item, writer);
}
writer.putInt(playerCharacter.getRank());
writer.putInt(playerCharacter.getLevel());
if (loginData)
writer.putInt(5);
else
writer.putInt(playerCharacter.getIsSittingAsInt()); // 5
writer.putInt(playerCharacter.getIsWalkingAsInt()); // 1
writer.putInt(playerCharacter.getIsCombatAsInt()); // 1
writer.putInt(playerCharacter.getIsFlightAsInt()); // 2 or 3
writer.putInt(playerCharacter.getIsLfGroupAsInt()); // 1
// if (loginData)
// writer.putInt(0);
// else
writer.putInt(playerCharacter.getHeadlightsAsInt());
if (playerCharacter.region != null && !loginData) {
Building building = Regions.GetBuildingForRegion(playerCharacter.region);
if (building == null) {
writer.putInt(0);
writer.putInt(0);
} else {
writer.putInt(Enum.GameObjectType.Building.ordinal());
writer.putInt(building.getObjectUUID());
}
} else {
writer.putInt(0);
writer.putInt(0);
}
writer.put((byte) 0);
writer.put((byte) 0);
writer.put((byte) 0);
writer.putInt(0);
writer.put((byte) 0);
writer.put((byte) 0);
writer.put((byte) 0);
// writer.putInt(0);
// writer.putInt(0);
writer.putInt(0);
writer.putInt(0);
writer.putInt(0);
writer.putInt(0);
if (!playerCharacter.isAlive() && otherPlayer) {
writer.putInt(0);
writer.putInt(0);
}
//TODO FIGURE OUT THE REAL SEARLIZATION FOR NEXT 2 SHORTS?
writer.putInt(playerCharacter.getSkinColor()); // Skin Color
writer.putFloat(20);
writer.put((byte) 0); //Unknown
//unknown object
writer.putInt(0);
writer.putInt(0);
//unknown type
writer.putInt(0);
//0x4080 should be the next short here, instead it wraps 0's down their in for loops.. seriously.. who wrote playerCharacter shit.
// playerCharacter aint right!
// ByteBufferUtils.putString(writer, playerCharacter.guild.getName());
// writer.putInt(playerCharacter.getGuild().getUUID());
// ByteBufferUtils.putString(writer, playerCharacter.guild.getNation().getName());
// writer.putInt(playerCharacter.getGuild().getNation().getUUID());
Guild.serializeForClientMsg(playerCharacter.getGuild(), writer, playerCharacter, false);
//Send Tokens for race/class/promotion (disciplines?)
if (playerCharacter.getPromotionClass() != null)
writer.putInt(3);
else
writer.putInt(2);
writer.putInt(playerCharacter.getRace().getToken());
writer.putInt(playerCharacter.getBaseClass().getToken());
if (playerCharacter.getPromotionClass() != null)
writer.putInt(playerCharacter.getPromotionClass().getToken());
writer.putFloat(playerCharacter.getAltitude()); // altitude?
writer.putFloat(playerCharacter.getAltitude()); // altitude?
writer.put((byte) 0); // End Datablock byte
writer.putFloat(playerCharacter.healthMax);
writer.putFloat(playerCharacter.health.get());
writer.put((byte) 0); // End Datablock byte
//size
if (loginData) {
writer.putInt(0);
} else {
int indexPosition = writer.position();
writer.putInt(0); //placeholder for item cnt
int total = 0;
// Logger.info("",""+ playerCharacter.getEffects().size());
for (Effect eff : playerCharacter.getEffects().values()) {
if (eff.getPower() == null && otherPlayer)
continue;
if (eff.getPower() != null && eff.getPower().token == 429506619) // Oblivion's Caress
continue;
if (!eff.serializeForLoad(writer))
continue;
++total;
}
writer.putIntAt(total, indexPosition);
}
if (otherPlayer) {
writer.put((byte) 0); // End Datablock Byte
return;
}
//made up for sendalleffects
//writer.putInt(0); // Pad
//writer.put((byte) 0); // End Datablock byte
writer.putInt(playerCharacter.getUnusedStatPoints());
writer.putInt(playerCharacter.getLevel());
writer.putInt(playerCharacter.getExp() + playerCharacter.getOverFlowEXP());
writer.putFloat(playerCharacter.getManaMax());
writer.putFloat(playerCharacter.mana.get());
writer.putFloat(playerCharacter.getStaminaMax());
writer.putFloat(playerCharacter.stamina.get());
writer.putInt(playerCharacter.getAtrHandOne());
writer.putInt(playerCharacter.getAtrHandTwo());
writer.putInt(playerCharacter.getDefenseRating());
if (MBServerStatics.POWERS_DEBUG) //debug mode, grant lots of trains
writer.putInt(1000);
else
writer.putInt(playerCharacter.trainsAvailable.get());
/*
* Skills
*/
if (loginData)
writer.putInt(0); // Skip skills
else {
writer.putInt(playerCharacter.getSkills().size());
Iterator<String> it = playerCharacter.getSkills().keySet().iterator();
while (it.hasNext()) {
String name = it.next();
CharacterSkill.serializeForClientMsg(playerCharacter.getSkills().get(name), writer);
}
}
/*
* Powers
*/
if (loginData)
writer.putInt(0); // Skip Powers
else if (MBServerStatics.POWERS_DEBUG) //debug mode, grant all powers
PowersManager.testPowers(writer);
else {
writer.putInt(playerCharacter.getPowers().size());
for (CharacterPower sp : playerCharacter.getPowers().values()) {
CharacterPower.serializeForClientMsg(sp, writer);
}
}
/*
* Inventory
*/
if (loginData) {
writer.putInt(0); // Skip Inventory
writer.putInt(playerCharacter.getInventoryCapacity()); // Inventory Capacity
} else {
ArrayList<Item> inv = playerCharacter.getCharItemManager().getInventory(true);
Item.putList(writer, inv, false, playerCharacter.getObjectUUID());
writer.putInt(playerCharacter.getInventoryCapacityRemaining());
}
/*
* Bank
*/
if (loginData) {
writer.putInt(0); // Skip Bank
writer.putInt(AbstractCharacter.getBankCapacity()); // Bank Capacity
} else {
ArrayList<Item> bank = playerCharacter.getCharItemManager().getBank();
Item.putList(writer, bank, false, playerCharacter.getObjectUUID());
writer.putInt(playerCharacter.getBankCapacityRemaining());
}
//load player friends.
if (loginData)
writer.putInt(0);
else {
HashSet<Integer> friendMap = PlayerFriends.PlayerFriendsMap.get(playerCharacter.getObjectUUID());
if (friendMap == null)
writer.putInt(0);
else {
writer.putInt(friendMap.size());
for (int friendID : friendMap) {
PlayerCharacter friend = getFromCache(friendID);
//shouldn't get here, but if null serialize blank friend.
if (friend == null) {
writer.putInt(0);
writer.putInt(0);
writer.putInt(0);
writer.putInt(0);
writer.putInt(0);
} else {
writer.putInt(friend.getObjectType().ordinal());
writer.putInt(friend.getObjectUUID());
writer.putString(friend.getName());
boolean online = SessionManager.getPlayerCharacterByID(friend.getObjectUUID()) != null ? true : false;
writer.putInt(online ? 0 : 1);
writer.putInt(friend.friendStatus.ordinal());
}
}
}
}
writer.putInt(0);
writer.putInt(0);
writer.putInt(0);
writer.putInt(0);
writer.putInt(0);
writer.putInt(0);
writer.putInt(0);
writer.putInt(0);
writer.putInt(0);
writer.putInt(0);
writer.putInt(0);
writer.putInt(0);
writer.putInt(0);
writer.putShort((short) 0);
writer.put((byte) 0);
// playerCharacter is for send self in enter world (full character)
if (!loginData && !freshChar) {
int size = playerCharacter.getRecycleTimers().size();
writer.putInt(size);
if (size > 0)
for (int token : playerCharacter.getRecycleTimers().keySet()) {
JobContainer frtj = playerCharacter.getRecycleTimers().get(token);
long timeLeft = frtj.timeOfExection() - System.currentTimeMillis();
writer.putInt(token);
writer.putInt((int) timeLeft / 1000);
}
DateTime enterWorld = new DateTime(playerCharacter.getTimestamps().get("EnterWorld"));
writer.putDateTime(enterWorld);
writer.putInt(0x49EF1E98); //DUnno what playerCharacter is.
writer.putFloat(DateTime.now().hourOfDay().get()); //daylight in float.
writer.putFloat(6); //interval of light to change per game hour //float
//writer.putInt(1637194901); //playerCharacter is actually an opcode taht is in recordings, no clue what it is, dumped it and it changes nothing
} else {
writer.put((byte) 0); //added to compensate the cooldown check.
//add server up or down
int serverUp = LoginServer.worldServerRunning ? 1 : 0;
if (playerCharacter.getAccount() == null)
serverUp = 0;
if ((playerCharacter.getAccount().status.equals(Enum.AccountStatus.ADMIN) == false) &&
(playerCharacter.getAccount().status.equals(WorldServer.worldAccessLevel) == false))
serverUp = 0;
writer.putInt(serverUp);
writer.putInt(0); // effects, not sure used by players
writer.put((byte) 0); // End Player Datablock
}
}
public static PlayerCharacter generatePCFromCommitNewCharacterMsg(Account a, CommitNewCharacterMsg msg, ClientConnection clientConnection) {
String firstName = msg.getFirstName().trim();
String lastName = msg.getLastName().trim();
if (firstName.length() < 3) {
LoginServerMsgHandler.sendInvalidNameMsg(firstName, lastName, MBServerStatics.INVALIDNAME_FIRSTNAME_MUST_BE_LONGER,
clientConnection);
return null;
}
// Ensure names are below required length
if (firstName.length() > 15 || lastName.length() > 15) {
LoginServerMsgHandler.sendInvalidNameMsg(firstName, lastName, MBServerStatics.INVALIDNAME_FIRSTANDLAST_MUST_BE_SHORTER,
clientConnection);
return null;
}
// Check if firstname is valid
if (MiscUtils.checkIfFirstNameInvalid(firstName)) {
LoginServerMsgHandler.sendInvalidNameMsg(firstName, lastName, MBServerStatics.INVALIDNAME_PLEASE_CHOOSE_ANOTHER_FIRSTNAME,
clientConnection);
return null;
}
// Check if last name is valid
if (MiscUtils.checkIfLastNameInvalid(lastName)) {
LoginServerMsgHandler.sendInvalidNameMsg(firstName, lastName, MBServerStatics.INVALIDNAME_LASTNAME_UNAVAILABLE,
clientConnection);
return null;
}
// Verify Race
int raceID = msg.getRace();
if(raceID == 0)
raceID = 1999;
Race race = Race.getRace(raceID);
if (race == null) {
Logger.info("Invalid RaceID: " + raceID);
return null;
}
// Verify BaseClass Object.
int baseClassID = msg.getBaseClass();
BaseClass baseClass = DbManager.BaseClassQueries.GET_BASE_CLASS(baseClassID);
if (baseClass == null) {
Logger.info("Invalid BaseClasID: " + baseClassID);
return null;
}
// Verify Race/baseClass combo.
boolean valid = false;
for (BaseClass bc : race.getValidBaseClasses()) {
if (bc.getObjectUUID() == baseClassID) {
valid = true;
break;
}
}
if (!valid) {
Logger.info("Invalid BaseClass/Race Combo");
return null;
}
// Verify HairStyle/BeardStyle/SkinColor/HairColor/BeardColor
int hairStyleID = msg.getHairStyle();
int beardStyleID = msg.getBeardStyle();
int skinColorID = msg.getSkinColor();
int hairColorID = msg.getHairColor();
int beardColorID = msg.getBeardColor();
if(raceID != 1999) {
if (!race.isValidHairStyle(hairStyleID)) {
Logger.info("Invalid HairStyleID: " + hairStyleID + " for race: " + race.getName());
return null;
}
if (!race.isValidSkinColor(skinColorID)) {
Logger.info("Invalid skinColorID: " + skinColorID + " for race: " + race.getName());
return null;
}
if (!race.isValidHairColor(hairColorID)) {
Logger.info("Invalid hairColorID: " + hairColorID + " for race: " + race.getName());
return null;
}
if (!race.isValidBeardColor(beardColorID)) {
Logger.info("Invalid beardColorID: " + beardColorID + " for race: " + race.getName());
return null;
}
}
// Get stat modifiers
int strMod = msg.getStrengthMod();
int dexMod = msg.getDexterityMod();
int conMod = msg.getConstitutionMod();
int intMod = msg.getIntelligenceMod();
int spiMod = msg.getSpiritMod();
if (intMod < -5 || dexMod < -5 || conMod < -5 || strMod < -5 || spiMod < -5) {
Logger.error("NEGATIVE STAT CHEAT ATTEMPTED! ACCOUNT: " + a.getUname() + "(" + a.getObjectUUID() + ") IP ADDRESS: " + clientConnection.getClientIpAddress());
return null;
}
// calculate current stats:
short strCur = (short) (race.getStrStart() + baseClass.getStrMod() + strMod);
short dexCur = (short) (race.getDexStart() + baseClass.getDexMod() + dexMod);
short conCur = (short) (race.getConStart() + baseClass.getConMod() + conMod);
short intCur = (short) (race.getIntStart() + baseClass.getIntMod() + intMod);
short spiCur = (short) (race.getSpiStart() + baseClass.getSpiMod() + spiMod);
// calculate max stats:
short strMax = race.getStrMax();
short dexMax = race.getDexMax();
short conMax = race.getConMax();
short intMax = race.getIntMax();
short spiMax = race.getSpiMax();
// Verify not too many runes applied
int numRunes = msg.getNumRunes();
if (numRunes > 16) {
Logger.info("Too many Runes applied");
return null;
}
// Get Runes
// ArrayList<RuneBase> characterRunesUsed = new ArrayList<RuneBase>();
// ArrayList<Byte> subtypesUsed = new ArrayList<Byte>();
int remainingPoints = race.getStartingPoints() - strMod - dexMod - conMod - intMod - spiMod;
int[] characterRunes = msg.getRunes();
HashSet<Byte> usedRunesSubType = new HashSet<>();
HashSet<RuneBase> usedRunes = new HashSet<>();
// So that all the penalties can be added at the end.
ConcurrentHashMap<String, Integer> penalties = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
penalties.put("StrCur", 0);
penalties.put("StrMax", 0);
penalties.put("DexCur", 0);
penalties.put("DexMax", 0);
penalties.put("ConCur", 0);
penalties.put("ConMax", 0);
penalties.put("IntCur", 0);
penalties.put("IntMax", 0);
penalties.put("SpiCur", 0);
penalties.put("SpiMax", 0);
PriorityQueue<Map.Entry<Integer, RuneBase>> orderedRunes = new PriorityQueue<>(14,
new Comparator<Map.Entry<Integer, RuneBase>>() {
@Override
public int compare(Map.Entry<Integer, RuneBase> o1, Map.Entry<Integer, RuneBase> o2) {
return o1.getKey() - o2.getKey();
}
});
// Figure out which Runes we are adding.
for (int i : characterRunes) {
// Zero skip
if (i == 0)
continue;
// Skip the Race and BaseClass runes... already dealt with.
if (i == raceID || i == baseClassID)
continue;
RuneBase runeBase = RuneBase.getRuneBase(i);
// Null check
if (runeBase == null) {
Logger.info("GOM returned NULL RuneBase");
return null;
}
// Validate Rune against Race
if(raceID != 1999) {
if (!race.isAllowedRune(runeBase)) {
Logger.info("Trait Not valid for Race");
return null;
}
}
// Validate BaseClass against Race
if (!baseClass.isAllowedRune(runeBase)) {
Logger.info("Trait Not valid for BaseClass");
return null;
}
int previous_size = usedRunes.size();
int previous_subtype = usedRunesSubType.size();
usedRunes.add(runeBase);
usedRunesSubType.add(runeBase.getSubtype());
// Duplicate Rune check
if (usedRunes.size() <= previous_size) {
Logger.info("Duplicate RuneBase");
return null;
}
// Duplicate Subtype check
if (runeBase.getSubtype() != 0 && usedRunesSubType.size() <= previous_subtype) {
Logger.info("Duplicate RuneBase Subtype");
return null;
}
int maxValue = 0;
// Every attempt is made to load MIN_NEEDED_ATTRIBUTES first.
if (runeBase.getAttrs() != null)
for (RuneBaseAttribute rba : runeBase.getAttrs()) {
if (rba.getAttributeID() == MBServerStatics.RUNE_STR_MIN_NEEDED_ATTRIBUTE_ID
|| rba.getAttributeID() == MBServerStatics.RUNE_DEX_MIN_NEEDED_ATTRIBUTE_ID
|| rba.getAttributeID() == MBServerStatics.RUNE_CON_MIN_NEEDED_ATTRIBUTE_ID
|| rba.getAttributeID() == MBServerStatics.RUNE_INT_MIN_NEEDED_ATTRIBUTE_ID
|| rba.getAttributeID() == MBServerStatics.RUNE_SPI_MIN_NEEDED_ATTRIBUTE_ID) {
maxValue = rba.getModValue();
if (runeBase.getName().equals("Giant's Blood"))
maxValue = 45; // Take care of the Giant's Blood special
// case.
break;
}
}
orderedRunes.add(new AbstractMap.SimpleEntry<>(maxValue, runeBase));
}
while (orderedRunes.size() > 0) {
RuneBase rb = orderedRunes.remove().getValue();
ArrayList<RuneBaseAttribute> attrs = rb.getAttrs();
if (attrs != null)
for (RuneBaseAttribute abr : attrs) {
int attrID = abr.getAttributeID();
int value = abr.getModValue();
switch (attrID) {
case MBServerStatics.RUNE_COST_ATTRIBUTE_ID:
Logger.info("Bought " + rb.getName() + " for " + value + " points. "
+ (remainingPoints - value) + " left.");
if ((remainingPoints - value) >= 0) {
remainingPoints -= value;
continue;
}
Logger.info("Not enough points left");
return null;
case MBServerStatics.RUNE_STR_MIN_NEEDED_ATTRIBUTE_ID:
if (strCur >= value)
continue;
Logger.info("STR fails to meet Rune Minimum --> " + rb.getName());
return null;
case MBServerStatics.RUNE_DEX_MIN_NEEDED_ATTRIBUTE_ID:
if (dexCur >= value)
continue;
Logger.info("DEX fails to meet Rune Minimum --> " + rb.getName());
return null;
case MBServerStatics.RUNE_CON_MIN_NEEDED_ATTRIBUTE_ID:
if (conCur >= value)
continue;
Logger.info("CON fails to meet Rune Minimum --> " + rb.getName());
return null;
case MBServerStatics.RUNE_INT_MIN_NEEDED_ATTRIBUTE_ID:
if (intCur >= value)
continue;
Logger.info("INT fails to meet Rune Minimum --> " + rb.getName());
return null;
case MBServerStatics.RUNE_SPI_MIN_NEEDED_ATTRIBUTE_ID:
if (spiCur >= value)
continue;
Logger.info("SPI fails to meet Rune Minimum --> " + rb.getName());
return null;
case MBServerStatics.RUNE_STR_ATTRIBUTE_ID:
if (value < 0)
penalties.put("StrCur", (penalties.get("StrCur") + value));
else
strCur += value;
continue;
case MBServerStatics.RUNE_DEX_ATTRIBUTE_ID:
if (value < 0)
penalties.put("DexCur", (penalties.get("DexCur") + value));
else
dexCur += value;
continue;
case MBServerStatics.RUNE_CON_ATTRIBUTE_ID:
if (value < 0)
penalties.put("ConCur", (penalties.get("ConCur") + value));
else
conCur += value;
continue;
case MBServerStatics.RUNE_INT_ATTRIBUTE_ID:
if (value < 0)
penalties.put("IntCur", (penalties.get("IntCur") + value));
else
intCur += value;
continue;
case MBServerStatics.RUNE_SPI_ATTRIBUTE_ID:
if (value < 0)
penalties.put("SpiCur", (penalties.get("SpiCur") + value));
else
spiCur += value;
continue;
case MBServerStatics.RUNE_STR_MAX_ATTRIBUTE_ID:
if (value < 0)
penalties.put("StrMax", (penalties.get("StrMax") + value));
else
strMax += value;
continue;
case MBServerStatics.RUNE_DEX_MAX_ATTRIBUTE_ID:
if (value < 0)
penalties.put("DexMax", (penalties.get("DexMax") + value));
else
dexMax += value;
continue;
case MBServerStatics.RUNE_CON_MAX_ATTRIBUTE_ID:
if (value < 0)
penalties.put("ConMax", (penalties.get("ConMax") + value));
else
conMax += value;
continue;
case MBServerStatics.RUNE_INT_MAX_ATTRIBUTE_ID:
if (value < 0)
penalties.put("IntMax", (penalties.get("IntMax") + value));
else
intMax += value;
continue;
case MBServerStatics.RUNE_SPI_MAX_ATTRIBUTE_ID:
if (value < 0)
penalties.put("SpiMax", (penalties.get("SpiMax") + value));
else
spiMax += value;
continue;
default:
Logger.info("Unknown ATTRIBUTE_ID while checking RuneBaseAttributes: " + attrID);
return null;
}
}
}
// Add in all of the penalties.
strCur += penalties.get("StrCur");
strMax += penalties.get("StrMax");
dexCur += penalties.get("DexCur");
dexMax += penalties.get("DexMax");
conCur += penalties.get("ConCur");
conMax += penalties.get("ConMax");
intCur += penalties.get("IntCur");
intMax += penalties.get("IntMax");
spiCur += penalties.get("SpiCur");
spiMax += penalties.get("SpiMax");
int kitID = msg.getKit();
// get the correctKit
int raceClassID;
if(raceID != 1999){
raceClassID = Kit.GetKitIDByRaceClass(raceID, baseClassID);
}else{
raceClassID = Kit.GetKitIDByRaceClass(2011, baseClassID);
}
ArrayList<Kit> allKits = Kit.RaceClassIDMap.get(raceClassID);
Kit kit = null;
for (Kit k : allKits) {
if (k.getKitNumber() == kitID) {
kit = k;
break;
}
}
if (kit == null) {
Logger.info("Unable to find matching kitID: " + kitID);
return null;
}
byte runningTrains = 0;
PlayerCharacter playerCharacter;
//Synchronized block to allow exclusive access when confirming
//uniqueness of FirstName and subsequently saving the new record
//to the database with that FirstName
synchronized (PlayerCharacter.FirstNameLock) {
// Test if FirstName already exists.
// This must be the very last check before calling the
// DB to create the character record
if (DbManager.PlayerCharacterQueries.IS_CHARACTER_NAME_UNIQUE(firstName) == false) {
LoginServerMsgHandler.sendInvalidNameMsg(firstName, lastName, MBServerStatics.INVALIDNAME_FIRSTNAME_UNAVAILABLE,
clientConnection);
return null;
}
if(raceID == 1999){
hairStyleID = 0;
beardStyleID = 0;
skinColorID = 0;
hairColorID = 0;
beardColorID = 0;
}
// Make PC
PlayerCharacter pcWithoutID = new PlayerCharacter(firstName, lastName, (short) strMod, (short) dexMod, (short) conMod,
(short) intMod, (short) spiMod, Guild.getErrantGuild(), runningTrains, a, race, baseClass, (byte) skinColorID, (byte) hairColorID,
(byte) beardColorID, (byte) beardStyleID, (byte) hairStyleID);
try {
playerCharacter = DbManager.PlayerCharacterQueries.ADD_PLAYER_CHARACTER(pcWithoutID);
} catch (Exception e) {
Logger.error("generatePCFromCommitNewCharacterMsg", "An error occurred while saving new PlayerCharacter to DB", e);
return null;
}
if (playerCharacter == null) {
Logger.info("GOM Failed to create PlayerCharacter");
return null;
}
} // END synchronized(FirstNameLock)
// Add creation runes
for (RuneBase rb : usedRunes) {
CharacterRune runeWithoutID = new CharacterRune(rb, playerCharacter.getObjectUUID());
CharacterRune characterRune;
try {
characterRune = DbManager.CharacterRuneQueries.ADD_CHARACTER_RUNE(runeWithoutID);
} catch (Exception e) {
characterRune = null;
}
if (characterRune == null) {
playerCharacter.deactivateCharacter();
Logger.info("GOM Failed to create CharacterRune");
return null;
}
playerCharacter.addRune(characterRune);
}
if (hairStyleID != 0) {
// Create Hair
Item tempHair = new Item(ItemBase.getItemBase(hairStyleID), playerCharacter.getObjectUUID(), Enum.OwnerType.PlayerCharacter,
(byte) 0, (byte) 0, (short) 1, (short) 1, false, false, Enum.ItemContainerType.EQUIPPED,
(byte) MBServerStatics.SLOT_HAIRSTYLE, new ArrayList<>(), "");
Item hair;
try {
hair = DbManager.ItemQueries.ADD_ITEM(tempHair);
} catch (Exception e) {
hair = null;
}
if (hair == null) {
playerCharacter.deactivateCharacter();
Logger.info("GameObjectManager failed to create Hair:" + hairStyleID + " in Slot:"
+ MBServerStatics.SLOT_HAIRSTYLE);
return null;
}
}
if (beardStyleID != 0) {
// Create Beard
Item tempBeard = new Item(ItemBase.getItemBase(beardStyleID), playerCharacter.getObjectUUID(), Enum.OwnerType.PlayerCharacter,
(byte) 0, (byte) 0, (short) 1, (short) 1, false, false, Enum.ItemContainerType.EQUIPPED,
(byte) MBServerStatics.SLOT_BEARDSTYLE, new ArrayList<>(), "");
Item beard;
try {
beard = DbManager.ItemQueries.ADD_ITEM(tempBeard);
} catch (Exception e) {
beard = null;
}
if (beard == null) {
playerCharacter.deactivateCharacter();
Logger.info("GameObjectManager failed to create Beard:" + beardStyleID + " in Slot:"
+ MBServerStatics.SLOT_BEARDSTYLE);
return null;
}
}
// Create items from Kit and equip on character.
try {
kit.equipPCwithKit(playerCharacter);
} catch (Exception e) {
Logger.info("Unable to find KIT ID for Race: " + raceID + "||" + "Class:" + baseClassID);
playerCharacter.deactivateCharacter();
return null;
}
// Get any new skills that belong to the player
playerCharacter.calculateSkills();
a.setLastCharacter(playerCharacter.getObjectUUID());
playerCharacter.getCharItemManager().load();
playerCharacter.activateCharacter();
return playerCharacter;
}
public static boolean isIgnoreListFull() {
return false; //Why were we setting a limit on ignores? -
//return (ignoredPlayerIDs.size() >= MBServerStatics.IGNORE_LIST_MAX);
}
public static boolean isIgnorable() {
return true;
// // if (account == null) return false;
// if (account.getAccessLevel() > 0) {
// return false;
// }
// return true;
}
/**
* @ Initialize player upon creation
*/
public static void initializePlayer(PlayerCharacter player) {
if (player.initialized)
return;
// Logger.info("", " Initializing " + player.getCombinedName());
player.skills = DbManager.CharacterSkillQueries.GET_SKILLS_FOR_CHARACTER(player);
player.powers = player.initializePowers();
if (ConfigManager.serverType.equals(Enum.ServerType.WORLDSERVER))
player.setLoc(player.getBindLoc());
player.endLoc = Vector3fImmutable.ZERO;
//get level based on experience
player.level = (short) Experience.getLevel(player.getExp());
player.setHealth(999999f);
player.mana.set(999999f);
player.stamina.set(999999f);
player.bonuses = new PlayerBonuses(player);
PlayerBonuses.InitializeBonuses(player);
player.setResists(new Resists(player));
player.getCharItemManager().load();
if (ConfigManager.serverType.equals(Enum.ServerType.WORLDSERVER)) {
//CharacterSkill.updateAllBaseAmounts(this);
CharacterPower.grantTrains(player);
// calculate skills. Make sure none are missing.
AbstractCharacter.runBonusesOnLoad(player);
InitializeSkillsOnLoad(player);
//apply all bonuses
player.recalculatePlayerStats(true);
player.trainsAvailable.set(CharacterSkill.getTrainsAvailable(player));
if (player.trainsAvailable.get() < 0)
player.recalculateTrains();
//this.resists.calculateResists(this);
player.newChar = true;
//check current guild valid for player
checkGuildStatus(player);
player.setHealth(player.getHealthMax());
player.mana.set(player.getManaMax());
player.stamina.set(player.getStaminaMax());
} else
player.setBindLoc(Vector3fImmutable.ZERO);
player.initialized = true;
String lastAscii = player.getLastName().replaceAll("[^\\p{ASCII}]", "");
player.asciiLastName = lastAscii.equals(player.getLastName());
}
public static void recalculatePlayerStatsOnLoad(PlayerCharacter pc) {
//calculate base stats
pc.calculateBaseStats();
//calculate base skills
CharacterSkill.updateAllBaseAmounts(pc);
pc.calculateModifiedStats();
//calculate modified skills
CharacterSkill.updateAllModifiedAmounts(pc);
//calculate modified stats
//calculate ATR, damage and defense
pc.calculateAtrDefenseDamage();
//calculate movement bonus
calculateSpeedMod(pc);
// recalculate Max Health/Mana/Stamina
pc.calculateMaxHealthManaStamina();
// recalculate Resists
Resists.calculateResists(pc);
}
public static boolean hideNonAscii() {
return false;
}
public static float getDexPenalty(Item armor) {
if (armor == null)
return 0f;
ItemBase ab = armor.getItemBase();
if (ab == null)
return 0f;
return ab.getDexPenalty();
}
public static float getModifiedAmount(CharacterSkill skill) {
if (skill == null)
return 0f;
return skill.getModifiedAmount();
}
public static void InitializeSkillsOnLoad(PlayerCharacter pc) {
try {
{
//see if any new skills or powers granted
CharacterSkill.calculateSkills(pc);
// calculate granted Trains in powers.
CharacterPower.grantTrains(pc);
//see if any new powers unlocked from previous check
CharacterPower.calculatePowers(pc);
}
} catch (Exception e) {
Logger.error(e.getMessage());
}
}
public static String getFirstName(int tableId) {
PlayerCharacter player;
if (tableId == 0)
return "";
player = (PlayerCharacter) DbManager.getObject(Enum.GameObjectType.PlayerCharacter, tableId);
return player.getFirstName();
}
public static PlayerCharacter getFromCache(int id) {
return (PlayerCharacter) DbManager.getFromCache(Enum.GameObjectType.PlayerCharacter, id);
}
public static PlayerCharacter getByFirstName(String name) {
PlayerCharacter returnPlayer = null;
for (AbstractGameObject ago : DbManager.getList(Enum.GameObjectType.PlayerCharacter)) {
PlayerCharacter cachePlayer = (PlayerCharacter) ago;
if (!name.equalsIgnoreCase(cachePlayer.getFirstName()))
continue;
if (cachePlayer.isDeleted())
continue;
returnPlayer = cachePlayer;
break;
}
return returnPlayer;
}
public static PlayerCharacter getPlayerCharacter(int uuid) {
PlayerCharacter outPlayer;
outPlayer = DbManager.PlayerCharacterQueries.GET_PLAYER_CHARACTER(uuid);
if (outPlayer != null)
return outPlayer;
return (PlayerCharacter) DbManager.getFromCache(Enum.GameObjectType.PlayerCharacter, uuid);
}
public static int GetPlayerRealmTitle(PlayerCharacter player) {
if (player.getGuild().isEmptyGuild())
return 0;
if (!player.getGuild().isGuildLeader(player.getObjectUUID()))
return 0;
if (player.getGuild().getOwnedCity() == null)
return 10;
if (player.getGuild().getOwnedCity().getRealm() == null)
return 10;
if (player.getGuild().getOwnedCity().getRealm().getRulingCity() == null)
return 10;
if (player.getGuild().getOwnedCity().getRealm().getRulingCity().getObjectUUID() != player.getGuild().getOwnedCity().getObjectUUID())
return 10;
int realmTitle = 1;
if (player.getGuild().getSubGuildList() == null || player.getGuild().getSubGuildList().isEmpty())
return 11;
for (Guild subGuild : player.getGuild().getSubGuildList()) {
if (subGuild.getOwnedCity() == null)
continue;
if (subGuild.getOwnedCity().getRealm() == null)
continue;
if (subGuild.getOwnedCity().getRealm().getRulingCity() == null)
continue;
if (subGuild.getOwnedCity().getRealm().getRulingCity().getObjectUUID() != subGuild.getOwnedCity().getObjectUUID())
continue;
realmTitle++;
}
if (realmTitle < 3)
return 11;
else if (realmTitle < 5)
return 12;
else
return 13;
}
public static void UpdateClientPlayerRank(PlayerCharacter pc) {
if (pc == null)
return;
boolean disable = true;
if (disable)
return;
UpdateCharOrMobMessage ucm = new UpdateCharOrMobMessage(pc, 2, pc.getRank());
DispatchMessage.sendToAllInRange(pc, ucm);
}
public static void GroundPlayer(PlayerCharacter groundee) {
if (groundee.getDesiredAltitude() == 0 && groundee.getAltitude() == 0)
return;
groundee.setAltitude(groundee.getAltitude());
groundee.setDesiredAltitude(0);
groundee.setTakeOffTime(System.currentTimeMillis());
ChangeAltitudeMsg msg = ChangeAltitudeMsg.GroundPlayerMsg(groundee);
// force a landing
DispatchMessage.dispatchMsgToInterestArea(groundee, msg, Enum.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
}
public static boolean CanBreathe(PlayerCharacter breather) {
try {
if (isFlying(breather))
return true;
Zone zone = ZoneManager.findSmallestZone(breather.getLoc());
if (zone.getSeaLevel() != 0) {
float localAltitude = breather.getLoc().y;
if (localAltitude + breather.getCharacterHeight() < zone.getSeaLevel() - 2)
return false;
if (breather.isMoving()) {
if (localAltitude + breather.getCharacterHeight() < zone.getSeaLevel())
return false;
}
} else {
if (breather.getLoc().y + breather.getCharacterHeight() < -2)
return false;
if (breather.isMoving()) {
if (breather.getLoc().y + breather.getCharacterHeight() < 0)
return false;
}
}
} catch (Exception e) {
Logger.info(breather.getName() + e);
}
return true;
}
public static boolean enterWater(PlayerCharacter enterer) {
try {
if (isFlying(enterer))
return false;
Zone zone = ZoneManager.findSmallestZone(enterer.getLoc());
if (zone.getSeaLevel() != 0) {
float localAltitude = enterer.getLoc().y + enterer.getCharacterHeight();
if (localAltitude < zone.getSeaLevel())
return true;
} else {
if (enterer.getLoc().y + enterer.getCharacterHeight() < 0)
return true;
}
} catch (Exception e) {
Logger.info(enterer.getName() + e);
}
return false;
}
public static boolean LeaveWater(PlayerCharacter leaver) {
try {
Zone zone = ZoneManager.findSmallestZone(leaver.getLoc());
float leaveWater = leaver.centerHeight;
if (leaver.isMoving())
leaveWater = 1f;
if (zone.getSeaLevel() != 0) {
float localAltitude = leaver.getLoc().y;
if (localAltitude + leaveWater < zone.getSeaLevel())
return false;
} else {
if (leaver.getLoc().y + leaveWater < 0)
return false;
}
} catch (Exception e) {
Logger.info(leaver.getName() + e);
}
return true;
}
public static boolean CanBindToBuilding(PlayerCharacter player, int buildingID) {
if (buildingID == 0)
return false;
Building bindBuilding = BuildingManager.getBuildingFromCache(buildingID);
if (bindBuilding == null)
return false;
if (!BuildingManager.playerCanManage(player, bindBuilding))
return false;
return true;
}
public static void forceRespawn(PlayerCharacter sourcePlayer) throws MsgSendException {
if (sourcePlayer == null)
return;
try {
sourcePlayer.getClientConnection().disconnect();
} catch (Exception e) {
}
}
public static void unboxPlayer(PlayerCharacter player){
String machineID = player.getClientConnection().machineID;
ArrayList<PlayerCharacter> sameMachine = new ArrayList<>();
for(PlayerCharacter pc : SessionManager.getAllActivePlayerCharacters()){
if(!pc.equals(player) && pc.isActive() && pc.isEnteredWorld() && pc.getClientConnection().machineID.equals(machineID)){
sameMachine.add(pc);
}
}
for(PlayerCharacter pc : sameMachine)
pc.isBoxed = true;
player.isBoxed = false;
if(player.containsEffect(1672601862)) {
player.removeEffectBySource(Enum.EffectSourceType.DeathShroud,41,false);
}
}
public static boolean checkIfBoxed(PlayerCharacter player){
if(ConfigManager.MB_WORLD_TESTMODE.getValue().equals("true")) {
return false;
}
try {
String machineID = player.getClientConnection().machineID;
ArrayList<PlayerCharacter> sameMachine = new ArrayList<>();
for (PlayerCharacter pc : SessionManager.getAllActivePlayerCharacters()) {
if (!pc.equals(player) && pc.isActive() && pc.isEnteredWorld() && pc.getClientConnection().machineID.equals(machineID)) {
sameMachine.add(pc);
}
}
boolean boxed = false;
for (PlayerCharacter pc : sameMachine)
if (!pc.isBoxed)
boxed = true;
return boxed;
}catch(Exception e){
return false;
}
}
public static void setGuildTitle(PlayerCharacter playerCharacter, int value) {
if (GuildStatusController.getTitle(playerCharacter.getGuildStatus()) == value)
return;
DbManager.PlayerCharacterQueries.SET_GUILD_TITLE(playerCharacter, value);
GuildStatusController.setTitle(playerCharacter.getGuildStatus(), value);
}
public static void setFullMember(PlayerCharacter playerCharacter, boolean value) {
if (GuildStatusController.isFullMember(playerCharacter.getGuildStatus()) == value)
return;
DbManager.PlayerCharacterQueries.SET_FULL_MEMBER(playerCharacter, value);
GuildStatusController.setFullMember(playerCharacter.getGuildStatus(), value);
}
public static void setRecruiter(PlayerCharacter playerCharacter, boolean value) {
if (GuildStatusController.isRecruiter(playerCharacter.getGuildStatus()) == value)
return;
DbManager.PlayerCharacterQueries.SET_RECRUITER(playerCharacter, value);
GuildStatusController.setRecruiter(playerCharacter.getGuildStatus(), value);
}
public static void setTaxCollector(PlayerCharacter playerCharacter, boolean value) {
if (GuildStatusController.isTaxCollector(playerCharacter.getGuildStatus()) == value)
return;
DbManager.PlayerCharacterQueries.SET_TAX_COLLECTOR(playerCharacter, value);
GuildStatusController.setTaxCollector(playerCharacter.getGuildStatus(), value);
}
public static void setInnerCouncil(PlayerCharacter playerCharacter, boolean value) {
// dont update if its the same.
if (GuildStatusController.isInnerCouncil(playerCharacter.getGuildStatus()) == value)
return;
DbManager.PlayerCharacterQueries.SET_INNERCOUNCIL(playerCharacter, value);
GuildStatusController.setInnerCouncil(playerCharacter.getGuildStatus(), value);
}
public static void setGuildLeader(PlayerCharacter playerCharacter, boolean value) {
if (GuildStatusController.isGuildLeader(playerCharacter.getGuildStatus()) == value)
return;
GuildStatusController.setGuildLeader(playerCharacter.getGuildStatus(), value);
if (value == true) {
setInnerCouncil(playerCharacter, true);
setFullMember(playerCharacter, true);
}
}
//END -> Guild Status Interface
public static void resetGuildStatuses(PlayerCharacter playerCharacter) {
setInnerCouncil(playerCharacter, false);
setFullMember(playerCharacter, false);
setGuildTitle(playerCharacter, 0);
setTaxCollector(playerCharacter, false);
setRecruiter(playerCharacter, false);
setGuildLeader(playerCharacter, false);
}
public static void setEnteredWorld(PlayerCharacter playerCharacter, boolean enteredWorld) {
playerCharacter.enteredWorld = enteredWorld;
}
public static boolean isLastSwimming(PlayerCharacter playerCharacter) {
return playerCharacter.lastSwimming;
}
public static void teleport(PlayerCharacter playerCharacter, final Vector3fImmutable targetLoc) {
Regions targetRegion = Regions.GetRegionForTeleport(targetLoc);
playerCharacter.locationLock.writeLock().lock();
try {
MovementManager.translocate(playerCharacter, targetLoc, targetRegion);
} catch (Exception e) {
Logger.error(e);
} finally {
playerCharacter.locationLock.writeLock().unlock();
}
}
public static float getBargain(PlayerCharacter playerCharacter) {
float bargain = 0;
CharacterSkill bargainSkill = playerCharacter.getSkills().get(Enum.CharacterSkills.Bargaining.name());
if (bargainSkill != null)
bargain = bargainSkill.getModifiedAmountBeforeMods();
if (bargain > 100)
bargain = 100;
bargain *= .01f;
return bargain;
}
public static boolean isDirtyLoad(PlayerCharacter playerCharacter) {
boolean dirtyValue;
playerCharacter.dirtyLock.readLock().lock();
dirtyValue = playerCharacter.dirtyLoad;
playerCharacter.dirtyLock.readLock().unlock();
return dirtyValue;
}
public static void setDirtyLoad(PlayerCharacter playerCharacter, boolean dirtyLoad) {
playerCharacter.dirtyLock.writeLock().lock();
playerCharacter.dirtyLoad = dirtyLoad;
playerCharacter.dirtyLock.writeLock().unlock();
}
public static void ResetLevel(PlayerCharacter playerCharacter, short targetLevel) {
if (targetLevel > 13) {
ChatManager.chatSystemError(playerCharacter, "Please choose a level between 1 and 13.");
return;
}
playerCharacter.promotionClass = null;
if (targetLevel > 10) {
playerCharacter.level = 10;
playerCharacter.exp = Experience.getBaseExperience(11);
int maxEXP = Experience.getBaseExperience(targetLevel); //target level exp;
playerCharacter.setOverFlowEXP(maxEXP - playerCharacter.exp);
} else {
playerCharacter.level = targetLevel;
playerCharacter.exp = Experience.getBaseExperience(playerCharacter.level);
playerCharacter.setOverFlowEXP(0);
}
for (CharacterSkill skill : playerCharacter.getSkills().values()) {
skill.reset(playerCharacter, true);
}
for (CharacterPower power : playerCharacter.getPowers().values()) {
power.reset(playerCharacter);
}
playerCharacter.recalculatePlayerStats(playerCharacter.initialized);
playerCharacter.recalculate();
ChatManager.chatSystemInfo(playerCharacter, "Character reset to " + targetLevel + ". All training points have been refunded. Relog to update changes on client.");
}
public static void updateSkillsAndPowersToDatabase(PlayerCharacter playerCharacter) {
if (playerCharacter.skills != null)
for (CharacterSkill skill : playerCharacter.skills.values()) {
DbManager.CharacterSkillQueries.UPDATE_TRAINS(skill);
if (playerCharacter.powers != null)
for (CharacterPower power : playerCharacter.powers.values()) {
DbManager.CharacterPowerQueries.UPDATE_TRAINS(power);
}
}
}
public static boolean commandSiegeMinion(PlayerCharacter playerCharacter, Mob toCommand) {
if (!toCommand.isSiege())
return false;
if (toCommand.isPet() || !toCommand.isAlive())
return false;
if (toCommand.getGuild().getNation() != playerCharacter.getGuild().getNation())
return false;
if (playerCharacter.getPet() != null) {
Mob currentPet = playerCharacter.getPet();
if (!currentPet.isSiege()) {
currentPet.setCombatTarget(null);
if (currentPet.getParentZone() != null)
currentPet.getParentZone().zoneMobSet.remove(currentPet);
try {
currentPet.clearEffects();
} catch (Exception e) {
Logger.error(e.getMessage());
}
currentPet.playerAgroMap.clear();
WorldGrid.RemoveWorldObject(currentPet);
DbManager.removeFromCache(currentPet);
} else if (currentPet.isSiege()) {
currentPet.agentType = Enum.AIAgentType.MOBILE;
currentPet.setOwner(null);
currentPet.setCombatTarget(null);
if (currentPet.isAlive())
WorldGrid.updateObject(currentPet);
}
}
toCommand.setPet(playerCharacter, false);
playerCharacter.setPet(toCommand);
toCommand.setCombatTarget(null);
PetMsg petMsg = new PetMsg(6, toCommand);
Dispatch dispatch = Dispatch.borrow(playerCharacter, petMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
if (toCommand.isAlive())
WorldGrid.updateObject(toCommand);
return true;
}
public static boolean isFlying(PlayerCharacter playerCharacter) {
return playerCharacter.getAltitude() > 0;
}
public static boolean isSwimming(PlayerCharacter playerCharacter) {
// If char is flying they aren't quite swimming
try {
if (isFlying(playerCharacter))
return false;
Zone zone = ZoneManager.findSmallestZone(playerCharacter.getLoc());
if (zone.getSeaLevel() != 0) {
float localAltitude = playerCharacter.getLoc().y + playerCharacter.centerHeight;
if (localAltitude < zone.getSeaLevel())
return true;
} else {
if (playerCharacter.getLoc().y + playerCharacter.centerHeight < 0)
return true;
}
} catch (Exception e) {
Logger.info(playerCharacter.getName() + e);
}
return false;
}
public static boolean hasBoon(PlayerCharacter playerCharacter) {
for (Effect eff : playerCharacter.getEffects().values()) {
if (eff.getPowerToken() == -587743986 || eff.getPowerToken() == -1660519801 || eff.getPowerToken() == -1854683250)
return true;
}
return false;
}
public static void updateBlessingMessage(PlayerCharacter playerCharacter) {
if (playerCharacter.getTimeStamp("RealmClaim") > System.currentTimeMillis())
return;
int count = 0;
for (Effect eff : playerCharacter.getEffects().values()) {
if (eff.getPowerToken() == -587743986 || eff.getPowerToken() == -1660519801 || eff.getPowerToken() == -1854683250)
count++;
}
if (count > 0) {
playerCharacter.getTimestamps().put("RealmClaim", DateTime.now().plusMinutes(3).getMillis());
for (PlayerCharacter toSend : SessionManager.getAllActivePlayerCharacters()) {
ChatManager.chatSystemInfo(toSend, playerCharacter.getCombinedName() + " is seeking to claim a realm and already has " + count + " blessngs!");
}
}
}
public static void respawn(PlayerCharacter playerCharacter, boolean setAlive, boolean enterWorld, boolean makeCorpse) {
// Recalculate everything
if(playerCharacter.getTimestamps().containsKey("DeathTime"))
playerCharacter.getTimestamps().remove("DeathTime");
playerCharacter.recalculatePlayerStats(true);
playerCharacter.setCombat(false);
// Set Health to 1/4 max
Corpse corpse = null;
if (makeCorpse) {
try {
corpse = Corpse.makeCorpse(playerCharacter, enterWorld);
} catch (Exception e) {
Logger.error(e);
}
//if we're not making corpse, just purge inventory. used for characters dead while logged out.
}
if (!setAlive) {
if (corpse == null && makeCorpse) {
Logger.error("Corpse not created.");
} else {
if (makeCorpse && corpse != null) {
InterestManager.forceLoad(corpse);
}
}
return;
}
playerCharacter.setHealth((float) (playerCharacter.healthMax * .25));
playerCharacter.isAlive.set(true);
// Put player in safe mode
// Teleport the player to his bind loc
// or to a ruin as apporpriate.
Building bindBuilding = BuildingManager.getBuildingFromCache(playerCharacter.getBindBuildingID());
if (enterWorld) {
playerCharacter.stopMovement(playerCharacter.getBindLoc());
} else if (bindBuilding != null) {
if (bindBuilding.getParentZone().equals(ZoneManager.findSmallestZone(playerCharacter.getLoc())))
teleport(playerCharacter, Enum.Ruins.getRandomRuin().getLocation());
else
teleport(playerCharacter, playerCharacter.getBindLoc());
} else // no bind building found for player, teleport to ruins.
teleport(playerCharacter, Enum.Ruins.getRandomRuin().getLocation());
playerCharacter.lastUpdateTime = System.currentTimeMillis();
playerCharacter.lastStamUpdateTime = System.currentTimeMillis();
playerCharacter.update(false);
PowersManager.applyPower(playerCharacter, playerCharacter, Vector3fImmutable.ZERO, -1661758934, 40, false);
if (corpse == null && makeCorpse) {
Logger.error("Corpse not created.");
} else {
if (makeCorpse && corpse != null) {
InterestManager.forceLoad(corpse);
}
}
}
public static Effect addCityEffect(PlayerCharacter playerCharacter, String name, EffectsBase eb, int trains, int duration, boolean onEnter, City city) {
JobContainer jc = null;
if (onEnter) {
NoTimeJob ntj = new NoTimeJob(playerCharacter, name, eb, trains); //infinite timer
ntj.setEffectSourceType(city.getObjectType().ordinal());
ntj.setEffectSourceID(city.getObjectUUID());
jc = new JobContainer(ntj);
} else {
FinishSpireEffectJob fsej = new FinishSpireEffectJob(playerCharacter, name, eb, trains);
fsej.setEffectSourceType(city.getObjectType().ordinal());
fsej.setEffectSourceID(city.getObjectUUID());
jc = JobScheduler.getInstance().scheduleJob(fsej, duration);
}
if (playerCharacter.effects.get(name) != null)
playerCharacter.effects.get(name).cancelJob();
Effect eff = new Effect(jc, eb, trains);
playerCharacter.effects.put(name, eff);
playerCharacter.applyAllBonuses();
eff.sendSpireEffect(playerCharacter.getClientConnection(), onEnter);
return eff;
}
public static void addStr(PlayerCharacter playerCharacter, int amount) {
boolean worked = false;
short newStr = (short) 0;
while (!worked) {
if ((playerCharacter.getUnusedStatPoints() - playerCharacter.trainedStatPoints) <= 0)
return;
newStr = (short) (playerCharacter.statStrBase + amount);
short mod = (short) playerCharacter.strMod.get();
short newStrMod = (short) (mod + amount);
if (newStr > playerCharacter.statStrMax) {
newStrMod += (playerCharacter.statStrMax - newStr);
newStr = playerCharacter.statStrMax;
}
worked = playerCharacter.strMod.compareAndSet(mod, newStrMod);
}
playerCharacter.trainedStatPoints++;
playerCharacter.statStrBase = newStr;
playerCharacter.addDatabaseJob("Stats", MBServerStatics.THIRTY_SECONDS);
playerCharacter.applyBonuses();
playerCharacter.calculateSkills();
}
public static void addDex(PlayerCharacter playerCharacter, int amount) {
boolean worked = false;
short newDex = (short) 0;
while (!worked) {
if ((playerCharacter.getUnusedStatPoints() - playerCharacter.trainedStatPoints) <= 0)
return;
newDex = (short) (playerCharacter.statDexBase + amount);
short mod = (short) playerCharacter.dexMod.get();
short newDexMod = (short) (mod + amount);
if (newDex > playerCharacter.statDexMax) {
newDexMod += (playerCharacter.statDexMax - newDex);
newDex = playerCharacter.statDexMax;
}
worked = playerCharacter.dexMod.compareAndSet(mod, newDexMod);
}
playerCharacter.trainedStatPoints++;
playerCharacter.statDexBase = newDex;
playerCharacter.addDatabaseJob("Stats", MBServerStatics.THIRTY_SECONDS);
playerCharacter.applyBonuses();
playerCharacter.calculateSkills();
}
public static void addCon(PlayerCharacter playerCharacter, int amount) {
boolean worked = false;
short newCon = (short) 0;
while (!worked) {
if ((playerCharacter.getUnusedStatPoints() - playerCharacter.trainedStatPoints) <= 0)
return;
newCon = (short) (playerCharacter.statConBase + amount);
short mod = (short) playerCharacter.conMod.get();
short newConMod = (short) (mod + amount);
if (newCon > playerCharacter.statConMax) {
newConMod += (playerCharacter.statConMax - newCon);
newCon = playerCharacter.statConMax;
}
worked = playerCharacter.conMod.compareAndSet(mod, newConMod);
}
playerCharacter.trainedStatPoints++;
playerCharacter.statConBase = newCon;
playerCharacter.addDatabaseJob("Stats", MBServerStatics.THIRTY_SECONDS);
playerCharacter.applyBonuses();
playerCharacter.calculateSkills();
}
public static void addInt(PlayerCharacter playerCharacter, int amount) {
boolean worked = false;
short newInt = (short) 0;
while (!worked) {
if ((playerCharacter.getUnusedStatPoints() - playerCharacter.trainedStatPoints) <= 0)
return;
newInt = (short) (playerCharacter.statIntBase + amount);
short mod = (short) playerCharacter.intMod.get();
short newIntMod = (short) (mod + amount);
if (newInt > playerCharacter.statIntMax) {
newIntMod += (playerCharacter.statIntMax - newInt);
newInt = playerCharacter.statIntMax;
}
worked = playerCharacter.intMod.compareAndSet(mod, newIntMod);
}
playerCharacter.trainedStatPoints++;
playerCharacter.statIntBase = newInt;
playerCharacter.addDatabaseJob("Stats", MBServerStatics.THIRTY_SECONDS);
playerCharacter.applyBonuses();
playerCharacter.calculateSkills();
}
public static void addSpi(PlayerCharacter playerCharacter, int amount) {
boolean worked = false;
short newSpi = (short) 0;
while (!worked) {
if ((playerCharacter.getUnusedStatPoints() - playerCharacter.trainedStatPoints) <= 0)
return;
newSpi = (short) (playerCharacter.statSpiBase + amount);
short mod = (short) playerCharacter.spiMod.get();
short newSpiMod = (short) (mod + amount);
if (newSpi > playerCharacter.statSpiMax) {
newSpiMod += (playerCharacter.statSpiMax - newSpi);
newSpi = playerCharacter.statSpiMax;
}
worked = playerCharacter.spiMod.compareAndSet(mod, newSpiMod);
}
playerCharacter.trainedStatPoints++;
playerCharacter.statSpiBase = newSpi;
playerCharacter.addDatabaseJob("Stats", MBServerStatics.THIRTY_SECONDS);
playerCharacter.applyBonuses();
playerCharacter.calculateSkills();
}
public static boolean refineStr(PlayerCharacter playerCharacter) {
boolean worked = false;
short newStr = (short) 0;
while (!worked) {
newStr = (short) (playerCharacter.statStrBase - 1);
short mod = (short) playerCharacter.strMod.get();
if (mod == 0)
return false;
short newStrMod = (short) (mod - 1);
if (newStr < playerCharacter.statStrMin)
return false;
if (!canRefineLower(playerCharacter, MBServerStatics.STAT_STR_ID))
return false;
worked = playerCharacter.strMod.compareAndSet(mod, newStrMod);
}
playerCharacter.trainedStatPoints--;
playerCharacter.statStrBase = newStr;
playerCharacter.addDatabaseJob("Stats", MBServerStatics.THIRTY_SECONDS);
playerCharacter.applyBonuses();
playerCharacter.calculateSkills();
return true;
}
public static boolean refineDex(PlayerCharacter playerCharacter) {
boolean worked = false;
short newDex = (short) 0;
while (!worked) {
newDex = (short) (playerCharacter.statDexBase - 1);
short mod = (short) playerCharacter.dexMod.get();
if (mod == 0)
return false;
short newDexMod = (short) (mod - 1);
if (newDex < playerCharacter.statDexMin)
return false;
if (!canRefineLower(playerCharacter, MBServerStatics.STAT_DEX_ID))
return false;
worked = playerCharacter.dexMod.compareAndSet(mod, newDexMod);
}
playerCharacter.trainedStatPoints--;
playerCharacter.statDexBase = newDex;
playerCharacter.addDatabaseJob("Stats", MBServerStatics.THIRTY_SECONDS);
playerCharacter.applyBonuses();
playerCharacter.calculateSkills();
return true;
}
public static boolean refineCon(PlayerCharacter playerCharacter) {
boolean worked = false;
short newCon = (short) 0;
while (!worked) {
newCon = (short) (playerCharacter.statConBase - 1);
short mod = (short) playerCharacter.conMod.get();
if (mod == 0)
return false;
short newConMod = (short) (mod - 1);
if (newCon < playerCharacter.statConMin)
return false;
if (!canRefineLower(playerCharacter, MBServerStatics.STAT_CON_ID))
return false;
worked = playerCharacter.conMod.compareAndSet(mod, newConMod);
}
playerCharacter.trainedStatPoints--;
playerCharacter.statConBase = newCon;
playerCharacter.addDatabaseJob("Stats", MBServerStatics.THIRTY_SECONDS);
playerCharacter.applyBonuses();
playerCharacter.calculateSkills();
return true;
}
public static boolean refineInt(PlayerCharacter playerCharacter, RefineMsg msg) {
boolean worked = false;
short newInt = (short) 0;
while (!worked) {
newInt = (short) (playerCharacter.statIntBase - 1);
short mod = (short) playerCharacter.intMod.get();
if (mod == 0)
return false;
short newIntMod = (short) (mod
- 1);
if (newInt < playerCharacter.statIntMin)
return false;
if (!canRefineLower(playerCharacter, MBServerStatics.STAT_INT_ID))
return false;
worked = playerCharacter.intMod.compareAndSet(mod, newIntMod);
}
playerCharacter.trainedStatPoints--;
playerCharacter.statIntBase = newInt;
playerCharacter.addDatabaseJob("Stats", MBServerStatics.THIRTY_SECONDS);
verifySkillMax(playerCharacter, msg);
playerCharacter.applyBonuses();
playerCharacter.calculateSkills();
return true;
}
public static boolean refineSpi(PlayerCharacter playerCharacter) {
boolean worked = false;
short newSpi = (short) 0;
while (!worked) {
newSpi = (short) (playerCharacter.statSpiBase - 1);
short mod = (short) playerCharacter.spiMod.get();
if (mod == 0)
return false;
short newSpiMod = (short) (mod - 1);
if (newSpi < playerCharacter.statSpiMin)
return false;
if (!canRefineLower(playerCharacter, MBServerStatics.STAT_SPI_ID))
return false;
worked = playerCharacter.spiMod.compareAndSet(mod, newSpiMod);
}
playerCharacter.trainedStatPoints--;
playerCharacter.statSpiBase = newSpi;
playerCharacter.addDatabaseJob("Stats", MBServerStatics.THIRTY_SECONDS);
playerCharacter.applyBonuses();
playerCharacter.calculateSkills();
return true;
}
//this verifies stat doesn't fall too low to keep runes applied while refining
private static boolean canRefineLower(PlayerCharacter playerCharacter, int stat) {
for (CharacterRune cr : playerCharacter.getRunes()) {
if (cr != null) {
RuneBase rb = cr.getRuneBase();
if (rb != null) {
ArrayList<RuneBaseAttribute> attrs = rb.getAttrs();
if (attrs != null)
for (RuneBaseAttribute rba : attrs) {
int attrID = rba.getAttributeID();
int mod = rba.getModValue();
if (stat == MBServerStatics.STAT_STR_ID) {
if (attrID == MBServerStatics.RUNE_STR_MIN_NEEDED_ATTRIBUTE_ID && ((int) playerCharacter.statStrBase <= mod))
return false;
} else if (stat == MBServerStatics.STAT_DEX_ID) {
if (attrID == MBServerStatics.RUNE_DEX_MIN_NEEDED_ATTRIBUTE_ID && ((int) playerCharacter.statDexBase <= mod))
return false;
} else if (stat == MBServerStatics.STAT_CON_ID) {
if (attrID == MBServerStatics.RUNE_CON_MIN_NEEDED_ATTRIBUTE_ID && ((int) playerCharacter.statConBase <= mod))
return false;
} else if (stat == MBServerStatics.STAT_INT_ID) {
if (attrID == MBServerStatics.RUNE_INT_MIN_NEEDED_ATTRIBUTE_ID && ((int) playerCharacter.statIntBase <= mod))
return false;
} else if (stat == MBServerStatics.STAT_SPI_ID)
if (attrID == MBServerStatics.RUNE_SPI_MIN_NEEDED_ATTRIBUTE_ID && ((int) playerCharacter.statSpiBase <= mod))
return false;
}
}
}
}
return true;
}
//checked on refining int to see if skills need refined also.
private static void verifySkillMax(PlayerCharacter playerCharacter, RefineMsg msg) {
ConcurrentHashMap<String, CharacterSkill> skills = playerCharacter.getSkills();
//make sure no skills are over the max number of trains
int maxTrains = CharacterSkill.getMaxTrains((int) playerCharacter.statIntBase);
RefineMsg rm = new RefineMsg(msg.getNpcType(), msg.getNpcID(), 0, 0);
for (CharacterSkill skill : skills.values()) {
while (skill.getNumTrains() > maxTrains) {
boolean worked = skill.refine(playerCharacter, false); //refine skill, do not recalculate everything
if (worked) {
rm.setToken(skill.getToken());
Dispatch dispatch = Dispatch.borrow(playerCharacter, rm);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
} else {
Logger.error("Failed to force refine of skill " + skill.getObjectUUID() + " by character " + playerCharacter.getObjectUUID());
break;
}
}
}
}
public static int getClassToken(PlayerCharacter playerCharacter) {
if (playerCharacter.promotionClass != null)
return playerCharacter.promotionClass.getToken();
else if (playerCharacter.getBaseClass() != null)
return playerCharacter.getBaseClass().getToken();
return 0;
}
public static int getRaceToken(PlayerCharacter playerCharacter) {
if (playerCharacter.getRace() == null)
return 0;
return playerCharacter.getRace().getToken();
}
public static synchronized void grantXP(PlayerCharacter playerCharacter, int xp) {
if(playerCharacter.promotionClass == null && playerCharacter.level == 10){
playerCharacter.setOverFlowEXP(0);
playerCharacter.update(false);
playerCharacter.incVer();
playerCharacter.recalculate();
playerCharacter.calculateMaxHealthManaStamina();
playerCharacter.setHealth(playerCharacter.healthMax);
playerCharacter.mana.set(playerCharacter.getManaMax());
playerCharacter.stamina.set(playerCharacter.getStaminaMax());
//LoadJob.reloadCharacter(this);
DbManager.PlayerCharacterQueries.SET_PROPERTY(playerCharacter, "char_experience", playerCharacter.exp);
// updateDatabase();
DbManager.AccountQueries.INVALIDATE_LOGIN_CACHE(playerCharacter.getObjectUUID(), "character");
return;
}
// Stop players from getting experience past the cap
if (playerCharacter.exp + xp >= Experience.getBaseExperience(MBServerStatics.LEVELCAP))
xp = Experience.getBaseExperience(MBServerStatics.LEVELCAP) - playerCharacter.exp + 1;
if (xp == 0)
xp = 1;
boolean isNewLevel = false;
boolean charReloadRequired = false;
int remainingXP = xp;
int neededXP = 0;
// handle players that have not yet promoted.
ClientConnection origin = playerCharacter.getClientConnection();
//not promoted at level 10, start checking for negative EXP
if (playerCharacter.promotionClass == null && playerCharacter.getLevel() == 10) {
if (playerCharacter.getExp() == Experience.getBaseExperience(11)) {
if (playerCharacter.overFlowEXP == 110000)
return;
if (playerCharacter.overFlowEXP + xp > 110000) {
remainingXP = 110000 - playerCharacter.overFlowEXP;
playerCharacter.overFlowEXP = 110000;
} else {
playerCharacter.overFlowEXP += remainingXP;
}
GrantExperienceMsg gem = new GrantExperienceMsg(playerCharacter, remainingXP);
Dispatch dispatch = Dispatch.borrow(playerCharacter, gem);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
playerCharacter.addDatabaseJob("EXP", MBServerStatics.FIVE_MINUTES);
return;
//didnt reach level 11 EXP to start overflow, add exp normally till we get here;
} else {
//Player exp begins negative exp, add remaing exp after level 11 to overflow
if (playerCharacter.getExp() + remainingXP >= Experience.getBaseExperience(11)) {
playerCharacter.overFlowEXP = remainingXP - (Experience.getBaseExperience(11) - playerCharacter.getExp());
playerCharacter.exp = Experience.getBaseExperience(11);
GrantExperienceMsg grantExperienceMsg = new GrantExperienceMsg(playerCharacter, remainingXP);
Dispatch dispatch = Dispatch.borrow(playerCharacter, grantExperienceMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
playerCharacter.addDatabaseJob("EXP", MBServerStatics.FIVE_MINUTES);
return;
//didnt reach negative exp yet, just do normal exp gain.
} else {
playerCharacter.exp += remainingXP;
GrantExperienceMsg grantExperienceMsg = new GrantExperienceMsg(playerCharacter, remainingXP);
remainingXP = 0;
Dispatch dispatch = Dispatch.borrow(playerCharacter, grantExperienceMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
playerCharacter.addDatabaseJob("EXP", MBServerStatics.FIVE_MINUTES);
return;
}
}
}
if (playerCharacter.overFlowEXP > 0) {
int nextLevel;
if (playerCharacter.level == 10)
nextLevel = 12;
else
nextLevel = playerCharacter.level + 2;
int nextLevelEXP = Experience.getBaseExperience(nextLevel);
// if overflow > 0, u have level 11 experience + overflow, but level is still 10 due to just promoting.
//Use level + 2 experience for next level.
playerCharacter.overFlowEXP += 1;
if (playerCharacter.getExp() + playerCharacter.overFlowEXP >= nextLevelEXP) {
int expToNextLevel = nextLevelEXP - playerCharacter.getExp();
playerCharacter.overFlowEXP -= expToNextLevel;
playerCharacter.exp += expToNextLevel;
playerCharacter.level++;
charReloadRequired = true;
GrantExperienceMsg grantExperienceMsg = new GrantExperienceMsg(playerCharacter, 1);
Dispatch dispatch = Dispatch.borrow(playerCharacter, grantExperienceMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
SetObjectValueMsg upm = new SetObjectValueMsg(playerCharacter, 9);
DispatchMessage.dispatchMsgToInterestArea(playerCharacter, upm, Enum.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false);
checkGuildStatus(playerCharacter);
playerCharacter.addDatabaseJob("EXP", MBServerStatics.FIVE_MINUTES);
// double overflow exp used up, remaining overflow will just add to level + 1.
} else if (playerCharacter.getExp() + playerCharacter.overFlowEXP >= Experience.getBaseExperience(playerCharacter.level + 1)) {
int nextExperience = Experience.getBaseExperience(playerCharacter.level + 1) + playerCharacter.overFlowEXP;
playerCharacter.exp = nextExperience;
playerCharacter.level++;
charReloadRequired = true;
playerCharacter.overFlowEXP = 0;
GrantExperienceMsg grantExperienceMsg = new GrantExperienceMsg(playerCharacter, 1);
Dispatch dispatch = Dispatch.borrow(playerCharacter, grantExperienceMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
SetObjectValueMsg upm = new SetObjectValueMsg(playerCharacter, 9);
DispatchMessage.dispatchMsgToInterestArea(playerCharacter, upm, Enum.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false);
checkGuildStatus(playerCharacter);
playerCharacter.addDatabaseJob("EXP", MBServerStatics.FIVE_MINUTES);
}
} else {
// Hand out each Level one at a time.
isNewLevel = Experience.getLevel(playerCharacter.exp + remainingXP) > playerCharacter.getLevel();
if (isNewLevel) {
neededXP = Experience.getBaseExperience(playerCharacter.getLevel() + 1) - playerCharacter.exp;
charReloadRequired = true;
playerCharacter.exp += neededXP;
playerCharacter.level++;
GrantExperienceMsg grantExperienceMsg = new GrantExperienceMsg(playerCharacter, neededXP);
Dispatch dispatch = Dispatch.borrow(playerCharacter, grantExperienceMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
remainingXP -= neededXP;
//Send newLevel.
SetObjectValueMsg upm = new SetObjectValueMsg(playerCharacter, 9);
DispatchMessage.dispatchMsgToInterestArea(playerCharacter, upm, Enum.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false);
checkGuildStatus(playerCharacter);
} else {
playerCharacter.exp += remainingXP;
GrantExperienceMsg grantExperienceMsg = new GrantExperienceMsg(playerCharacter, remainingXP);
remainingXP = 0;
Dispatch dispatch = Dispatch.borrow(playerCharacter, grantExperienceMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
playerCharacter.addDatabaseJob("EXP", MBServerStatics.FIVE_MINUTES);
}
}
if (charReloadRequired) {
playerCharacter.update(false);
playerCharacter.incVer();
playerCharacter.recalculate();
playerCharacter.calculateMaxHealthManaStamina();
playerCharacter.setHealth(playerCharacter.healthMax);
playerCharacter.mana.set(playerCharacter.getManaMax());
playerCharacter.stamina.set(playerCharacter.getStaminaMax());
//LoadJob.reloadCharacter(this);
DbManager.PlayerCharacterQueries.SET_PROPERTY(playerCharacter, "char_experience", playerCharacter.exp);
// updateDatabase();
DbManager.AccountQueries.INVALIDATE_LOGIN_CACHE(playerCharacter.getObjectUUID(), "character");
}
}
//This checks if a player meets the requirements to be in current guild.
public static void checkGuildStatus(PlayerCharacter playerCharacter) {
Guild g = playerCharacter.guild;
if (g == null || g.isEmptyGuild() || GuildStatusController.isGuildLeader(playerCharacter.getGuildStatus()))
return;
//check level
int curLevel = (int) playerCharacter.getPCLevel();
if (curLevel < g.getRepledgeMin() || curLevel >= g.getRepledgeKick()) {
//TODO kick from guild
g.removePlayer(playerCharacter, Enum.GuildHistoryType.LEAVE);
ChatManager.chatGuildInfo(playerCharacter, "You no longer meet the level requirements for the guild.");
}
}
public static void calculateSpeedMod(PlayerCharacter playerCharacter) {
// get base race speed modifer
//this is retarded. *** Refactor
// if (this.race != null) {
// int ID = this.race.getObjectUUID();
// if (ID == 2004 || ID == 2005)
// this.raceRunMod = 1.21f; // centaur run bonus 22%
//// else if (ID == 2017)
//// this.raceRunMod = 1.14f; // mino run bonus 15%
// else
// this.raceRunMod = 1;
// } else
// this.raceRunMod = 1;
float bonus = 1f;
// // TODO: hardcoded, as didnt have time to introduce DB column to base object
// if (baseClass.getName().equals("Fighter") || baseClass.getName().equals("Rogue"))
// bonus += .05f;
// get running skill
if (playerCharacter.skills != null) {
CharacterSkill running = playerCharacter.skills.get("Running");
if (running != null) {
float runningBonus = (float) (Math.log(Math.round(running.getModifiedAmount()) * .01f) / Math.log(2) * .50f);
runningBonus = (float) (Math.pow(2, runningBonus) - 1);
runningBonus += 1;
runningBonus *= .25f;
bonus += runningBonus;
}
}
if (playerCharacter.bonuses != null)
// get rune and effect bonuses
bonus += playerCharacter.bonuses.getFloatPercentNullZero(Enum.ModType.Speed, Enum.SourceType.None);
// TODO get equip bonus
playerCharacter.update(false);
playerCharacter.speedMod = bonus;
}
}