Форум администраторов игровых серверов

Форум администраторов игровых серверов (https://forum.zone-game.info/TT.php)
-   Работа со скриптами (https://forum.zone-game.info/forumdisplay.php?f=37)
-   -   Class Master на L2jServer как на L2jFree (https://forum.zone-game.info/showthread.php?t=3280)

SpeedFaer 24.03.2009 12:01

Class Master на L2jServer как на L2jFree
 
Сегодня мы сделаем на свой сервер классного классмастера для L2jServer. Те у кого стоит эта сборка вкурсе какой он невзрачный.

Начнём:

Файл: \L2_GameServer\java\net\sf\l2j\Config.java

Находим:
Код:

package net.sf.l2j;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;

import javolution.util.FastList;
import javolution.util.FastMap;
import net.sf.l2j.gameserver.util.StringUtil;

Заменяем на:
Код:

package net.sf.l2j;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import javolution.util.FastList;
import javolution.util.FastMap;
import net.sf.l2j.gameserver.util.StringUtil;

Находим:
Код:

        public static boolean        ALLOW_CLASS_MASTERS;
Перед вставляем:
Код:

        public static boolean        ALT_CLASS_MASTER_STRIDER_UPDATE;
        public static String        ALT_CLASS_MASTER_SETTINGS_LINE;
        public static ClassMasterSettings        ALT_CLASS_MASTER_SETTINGS;

Находим:
Код:

ALLOW_CLASS_MASTERS                                        = Boolean.parseBoolean(Character.getProperty("AllowClassMasters", "False"));
Заменяем на:
Код:

                                        ALLOW_CLASS_MASTERS                                = Boolean.parseBoolean(Character.getProperty("SpawnClassMaster", "False"));
                                       
                                        ALT_CLASS_MASTER_STRIDER_UPDATE        = Boolean.parseBoolean(Character.getProperty("ClassMasterUpdateStrider", "False"));
                                        if (!Character.getProperty("ConfigClassMaster").trim().equalsIgnoreCase("False"))
                                                ALT_CLASS_MASTER_SETTINGS_LINE        = Character.getProperty("ConfigClassMaster");

                                        ALT_CLASS_MASTER_SETTINGS                        = new ClassMasterSettings(ALT_CLASS_MASTER_SETTINGS_LINE);

Идём на 2094 строку и добавляем это:
Код:

        public static class ClassMasterSettings
        {
                private FastMap<Integer, FastMap<Integer, Integer>> _claimItems;
                private FastMap<Integer, FastMap<Integer, Integer>> _rewardItems;
                private FastMap<Integer, Boolean>                                        _allowedClassChange;

                public ClassMasterSettings(String _configLine)
                {
                        _claimItems = new FastMap<Integer, FastMap<Integer, Integer>>();
                        _rewardItems = new FastMap<Integer, FastMap<Integer, Integer>>();
                        _allowedClassChange = new FastMap<Integer, Boolean>();
                        if (_configLine != null)
                                parseConfigLine(_configLine.trim());
                }

                private void parseConfigLine(String _configLine)
                {
                        StringTokenizer st = new StringTokenizer(_configLine, ";");

                        while (st.hasMoreTokens())
                        {
                                // get allowed class change
                                int job = Integer.parseInt(st.nextToken());

                                _allowedClassChange.put(job, true);

                                FastMap<Integer, Integer> _items = new FastMap<Integer, Integer>();
                                // parse items needed for class change
                                if (st.hasMoreTokens())
                                {
                                        StringTokenizer st2 = new StringTokenizer(st.nextToken(), "[],");

                                        while (st2.hasMoreTokens())
                                        {
                                                StringTokenizer st3 = new StringTokenizer(st2.nextToken(), "()");
                                                int _itemId = Integer.parseInt(st3.nextToken());
                                                int _quantity = Integer.parseInt(st3.nextToken());
                                                _items.put(_itemId, _quantity);
                                        }
                                }

                                _claimItems.put(job, _items);

                                _items = new FastMap<Integer, Integer>();
                                // parse gifts after class change
                                if (st.hasMoreTokens())
                                {
                                        StringTokenizer st2 = new StringTokenizer(st.nextToken(), "[],");

                                        while (st2.hasMoreTokens())
                                        {
                                                StringTokenizer st3 = new StringTokenizer(st2.nextToken(), "()");
                                                int _itemId = Integer.parseInt(st3.nextToken());
                                                int _quantity = Integer.parseInt(st3.nextToken());
                                                _items.put(_itemId, _quantity);
                                        }
                                }

                                _rewardItems.put(job, _items);
                        }
                }

                public boolean isAllowed(int job)
                {
                        if (_allowedClassChange == null)
                                return false;
                        if (_allowedClassChange.containsKey(job))
                                return _allowedClassChange.get(job);

                        return false;
                }

                public FastMap<Integer, Integer> getRewardItems(int job)
                {
                        if (_rewardItems.containsKey(job))
                                return _rewardItems.get(job);

                        return null;
                }

                public FastMap<Integer, Integer> getRequireItems(int job)
                {
                        if (_claimItems.containsKey(job))
                                return _claimItems.get(job);

                        return null;
                }

        }

Файл: \L2_GameServer\java\net\sf\l2j\gameserver\datatabl es\CharTemplateTable.java
Находим:
Код:

public class CharTemplateTable
{

Сразу после добавляем:
Код:

                public static final String[]                        CHAR_CLASSES        =
                                                                                                                        {
                        "Human Fighter",
                        "Warrior",
                        "Gladiator",
                        "Warlord",
                        "Human Knight",
                        "Paladin",
                        "Dark Avenger",
                        "Rogue",
                        "Treasure Hunter",
                        "Hawkeye",
                        "Human Mystic",
                        "Human Wizard",
                        "Sorceror",
                        "Necromancer",
                        "Warlock",
                        "Cleric",
                        "Bishop",
                        "Prophet",
                        "Elven Fighter",
                        "Elven Knight",
                        "Temple Knight",
                        "Swordsinger",
                        "Elven Scout",
                        "Plainswalker",
                        "Silver Ranger",
                        "Elven Mystic",
                        "Elven Wizard",
                        "Spellsinger",
                        "Elemental Summoner",
                        "Elven Oracle",
                        "Elven Elder",
                        "Dark Fighter",
                        "Palus Knight",
                        "Shillien Knight",
                        "Bladedancer",
                        "Assassin",
                        "Abyss Walker",
                        "Phantom Ranger",
                        "Dark Elven Mystic",
                        "Dark Elven Wizard",
                        "Spellhowler",
                        "Phantom Summoner",
                        "Shillien Oracle",
                        "Shillien Elder",
                        "Orc Fighter",
                        "Orc Raider",
                        "Destroyer",
                        "Orc Monk",
                        "Tyrant",
                        "Orc Mystic",
                        "Orc Shaman",
                        "Overlord",
                        "Warcryer",
                        "Dwarven Fighter",
                        "Dwarven Scavenger",
                        "Bounty Hunter",
                        "Dwarven Artisan",
                        "Warsmith",
                        "dummyEntry1",
                        "dummyEntry2",
                        "dummyEntry3",
                        "dummyEntry4",
                        "dummyEntry5",
                        "dummyEntry6",
                        "dummyEntry7",
                        "dummyEntry8",
                        "dummyEntry9",
                        "dummyEntry10",
                        "dummyEntry11",
                        "dummyEntry12",
                        "dummyEntry13",
                        "dummyEntry14",
                        "dummyEntry15",
                        "dummyEntry16",
                        "dummyEntry17",
                        "dummyEntry18",
                        "dummyEntry19",
                        "dummyEntry20",
                        "dummyEntry21",
                        "dummyEntry22",
                        "dummyEntry23",
                        "dummyEntry24",
                        "dummyEntry25",
                        "dummyEntry26",
                        "dummyEntry27",
                        "dummyEntry28",
                        "dummyEntry29",
                        "dummyEntry30",
                        "Duelist",
                        "DreadNought",
                        "Phoenix Knight",
                        "Hell Knight",
                        "Sagittarius",
                        "Adventurer",
                        "Archmage",
                        "Soultaker",
                        "Arcana Lord",
                        "Cardinal",
                        "Hierophant",
                        "Eva Templar",
                        "Sword Muse",
                        "Wind Rider",
                        "Moonlight Sentinel",
                        "Mystic Muse",
                        "Elemental Master",
                        "Eva's Saint",
                        "Shillien Templar",
                        "Spectral Dancer",
                        "Ghost Hunter",
                        "Ghost Sentinel",
                        "Storm Screamer",
                        "Spectral Master",
                        "Shillien Saint",
                        "Titan",
                        "Grand Khavatari",
                        "Dominator",
                        "Doomcryer",
                        "Fortune Seeker",
                        "Maestro",
                        "dummyEntry31",
                        "dummyEntry32",
                        "dummyEntry33",
                        "dummyEntry34",
                        "Male Soldier",
                        "Female Soldier",
                        "Dragoon",
                        "Warder",
                        "Berserker",
                        "Male Soulbreaker",
                        "Female Soulbreaker",
                        "Arbalester",
                        "Doombringer",
                        "Male Soulhound",
                        "Female Soulhound",
                        "Trickster",
                        "Inspector",
                        "Judicator"                                                                        };

Находим:
Код:

        public final String getClassNameById(int classId)
        {
                L2PcTemplate pcTemplate = _templates.get(classId);
                if (pcTemplate == null)
                {
                        throw new IllegalArgumentException("No template for classId: " + classId);
                }
                return pcTemplate.className;
        }

И после добавляем:
Код:

        public static final String getClassNameByIdFix(int classId)
        {
                return CHAR_CLASSES[classId];
        }

Файл: \L2_GameServer\java\net\sf\l2j\gameserver\model\ac tor\instance\L2ClassMasterInstance.java

Открываем и всё заменяем на этот код:
Код:

package net.sf.l2j.gameserver.model.actor.instance;

import javolution.text.TextBuilder;

import java.util.Collection;
import net.sf.l2j.Config;
import net.sf.l2j.gameserver.ai.CtrlIntention;
import net.sf.l2j.gameserver.datatables.CharTemplateTable;
import net.sf.l2j.gameserver.datatables.ItemTable;
import net.sf.l2j.gameserver.model.L2ItemInstance;
import net.sf.l2j.gameserver.model.base.ClassId;
import net.sf.l2j.gameserver.model.base.ClassLevel;
import net.sf.l2j.gameserver.model.base.PlayerClass;
import net.sf.l2j.gameserver.model.quest.Quest;
import net.sf.l2j.gameserver.network.SystemMessageId;
import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
import net.sf.l2j.gameserver.network.serverpackets.MyTargetSelected;
import net.sf.l2j.gameserver.network.serverpackets.NpcHtmlMessage;
import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
import net.sf.l2j.gameserver.network.serverpackets.ValidateLocation;
import net.sf.l2j.gameserver.templates.chars.L2NpcTemplate;
import net.sf.l2j.gameserver.util.StringUtil;

/**
 * Class Master implementation
 * ths npc is used for changing character occupation
 **/
public final class L2ClassMasterInstance extends L2FolkInstance
{

        /**
        * @param template
        */
        public L2ClassMasterInstance(int objectId, L2NpcTemplate template)
        {
                super(objectId, template);
        }

        @Override
        public void onAction(L2PcInstance player)
        {
                if (!canTarget(player)) return;

                // Check if the L2PcInstance already target the L2NpcInstance
                if (getObjectId() != player.getTargetId())
                {
                        // Set the target of the L2PcInstance player
                        player.setTarget(this);

                        // Send a Server->Client packet MyTargetSelected to the L2PcInstance player
                        player.sendPacket(new MyTargetSelected(getObjectId(), 0));

                        // Send a Server->Client packet ValidateLocation to correct the L2NpcInstance position and heading on the client
                        player.sendPacket(new ValidateLocation(this));
                }
                else
                {
                        if (!canInteract(player))
                        {
                                player.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, this);
                                return;
                        }

                        NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
                        TextBuilder sb = new TextBuilder();
                        sb.append("<html><body>");
                        sb.append(getName() + ":<br>");
                        sb.append("<br>");

                        ClassId classId = player.getClassId();
                        int level = player.getLevel();
                        int jobLevel = classId.level();

                        int newJobLevel = jobLevel + 1;

                        if ((((level >= 20 && jobLevel == 0) || (level >= 40 && jobLevel == 1) || (level >= 76 && jobLevel == 2)) && Config.ALT_CLASS_MASTER_SETTINGS.isAllowed(newJobLevel)) || Config.ALT_CLASS_MASTER_STRIDER_UPDATE)
                        {
                                if (((level >= 20 && jobLevel == 0) || (level >= 40 && jobLevel == 1) || (level >= 76 && jobLevel == 2)) && Config.ALT_CLASS_MASTER_SETTINGS.isAllowed(newJobLevel))
                                {
                                        sb.append("\u0412\u044B \u043C\u043E\u0436\u0435\u0442\u0435 \u0432\u044B\u0443\u0447\u0438\u0442\u044C \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0435 \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u0438:<br>");

                                        for (ClassId child : ClassId.values())
                                                if (child.childOf(classId) && child.level() == newJobLevel)
                                                        sb.append("<br><a action=\"bypass -h npc_" + getObjectId() + "_change_class " + (child.getId()) + "\"> " + CharTemplateTable.getClassNameByIdFix(child.getId()) + "</a>");

                                        if (Config.ALT_CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel) != null && Config.ALT_CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel).size() > 0)
                                        {
                                                sb.append("<br><br>\u0414\u043B\u044F \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u0438\u044F \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u0438, \u043D\u0443\u0436\u043D\u043E:");
                                                sb.append("<table width=270>");
                                                for (Integer _itemId : Config.ALT_CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel).keySet())
                                                {
                                                        int _count = Config.ALT_CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel).get(_itemId);
                                                        sb.append("<tr><td><font color=\"LEVEL\">" + _count + "</font></td><td>" + ItemTable.getInstance().getTemplate(_itemId).getName()+ "</td></tr>");
                                                }
                                                sb.append("</table>");
                                        }
                                }

                                if (Config.ALT_CLASS_MASTER_STRIDER_UPDATE)
                                {
                                        sb.append("<table width=270>");
                                        sb.append("<tr><td><br></td></tr>");
                                        sb.append("<tr><td><a action=\"bypass -h npc_" + getObjectId() + "_upgrade_hatchling\">Upgrade Hatchling to Strider</a></td></tr>");
                                        sb.append("</table>");
                                }
                                sb.append("<br>");
                        }
                        else
                        {
                                switch (jobLevel)
                                {
                                case 0:
                                        if (Config.ALT_CLASS_MASTER_SETTINGS.isAllowed(1))
                                                sb.append("\u0412\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0439\u0442\u0435\u0441\u044C \u0441\u044E\u0434\u0430, \u043A\u0430\u043A \u0434\u043E\u0441\u0442\u0438\u0433\u043D\u0435\u0442\u0435 20 \u0443\u0440\u043E\u0432\u043D\u044F, \u0447\u0442\u043E\u0431\u044B \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u043D\u043E\u0432\u0443\u044E \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u044E.<br>");
                                        else if (Config.ALT_CLASS_MASTER_SETTINGS.isAllowed(2))
                                                sb.append("\u0412\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0439\u0442\u0435\u0441\u044C \u043F\u043E\u0441\u043B\u0435 \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u0438\u044F \u043F\u0435\u0440\u0432\u043E\u0439 \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u0438.<br>");
                                        else if (Config.ALT_CLASS_MASTER_SETTINGS.isAllowed(3))
                                                sb.append("\u0412\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0439\u0442\u0435\u0441\u044C \u043F\u043E\u0441\u043B\u0435 \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u0438\u044F \u0432\u0442\u043E\u0440\u043E\u0439 \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u0438.<br>");
                                        else
                                                sb.append("\u042F \u043D\u0435 \u043C\u043E\u0433\u0443 \u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0432\u0430\u0448\u0443 \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u044E.<br>");
                                        break;
                                case 1:
                                        if (Config.ALT_CLASS_MASTER_SETTINGS.isAllowed(2))
                                                sb.append("\u0412\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0439\u0442\u0435\u0441\u044C \u0441\u044E\u0434\u0430, \u043A\u043E\u0433\u0434\u0430 \u0412\u044B \u0434\u043E\u0441\u0442\u0438\u0433\u043D\u0435\u0442\u0435 40 \u0443\u0440\u043E\u0432\u043D\u044F, \u0447\u0442\u043E \u0431\u044B \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u043D\u043E\u0432\u0443\u044E \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u044E.<br>");
                                        else if (Config.ALT_CLASS_MASTER_SETTINGS.isAllowed(3))
                                                sb.append("\u0412\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0439\u0442\u0435\u0441\u044C \u043F\u043E\u0441\u043B\u0435 \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u0438\u044F \u0432\u0442\u043E\u0440\u043E\u0439 \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u0438.<br>");
                                        else
                                                sb.append("\u042F \u043D\u0435 \u043C\u043E\u0433\u0443 \u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0432\u0430\u0448\u0443 \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u044E.<br>");
                                        break;
                                case 2:
                                        if (Config.ALT_CLASS_MASTER_SETTINGS.isAllowed(3))
                                                sb.append("\u0412\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0439\u0442\u0435\u0441\u044C \u0441\u044E\u0434\u0430, \u043A\u043E\u0433\u0434\u0430 \u0412\u044B \u0434\u043E\u0441\u0442\u0438\u0433\u043D\u0435\u0442\u0435 76 \u0443\u0440\u043E\u0432\u043D\u044F, \u0447\u0442\u043E\u0431\u044B \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u043D\u043E\u0432\u0443\u044E \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u044E.<br>");
                                        else
                                                sb.append("\u042F \u043D\u0435 \u043C\u043E\u0433\u0443 \u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0432\u0430\u0448\u0443 \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u044E.<br>");
                                        break;
                                case 3:
                                        sb.append("\u0412\u044B \u043F\u043E\u043B\u0443\u0447\u0438\u043B\u0438 \u0432\u0441\u0435 \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0435 \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u0438.<br>");
                                        break;
                                }
                                //If the player hasn't available class , he can change pet too...
                                if (Config.ALT_CLASS_MASTER_STRIDER_UPDATE)
                                {
                                        sb.append("<table width=270>");
                                        sb.append("<tr><td><br></td></tr>");
                                        sb.append("<tr><td><a action=\"bypass -h npc_" + getObjectId() + "_upgrade_hatchling\">Upgrade Hatchling to Strider</a></td></tr>");
                                        sb.append("</table>");
                                }
                                sb.append("<br>");
                        }

                        for (Quest q : Quest.findAllEvents())
                                sb.append("Event: <a action=\"bypass -h Quest " + q.getName() + "\">" + q.getDescr() + "</a><br>");
                        sb.append("</body></html>");
                        html.setHtml(sb.toString());
                        player.sendPacket(html);

                }
                player.sendPacket(ActionFailed.STATIC_PACKET);
        }

        @Override
        public void onBypassFeedback(L2PcInstance player, String command)
        {
                if (command.startsWith("change_class"))
                {
                        int val = Integer.parseInt(command.substring(13));

                        ClassId classId = player.getClassId();
                        ClassId newClassId = ClassId.values()[val];

                        int level = player.getLevel();
                        int jobLevel = classId.level();
                        int newJobLevel = newClassId.level();

                        // -- Exploit prevention
                        // Prevents changing if config option disabled
                        if (!Config.ALT_CLASS_MASTER_SETTINGS.isAllowed(newJobLevel))
                                return;

                        // Prevents changing to class not in same class tree
                        if (!newClassId.childOf(classId))
                                return;

                        // Prevents changing between same level jobs
                        if (newJobLevel != jobLevel + 1)
                                return;

                        // Check for player level
                        if (level < 20 && newJobLevel > 1)
                                return;
                        if (level < 40 && newJobLevel > 2)
                                return;
                        if (level < 76 && newJobLevel > 3)
                                return;
                        // -- Prevention ends

                        // Check if player have all required items for class transfer
                        for (Integer _itemId : Config.ALT_CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel).keySet())
                        {
                                int _count = Config.ALT_CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel).get(_itemId);
                                if (player.getInventory().getInventoryItemCount(_itemId, -1) < _count)
                                {
                                        player.sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ITEMS));
                                        return;
                                }
                        }

                        // Get all required items for class transfer
                        for (Integer _itemId : Config.ALT_CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel).keySet())
                        {
                                int _count = Config.ALT_CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel).get(_itemId);
                                player.destroyItemByItemId("ClassMaster", _itemId, _count, player, true);
                        }

                        // Reward player with items
                        for (Integer _itemId : Config.ALT_CLASS_MASTER_SETTINGS.getRewardItems(newJobLevel).keySet())
                        {
                                int _count = Config.ALT_CLASS_MASTER_SETTINGS.getRewardItems(newJobLevel).get(_itemId);
                                player.addItem("ClassMaster", _itemId, _count, player, true);
                        }

                        changeClass(player, val);

                        player.rewardSkills();

                        NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
                        TextBuilder sb = new TextBuilder();
                        sb.append("<html><body>");
                        sb.append(getName() + ":<br>");
                        sb.append("<br>");
                        sb.append("\u041F\u043E\u0437\u0434\u0440\u0430\u0432\u043B\u044F\u044E! \u0422\u0435\u043F\u0435\u0440\u044C \u0412\u044B \u0441\u0442\u0430\u043B\u0438 <font color=\"LEVEL\">" + CharTemplateTable.getClassNameByIdFix(player.getClassId().getId()) + "</font>.");
                        sb.append("</body></html>");
                        html.setHtml(sb.toString());
                        player.sendPacket(html);

                        // Update the overloaded status of the L2PcInstance
                        player.refreshOverloaded();
                        // Update the expertise status of the L2PcInstance
                        player.refreshExpertisePenalty();
                }
                else if (command.startsWith("upgrade_hatchling") && Config.ALT_CLASS_MASTER_STRIDER_UPDATE)
                {
                        boolean canUpgrade = false;
                        if (player.getPet() != null)
                        {
                                if (player.getPet().getNpcId() == 12311 || player.getPet().getNpcId() == 12312 || player.getPet().getNpcId() == 12313)
                                {
                                        if (player.getPet().getLevel() >= 55)
                                                canUpgrade = true;
                                        else
                                                player.sendMessage("The level of your hatchling is too low to be upgraded.");
                                }
                                else
                                        player.sendMessage("You have to summon your hatchling.");
                        }
                        else
                                player.sendMessage("You have to summon your hatchling if you want to upgrade him.");

                        if (!canUpgrade)
                                return;

                        int[] hatchCollar =
                        { 3500, 3501, 3502 };
                        int[] striderCollar =
                        { 4422, 4423, 4424 };

                        //TODO: Maybe show a complete list of all hatchlings instead of using first one
                        for (int i = 0; i < 3; i++)
                        {
                                L2ItemInstance collar = player.getInventory().getItemByItemId(hatchCollar[i]);

                                if (collar != null)
                                {
                                        // Unsummon the hatchling
                                        player.getPet().unSummon(player);
                                        player.destroyItem("ClassMaster", collar, player, true);
                                        player.addItem("ClassMaster", striderCollar[i], 1, player, true);

                                        return;
                                }
                        }
                }
                else
                {
                        super.onBypassFeedback(player, command);
                }
        }

        private void changeClass(L2PcInstance player, int val)
        {
                player.setClassId(val);

                if (player.isSubClassActive())
                        player.getSubClasses().get(player.getClassIndex()).setClassId(player.getActiveClass());
                else
                        player.setBaseClass(player.getActiveClass());

                player.broadcastUserInfo();
        }
}

Теперь конфиги, отрываем: Character.properties

Находим:
Код:

# Allow use of Event Managers for changing occupation without
# any quests needing completion.
# Retail: false
AllowClassMasters = False

И заменяем на:
Код:

# -------------------------------------------------------------
# Class Master
# -------------------------------------------------------------
# Config for special Class Master npc that can change players occupation
# If you need change occupation only use quest then set this to False (Default)
# Syntax: occupation number;[required item id(count)],[],...;[reward item id(count)],[],...;occupation number...
# Examples:
#
# ConfigClassMaster=1;[57(100000)];[];2;[57(1000000)];[];3;[57(10000000)],[5575(1000000)];[6622(1)]
# 1st occupation change for 100.000 Adena (item id 57)
# 2nd occupation change for 1.000.0000 Adena (item id 57)
# 3rd occupation change for 10.000.0000 Adena (item id 57) and 1.000.000 Ancient Adena (item id 5575)
# on 3rd occupation change player will be rewarded with 1 Book of Giants (item id 6622)
#
# ConfigClassMaster=1;[];[];2;[];[];3;[];[]
# 1st, 2nd, 3rd occupation change for free, without rewards
ConfigClassMaster = 1;[57(100000)];[];2;[57(1000000)];[];3;[57(10000000)],[5575(1000000)];[6622(1)]
# Spawn Class Master npc if you have any in spawnlist. Default = False
SpawnClassMaster = True

# Allows Strider Update
ClassMasterUpdateStrider = False


SpeedFaer 23.06.2009 09:53

Ответ: Class Master на L2jServer как на L2jFree
 
Скачал новую версию сервера, увидел необходимость в доработке написанного ранее. Приступим...

Файл: \L2_GameServer\java\net\sf\l2j\Config.java

Находим:
Код:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;

import javolution.util.FastList;
import javolution.util.FastMap;
import net.sf.l2j.gameserver.util.FloodProtectorConfig;
import net.sf.l2j.gameserver.util.StringUtil;

Заменяем на:
Код:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import javolution.util.FastList;
import javolution.util.FastMap;
import net.sf.l2j.gameserver.util.FloodProtectorConfig;
import net.sf.l2j.gameserver.util.StringUtil;

------------------------------------------------------------

Находим строку:
Код:

public static final String FLOOD_PROTECTOR_FILE = "./config/floodprotector.properties";
Сразу после добавляем следующее:
Код:

public static final String CLASS_MASTER_FILE = "./config/ClassMaster.properties";

public static boolean ALT_CLASS_MASTER_STRIDER_UPDATE;
public static String ALT_CLASS_MASTER_SETTINGS_LINE;
public static ClassMasterSettings ALT_CLASS_MASTER_SETTINGS;

(Вынесем конфиг с нашим нпс в отдельный файл)
------------------------------------------------------------

Если всё в точности как написано выше, то на 815 строку надо добавить следующее:
Код:

                                try
                                {
                                        Properties ClassMasterSettings = new Properties();
                                        is = new FileInputStream(new File(CLASS_MASTER_FILE));
                                        ClassMasterSettings.load(is);
                                       
                                        ALLOW_CLASS_MASTERS = Boolean.parseBoolean(ClassMasterSettings.getProperty("SpawnClassMaster", "False"));
                                       
                                        ALT_CLASS_MASTER_STRIDER_UPDATE = Boolean.parseBoolean(ClassMasterSettings.getProperty("ClassMasterUpdateStrider", "False"));
                                        if (!ClassMasterSettings.getProperty("ConfigClassMaster").trim().equalsIgnoreCase("False"))
                                                ALT_CLASS_MASTER_SETTINGS_LINE = ClassMasterSettings.getProperty("ConfigClassMaster");

                                        ALT_CLASS_MASTER_SETTINGS = new ClassMasterSettings(ALT_CLASS_MASTER_SETTINGS_LINE);
                               
                                }
                                catch (Exception e)
                                {
                                        e.printStackTrace();
                                        throw new Error("Failed to Load "+CLASS_MASTER_FILE+" File.");
                                }

Вот куда мы должны его добавить:
Код:

                        _log.info("Loading GameServer Configuration Files...");
                        InputStream is = null;
                        try
                        {
                                ##### ВОТ СЮДА #####
                                try
                                {
                                        Properties serverSettings = new Properties();
                                        is = new FileInputStream(new File(CONFIGURATION_FILE));
                                        serverSettings.load(is);

------------------------------------------------------------

Находим и удаляем эту строку:
Код:

ALLOW_CLASS_MASTERS = Boolean.parseBoolean(Character.getProperty("AllowClassMasters", "False"));
------------------------------------------------------------

Идём на 2028 строку, выглядит так:
Код:

                else
                {
                        _log.severe("Could not Load Config: server mode was not set");
                }
        }
        ##### ВОТ СЮДА #####
        /**
        * Set a new value to a game parameter from the admin console.
        * @param pName (String) : name of the parameter to change
        * @param pValue (String) : new value of the parameter
        * @return boolean : true if modification has been made
        * @link useAdminCommand
        */

И туда мы добавляем вот этот код:
Код:

        public static class ClassMasterSettings
        {
                private FastMap<Integer, FastMap<Integer, Integer>> _claimItems;
                private FastMap<Integer, FastMap<Integer, Integer>> _rewardItems;
                private FastMap<Integer, Boolean>                                        _allowedClassChange;

                public ClassMasterSettings(String _configLine)
                {
                        _claimItems = new FastMap<Integer, FastMap<Integer, Integer>>();
                        _rewardItems = new FastMap<Integer, FastMap<Integer, Integer>>();
                        _allowedClassChange = new FastMap<Integer, Boolean>();
                        if (_configLine != null)
                                parseConfigLine(_configLine.trim());
                }

                private void parseConfigLine(String _configLine)
                {
                        StringTokenizer st = new StringTokenizer(_configLine, ";");

                        while (st.hasMoreTokens())
                        {
                                // get allowed class change
                                int job = Integer.parseInt(st.nextToken());

                                _allowedClassChange.put(job, true);

                                FastMap<Integer, Integer> _items = new FastMap<Integer, Integer>();
                                // parse items needed for class change
                                if (st.hasMoreTokens())
                                {
                                        StringTokenizer st2 = new StringTokenizer(st.nextToken(), "[],");

                                        while (st2.hasMoreTokens())
                                        {
                                                StringTokenizer st3 = new StringTokenizer(st2.nextToken(), "()");
                                                int _itemId = Integer.parseInt(st3.nextToken());
                                                int _quantity = Integer.parseInt(st3.nextToken());
                                                _items.put(_itemId, _quantity);
                                        }
                                }

                                _claimItems.put(job, _items);

                                _items = new FastMap<Integer, Integer>();
                                // parse gifts after class change
                                if (st.hasMoreTokens())
                                {
                                        StringTokenizer st2 = new StringTokenizer(st.nextToken(), "[],");

                                        while (st2.hasMoreTokens())
                                        {
                                                StringTokenizer st3 = new StringTokenizer(st2.nextToken(), "()");
                                                int _itemId = Integer.parseInt(st3.nextToken());
                                                int _quantity = Integer.parseInt(st3.nextToken());
                                                _items.put(_itemId, _quantity);
                                        }
                                }

                                _rewardItems.put(job, _items);
                        }
                }

                public boolean isAllowed(int job)
                {
                        if (_allowedClassChange == null)
                                return false;
                        if (_allowedClassChange.containsKey(job))
                                return _allowedClassChange.get(job);

                        return false;
                }

                public FastMap<Integer, Integer> getRewardItems(int job)
                {
                        if (_rewardItems.containsKey(job))
                                return _rewardItems.get(job);

                        return null;
                }

                public FastMap<Integer, Integer> getRequireItems(int job)
                {
                        if (_claimItems.containsKey(job))
                                return _claimItems.get(job);

                        return null;
                }

        }

------------------------------------------------------------

Сохраняем этот файл. И находим следующий: Файл: \L2_GameServer\java\net\sf\l2j\gameserver\datatabl es\CharTemplateTable.java

Находим:
Код:

public class CharTemplateTable
{

Сразу после добавляем:
Код:

        public static final String[] CHAR_CLASSES =
        {
                "Human Fighter",
                "Warrior",
                "Gladiator",
                "Warlord",
                "Human Knight",
                "Paladin",
                "Dark Avenger",
                "Rogue",
                "Treasure Hunter",
                "Hawkeye",
                "Human Mystic",
                "Human Wizard",
                "Sorceror",
                "Necromancer",
                "Warlock",
                "Cleric",
                "Bishop",
                "Prophet",
                "Elven Fighter",
                "Elven Knight",
                "Temple Knight",
                "Swordsinger",
                "Elven Scout",
                "Plainswalker",
                "Silver Ranger",
                "Elven Mystic",
                "Elven Wizard",
                "Spellsinger",
                "Elemental Summoner",
                "Elven Oracle",
                "Elven Elder",
                "Dark Fighter",
                "Palus Knight",
                "Shillien Knight",
                "Bladedancer",
                "Assassin",
                "Abyss Walker",
                "Phantom Ranger",
                "Dark Elven Mystic",
                "Dark Elven Wizard",
                "Spellhowler",
                "Phantom Summoner",
                "Shillien Oracle",
                "Shillien Elder",
                "Orc Fighter",
                "Orc Raider",
                "Destroyer",
                "Orc Monk",
                "Tyrant",
                "Orc Mystic",
                "Orc Shaman",
                "Overlord",
                "Warcryer",
                "Dwarven Fighter",
                "Dwarven Scavenger",
                "Bounty Hunter",
                "Dwarven Artisan",
                "Warsmith",
                "dummyEntry1",
                "dummyEntry2",
                "dummyEntry3",
                "dummyEntry4",
                "dummyEntry5",
                "dummyEntry6",
                "dummyEntry7",
                "dummyEntry8",
                "dummyEntry9",
                "dummyEntry10",
                "dummyEntry11",
                "dummyEntry12",
                "dummyEntry13",
                "dummyEntry14",
                "dummyEntry15",
                "dummyEntry16",
                "dummyEntry17",
                "dummyEntry18",
                "dummyEntry19",
                "dummyEntry20",
                "dummyEntry21",
                "dummyEntry22",
                "dummyEntry23",
                "dummyEntry24",
                "dummyEntry25",
                "dummyEntry26",
                "dummyEntry27",
                "dummyEntry28",
                "dummyEntry29",
                "dummyEntry30",
                "Duelist",
                "DreadNought",
                "Phoenix Knight",
                "Hell Knight",
                "Sagittarius",
                "Adventurer",
                "Archmage",
                "Soultaker",
                "Arcana Lord",
                "Cardinal",
                "Hierophant",
                "Eva Templar",
                "Sword Muse",
                "Wind Rider",
                "Moonlight Sentinel",
                "Mystic Muse",
                "Elemental Master",
                "Eva's Saint",
                "Shillien Templar",
                "Spectral Dancer",
                "Ghost Hunter",
                "Ghost Sentinel",
                "Storm Screamer",
                "Spectral Master",
                "Shillien Saint",
                "Titan",
                "Grand Khavatari",
                "Dominator",
                "Doomcryer",
                "Fortune Seeker",
                "Maestro",
                "dummyEntry31",
                "dummyEntry32",
                "dummyEntry33",
                "dummyEntry34",
                "Male Soldier",
                "Female Soldier",
                "Dragoon",
                "Warder",
                "Berserker",
                "Male Soulbreaker",
                "Female Soulbreaker",
                "Arbalester",
                "Doombringer",
                "Male Soulhound",
                "Female Soulhound",
                "Trickster",
                "Inspector",
                "Judicator"
        };

Находим:
Код:

        public final String getClassNameById(int classId)
        {
                L2PcTemplate pcTemplate = _templates.get(classId);
                if (pcTemplate == null)
                {
                        throw new IllegalArgumentException("No template for classId: " + classId);
                }
                return pcTemplate.className;
        }

И после добавляем:
Код:

        public static final String getClassNameByIdFix(int classId)
        {
                return CHAR_CLASSES[classId];
        }

------------------------------------------------------------

Сохраняем файл. Находим следующий: \L2_GameServer\java\net\sf\l2j\gameserver\model\ac tor\instance\L2ClassMasterInstance.java

Заменяем всё что в нём было на это:
Код:

package net.sf.l2j.gameserver.model.actor.instance;

import javolution.text.TextBuilder;

import java.util.Collection;
import net.sf.l2j.Config;
import net.sf.l2j.gameserver.ai.CtrlIntention;
import net.sf.l2j.gameserver.datatables.CharTemplateTable;
import net.sf.l2j.gameserver.datatables.ItemTable;
import net.sf.l2j.gameserver.model.L2ItemInstance;
import net.sf.l2j.gameserver.model.base.ClassId;
import net.sf.l2j.gameserver.model.base.ClassLevel;
import net.sf.l2j.gameserver.model.base.PlayerClass;
import net.sf.l2j.gameserver.model.quest.Quest;
import net.sf.l2j.gameserver.network.SystemMessageId;
import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
import net.sf.l2j.gameserver.network.serverpackets.MyTargetSelected;
import net.sf.l2j.gameserver.network.serverpackets.NpcHtmlMessage;
import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
import net.sf.l2j.gameserver.network.serverpackets.ValidateLocation;
import net.sf.l2j.gameserver.templates.chars.L2NpcTemplate;
import net.sf.l2j.gameserver.util.StringUtil;

/**
 * Class Master implementation
 * ths npc is used for changing character occupation
 **/
public final class L2ClassMasterInstance extends L2NpcInstance
{

        /**
        * @param template
        */
        public L2ClassMasterInstance(int objectId, L2NpcTemplate template)
        {
                super(objectId, template);
        }

        @Override
        public void onAction(L2PcInstance player)
        {
                if (!canTarget(player)) return;

                // Check if the L2PcInstance already target the L2NpcInstance
                if (getObjectId() != player.getTargetId())
                {
                        // Set the target of the L2PcInstance player
                        player.setTarget(this);

                        // Send a Server->Client packet MyTargetSelected to the L2PcInstance player
                        player.sendPacket(new MyTargetSelected(getObjectId(), 0));

                        // Send a Server->Client packet ValidateLocation to correct the L2NpcInstance position and heading on the client
                        player.sendPacket(new ValidateLocation(this));
                }
                else
                {
                        if (!canInteract(player))
                        {
                                player.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, this);
                                return;
                        }

                        NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
                        TextBuilder sb = new TextBuilder();
                        sb.append("<html><body>");
                        sb.append(getName() + ":<br>");
                        sb.append("<br>");

                        ClassId classId = player.getClassId();
                        int level = player.getLevel();
                        int jobLevel = classId.level();

                        int newJobLevel = jobLevel + 1;

                        if ((((level >= 20 && jobLevel == 0) || (level >= 40 && jobLevel == 1) || (level >= 76 && jobLevel == 2)) && Config.ALT_CLASS_MASTER_SETTINGS.isAllowed(newJobLevel)) || Config.ALT_CLASS_MASTER_STRIDER_UPDATE)
                        {
                                if (((level >= 20 && jobLevel == 0) || (level >= 40 && jobLevel == 1) || (level >= 76 && jobLevel == 2)) && Config.ALT_CLASS_MASTER_SETTINGS.isAllowed(newJobLevel))
                                {
                                        sb.append("\u0412\u044B \u043C\u043E\u0436\u0435\u0442\u0435 \u0432\u044B\u0443\u0447\u0438\u0442\u044C \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0435 \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u0438:<br>");

                                        for (ClassId child : ClassId.values())
                                                if (child.childOf(classId) && child.level() == newJobLevel)
                                                        sb.append("<br><a action=\"bypass -h npc_" + getObjectId() + "_change_class " + (child.getId()) + "\"> " + CharTemplateTable.getClassNameByIdFix(child.getId()) + "</a>");

                                        if (Config.ALT_CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel) != null && Config.ALT_CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel).size() > 0)
                                        {
                                                sb.append("<br><br>\u0414\u043B\u044F \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u0438\u044F \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u0438, \u043D\u0443\u0436\u043D\u043E:");
                                                sb.append("<table width=270>");
                                                for (Integer _itemId : Config.ALT_CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel).keySet())
                                                {
                                                        int _count = Config.ALT_CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel).get(_itemId);
                                                        sb.append("<tr><td><font color=\"LEVEL\">" + _count + "</font></td><td>" + ItemTable.getInstance().getTemplate(_itemId).getName()+ "</td></tr>");
                                                }
                                                sb.append("</table>");
                                        }
                                }

                                if (Config.ALT_CLASS_MASTER_STRIDER_UPDATE)
                                {
                                        sb.append("<table width=270>");
                                        sb.append("<tr><td><br></td></tr>");
                                        sb.append("<tr><td><a action=\"bypass -h npc_" + getObjectId() + "_upgrade_hatchling\">Upgrade Hatchling to Strider</a></td></tr>");
                                        sb.append("</table>");
                                }
                                sb.append("<br>");
                        }
                        else
                        {
                                switch (jobLevel)
                                {
                                case 0:
                                        if (Config.ALT_CLASS_MASTER_SETTINGS.isAllowed(1))
                                                sb.append("\u0412\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0439\u0442\u0435\u0441\u044C \u0441\u044E\u0434\u0430, \u043A\u0430\u043A \u0434\u043E\u0441\u0442\u0438\u0433\u043D\u0435\u0442\u0435 20 \u0443\u0440\u043E\u0432\u043D\u044F, \u0447\u0442\u043E\u0431\u044B \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u043D\u043E\u0432\u0443\u044E \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u044E.<br>");
                                        else if (Config.ALT_CLASS_MASTER_SETTINGS.isAllowed(2))
                                                sb.append("\u0412\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0439\u0442\u0435\u0441\u044C \u043F\u043E\u0441\u043B\u0435 \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u0438\u044F \u043F\u0435\u0440\u0432\u043E\u0439 \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u0438.<br>");
                                        else if (Config.ALT_CLASS_MASTER_SETTINGS.isAllowed(3))
                                                sb.append("\u0412\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0439\u0442\u0435\u0441\u044C \u043F\u043E\u0441\u043B\u0435 \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u0438\u044F \u0432\u0442\u043E\u0440\u043E\u0439 \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u0438.<br>");
                                        else
                                                sb.append("\u042F \u043D\u0435 \u043C\u043E\u0433\u0443 \u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0432\u0430\u0448\u0443 \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u044E.<br>");
                                        break;
                                case 1:
                                        if (Config.ALT_CLASS_MASTER_SETTINGS.isAllowed(2))
                                                sb.append("\u0412\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0439\u0442\u0435\u0441\u044C \u0441\u044E\u0434\u0430, \u043A\u043E\u0433\u0434\u0430 \u0412\u044B \u0434\u043E\u0441\u0442\u0438\u0433\u043D\u0435\u0442\u0435 40 \u0443\u0440\u043E\u0432\u043D\u044F, \u0447\u0442\u043E \u0431\u044B \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u043D\u043E\u0432\u0443\u044E \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u044E.<br>");
                                        else if (Config.ALT_CLASS_MASTER_SETTINGS.isAllowed(3))
                                                sb.append("\u0412\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0439\u0442\u0435\u0441\u044C \u043F\u043E\u0441\u043B\u0435 \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u0438\u044F \u0432\u0442\u043E\u0440\u043E\u0439 \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u0438.<br>");
                                        else
                                                sb.append("\u042F \u043D\u0435 \u043C\u043E\u0433\u0443 \u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0432\u0430\u0448\u0443 \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u044E.<br>");
                                        break;
                                case 2:
                                        if (Config.ALT_CLASS_MASTER_SETTINGS.isAllowed(3))
                                                sb.append("\u0412\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0439\u0442\u0435\u0441\u044C \u0441\u044E\u0434\u0430, \u043A\u043E\u0433\u0434\u0430 \u0412\u044B \u0434\u043E\u0441\u0442\u0438\u0433\u043D\u0435\u0442\u0435 76 \u0443\u0440\u043E\u0432\u043D\u044F, \u0447\u0442\u043E\u0431\u044B \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u043D\u043E\u0432\u0443\u044E \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u044E.<br>");
                                        else
                                                sb.append("\u042F \u043D\u0435 \u043C\u043E\u0433\u0443 \u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0432\u0430\u0448\u0443 \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u044E.<br>");
                                        break;
                                case 3:
                                        sb.append("\u0412\u044B \u043F\u043E\u043B\u0443\u0447\u0438\u043B\u0438 \u0432\u0441\u0435 \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0435 \u043F\u0440\u043E\u0444\u0435\u0441\u0441\u0438\u0438.<br>");
                                        break;
                                }
                                //If the player hasn't available class , he can change pet too...
                                if (Config.ALT_CLASS_MASTER_STRIDER_UPDATE)
                                {
                                        sb.append("<table width=270>");
                                        sb.append("<tr><td><br></td></tr>");
                                        sb.append("<tr><td><a action=\"bypass -h npc_" + getObjectId() + "_upgrade_hatchling\">Upgrade Hatchling to Strider</a></td></tr>");
                                        sb.append("</table>");
                                }
                                sb.append("<br>");
                        }

                        for (Quest q : Quest.findAllEvents())
                                sb.append("Event: <a action=\"bypass -h Quest " + q.getName() + "\">" + q.getDescr() + "</a><br>");
                        sb.append("</body></html>");
                        html.setHtml(sb.toString());
                        player.sendPacket(html);

                }
                player.sendPacket(ActionFailed.STATIC_PACKET);
        }

        @Override
        public void onBypassFeedback(L2PcInstance player, String command)
        {
                if (command.startsWith("change_class"))
                {
                        int val = Integer.parseInt(command.substring(13));

                        ClassId classId = player.getClassId();
                        ClassId newClassId = ClassId.values()[val];

                        int level = player.getLevel();
                        int jobLevel = classId.level();
                        int newJobLevel = newClassId.level();

                        // -- Exploit prevention
                        // Prevents changing if config option disabled
                        if (!Config.ALT_CLASS_MASTER_SETTINGS.isAllowed(newJobLevel))
                                return;

                        // Prevents changing to class not in same class tree
                        if (!newClassId.childOf(classId))
                                return;

                        // Prevents changing between same level jobs
                        if (newJobLevel != jobLevel + 1)
                                return;

                        // Check for player level
                        if (level < 20 && newJobLevel > 1)
                                return;
                        if (level < 40 && newJobLevel > 2)
                                return;
                        if (level < 76 && newJobLevel > 3)
                                return;
                        // -- Prevention ends

                        // Check if player have all required items for class transfer
                        for (Integer _itemId : Config.ALT_CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel).keySet())
                        {
                                int _count = Config.ALT_CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel).get(_itemId);
                                if (player.getInventory().getInventoryItemCount(_itemId, -1) < _count)
                                {
                                        player.sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ITEMS));
                                        return;
                                }
                        }

                        // Get all required items for class transfer
                        for (Integer _itemId : Config.ALT_CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel).keySet())
                        {
                                int _count = Config.ALT_CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel).get(_itemId);
                                player.destroyItemByItemId("ClassMaster", _itemId, _count, player, true);
                        }

                        // Reward player with items
                        for (Integer _itemId : Config.ALT_CLASS_MASTER_SETTINGS.getRewardItems(newJobLevel).keySet())
                        {
                                int _count = Config.ALT_CLASS_MASTER_SETTINGS.getRewardItems(newJobLevel).get(_itemId);
                                player.addItem("ClassMaster", _itemId, _count, player, true);
                        }

                        changeClass(player, val);

                        player.rewardSkills();

                        NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
                        TextBuilder sb = new TextBuilder();
                        sb.append("<html><body>");
                        sb.append(getName() + ":<br>");
                        sb.append("<br>");
                        sb.append("\u041F\u043E\u0437\u0434\u0440\u0430\u0432\u043B\u044F\u044E! \u0422\u0435\u043F\u0435\u0440\u044C \u0412\u044B \u0441\u0442\u0430\u043B\u0438 <font color=\"LEVEL\">" + CharTemplateTable.getClassNameByIdFix(player.getClassId().getId()) + "</font>.");
                        sb.append("</body></html>");
                        html.setHtml(sb.toString());
                        player.sendPacket(html);

                        // Update the overloaded status of the L2PcInstance
                        player.refreshOverloaded();
                        // Update the expertise status of the L2PcInstance
                        player.refreshExpertisePenalty();
                }
                else if (command.startsWith("upgrade_hatchling") && Config.ALT_CLASS_MASTER_STRIDER_UPDATE)
                {
                        boolean canUpgrade = false;
                        if (player.getPet() != null)
                        {
                                if (player.getPet().getNpcId() == 12311 || player.getPet().getNpcId() == 12312 || player.getPet().getNpcId() == 12313)
                                {
                                        if (player.getPet().getLevel() >= 55)
                                                canUpgrade = true;
                                        else
                                                player.sendMessage("The level of your hatchling is too low to be upgraded.");
                                }
                                else
                                        player.sendMessage("You have to summon your hatchling.");
                        }
                        else
                                player.sendMessage("You have to summon your hatchling if you want to upgrade him.");

                        if (!canUpgrade)
                                return;

                        int[] hatchCollar =
                        { 3500, 3501, 3502 };
                        int[] striderCollar =
                        { 4422, 4423, 4424 };

                        //TODO: Maybe show a complete list of all hatchlings instead of using first one
                        for (int i = 0; i < 3; i++)
                        {
                                L2ItemInstance collar = player.getInventory().getItemByItemId(hatchCollar[i]);

                                if (collar != null)
                                {
                                        // Unsummon the hatchling
                                        player.getPet().unSummon(player);
                                        player.destroyItem("ClassMaster", collar, player, true);
                                        player.addItem("ClassMaster", striderCollar[i], 1, player, true);

                                        return;
                                }
                        }
                }
                else
                {
                        super.onBypassFeedback(player, command);
                }
        }

        private void changeClass(L2PcInstance player, int val)
        {
                player.setClassId(val);

                if (player.isSubClassActive())
                        player.getSubClasses().get(player.getClassIndex()).setClassId(player.getActiveClass());
                else
                        player.setBaseClass(player.getActiveClass());

                player.broadcastUserInfo();
        }
}

------------------------------------------------------------
Сохраняем, и открываем файл: Character.properties, и удаляем:
Код:

# Allow use of Event Managers for changing occupation without
# any quests needing completion.
# Retail: false
AllowClassMasters = False

Зыкрываем. Создаём файл: ClassMaster.properties, и в него добавляем:

Код:

# -------------------------------------------------------------
# Class Master
# -------------------------------------------------------------
# Config for special Class Master npc that can change players occupation
# If you need change occupation only use quest then set this to False (Default)
# Syntax: occupation number;[required item id(count)],[],...;[reward item id(count)],[],...;occupation number...
# Examples:
#
# ConfigClassMaster=1;[57(100000)];[];2;[57(1000000)];[];3;[57(10000000)],[5575(1000000)];[6622(1)]
# 1st occupation change for 100.000 Adena (item id 57)
# 2nd occupation change for 1.000.0000 Adena (item id 57)
# 3rd occupation change for 10.000.0000 Adena (item id 57) and 1.000.000 Ancient Adena (item id 5575)
# on 3rd occupation change player will be rewarded with 1 Book of Giants (item id 6622)
#
# ConfigClassMaster=1;[];[];2;[];[];3;[];[]
# 1st, 2nd, 3rd occupation change for free, without rewards
ConfigClassMaster = 1;[57(100000)];[];2;[57(1000000)];[];3;[57(10000000)],[5575(1000000)];[6622(1)]
# Spawn Class Master npc if you have any in spawnlist. Default = False
SpawnClassMaster = True

# Allows Strider Update
ClassMasterUpdateStrider = False

---------------------------------------------------------------
Если будут ошибки пишите, так же ссылка на архив со всеми изменёнными файлами (Пароль: www.zone-game.info ссылка: _http://dump.ru/file/2953025). Просто раскидываем их в папки и компилируем.

ggserver 27.02.2010 16:56

Re: Class Master на L2jServer как на L2jFree
 
Прошу помочь в настройке файла "byRuLeZzz.jar" http://depositfiles.com/files/96zd0852s изменить именно "При неудачной заточке вещь становится+15" сделать +0, я в этом не разбираюсь, или дайте инфу как можно самому сделать это.
С Уважением, ggserver.

iamhawk 14.04.2010 13:09

Re: Class Master на L2jServer как на L2jFree
 
Цитата:

Сообщение от ggserver (Сообщение 57387)
Прошу помочь в настройке файла "byRuLeZzz.jar" http://depositfiles.com/files/96zd0852s изменить именно "При неудачной заточке вещь становится+15" сделать +0, я в этом не разбираюсь, или дайте инфу как можно самому сделать это.
С Уважением, ggserver.

Это что вообще? тут классмастер обсуждается.

Добавлено через 1 минуту
Цитата:

Сообщение от SpeedFaer (Сообщение 35128)
Скачал новую версию сервера, увидел необходимость в доработке написанного ранее. Приступим...

То есть это можно с нуля вставлять в свой код?


Текущее время: 13:49. Часовой пояс GMT +3.

Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2023, Jelsoft Enterprises Ltd. Перевод: zCarot