/* * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If * not, see <http://www.gnu.org/licenses/>. */ package silentium.gameserver.network.clientpackets; import silentium.gameserver.configs.CustomConfig; import silentium.gameserver.configs.MainConfig; import silentium.gameserver.configs.PlayersConfig; import silentium.gameserver.data.xml.CharTemplateData; import silentium.gameserver.data.xml.SkillTreeData; import silentium.gameserver.idfactory.IdFactory; import silentium.gameserver.instancemanager.QuestManager; import silentium.gameserver.model.L2ItemInstance; import silentium.gameserver.model.L2ShortCut; import silentium.gameserver.model.L2SkillLearn; import silentium.gameserver.model.L2World; import silentium.gameserver.model.actor.instance.L2PcInstance; import silentium.gameserver.model.quest.Quest; import silentium.gameserver.model.quest.QuestState; import silentium.gameserver.model.quest.State; import silentium.gameserver.network.L2GameClient; import silentium.gameserver.network.serverpackets.CharCreateFail; import silentium.gameserver.network.serverpackets.CharCreateOk; import silentium.gameserver.network.serverpackets.CharSelectInfo; import silentium.gameserver.tables.CharNameTable; import silentium.gameserver.tables.SkillTable; import silentium.gameserver.templates.chars.L2PcTemplate; import silentium.gameserver.templates.item.L2Item; import silentium.gameserver.utils.Util; @SuppressWarnings("unused") public final class CharacterCreate extends L2GameClientPacket { // cSdddddddddddd private String _name; private int _race; private byte _sex; private int _classId; private int _int; private int _str; private int _con; private int _men; private int _dex; private int _wit; private byte _hairStyle; private byte _hairColor; private byte _face; @Override protected void readImpl() { _name = readS(); _race = readD(); _sex = (byte) readD(); _classId = readD(); _int = readD(); _str = readD(); _con = readD(); _men = readD(); _dex = readD(); _wit = readD(); _hairStyle = (byte) readD(); _hairColor = (byte) readD(); _face = (byte) readD(); } @Override protected void runImpl() { if (_name.length() > 16) { log.debug("Character Creation Failure: name " + _name + " is too long. Creation has failed."); sendPacket(new CharCreateFail(CharCreateFail.REASON_16_ENG_CHARS)); return; } if (!Util.isValidPlayerName(_name)) { log.debug("Character Creation Failure: name " + _name + " is invalid. Creation has failed."); sendPacket(new CharCreateFail(CharCreateFail.REASON_INCORRECT_NAME)); return; } if (_face > 2 || _face < 0) { log.warn("Character Creation Failure: Character face " + _face + " is invalid. Possible client hack: " + getClient()); sendPacket(new CharCreateFail(CharCreateFail.REASON_CREATION_FAILED)); return; } if (_hairStyle < 0 || (_sex == 0 && _hairStyle > 4) || (_sex != 0 && _hairStyle > 6)) { log.warn("Character Creation Failure: Character hair style " + _hairStyle + " is invalid. Possible client hack: " + getClient()); sendPacket(new CharCreateFail(CharCreateFail.REASON_CREATION_FAILED)); return; } if (_hairColor > 3 || _hairColor < 0) { log.warn("Character Creation Failure: Character hair color " + _hairColor + " is invalid. Possible client hack: " + getClient()); sendPacket(new CharCreateFail(CharCreateFail.REASON_CREATION_FAILED)); return; } L2PcInstance newChar = null; L2PcTemplate template = null; /* * DrHouse: Since checks for duplicate names are done using SQL, lock must be held until data is written to DB as well. */ synchronized (CharNameTable.getInstance()) { if (CharNameTable.accountCharNumber(getClient().getAccountName()) >= 7) { log.debug("Max number of characters reached. Creation failed."); sendPacket(new CharCreateFail(CharCreateFail.REASON_TOO_MANY_CHARACTERS)); return; } else if (CharNameTable.doesCharNameExist(_name)) { log.debug("Character Creation Failure: " + _name + " already exists. Creation has failed."); sendPacket(new CharCreateFail(CharCreateFail.REASON_NAME_ALREADY_EXISTS)); return; } template = CharTemplateData.getInstance().getTemplate(_classId); if (template == null || template.classBaseLevel > 1) { sendPacket(new CharCreateFail(CharCreateFail.REASON_CREATION_FAILED)); return; } int objectId = IdFactory.getInstance().getNextId(); newChar = L2PcInstance.create(objectId, template, getClient().getAccountName(), _name, _hairStyle, _hairColor, _face, _sex != 0); } newChar.setCurrentCp(0); newChar.setCurrentHp(newChar.getMaxHp()); newChar.setCurrentMp(newChar.getMaxMp()); // send acknowledgement sendPacket(CharCreateOk.STATIC_PACKET); initNewChar(getClient(), newChar); } private static void initNewChar(L2GameClient client, L2PcInstance newChar) { log.trace("Character initialization is started."); L2World.getInstance().storeObject(newChar); L2PcTemplate template = newChar.getTemplate(); newChar.addAdena("Init", PlayersConfig.STARTING_ADENA, null, false); if (CustomConfig.SPAWN_CHAR) newChar.setXYZInvisible(CustomConfig.SPAWN_X, CustomConfig.SPAWN_Y, CustomConfig.SPAWN_Z); else newChar.setXYZInvisible(template.spawnX, template.spawnY, template.spawnZ); newChar.setTitle(""); newChar.registerShortCut(new L2ShortCut(0, 0, 3, 2, -1, 1)); // attack shortcut newChar.registerShortCut(new L2ShortCut(3, 0, 3, 5, -1, 1)); // take shortcut newChar.registerShortCut(new L2ShortCut(10, 0, 3, 0, -1, 1)); // sit shortcut for (L2Item ia : template.getItems()) { L2ItemInstance item = newChar.getInventory().addItem("Init", ia.getItemId(), 1, newChar, null); if (item.getItemId() == 5588) // tutorial book shortcut newChar.registerShortCut(new L2ShortCut(11, 0, 1, item.getObjectId(), -1, 1)); if (item.isEquipable()) { if (newChar.getActiveWeaponItem() == null || !(item.getItem().getType2() != L2Item.TYPE2_WEAPON)) newChar.getInventory().equipItemAndRecord(item); } } for (L2SkillLearn skill : SkillTreeData.getInstance().getAvailableSkills(newChar, newChar.getClassId())) { newChar.addSkill(SkillTable.getInstance().getInfo(skill.getId(), skill.getLevel()), true); if (skill.getId() == 1001 || skill.getId() == 1177) newChar.registerShortCut(new L2ShortCut(1, 0, 2, skill.getId(), 1, 1)); if (skill.getId() == 1216) newChar.registerShortCut(new L2ShortCut(10, 0, 2, skill.getId(), 1, 1)); log.debug("adding starter skill:" + skill.getId() + " / " + skill.getLevel()); } if (!MainConfig.DISABLE_TUTORIAL) startTutorialQuest(newChar); newChar.setOnlineStatus(true, false); newChar.deleteMe(); CharSelectInfo cl = new CharSelectInfo(client.getAccountName(), client.getSessionId().playOkID1); client.getConnection().sendPacket(cl); client.setCharSelection(cl.getCharInfo()); log.trace("Character init end"); } public static void startTutorialQuest(L2PcInstance player) { QuestState qs = player.getQuestState("Tutorial"); Quest q = null; if (qs == null) q = QuestManager.getInstance().getQuest("Tutorial"); if (q != null) q.newQuestState(player).setState(State.STARTED); } }