/*
* 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 com.l2jfrozen.gameserver.model.actor.instance;
import com.l2jfrozen.Config;
import com.l2jfrozen.gameserver.datatables.sql.CharTemplateTable;
import com.l2jfrozen.gameserver.datatables.sql.ItemTable;
import com.l2jfrozen.gameserver.model.L2Object;
import com.l2jfrozen.gameserver.model.base.ClassId;
import com.l2jfrozen.gameserver.network.SystemMessageId;
import com.l2jfrozen.gameserver.network.serverpackets.ActionFailed;
import com.l2jfrozen.gameserver.network.serverpackets.MagicSkillUser;
import com.l2jfrozen.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jfrozen.gameserver.network.serverpackets.SystemMessage;
import com.l2jfrozen.gameserver.network.serverpackets.UserInfo;
import com.l2jfrozen.gameserver.templates.L2NpcTemplate;
import com.l2jfrozen.util.StringUtil;
/**
* Custom class allowing you to choose your class.
* You can customize class rewards as needed items. Check npc.properties for more informations.
*
* This NPC type got 2 differents ways to level :
* - the normal one, where you have to be at least of the good level
* NOTE : you have to take 1st class then 2nd, if you try to take 2nd directly it won't work.
* - the "allow_entire_tree" version, where you can take class depending of your current path.
* NOTE : you don't need to be of the good level.
*
* Added to the "change class" function, this NPC can noblesse and give available skills (related to
* your current class and level).
*/
public final class L2ClassMasterInstance extends L2NpcInstance
{
/**
* @param template
*/
public L2ClassMasterInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
}
@Override
public void showChatWindow(L2PcInstance player)
{
player.sendPacket(ActionFailed.STATIC_PACKET);
String filename = "data/html/classmaster/disabled.htm";
if (Config.ALLOW_CLASS_MASTERS)
filename = "data/html/classmaster/" + getNpcId() + ".htm";
// Send a Server->Client NpcHtmlMessage containing the text of the L2Npc to the L2PcInstance
NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(filename);
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
}
@Override
public void onBypassFeedback(L2PcInstance player, String command)
{
if (!Config.ALLOW_CLASS_MASTERS)
return;
if (command.startsWith("1stClass"))
showHtmlMenu(player, getObjectId(), 1);
else if (command.startsWith("2ndClass"))
showHtmlMenu(player, getObjectId(), 2);
else if (command.startsWith("3rdClass"))
showHtmlMenu(player, getObjectId(), 3);
else if (command.startsWith("change_class"))
{
int val = Integer.parseInt(command.substring(13));
if (checkAndChangeClass(player, val))
{
// self-animation
player.broadcastPacket(new MagicSkillUser(player, player, 5103, 1, 0, 0));
NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile("data/html/classmaster/ok.htm");
CharTemplateTable.getInstance();
html.replace("%name%", CharTemplateTable.getClassNameById(val));
player.sendPacket(html);
}
}
else if (command.startsWith("become_noble"))
{
NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
if (!player.isNoble())
{
player.setNoble(true);
player.sendPacket(new UserInfo(player));
html.setFile("data/html/classmaster/nobleok.htm");
player.sendPacket(html);
}
else
{
html.setFile("data/html/classmaster/alreadynoble.htm");
player.sendPacket(html);
}
}
else if (command.startsWith("learn_skills"))
{
player.giveAvailableSkills();
player.sendSkillList();
}
else
super.onBypassFeedback(player, command);
}
private static final void showHtmlMenu(L2PcInstance player, int objectId, int level)
{
NpcHtmlMessage html = new NpcHtmlMessage(objectId);
if (!Config.ALLOW_CLASS_MASTERS)
{
int jobLevel = player.getClassId().level();
final StringBuilder sb = new StringBuilder(100);
sb.append("<html><body>");
switch (jobLevel)
{
case 0:
if (Config.ALLOW_CLASS_MASTERS)
sb.append("Come back here when you reached level 20 to change your class.<br>");
else if (Config.ALLOW_CLASS_MASTERS)
sb.append("Come back after your first occupation change.<br>");
else if (Config.ALLOW_CLASS_MASTERS)
sb.append("Come back after your second occupation change.<br>");
else
sb.append("I can't change your occupation.<br>");
break;
case 1:
if (Config.ALLOW_CLASS_MASTERS)
sb.append("Come back here when you reached level 40 to change your class.<br>");
else if (Config.ALLOW_CLASS_MASTERS)
sb.append("Come back after your second occupation change.<br>");
else
sb.append("I can't change your occupation.<br>");
break;
case 2:
if (Config.ALLOW_CLASS_MASTERS)
sb.append("Come back here when you reached level 76 to change your class.<br>");
else
sb.append("I can't change your occupation.<br>");
break;
case 3:
sb.append("There is no class change available for you anymore.<br>");
break;
}
sb.append("</body></html>");
html.setHtml(sb.toString());
}
else
{
final ClassId currentClassId = player.getClassId();
if (currentClassId.level() >= level)
html.setFile("data/html/classmaster/nomore.htm");
else
{
final int minLevel = getMinLevel(currentClassId.level());
{
final StringBuilder menu = new StringBuilder(100);
for (ClassId cid : ClassId.values())
{
if (validateClassId(currentClassId, cid) && cid.level() == level)
{
CharTemplateTable.getInstance();
StringUtil.append(menu, "<a action=\"bypass -h npc_%objectId%_change_class ", String.valueOf(cid.getId()), "\">", CharTemplateTable.getClassNameById(cid.getId()), "</a><br>");
}
}
if (menu.length() > 0)
{
html.setFile("data/html/classmaster/template.htm");
CharTemplateTable.getInstance();
html.replace("%name%", CharTemplateTable.getClassNameById(currentClassId.getId()));
html.replace("%menu%", menu.toString());
}
else
{
html.setFile("data/html/classmaster/comebacklater.htm");
html.replace("%level%", String.valueOf(getMinLevel(level - 1)));
}
}
{
if (minLevel < Integer.MAX_VALUE)
{
html.setFile("data/html/classmaster/comebacklater.htm");
html.replace("%level%", String.valueOf(minLevel));
}
else
html.setFile("data/html/classmaster/nomore.htm");
}
}
}
html.replace("%objectId%", String.valueOf(objectId));
html.replace("%req_items%", getRequiredItems(level));
player.sendPacket(html);
}
private static final boolean checkAndChangeClass(L2PcInstance player, int val)
{
final ClassId currentClassId = player.getClassId();
if (!validateClassId(currentClassId, val))
return false;
int newJobLevel = currentClassId.level() + 1;
// Weight/Inventory check
if(!Config.CLASS_MASTER_SETTINGS.getRewardItems(newJobLevel).isEmpty())
{
if (player.getWeightPenalty() >= 3)
{
player.sendPacket(new SystemMessage(SystemMessageId.INVENTORY_LESS_THAN_80_PERCENT));
return false;
}
}
// check if player have all required items for class transfer
for (int _itemId : Config.CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel).keySet())
{
int _count = Config.CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel).get(_itemId);
if (player.getInventory().getInventoryItemCount(_itemId, -1) < _count)
{
player.sendPacket(SystemMessageId.NOT_ENOUGH_ITEMS);
return false;
}
}
// get all required items for class transfer
for (int _itemId : Config.CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel).keySet())
{
int _count = Config.CLASS_MASTER_SETTINGS.getRequireItems(newJobLevel).get(_itemId);
if (!player.destroyItemByItemId("ClassMaster", _itemId, _count, player, true))
return false;
}
// reward player with items
for (int _itemId : Config.CLASS_MASTER_SETTINGS.getRewardItems(newJobLevel).keySet())
{
int _count = Config.CLASS_MASTER_SETTINGS.getRewardItems(newJobLevel).get(_itemId);
player.addItem("ClassMaster", _itemId, _count, player, true);
}
player.setClassId(val);
if (player.isSubClassActive())
player.getSubClasses().get(player.getClassIndex()).setClassId(player.getActiveClass());
else
player.setBaseClass(player.getActiveClass());
player.broadcastUserInfo();
return true;
}
/**
* Returns minimum player level required for next class transfer
* @param level - current skillId level (0 - start, 1 - first, etc)
*/
private static final int getMinLevel(int level)
{
switch (level)
{
case 0:
return 20;
case 1:
return 40;
case 2:
return 76;
default:
return Integer.MAX_VALUE;
}
}
/**
* Returns true if class change is possible
* @param oldCID current player ClassId
* @param val new class index
* @return
*/
private static final boolean validateClassId(ClassId oldCID, int val)
{
try
{
return validateClassId(oldCID, ClassId.values()[val]);
}
catch (Exception e)
{
// possible ArrayOutOfBoundsException
}
return false;
}
/**
* Returns true if class change is possible
* @param oldCID current player ClassId
* @param newCID new ClassId
* @return true if class change is possible
*/
private static final boolean validateClassId(ClassId oldCID, ClassId newCID)
{
if (newCID == null || newCID.getRace() == null)
return false;
if (oldCID.equals(newCID.getParent()))
return true;
return false;
}
private static String getRequiredItems(int level)
{
if (Config.CLASS_MASTER_SETTINGS.getRequireItems(level) == null || Config.CLASS_MASTER_SETTINGS.getRequireItems(level).isEmpty())
return "<tr><td>none</td></r>";
StringBuilder sb = new StringBuilder();
for (int _itemId : Config.CLASS_MASTER_SETTINGS.getRequireItems(level).keySet())
{
int _count = Config.CLASS_MASTER_SETTINGS.getRequireItems(level).get(_itemId);
sb.append("<tr><td><font color=\"LEVEL\">" + _count + "</font></td><td>" + ItemTable.getInstance().getTemplate(_itemId).getName() + "</td></tr>");
}
return sb.toString();
}
/**
* @return
*/
public static L2ClassMasterInstance getInstance()
{
// TODO Auto-generated method stub
return null;
}
}
You can post now and register later.
If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.
From Salvation onwards I think you need a patched nwindow.dll that allows such modifications, try to see if you get what you need here:
https://drive.google.com/drive/u/1/folders/1LLbQFGf8KlR-O0Iv5umfF-pwZgrDh9bd
hello everyone!
I am wanting to save the files (Ini. - Data - ) of the EP5 Client: Salvation... But they generate the error "corrupt files"... I tried several versions of L2FileEditor without good results.
I need help! Thank you!
Opening December 6th at 19:00 (GMT +3)!
Open Beta Test from November 30th!
https://l2soe.com/
🌟 Introducing L2 Saga of Eternia: A Revolution in Lineage 2 High Five! 🌟
Dear Lineage 2 enthusiasts,
Prepare to witness the future of private servers! L2 Saga of Eternia is not just another High Five project—it’s a game-changing experience designed to compete with the giants of the Lineage 2 private server scene. Built for the community, by the community, we’re here to raise the bar in quality, innovation, and longevity.
What Sets Us Apart?
💎 No Wipes, Ever
Say goodbye to the fear of losing your progress. Our server is built to last and will never close. Stability and consistency are our promises to you.
⚔️ Weekly New Content
Our dedicated development team ensures fresh challenges, events, and updates every week. From custom quests to exclusive features, there will always be something exciting to explore.
💰 No Pay-to-Win
Skill and strategy matter most here. Enjoy a balanced gameplay environment where your achievements come from effort, not your wallet.
🌍 A Massive Community
With 2000+ players expected, join a vibrant and active community of like-minded adventurers ready to conquer the world of Aden.
🏆 Fair and Competitive Gameplay
Our systems are designed to promote healthy competition while avoiding abusive mechanics and exploits.
🔧 Professional Development
From advanced bug fixes to carefully curated content, we pride ourselves on smooth performance, no lag, and unparalleled server quality.
Key Features
Chronicle: High Five with unique interface
Rate: Dynamic x10 rates
Class Balance: Carefully fine-tuned for a fair experience
PvP Focused: PvP Ranking & aura display effect for 3 Top PvPers every week
Custom Events: Seasonal and permanent events to keep you engaged
Additional Features:
Custom Endgame Content: Introduce unique dungeons, raids, or zones unavailable in other servers.
Player-Driven Economy: Implement a strong market system and avoid overinflated drops or rewards.
Epic Siege Battles: Announce special large-scale sieges and PvP events.
Incentives for Streamers and Clans: Attract influencers and big clans to boost server publicity.
Roadmap Transparency: Share a public roadmap of planned updates to build trust and excitemen
Here you can read all the features: https://l2soe.com/features
Video preview:
Join the Revolution!
This is your chance to be part of something legendary. L2 Saga of Eternia is not just a server; it’s a movement to redefine what Lineage 2 can be. Whether you’re a seasoned veteran or a newcomer to the world of Aden, we invite you to experience Lineage 2 at its finest.
Official Launch Date: December 6th 2024
Website: https://l2soe.com/
Facebook: https://www.facebook.com/l2soe
Discord: https://discord.com/invite/l2eternia
Let’s build the ultimate Lineage 2 experience together. See you in-game! 🎮
Question
Andrey™
1. ClassMaster from aCis. Who can help me to adapt it for frozen? I already try but don't work! :(
aCis
Frozen (adapted by me) and don't work!!
3 answers to this question
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.