/*
* Copyright (C) 2004-2015 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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 ai.npc.MentorGuide;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.logging.Level;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import ai.npc.AbstractNpcAI;
import com.l2jserver.Config;
import com.l2jserver.gameserver.data.xml.IXmlReader;
import com.l2jserver.gameserver.enums.CategoryType;
import com.l2jserver.gameserver.enums.MailType;
import com.l2jserver.gameserver.instancemanager.MailManager;
import com.l2jserver.gameserver.instancemanager.MentorManager;
import com.l2jserver.gameserver.model.L2Mentee;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.base.ClassLevel;
import com.l2jserver.gameserver.model.entity.Message;
import com.l2jserver.gameserver.model.events.EventType;
import com.l2jserver.gameserver.model.events.ListenerRegisterType;
import com.l2jserver.gameserver.model.events.annotations.RegisterEvent;
import com.l2jserver.gameserver.model.events.annotations.RegisterType;
import com.l2jserver.gameserver.model.events.impl.character.player.OnPlayerLevelChanged;
import com.l2jserver.gameserver.model.events.impl.character.player.OnPlayerProfessionChange;
import com.l2jserver.gameserver.model.events.impl.character.player.mentoring.OnPlayerMenteeAdd;
import com.l2jserver.gameserver.model.events.impl.character.player.mentoring.OnPlayerMenteeLeft;
import com.l2jserver.gameserver.model.events.impl.character.player.mentoring.OnPlayerMenteeRemove;
import com.l2jserver.gameserver.model.events.impl.character.player.mentoring.OnPlayerMenteeStatus;
import com.l2jserver.gameserver.model.events.impl.character.player.mentoring.OnPlayerMentorStatus;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.skills.BuffInfo;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.gameserver.network.serverpackets.mentoring.ExMentorList;
import com.l2jserver.gameserver.util.Util;
/**
* Mentor Guide.
* @author Gnacik, UnAfraid
*/
public class MentorGuide extends AbstractNpcAI implements IXmlReader
{
// NPCs
private static final int MENTOR_GUIDE = 33587;
// Items
private static final int MENTEE_CERT = 33800;
private static final int MENTEE_MARK = 33804;
private static final int MENTEE_HEADPHONE = 34759;
private static final int DIPLOMA = 33805;
// Skills
private final static SkillHolder[] MENTEE_BUFFS =
{
new SkillHolder(9227, 1), // Mentor's Poem of Horn
new SkillHolder(9228, 1), // Mentor's Poem of Drum
new SkillHolder(9229, 1), // Mentor's Poem of Lute
new SkillHolder(9230, 1), // Mentor's Poem of Organ
new SkillHolder(9231, 1), // Mentor's Poem of Guitar
new SkillHolder(9232, 1), // Mentor's Poem of Harp
new SkillHolder(17082, 1), // Mentor's Prevailing Sonata
new SkillHolder(17083, 1), // Mentor's Daring Sonata
new SkillHolder(17084, 1), // Mentor's Refreshing Sonata
new SkillHolder(9233, 1), // Mentor's Guidance
};
protected static final SkillHolder[] MENTOR_BUFFS =
{
new SkillHolder(9256, 1), // Mentee's Appreciation;
};
private static final SkillHolder MENTEE_MENTOR_SUMMON = new SkillHolder(9379, 1); // Mentee's Mentor Summon
private static final SkillHolder MENTOR_KNIGHTS_HARMONY = new SkillHolder(9376, 1); // Mentor's Knight's Harmony
private static final SkillHolder MENTOR_WIZARDS_HARMONY = new SkillHolder(9377, 1); // Mentor's Wizard's Harmony
private static final SkillHolder MENTOR_WARRIORS_HARMONY = new SkillHolder(9378, 1); // Mentor's Warrior's Harmony
// Misc
private static final int MAX_LEVEL = 85;
private static final String LEVEL_UP_TITLE = "Mentee coin from Mentee leveling";
private static final String LEVEL_UP_BODY = "Your mentee %s has reached level %d, so you are receiving some Mentee Coin. After Mentee Coin has successfully been removed and placed into your inventory please be sure to delete this letter. If your mailbox is full when any future letters are sent to you cannot be delivered and you will not receive these items.";
private static final String MENTEE_ADDED_TITLE = "Congratulations on becoming a mentee.";
private static final String MENTEE_ADDED_BODY = "Greetings. This is the Mentor Guide.\n\nYou will experience a world of unlimited adventures with your mentor, Exciting, isn't it?\n\nWhen you graduate from mentee status (upon awakening at level 85), you will receive a Mentee Certificate. If you bring it to me, I will give you a Diploma that you can exchange for R-grade equipment.";
private static final String MENTEE_GRADUATE_TITLE = "Congratulations on your graduation";
private static final String MENTEE_GRADUATE_BODY = "Greetings! This is the Mentor Guide.\nCongratulations! Did you enjoy the time with a mentor? Here is a Mentee Certificate for graduating.\n\nFind me in town, and I'll give you a Diploma if you show me your Mentee Certificatee. You'll also get a small graduation gift!\n\nNow, on to your next Adventure!";
static final Map<Integer, Integer> MENTEE_COINS = new HashMap<>();
@Override
public void load()
{
parseDatapackFile("config/MentorCoins.xml");
LOGGER.log(Level.INFO, getClass().getSimpleName() + ": Loaded: " + MENTEE_COINS.size() + " mentee coins");
}
@Override
public void parseDocument(Document doc)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("mentee".equalsIgnoreCase(d.getNodeName()))
{
final int level = parseInteger(d.getAttributes(), "level");
final int coins = parseInteger(d.getAttributes(), "coins");
MENTEE_COINS.put(level, coins);
}
}
}
}
}
private MentorGuide()
{
super(MentorGuide.class.getSimpleName(), "ai/npc");
addFirstTalkId(MENTOR_GUIDE);
addStartNpc(MENTOR_GUIDE);
addTalkId(MENTOR_GUIDE);
load();
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
String htmltext = event;
if (event.equalsIgnoreCase("exchange"))
{
if (hasQuestItems(player, MENTEE_CERT) && (player.getLevel() >= MAX_LEVEL) && (player.getClassId().level() == ClassLevel.AWAKEN.ordinal()))
{
takeItems(player, MENTEE_CERT, 1);
giveItems(player, DIPLOMA, 1);
return null;
}
htmltext = "33587-04.htm";
}
else if (event.startsWith("REMOVE_BUFFS"))
{
final String[] params = event.split(" ");
if (Util.isDigit(params[1]))
{
final int objectId = Integer.valueOf(params[1]);
MentorManager.getInstance().getMentees(objectId).stream().filter(Objects::nonNull).filter(L2Mentee::isOnline).forEach(mentee ->
{
MentorManager.getInstance().cancelMentoringBuffs(mentee.getPlayerInstance());
mentee.sendPacket(new ExMentorList(mentee.getPlayerInstance()));
});
}
}
return htmltext;
}
@Override
public String onFirstTalk(L2Npc npc, L2PcInstance player)
{
return "33587-01.htm";
}
@RegisterEvent(EventType.ON_PLAYER_MENTEE_ADD)
@RegisterType(ListenerRegisterType.GLOBAL_PLAYERS)
public void onMenteeAdded(OnPlayerMenteeAdd event)
{
// Starting buffs for Mentor
for (SkillHolder sk : MENTOR_BUFFS)
{
sk.getSkill().applyEffects(event.getMentor(), event.getMentor());
}
// Starting buffs for Mentee
for (SkillHolder sk : MENTEE_BUFFS)
{
sk.getSkill().applyEffects(event.getMentee(), event.getMentee());
}
// Update mentor list
event.getMentor().sendPacket(new ExMentorList(event.getMentor()));
// Add the mentee skill
handleMenteeSkills(event.getMentee());
// Give mentor's buffs only if he didn't had them.
handleMentorSkills(event.getMentor());
// Send mail with the headphone
sendMail(event.getMentee(), MENTEE_ADDED_TITLE, MENTEE_ADDED_BODY, MENTEE_HEADPHONE, 1);
}
@RegisterEvent(EventType.ON_PLAYER_MENTEE_STATUS)
@RegisterType(ListenerRegisterType.GLOBAL_PLAYERS)
public void OnPlayerMenteeStatus(OnPlayerMenteeStatus event)
{
final L2PcInstance player = event.getMentee();
if (event.isMenteeOnline())
{
final L2Mentee mentor = MentorManager.getInstance().getMentor(player.getObjectId());
if ((mentor != null) && mentor.isOnline())
{
//@formatter:off
final long mentorBuffs = mentor.getPlayerInstance().getEffectList().getEffects()
.stream()
.map(BuffInfo::getSkill)
.filter(Skill::isMentoring)
.count();
//@formatter:on
if (mentorBuffs != MENTOR_BUFFS.length)
{
// Starting buffs for Mentor
for (SkillHolder sk : MENTOR_BUFFS)
{
sk.getSkill().applyEffects(mentor.getPlayerInstance(), mentor.getPlayerInstance());
}
}
// Starting buffs for Mentee
for (SkillHolder sk : MENTEE_BUFFS)
{
sk.getSkill().applyEffects(player, player);
}
// Add the mentee skill
handleMenteeSkills(player);
mentor.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOUR_MENTEE_S1_HAS_CONNECTED).addCharName(player));
mentor.sendPacket(new ExMentorList(mentor.getPlayerInstance()));
}
player.sendPacket(new ExMentorList(player));
}
else
{
final L2Mentee mentor = MentorManager.getInstance().getMentor(player.getObjectId());
if ((mentor != null) && mentor.isOnline())
{
if (MentorManager.getInstance().isAllMenteesOffline(mentor.getObjectId(), player.getObjectId()))
{
MentorManager.getInstance().cancelMentoringBuffs(mentor.getPlayerInstance());
}
mentor.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOUR_MENTEE_S1_HAS_DISCONNECTED).addCharName(player));
mentor.sendPacket(new ExMentorList(mentor.getPlayerInstance()));
}
}
}
@RegisterEvent(EventType.ON_PLAYER_MENTOR_STATUS)
@RegisterType(ListenerRegisterType.GLOBAL_PLAYERS)
public void OnPlayerMentorStatus(OnPlayerMentorStatus event)
{
final L2PcInstance player = event.getMentor();
if (event.isMentorOnline())
{
// stop buffs removal task
cancelQuestTimer("REMOVE_BUFFS " + player.getObjectId(), null, null);
MentorManager.getInstance().getMentees(player.getObjectId()).stream().filter(Objects::nonNull).filter(L2Mentee::isOnline).forEach(mentee ->
{
//@formatter:off
final long menteeBuffs = mentee.getPlayerInstance().getEffectList().getEffects()
.stream()
.map(BuffInfo::getSkill)
.filter(Skill::isMentoring)
.count();
//@formatter:on
if (menteeBuffs != MENTEE_BUFFS.length)
{
// Starting buffs for Mentee
for (SkillHolder sk : MENTEE_BUFFS)
{
sk.getSkill().applyEffects(mentee.getPlayerInstance(), mentee.getPlayerInstance());
}
}
mentee.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOUR_MENTOR_S1_HAS_CONNECTED).addCharName(player));
mentee.sendPacket(new ExMentorList(mentee.getPlayerInstance()));
});
if (MentorManager.getInstance().hasOnlineMentees(player.getObjectId()))
{
// Starting buffs for Mentor
for (SkillHolder sk : MENTOR_BUFFS)
{
sk.getSkill().applyEffects(player, player);
}
}
// Give mentor's buffs only if he didn't had them.
handleMentorSkills(player);
player.sendPacket(new ExMentorList(player));
}
else
{
startQuestTimer("REMOVE_BUFFS " + player.getObjectId(), 5 * 60 * 1000, null, null);
MentorManager.getInstance().getMentees(player.getObjectId()).stream().filter(Objects::nonNull).filter(L2Mentee::isOnline).forEach(mentee ->
{
mentee.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOUR_MENTOR_S1_HAS_DISCONNECTED).addCharName(player));
mentee.sendPacket(new ExMentorList(mentee.getPlayerInstance()));
});
}
}
@RegisterEvent(EventType.ON_PLAYER_PROFESSION_CHANGE)
@RegisterType(ListenerRegisterType.GLOBAL_PLAYERS)
public void onProfessionChange(OnPlayerProfessionChange event)
{
final L2PcInstance player = event.getActiveChar();
if (player.isMentor())
{
// Give mentor's buffs only if he didn't had them.
handleMentorSkills(player);
return;
}
// Not a mentee
if (!player.isMentee())
{
return;
}
handleMenteeSkills(player);
if (player.isInCategory(CategoryType.AWAKEN_GROUP))
{
handleGraduateMentee(player);
}
}
@RegisterEvent(EventType.ON_PLAYER_LEVEL_CHANGED)
@RegisterType(ListenerRegisterType.GLOBAL_PLAYERS)
public void onLevelIncreased(OnPlayerLevelChanged event)
{
final L2PcInstance player = event.getActiveChar();
// Not a mentee
if (!player.isMentee())
{
return;
}
checkLevelForReward(player); // Checking level to send a mail if is necessary
if (player.getLevel() > MAX_LEVEL)
{
handleGraduateMentee(player);
}
else
{
final L2Mentee mentor = MentorManager.getInstance().getMentor(player.getObjectId());
if ((mentor != null) && mentor.isOnline())
{
mentor.sendPacket(new ExMentorList(mentor.getPlayerInstance()));
}
}
}
@RegisterEvent(EventType.ON_PLAYER_MENTEE_LEFT)
@RegisterType(ListenerRegisterType.GLOBAL_PLAYERS)
public void onMenteeLeft(OnPlayerMenteeLeft event)
{
final L2PcInstance player = event.getMentee();
final L2PcInstance mentor = event.getMentor().getPlayerInstance();
// Remove the mentee skills
player.removeSkill(MENTEE_MENTOR_SUMMON.getSkill(), true);
// If player does not have any mentees anymore remove mentor skills.
if ((mentor != null) && (MentorManager.getInstance().getMentees(mentor.getObjectId()) == null))
{
mentor.removeSkill(MENTOR_KNIGHTS_HARMONY.getSkill(), true);
mentor.removeSkill(MENTOR_WIZARDS_HARMONY.getSkill(), true);
mentor.removeSkill(MENTOR_WARRIORS_HARMONY.getSkill(), true);
// Clear the mentee
mentor.sendPacket(new ExMentorList(mentor));
}
// Clear mentee status
player.sendPacket(new ExMentorList(player));
}
@RegisterEvent(EventType.ON_PLAYER_MENTEE_REMOVE)
@RegisterType(ListenerRegisterType.GLOBAL_PLAYERS)
public void onMenteeRemove(OnPlayerMenteeRemove event)
{
final L2Mentee mentee = event.getMentee();
final L2PcInstance mentor = event.getMentor();
final L2PcInstance player = mentee.getPlayerInstance();
if (player != null)
{
// Remove the mentee skills
player.removeSkill(MENTEE_MENTOR_SUMMON.getSkill(), true);
// Clear mentee status
player.sendPacket(new ExMentorList(player));
}
// If player does not have any mentees anymore remove mentor skills.
if (MentorManager.getInstance().getMentees(mentor.getObjectId()) == null)
{
mentor.removeSkill(MENTOR_KNIGHTS_HARMONY.getSkill(), true);
mentor.removeSkill(MENTOR_WIZARDS_HARMONY.getSkill(), true);
mentor.removeSkill(MENTOR_WARRIORS_HARMONY.getSkill(), true);
}
// Remove mentee from the list
event.getMentor().sendPacket(new ExMentorList(mentor));
}
private void handleMenteeSkills(L2PcInstance player)
{
// Give mentee's buffs only if he didn't had them.
if (player.getKnownSkill(MENTEE_MENTOR_SUMMON.getSkillId()) == null)
{
// Add the mentee skills
player.addSkill(MENTEE_MENTOR_SUMMON.getSkill(), false);
}
}
private void handleMentorSkills(L2PcInstance player)
{
// Give mentor's buffs only if he didn't had them.
if (player.getKnownSkill(MENTOR_KNIGHTS_HARMONY.getSkillId()) == null)
{
// Add the mentor skills
player.addSkill(MENTOR_KNIGHTS_HARMONY.getSkill(), false);
player.addSkill(MENTOR_WIZARDS_HARMONY.getSkill(), false);
player.addSkill(MENTOR_WARRIORS_HARMONY.getSkill(), false);
}
}
private void handleGraduateMentee(L2PcInstance player)
{
MentorManager.getInstance().cancelMentoringBuffs(player);
final L2Mentee mentor = MentorManager.getInstance().getMentor(player.getObjectId());
if (mentor != null)
{
MentorManager.getInstance().setPenalty(mentor.getObjectId(), Config.MENTOR_PENALTY_FOR_MENTEE_COMPLETE);
MentorManager.getInstance().deleteMentor(mentor.getObjectId(), player.getObjectId());
if (mentor.isOnline())
{
mentor.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S1_HAS_AWAKENED_AND_THE_MENTOR_MENTEE_RELATIONSHIP_HAS_ENDED_THE_MENTOR_CANNOT_OBTAIN_ANOTHER_MENTEE_FOR_ONE_DAY_AFTER_THE_MENTEE_S_GRADUATION).addPcName(player));
if (MentorManager.getInstance().isAllMenteesOffline(mentor.getObjectId(), player.getObjectId()))
{
MentorManager.getInstance().cancelMentoringBuffs(mentor.getPlayerInstance());
}
mentor.sendPacket(new ExMentorList(mentor.getPlayerInstance()));
}
// Remove the mentee skills
player.removeSkill(MENTEE_MENTOR_SUMMON.getSkill(), true);
// Clear mentee status
player.sendPacket(new ExMentorList(player));
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOUR_MENTOR_MENTEE_RELATIONSHIP_WITH_YOUR_MENTOR_S1_HAS_ENDED_AS_YOU_ARE_AN_AWAKENED_CHARACTER_OF_LV_85_OR_ABOVE_YOU_CAN_NO_LONGER_BE_PAIRED_WITH_A_MENTOR).addPcName(player));
sendMail(player, MENTEE_GRADUATE_TITLE, MENTEE_GRADUATE_BODY, MENTEE_CERT, 1);
}
}
/**
* Verifies if player is mentee and if his current level should reward his mentor and if so sends a mail with reward.
* @param player
*/
private void checkLevelForReward(L2PcInstance player)
{
if (!MENTEE_COINS.containsKey(player.getLevel()))
{
return;
}
final L2Mentee mentor = MentorManager.getInstance().getMentor(player.getObjectId());
if (mentor == null)
{
return;
}
int amount = MENTEE_COINS.get(player.getLevel());
if (amount > 0)
{
sendMail(mentor.getObjectId(), player, LEVEL_UP_TITLE, String.format(LEVEL_UP_BODY, player.getName(), player.getLevel()), MENTEE_MARK, amount);
}
}
private void sendMail(L2PcInstance player, String title, String body, int itemId, long amount)
{
sendMail(player.getObjectId(), player, title, body, itemId, amount);
}
private void sendMail(int objectId, L2PcInstance player, String title, String body, int itemId, long amount)
{
final Message msg = new Message(MENTOR_GUIDE, objectId, title, body, MailType.MENTOR_NPC);
msg.createAttachments().addItem(getName(), itemId, amount, null, player);
MailManager.getInstance().sendMessage(msg);
}
public static void main(String[] args)
{
new MentorGuide();
}
}