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 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 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 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 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 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 characterRunesUsed = new ArrayList(); // ArrayList subtypesUsed = new ArrayList(); int remainingPoints = race.getStartingPoints() - strMod - dexMod - conMod - intMod - spiMod; int[] characterRunes = msg.getRunes(); HashSet usedRunesSubType = new HashSet<>(); HashSet usedRunes = new HashSet<>(); // So that all the penalties can be added at the end. ConcurrentHashMap 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> orderedRunes = new PriorityQueue<>(14, new Comparator>() { @Override public int compare(Map.Entry o1, Map.Entry 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 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 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 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 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 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 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; } }