L2JMobius

Fafurion Q00465 The We Are Friends quest does not work correctly or does not work at all

Black Judge · 3 · 334

Offline Black Judge

  • Heir
  • **
    • Posts: 36
Hi all. In the process of completing quests, I discovered a quest that does not work correctly or does not work at all.
You can kill cocoons as much as you like, but the Fairy Citizen does not appear, also the centaurs that are needed (only one was discovered) behave like ordinary mobs and can be killed by players, it turns out that you cannot interact with them in any way during the quest. The quest file also doesn't mention cocoons, and the cocoons file doesn't mention this quest.

Code: [Select]
package quests.Q00465_WeAreFriends;

import org.l2jmobius.gameserver.enums.QuestSound;
import org.l2jmobius.gameserver.enums.QuestType;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.quest.Quest;
import org.l2jmobius.gameserver.model.quest.QuestState;
import org.l2jmobius.gameserver.model.quest.State;

/**
 * We Are Friends (465)
 * @URL https://l2wiki.com/We_Are_Friends
 * @author Gigi
 */
public class Q00465_WeAreFriends extends Quest
{
// NPCs
private static final int FAIRY_CITIZEN = 32921;
private static final int FAIRY_CITIZEN_SPAWN = 32923;
// Item
private static final int MARK_OF_FRIENDSHIP = 17377;
private static final int FAIRY_LEAF_FLUTE = 17378;
private static final int CERTIFICATE_OF_PROMISE = 30384;
// Misc
private static final int MIN_LEVEL = 88;

public Q00465_WeAreFriends()
{
super(465);
addStartNpc(FAIRY_CITIZEN);
addTalkId(FAIRY_CITIZEN, FAIRY_CITIZEN_SPAWN);
registerQuestItems(MARK_OF_FRIENDSHIP);
addCondMinLevel(MIN_LEVEL, "no_level.htm");
}

@Override
public String onAdvEvent(String event, Npc npc, Player player)
{
final QuestState qs = getQuestState(player, false);
if (qs == null)
{
return null;
}
String htmltext = null;
switch (event)
{
case "32921-02.htm":
case "32921-07.html":
{
htmltext = event;
break;
}
case "32921-03.htm":
{
qs.startQuest();
htmltext = event;
break;
}
case "32923-02.html":
{
giveItems(player, MARK_OF_FRIENDSHIP, 1);
playSound(player, QuestSound.ITEMSOUND_QUEST_ITEMGET);
if ((getQuestItemsCount(player, MARK_OF_FRIENDSHIP) >= 2))
{
qs.setCond(2, true);
}
htmltext = event;
npc.deleteMe();
break;
}
case "32921-08.html":
{
giveItems(player, FAIRY_LEAF_FLUTE, 1);
giveItems(player, CERTIFICATE_OF_PROMISE, getRandom(1, 4));
qs.exitQuest(QuestType.DAILY, true);
htmltext = event;
break;
}
}
return htmltext;
}

@Override
public String onTalk(Npc npc, Player player)
{
final QuestState qs = getQuestState(player, true);
String htmltext = getNoQuestMsg(player);
switch (qs.getState())
{
case State.COMPLETED:
{
if (!qs.isNowAvailable() && (npc.getId() == FAIRY_CITIZEN))
{
htmltext = "32921-04.html";
break;
}
qs.setState(State.CREATED);
// fallthrough
}
case State.CREATED:
{
if (npc.getId() == FAIRY_CITIZEN)
{
htmltext = "32921-01.htm";
}
}
break;
case State.STARTED:
{
switch (npc.getId())
{
case FAIRY_CITIZEN:
{
if (qs.isCond(1))
{
htmltext = "32921-05.html";
}
else if (qs.isCond(2))
{
htmltext = "32921-06.html";
}
break;
}
case FAIRY_CITIZEN_SPAWN:
{
if (qs.isCond(1) && npc.getTitle().equals(player.getName()))
{
htmltext = "32923-01.html";
break;
}
return null;
}
}
}
}
return htmltext;
}
}

Code: [Select]
package ai.areas.FairySettlement.LargeCocoon;

import org.l2jmobius.gameserver.instancemanager.QuestManager;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Playable;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureAttacked;
import org.l2jmobius.gameserver.model.quest.Quest;

import ai.AbstractNpcAI;
import quests.Q10305_UnstoppableFutileEfforts.Q10305_UnstoppableFutileEfforts;

/**
 * Large Cocoon AI.
 * @author St3eT
 */
public class LargeCocoon extends AbstractNpcAI
{
// NPCs
private static final int LARGE_COCOON = 32920;
private static final int COCOON = 32919;
private static final int LARGE_CONTAMINED_COCOON = 19394;
private static final int COCOON_DESTROYER = 19294;
private static final int FAIRY_WARRIOR = 22867;
private static final int FAIRY_WARRIOR_HARD = 22870;
private static final int FAIRY_ROGUE = 22875;
private static final int FAIRY_ROGUE_HARD = 22878;
private static final int FAIRY_KNIGHT = 22883;
private static final int FAIRY_KNIGHT_HARD = 22886;
private static final int FAIRY_SUMMONER = 22899;
private static final int FAIRY_SUMMONER_HARD = 22902;
private static final int FAIRY_WIZARD = 22891;
private static final int FAIRY_WIZARD_HARD = 22894;
private static final int FAIRY_WITCH = 22907;
private static final int FAIRY_WITCH_HARD = 22910;

private LargeCocoon()
{
addStartNpc(COCOON, LARGE_COCOON);
addTalkId(COCOON, LARGE_COCOON);
addFirstTalkId(COCOON, LARGE_COCOON);
addSpawnId(COCOON, LARGE_COCOON);
setCreatureAttackedId(this::onCreatureAttacked, LARGE_COCOON);
}

@Override
public String onAdvEvent(String event, Npc npc, Player player)
{
switch (event)
{
case "attack":
{
final OnCreatureAttacked attackEvent = new OnCreatureAttacked();
attackEvent.setAttacker(player);
attackEvent.setTarget(npc);
attackEvent.setSkill(null);
onCreatureAttacked(attackEvent);
break;
}
case "attackPowerful":
{
// TODO: Quest 466 stuffs
final Quest qs10305 = QuestManager.getInstance().getQuest(Q10305_UnstoppableFutileEfforts.class.getSimpleName());
if (qs10305 != null)
{
qs10305.notifyEvent("NOTIFY_Q10305", npc, player);
}

if (getRandom(3) < 1)
{
addSpawn(LARGE_CONTAMINED_COCOON, npc.getX(), npc.getY(), npc.getZ(), npc.getHeading(), false, 30000);
}
else
{
switch (getRandom(6))
{
case 0:
{
addAttackPlayerDesire(addSpawn(FAIRY_WARRIOR_HARD, npc, false, 90000), player);
addAttackPlayerDesire(addSpawn(FAIRY_ROGUE_HARD, npc, false, 90000), player);
addAttackPlayerDesire(addSpawn(FAIRY_WIZARD_HARD, npc, false, 90000), player);
break;
}
case 1:
{
addAttackPlayerDesire(addSpawn(FAIRY_KNIGHT_HARD, npc, false, 90000), player);
addAttackPlayerDesire(addSpawn(FAIRY_WITCH_HARD, npc, false, 90000), player);
addAttackPlayerDesire(addSpawn(FAIRY_SUMMONER_HARD, npc, false, 90000), player);
break;
}
case 2:
{
addAttackPlayerDesire(addSpawn(FAIRY_WARRIOR_HARD, npc, false, 90000), player);
addAttackPlayerDesire(addSpawn(FAIRY_WIZARD_HARD, npc, false, 90000), player);
addAttackPlayerDesire(addSpawn(FAIRY_WITCH_HARD, npc, false, 90000), player);
break;
}
case 3:
{
addAttackPlayerDesire(addSpawn(FAIRY_ROGUE_HARD, npc, false, 90000), player);
addAttackPlayerDesire(addSpawn(FAIRY_WARRIOR_HARD, npc, false, 90000), player);
addAttackPlayerDesire(addSpawn(FAIRY_ROGUE_HARD, npc, false, 90000), player);
break;
}
case 4:
{
addAttackPlayerDesire(addSpawn(FAIRY_WIZARD_HARD, npc, false, 90000), player);
addAttackPlayerDesire(addSpawn(FAIRY_SUMMONER_HARD, npc, false, 90000), player);
addAttackPlayerDesire(addSpawn(FAIRY_WITCH_HARD, npc, false, 90000), player);
break;
}
case 5:
{
addAttackPlayerDesire(addSpawn(FAIRY_KNIGHT_HARD, npc, false, 90000), player);
addAttackPlayerDesire(addSpawn(FAIRY_KNIGHT_HARD, npc, false, 90000), player);
addAttackPlayerDesire(addSpawn(FAIRY_WITCH_HARD, npc, false, 90000), player);
break;
}
}
}
npc.deleteMe();
break;
}
}
return super.onAdvEvent(event, npc, player);
}

@Override
public String onSpawn(Npc npc)
{
if (getRandom(3) < 1)
{
addSpawn(COCOON_DESTROYER, npc.getX() + 120, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
}

switch (getRandom(6))
{
case 0:
{
addSpawn(FAIRY_WARRIOR, npc.getX() + 270, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
addSpawn(FAIRY_ROGUE, npc.getX() + 230, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
break;
}
case 1:
{
addSpawn(FAIRY_KNIGHT, npc.getX() + 270, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
addSpawn(FAIRY_ROGUE, npc.getX() + 230, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
break;
}
case 2:
{
addSpawn(FAIRY_WARRIOR, npc.getX() + 270, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
addSpawn(FAIRY_KNIGHT, npc.getX() + 230, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
break;
}
case 3:
{
addSpawn(FAIRY_SUMMONER, npc.getX() + 270, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
addSpawn(FAIRY_WARRIOR, npc.getX() + 230, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
break;
}
case 4:
{
addSpawn(FAIRY_WITCH, npc.getX() + 270, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
addSpawn(FAIRY_SUMMONER, npc.getX() + 230, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
break;
}
case 5:
{
addSpawn(FAIRY_SUMMONER, npc.getX() + 270, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
addSpawn(FAIRY_WITCH, npc.getX() + 230, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
break;
}
}

switch (getRandom(6))
{
case 0:
{
addSpawn(FAIRY_ROGUE, npc.getX() - 270, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
addSpawn(FAIRY_WARRIOR, npc.getX() - 230, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
break;
}
case 1:
{
addSpawn(FAIRY_KNIGHT, npc.getX() - 270, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
addSpawn(FAIRY_ROGUE, npc.getX() - 230, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
break;
}
case 2:
{
addSpawn(FAIRY_WARRIOR, npc.getX() - 270, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
addSpawn(FAIRY_KNIGHT, npc.getX() - 230, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
break;
}
case 3:
{
addSpawn(FAIRY_SUMMONER, npc.getX() - 270, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
addSpawn(FAIRY_WIZARD, npc.getX() - 230, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
break;
}
case 4:
{
addSpawn(FAIRY_WITCH, npc.getX() - 270, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
addSpawn(FAIRY_SUMMONER, npc.getX() - 230, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
break;
}
case 5:
{
addSpawn(FAIRY_WIZARD, npc.getX() - 270, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
addSpawn(FAIRY_WITCH, npc.getX() - 230, npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
break;
}
}

switch (getRandom(6))
{
case 0:
{
addSpawn(FAIRY_ROGUE, npc.getX(), npc.getY() + 270, npc.getZ(), npc.getHeading(), false, 0);
addSpawn(FAIRY_WARRIOR, npc.getX(), npc.getY() + 230, npc.getZ(), npc.getHeading(), false, 0);
break;
}
case 1:
{
addSpawn(FAIRY_KNIGHT, npc.getX(), npc.getY() + 270, npc.getZ(), npc.getHeading(), false, 0);
addSpawn(FAIRY_ROGUE, npc.getX(), npc.getY() + 230, npc.getZ(), npc.getHeading(), false, 0);
break;
}
case 2:
{
addSpawn(FAIRY_WARRIOR, npc.getX(), npc.getY() + 270, npc.getZ(), npc.getHeading(), false, 0);
addSpawn(FAIRY_KNIGHT, npc.getX(), npc.getY() + 230, npc.getZ(), npc.getHeading(), false, 0);
break;
}
case 3:
{
addSpawn(FAIRY_SUMMONER, npc.getX(), npc.getY() + 270, npc.getZ(), npc.getHeading(), false, 0);
addSpawn(FAIRY_WIZARD, npc.getX(), npc.getY() + 230, npc.getZ(), npc.getHeading(), false, 0);
break;
}
case 4:
{
addSpawn(FAIRY_WITCH, npc.getX(), npc.getY() + 270, npc.getZ(), npc.getHeading(), false, 0);
addSpawn(FAIRY_SUMMONER, npc.getX(), npc.getY() + 230, npc.getZ(), npc.getHeading(), false, 0);
break;
}
case 5:
{
addSpawn(FAIRY_WIZARD, npc.getX(), npc.getY() + 270, npc.getZ(), npc.getHeading(), false, 0);
addSpawn(FAIRY_WITCH, npc.getX(), npc.getY() + 230, npc.getZ(), npc.getHeading(), false, 0);
break;
}
}

return super.onSpawn(npc);
}

public void onCreatureAttacked(OnCreatureAttacked event)
{
final Npc npc = (Npc) event.getTarget();
final Playable playable = (Playable) event.getAttacker();

// TODO: Quest 466 stuffs
final Quest qs10305 = QuestManager.getInstance().getQuest(Q10305_UnstoppableFutileEfforts.class.getSimpleName());
if (qs10305 != null)
{
qs10305.notifyEvent("NOTIFY_Q10305", npc, playable.getActingPlayer());
}

if (getRandom(3) < 1)
{
addSpawn(LARGE_CONTAMINED_COCOON, npc.getX(), npc.getY(), npc.getZ(), npc.getHeading(), false, 30000);
}
else
{
switch (getRandom(6))
{
case 0:
{
addAttackPlayerDesire(addSpawn(FAIRY_WARRIOR, npc, false, 90000), playable);
addAttackPlayerDesire(addSpawn(FAIRY_ROGUE, npc, false, 90000), playable);
addAttackPlayerDesire(addSpawn(FAIRY_WIZARD, npc, false, 90000), playable);
break;
}
case 1:
{
addAttackPlayerDesire(addSpawn(FAIRY_KNIGHT, npc, false, 90000), playable);
addAttackPlayerDesire(addSpawn(FAIRY_WITCH, npc, false, 90000), playable);
addAttackPlayerDesire(addSpawn(FAIRY_SUMMONER, npc, false, 90000), playable);
break;
}
case 2:
{
addAttackPlayerDesire(addSpawn(FAIRY_WARRIOR, npc, false, 90000), playable);
addAttackPlayerDesire(addSpawn(FAIRY_WIZARD, npc, false, 90000), playable);
addAttackPlayerDesire(addSpawn(FAIRY_WITCH, npc, false, 90000), playable);
break;
}
case 3:
{
addAttackPlayerDesire(addSpawn(FAIRY_ROGUE, npc, false, 90000), playable);
addAttackPlayerDesire(addSpawn(FAIRY_WARRIOR, npc, false, 90000), playable);
addAttackPlayerDesire(addSpawn(FAIRY_ROGUE, npc, false, 90000), playable);
break;
}
case 4:
{
addAttackPlayerDesire(addSpawn(FAIRY_WIZARD, npc, false, 90000), playable);
addAttackPlayerDesire(addSpawn(FAIRY_SUMMONER, npc, false, 90000), playable);
addAttackPlayerDesire(addSpawn(FAIRY_WITCH, npc, false, 90000), playable);
break;
}
case 5:
{
addAttackPlayerDesire(addSpawn(FAIRY_KNIGHT, npc, false, 90000), playable);
addAttackPlayerDesire(addSpawn(FAIRY_KNIGHT, npc, false, 90000), playable);
addAttackPlayerDesire(addSpawn(FAIRY_WITCH, npc, false, 90000), playable);
break;
}
}
}
npc.deleteMe();
}

public static void main(String[] args)
{
new LargeCocoon();
}
}

Passing the quest

     Talk to Kimerian Refugee Fairy Citizen (Spirit of Eris) View the position of the NPC on the map in Ancient City Arcan (Ancient City Arcan) View the location of the location on the map.
     Go to Fairy Settlement (Fairy Colony) View the location on the map, kill Cocoon (Lv. 1), Large Cocoon (Lv. 1), until a Fairy Citizen appears from the cocoon, talk to her and get Fairy friendship Proof of Friendship (Token of Appreciation). The second Fairy friendship Proof of Friendship can be obtained by assisting the Sentauer Archer living there.
     Return to Fairy Citizen in Ancient City Arcana and receive your reward.


Offline Black Judge

  • Heir
  • **
    • Posts: 36
there is code for a working quest, but I don’t know how to integrate it into the L2jMobius kernel code


Code: [Select]
{

private static final int Feya_Gorozhanin = 32922;

public static final int FEYA_STARTER = 32921;

public static final int COCON = 32919;
public static final int HUGE_COCON = 32920;

public static final int SIGN_OF_GRATITUDE = 17377;


private static NpcInstance npcFeya = null;

public _465_WeAreFriends()
{
super(PARTY_NONE, DAILY);
addStartNpc(FEYA_STARTER);
addTalkId(Feya_Gorozhanin);
addFirstTalkId(Feya_Gorozhanin);
addKillId(COCON);
addKillId(HUGE_COCON);
addQuestItem(SIGN_OF_GRATITUDE);
addLevelCheck("32921-lvl.htm", 88);
}

@Override
public String onEvent(String event, QuestState st, NpcInstance npc)
{
Player player = st.getPlayer();
String htmltext = event;
if(event.equalsIgnoreCase("32921-4.htm"))
{
st.setCond(1);
}
if(event.equalsIgnoreCase("32922-4.htm"))
{
st.setCond(2);
st.giveItems(SIGN_OF_GRATITUDE, 2);
if(npcFeya == null)
return null;
st.unset("q465feya");
npcFeya.deleteMe();
npcFeya = null;
return null;
}

if(event.equalsIgnoreCase("despawn_task"))
{
if(npcFeya == null)
return null;
st.unset("q465feya");
npcFeya.deleteMe();
npcFeya = null;
return null;
}

if(event.equalsIgnoreCase("32921-8.htm"))
{
st.takeItems(SIGN_OF_GRATITUDE, 2);
st.giveItems(17378, 1);
st.finishQuest();
//30384 2-4
if(st.getQuestItemsCount(SIGN_OF_GRATITUDE) > 0)
{
st.giveItems(30384, 2);
return "32921-10.htm";
}
else
{
st.giveItems(30384, 4);
return "32921-8.htm";
}
}

if(event.equalsIgnoreCase("32921-10.htm"))
{
st.giveItems(17378, 1);
st.finishQuest();
//30384 2-4
if(st.getQuestItemsCount(SIGN_OF_GRATITUDE) > 0)
{
st.giveItems(30384, 2);
return "32921-10.htm";
}
else
{
st.giveItems(30384, 4);
return "32921-8.htm";
}
}
return event;
}

@Override
public String onTalk(NpcInstance npc, QuestState st)
{
Player player = st.getPlayer();
int npcId = npc.getNpcId();
int cond = st.getCond();
if(npcId == FEYA_STARTER)
{
if(cond == 0)
return "32921.htm";
if(cond == 1)
return "32921-5.htm";
if(cond == 2)
return "32921-6.htm";
}
return NO_QUEST_DIALOG;
}

@Override
public String onCompleted(NpcInstance npc, QuestState st)
{
String htmltext = COMPLETED_DIALOG;
if(npc.getNpcId() == FEYA_STARTER)
htmltext = "32921-comp.htm";
return htmltext;
}

@Override
public String onKill(NpcInstance npc, QuestState st)
{
if(Rnd.chance(5))
{
npcFeya = NpcUtils.spawnSingle(Feya_Gorozhanin, Location.findPointToStay(st.getPlayer(), 50, 100));
st.set("q465feya", ""+npcFeya.getObjectId()+"");
st.startQuestTimer("despawn_task", 180000);
}
return null;
}

@Override
public String onFirstTalk(NpcInstance npc, Player player)
{
QuestState st = player.getQuestState(getId());
if(st == null)
return "32922.htm";
if(st.get("q465feya") != null && Integer.parseInt(st.get("q465feya")) != npc.getObjectId())
return "32922-1.htm";
if(st.get("q465feya") == null)
return "32922-1.htm";
return "32922-3.htm";
}
}


Offline Black Judge

  • Heir
  • **
    • Posts: 36
I also noticed that the logic of the Fairy Colony location is not implemented quite correctly, cocoons work strangely.