converted tests to QuestManuscript

This commit is contained in:
Hendrik Brummermann 2023-10-21 10:55:55 +02:00
parent 8cfee9a2e9
commit 47a587443e
27 changed files with 623 additions and 1887 deletions

View file

@ -69,10 +69,7 @@ public class FriendAchievementFactory extends AbstractAchievementFactory {
// Anna, in Ados
new QuestCompletedCondition("toys_collector"),
// Sally, Orril River
// 'completed' doesn't work for Sally - return player.hasQuest(QUEST_SLOT) && !"start".equals(player.getQuest(QUEST_SLOT)) && !"rejected".equals(player.getQuest(QUEST_SLOT));
new AndCondition(
new QuestActiveCondition("campfire"),
new QuestNotInStateCondition("campfire", "start")),
new QuestCompletedCondition("campfire"),
// Annie, Kalavan city gardens
new QuestStateStartsWithCondition("icecream_for_annie","eating;"),
// Elisabeth, Kirdneh
@ -86,9 +83,7 @@ public class FriendAchievementFactory extends AbstractAchievementFactory {
// Finn Farmer, George
new QuestCompletedCondition("coded_message"),
// Marianne, Deniran City S
new AndCondition(
new QuestActiveCondition("eggs_for_marianne"),
new QuestNotInStateCondition("eggs_for_marianne", "start"))
new QuestCompletedCondition("eggs_for_marianne")
)));
// quests about finding people

View file

@ -28,6 +28,7 @@ import games.stendhal.server.entity.npc.action.SetQuestAction;
import games.stendhal.server.entity.npc.action.SetQuestAndModifyKarmaAction;
import games.stendhal.server.entity.npc.condition.AndCondition;
import games.stendhal.server.entity.npc.condition.NotCondition;
import games.stendhal.server.entity.npc.condition.OrCondition;
import games.stendhal.server.entity.npc.condition.QuestActiveCondition;
import games.stendhal.server.entity.npc.condition.QuestCompletedCondition;
import games.stendhal.server.entity.npc.condition.QuestNotStartedCondition;
@ -39,6 +40,7 @@ import games.stendhal.server.entity.npc.condition.TimePassedCondition;
* @author hendrik
*/
public class QuestOfferBuilder<T extends QuestOfferBuilder<T>> {
protected String begOnGreeting = null;
protected String respondToRequest = null;
protected String respondToUnrepeatableRequest = "Thanks for your help. I have no new task for you.";
protected String respondToRepeatedRequest = null;
@ -54,6 +56,12 @@ public class QuestOfferBuilder<T extends QuestOfferBuilder<T>> {
super();
}
@SuppressWarnings("unchecked")
public T begOnGreeting(String begOnGreeting) {
this.begOnGreeting = begOnGreeting;
return (T) this;
}
@SuppressWarnings("unchecked")
public T respondToRequest(String respondToRequest) {
this.respondToRequest = respondToRequest;
@ -113,7 +121,9 @@ public class QuestOfferBuilder<T extends QuestOfferBuilder<T>> {
void simulateFirst(String npc, QuestSimulator simulator) {
simulator.playerSays("hi");
simulator.playerSays("quest");
if (begOnGreeting == null) {
simulator.playerSays("quest");
}
simulator.npcSays(npc, respondToRequest);
simulator.playerSays("no");
simulator.npcSays(npc, respondToReject);
@ -121,17 +131,21 @@ public class QuestOfferBuilder<T extends QuestOfferBuilder<T>> {
simulator.info("");
simulator.playerSays("hi");
simulator.playerSays("quest");
if (begOnGreeting == null) {
simulator.playerSays("quest");
}
simulator.npcSays(npc, respondToRequest);
simulator.playerSays("yes");
simulator.npcSays(npc, respondToAccept);
simulator.playerSays("bye");
simulator.info("");
simulator.playerSays("hi");
simulator.playerSays("quest");
simulator.npcSays(npc, remind);
simulator.info("");
if (begOnGreeting == null) {
simulator.playerSays("hi");
simulator.playerSays("quest");
simulator.npcSays(npc, remind);
simulator.info("");
}
}
void simulateNotRepeatable(String npc, QuestSimulator simulator) {
@ -156,6 +170,21 @@ public class QuestOfferBuilder<T extends QuestOfferBuilder<T>> {
ChatAction startQuestAction = task.buildStartQuestAction(questSlot);
ChatAction rejectQuestAction = task.buildRejectQuestAction(questSlot);
if (begOnGreeting != null) {
npc.add(ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new OrCondition(
new QuestNotStartedCondition(questSlot),
new AndCondition(
new QuestActiveCondition(questSlot),
new NotCondition(questCompletedCondition)
)
),
ConversationStates.QUEST_OFFERED,
begOnGreeting,
null);
}
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new QuestNotStartedCondition(questSlot),

View file

@ -591,6 +591,26 @@ public abstract class UpdateConverter {
player.setQuest(questSlot, "start;;;" + player.getQuest(questSlot));
}
}
// 1.44: Amazon Princess
questSlot = "amazon_princess";
if (player.hasQuest(questSlot)) {
final String fsState = player.getQuest(questSlot, 0);
if (fsState.equals("drinking")) {
player.setQuest(questSlot, 0, "done");
}
}
// 1.44: Campfire and Eggs for marianne
for (String slot : Arrays.asList("campfire", "eggs_for_marianne")) {
if (player.hasQuest(slot)) {
final String fsState = player.getQuest(slot, 0);
if (!fsState.equals("start") && !fsState.equals("rejected")) {
player.setQuest(slot, 1, fsState);
player.setQuest(slot, 0, "done");
}
}
}
}

View file

@ -63,7 +63,7 @@ public class PrincessNPC implements ZoneConfigurator {
@Override
protected void createDialog() {
addGreeting("Huh, what are you doing here?");
addGreeting("Huh, what are you doing here?");
addReply("sorry", "Well, so you should be, sneaking up on me like that!");
addReply("look", "You had better not poke around, this is all mine!");
addReply("nothing", "Go away and do this somewhere else but not in my hut!");

View file

@ -45,7 +45,7 @@ public class CampingGirlNPC implements ZoneConfigurator {
@Override
protected void createDialog() {
//addGreeting();
addGreeting("Hi, how are you?");
addJob("Work? I'm just a little girl! I'm a scout, you know.");
addHelp("You can find lots of useful stuff in the forest; wood and mushrooms, for example. But beware, some mushrooms are poisonous!");
addGoodbye();

View file

@ -1,6 +1,5 @@
/* $Id$ */
/***************************************************************************
* (C) Copyright 2003-2011 - Stendhal *
* (C) Copyright 2003-2023 - Stendhal *
***************************************************************************
***************************************************************************
* *
@ -12,37 +11,12 @@
***************************************************************************/
package games.stendhal.server.maps.quests;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import games.stendhal.common.Rand;
import games.stendhal.common.constants.SoundLayer;
import games.stendhal.common.grammar.Grammar;
import games.stendhal.common.parser.Sentence;
import games.stendhal.server.entity.npc.ChatAction;
import games.stendhal.server.entity.npc.ConversationPhrases;
import games.stendhal.server.entity.npc.ConversationStates;
import games.stendhal.server.entity.npc.EventRaiser;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.action.DropItemAction;
import games.stendhal.server.entity.npc.action.EquipItemAction;
import games.stendhal.server.entity.npc.action.EquipRandomAmountOfItemAction;
import games.stendhal.server.entity.npc.action.IncreaseKarmaAction;
import games.stendhal.server.entity.npc.action.InflictStatusOnNPCAction;
import games.stendhal.server.entity.npc.action.MultipleActions;
import games.stendhal.server.entity.npc.action.SayTimeRemainingAction;
import games.stendhal.server.entity.npc.action.SetQuestAction;
import games.stendhal.server.entity.npc.action.SetQuestAndModifyKarmaAction;
import games.stendhal.server.entity.npc.condition.AndCondition;
import games.stendhal.server.entity.npc.condition.NotCondition;
import games.stendhal.server.entity.npc.condition.PlayerHasItemWithHimCondition;
import games.stendhal.server.entity.npc.condition.QuestCompletedCondition;
import games.stendhal.server.entity.npc.condition.QuestInStateCondition;
import games.stendhal.server.entity.npc.condition.QuestNotInStateCondition;
import games.stendhal.server.entity.npc.condition.QuestNotStartedCondition;
import games.stendhal.server.entity.npc.condition.QuestStateStartsWithCondition;
import games.stendhal.server.entity.npc.condition.TimePassedCondition;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.events.SoundEvent;
import games.stendhal.server.entity.npc.action.PlaySoundAction;
import games.stendhal.server.entity.npc.quest.BringItemQuestBuilder;
import games.stendhal.server.entity.npc.quest.QuestManuscript;
import games.stendhal.server.maps.Region;
/**
@ -72,184 +46,53 @@ import games.stendhal.server.maps.Region;
* <li>You can repeat it once an hour.</li>
* </ul>
*/
public class AmazonPrincess extends AbstractQuest {
private static final String QUEST_SLOT = "amazon_princess";
// The delay between repeating quests is 60 minutes
private static final int REQUIRED_MINUTES = 60;
private static final List<String> triggers = Arrays.asList("drink", "pina colada", "cocktail", "cheers", "pina");
private void offerQuestStep() {
final SpeakerNPC npc = npcs.get("Princess Esclara");
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new QuestNotStartedCondition(QUEST_SLOT),
ConversationStates.QUEST_OFFERED,
"I'm looking for a drink, should be an exotic one. Can you bring me one?",
null);
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new QuestCompletedCondition(QUEST_SLOT),
ConversationStates.ATTENDING,
"I'm drunken now thank you!",
null);
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new AndCondition(new TimePassedCondition(QUEST_SLOT, 1, REQUIRED_MINUTES), new QuestStateStartsWithCondition(QUEST_SLOT, "drinking;")),
ConversationStates.QUEST_OFFERED,
"The last cocktail you brought me was so lovely. Will you bring me another?",
null);
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new AndCondition(new NotCondition(new TimePassedCondition(QUEST_SLOT, 1, REQUIRED_MINUTES)), new QuestStateStartsWithCondition(QUEST_SLOT, "drinking;")),
ConversationStates.ATTENDING,
null,
new SayTimeRemainingAction(QUEST_SLOT, 1, REQUIRED_MINUTES, "I'm sure I'll be too drunk to have another for at least "));
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES, null,
ConversationStates.ATTENDING,
"I like these exotic drinks, I forget the name of my favourite one.",
null);
// Player agrees to get the drink
npc.add(ConversationStates.QUEST_OFFERED,
ConversationPhrases.YES_MESSAGES, null,
ConversationStates.ATTENDING,
"Thank you! If you have found some, say #drink to me so I know you have it. I'll be sure to give you a nice reward.",
new SetQuestAction(QUEST_SLOT, "start"));
// Player says no, they've lost karma.
npc.add(ConversationStates.QUEST_OFFERED,
ConversationPhrases.NO_MESSAGES, null, ConversationStates.IDLE,
"Oh, never mind. Bye then.",
new SetQuestAndModifyKarmaAction(QUEST_SLOT, "rejected", -10.0));
}
/**
* Get Drink Step :
* src/games/stendhal/server/maps/athor/cocktail_bar/BarmanNPC.java he
* serves drinks to all, not just those with the quest
*/
private void bringCocktailStep() {
final SpeakerNPC npc = npcs.get("Princess Esclara");
npc.add(
ConversationStates.ATTENDING, triggers,
new AndCondition(new QuestInStateCondition(QUEST_SLOT, "start"), new PlayerHasItemWithHimCondition("pina colada")),
ConversationStates.ATTENDING,
null,
new MultipleActions(
new DropItemAction("pina colada"),
new ChatAction() {
@Override
public void fire(final Player player,
final Sentence sentence,
final EventRaiser npc) {
int pieAmount = Rand.roll1D6() + 1;
new EquipItemAction("fish pie", pieAmount, true).fire(player, sentence, npc);
npc.say("Thank you!! Take " +
Grammar.thisthese(pieAmount) + " " +
Grammar.quantityplnoun(pieAmount, "fish pie", "") +
" from my cook, and this kiss, from me.");
npc.addEvent(new SoundEvent("kiss-female-01", SoundLayer.CREATURE_NOISE));
new SetQuestAndModifyKarmaAction(getSlotName(), "drinking;"
+ System.currentTimeMillis(), 15.0).fire(player, sentence, npc);
}
},
new InflictStatusOnNPCAction("pina colada")
));
npc.add(
ConversationStates.ATTENDING, triggers,
new AndCondition(new QuestInStateCondition(QUEST_SLOT, "start"), new NotCondition(new PlayerHasItemWithHimCondition("pina colada"))),
ConversationStates.ATTENDING,
"You don't have any drink I like yet. Go, and you better get an exotic one!",
null);
npc.add(
ConversationStates.ATTENDING, triggers,
new QuestNotInStateCondition(QUEST_SLOT, "start"),
ConversationStates.ATTENDING,
"Sometime you could do me a #favour ...", null);
}
public class AmazonPrincess implements QuestManuscript {
@Override
public void addToWorld() {
fillQuestInfo(
"Amazon Princess",
"A thirsty princess wants a drink.",
true);
offerQuestStep();
bringCocktailStep();
public BringItemQuestBuilder story() {
BringItemQuestBuilder quest = new BringItemQuestBuilder();
quest.info()
.name("Amazon Princess")
.description("A thirsty princess wants a drink.")
.internalName("amazon_princess")
.repeatableAfterMinutes(60)
.minLevel(70)
.region(Region.AMAZON_ISLAND)
.questGiverNpc("Princess Esclara");
quest.history()
.whenNpcWasMet("Princess Esclara welcomed me to her home on Amazon Island.")
.whenQuestWasRejected("She asked me to fetch her a drink but I didn't think she should have one.")
.whenQuestWasAccepted("The Princess is thirsty, I promised her an exotic drink.")
.whenTaskWasCompleted("I found a pina colada for the Princess, I think she'd like that.")
.whenQuestWasCompleted("Princess Esclara loved the pina colada I gave to her. She gave me fish pies and a kiss!!")
.whenQuestCanBeRepeated("But I'd bet she's ready for another one. Maybe I'll get more fish pies.");
quest.offer()
.respondToRequest("I'm looking for a drink, should be an exotic one. Can you bring me one?")
.respondToUnrepeatableRequest("I'm sure I'll be too drunk to have another one now.") // TODO: for at least [time_remaining]
.respondToRepeatedRequest("The last cocktail you brought me was so lovely. Will you bring me another?")
.respondToAccept("Thank you! If you have found some, I'll be sure to give you a nice reward.")
.respondToReject("Oh, never mind. Bye then.")
.rejectionKarmaPenalty(10.0)
.remind("I like these exotic drinks, I forget the name of my favourite one.");
// Get Drink Step : athor/cocktail_bar/BarmanNPC.java he serves drinks to all, not just those with the quest
quest.task()
.requestItem(1, "pina colada");
quest.complete()
.greet("Ah, I see, you have a §'pina colada' Is it for me?")
.respondToReject("Well then, hopefully someone else will help.")
.respondToAccept(null)
.rewardWith(new IncreaseKarmaAction(15))
.rewardWith(new EquipRandomAmountOfItemAction("fish pie", 1, 6, 1,
"Thank you! Take [this_these] [number_item] from my cook, and this kiss from me."))
.rewardWith(new PlaySoundAction("kiss-female-01"))
.rewardWith(new InflictStatusOnNPCAction("pina colada"));
return quest;
}
@Override
public List<String> getHistory(final Player player) {
final List<String> res = new ArrayList<String>();
if (!player.hasQuest(QUEST_SLOT)) {
return res;
}
res.add("Princess Esclara welcomed me to her home on Amazon Island.");
final String questState = player.getQuest(QUEST_SLOT);
if ("rejected".equals(questState)) {
res.add("She asked me to fetch her a drink but I didn't think she should have one.");
}
if (player.isQuestInState(QUEST_SLOT, "start") || isCompleted(player)) {
res.add("The Princess is thirsty, I promised her an exotic drink, and should tell her 'drink' when I have it.");
}
if ("start".equals(questState) && player.isEquipped("pina colada") || isCompleted(player)) {
res.add("I found a pina colada for the Princess, I think she'd like that.");
}
if (isCompleted(player)) {
if (isRepeatable(player)) {
res.add("I took a pina colada to the Princess, but I'd bet she's ready for another. Maybe I'll get more fish pies.");
} else {
res.add("Princess Esclara loved the pina colada I took her, she's not thirsty now. She gave me fish pies and a kiss!!");
}
}
return res;
}
@Override
public String getSlotName() {
return QUEST_SLOT;
}
@Override
public String getName() {
return "AmazonPrincess";
}
// Amazon is dangerous below this level - don't hint to go there
@Override
public int getMinLevel() {
return 70;
}
@Override
public boolean isRepeatable(final Player player) {
return new AndCondition(new QuestStateStartsWithCondition(QUEST_SLOT,"drinking;"),
new TimePassedCondition(QUEST_SLOT, 1, REQUIRED_MINUTES)).fire(player,null, null);
}
@Override
public boolean isCompleted(final Player player) {
return new QuestStateStartsWithCondition(QUEST_SLOT,"drinking;").fire(player, null, null);
}
@Override
public String getRegion() {
return Region.AMAZON_ISLAND;
}
@Override
public String getNPCName() {
return "Princess Esclara";
}
}

View file

@ -1,4 +1,3 @@
/* $Id$ */
/***************************************************************************
* (C) Copyright 2003-2023 - Stendhal *
***************************************************************************
@ -12,30 +11,12 @@
***************************************************************************/
package games.stendhal.server.maps.quests;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import games.stendhal.server.core.engine.SingletonRepository;
import games.stendhal.server.entity.npc.ChatAction;
import games.stendhal.server.entity.npc.ConversationPhrases;
import games.stendhal.server.entity.npc.ConversationStates;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.action.DropItemAction;
import games.stendhal.server.entity.npc.action.EquipItemAction;
import games.stendhal.server.entity.npc.action.IncreaseKarmaAction;
import games.stendhal.server.entity.npc.action.IncreaseXPAction;
import games.stendhal.server.entity.npc.action.MultipleActions;
import games.stendhal.server.entity.npc.action.SetQuestAction;
import games.stendhal.server.entity.npc.action.SetQuestAndModifyKarmaAction;
import games.stendhal.server.entity.npc.condition.AndCondition;
import games.stendhal.server.entity.npc.condition.GreetingMatchesNameCondition;
import games.stendhal.server.entity.npc.condition.NotCondition;
import games.stendhal.server.entity.npc.condition.PlayerHasItemWithHimCondition;
import games.stendhal.server.entity.npc.condition.QuestActiveCondition;
import games.stendhal.server.entity.npc.condition.QuestCompletedCondition;
import games.stendhal.server.entity.npc.condition.QuestNotCompletedCondition;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.entity.npc.quest.BringItemQuestBuilder;
import games.stendhal.server.entity.npc.quest.QuestManuscript;
import games.stendhal.server.maps.Region;
import games.stendhal.server.maps.semos.guardhouse.RetiredAdventurerNPC;
import games.stendhal.server.util.ResetSpeakerNPC;
@ -67,183 +48,61 @@ import games.stendhal.server.util.ResetSpeakerNPC;
* <li>None</li>
* </ul>
*/
public class BeerForHayunn extends AbstractQuest {
public class BeerForHayunn implements QuestManuscript {
public static final String QUEST_SLOT = "beer_hayunn";
private static final String OTHER_QUEST_SLOT = "meet_hayunn";
@Override
public List<String> getHistory(final Player player) {
final List<String> res = new ArrayList<String>();
if (!player.hasQuest(QUEST_SLOT)) {
return res;
}
res.add("I have talked to Hayunn.");
final String questState = player.getQuest(QUEST_SLOT);
if ("rejected".equals(questState)) {
res.add("I do not want to make Hayunn drunk.");
}
if (player.isQuestInState(QUEST_SLOT, "start", "done")) {
res.add("I promised to buy him a beer from Margaret in Semos Tavern.");
}
if ("start".equals(questState) && player.isEquipped("beer")
|| "done".equals(questState)) {
res.add("I have a bottle of beer.");
}
if ("done".equals(questState)) {
res.add("I gave the beer to Hayunn. He paid me 20 gold coins and I got some experience.");
}
return res;
public BringItemQuestBuilder story() {
BringItemQuestBuilder quest = new BringItemQuestBuilder();
quest.info()
.name("Beer for Hayunn")
.description("Hayunn Naratha, the great warrior in Semos Guard House, wants a beer.")
.internalName(QUEST_SLOT)
.notRepeatable()
.minLevel(0)
.region(Region.SEMOS_CITY)
.questGiverNpc("Hayunn Naratha");
quest.history()
.whenNpcWasMet("I have talked to Hayunn Naratha.")
.whenQuestWasRejected("I do not want to make Hayunn drunk.")
.whenQuestWasAccepted("I promised to buy him a beer from Margaret in Semos Tavern.")
.whenTaskWasCompleted("I have a bottle of beer.")
.whenQuestWasCompleted("I gave the beer to Hayunn. He paid me 20 gold coins and I got some experience.");
// TODO: new QuestCompletedCondition(OTHER_QUEST_SLOT)),
quest.offer()
.respondToRequest("My mouth is dry, but I can't be seen to abandon this teaching room! Could you bring me some #beer from the #tavern?")
.respondToUnrepeatableRequest("Thanks all the same, but I don't want to get too heavily into drinking; I'm still on duty, you know! I'll need my wits about me if a student shows up...")
.respondToAccept("Thanks! I'll be right here, waiting. And guarding, of course.")
.respondToReject("Oh, well forget it then. I guess I'll just hope for it to start raining, and then stand with my mouth open.")
.rejectionKarmaPenalty(5.0)
.remind("Hey, I'm still waiting for that beer, remember? Anyway, what can I do for you?")
.respondTo("tavern").saying("If you don't know where the inn is, you could ask old Monogenes; he's good with directions. Are you going to help?")
.respondTo("beer").saying("A bottle of cool beer from #Margaret will be more than enough. So, will you do it?")
.respondTo("Margaret").saying("Margaret is the pretty maid in the tavern, of course! Quite a looker, too... heh. Will you go for me?");
quest.task()
.requestItem(1, "beer");
quest.complete()
.greet("Hey! Is that beer for me?")
.respondToReject("Drat! You remembered that I asked you for one, right? I could really use it right now.")
.respondToAccept("*glug glug* Ah! That hit the spot. Let me know if you need anything, ok?")
.rewardWith(new EquipItemAction("money", 20))
.rewardWith(new IncreaseXPAction(50))
.rewardWith(new IncreaseKarmaAction(10));
return quest;
}
private void prepareRequestingStep() {
final SpeakerNPC npc = npcs.get("Hayunn Naratha");
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
// Don't give the task until the previous is completed to avoid
// confusing Hayunn in a lot of places later.
new AndCondition(new QuestNotCompletedCondition(QUEST_SLOT),
new QuestCompletedCondition(OTHER_QUEST_SLOT)),
ConversationStates.QUEST_OFFERED,
"My mouth is dry, but I can't be seen to abandon this teaching room! Could you bring me some #beer from the #tavern?",
null);
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new QuestCompletedCondition(QUEST_SLOT),
ConversationStates.ATTENDING,
"Thanks all the same, but I don't want to get too heavily into drinking; I'm still on duty, you know! I'll need my wits about me if a student shows up...",
null);
npc.add(
ConversationStates.QUEST_OFFERED,
ConversationPhrases.YES_MESSAGES,
null,
ConversationStates.ATTENDING,
"Thanks! I'll be right here, waiting. And guarding, of course.",
new SetQuestAction(QUEST_SLOT, "start"));
npc.add(
ConversationStates.QUEST_OFFERED,
ConversationPhrases.NO_MESSAGES,
null,
ConversationStates.ATTENDING,
"Oh, well forget it then. I guess I'll just hope for it to start raining, and then stand with my mouth open.",
new SetQuestAndModifyKarmaAction(QUEST_SLOT, "rejected", -5.0));
npc.add(
ConversationStates.QUEST_OFFERED,
"tavern",
null,
ConversationStates.QUEST_OFFERED,
"If you don't know where the inn is, you could ask old Monogenes; he's good with directions. Are you going to help?",
null);
npc.add(
ConversationStates.QUEST_OFFERED,
"beer",
null,
ConversationStates.QUEST_OFFERED,
"A bottle of cool beer from #Margaret will be more than enough. So, will you do it?",
null);
npc.add(
ConversationStates.QUEST_OFFERED,
"Margaret",
null,
ConversationStates.QUEST_OFFERED,
"Margaret is the pretty maid in the tavern, of course! Quite a looker, too... heh. Will you go for me?",
null);
}
private void prepareBringingStep() {
final SpeakerNPC npc = npcs.get("Hayunn Naratha");
npc.add(ConversationStates.IDLE, ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(npc.getName()),
new QuestActiveCondition(QUEST_SLOT),
new PlayerHasItemWithHimCondition("beer")),
ConversationStates.QUEST_ITEM_BROUGHT,
"Hey! Is that beer for me?", null);
npc.add(ConversationStates.IDLE, ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(npc.getName()),
new QuestActiveCondition(QUEST_SLOT),
new NotCondition(new PlayerHasItemWithHimCondition("beer"))),
ConversationStates.ATTENDING,
"Hey, I'm still waiting for that beer, remember? Anyway, what can I do for you?",
null);
final List<ChatAction> reward = new LinkedList<ChatAction>();
reward.add(new DropItemAction("beer"));
reward.add(new EquipItemAction("money", 20));
reward.add(new IncreaseXPAction(50));
reward.add(new SetQuestAction(QUEST_SLOT, "done"));
reward.add(new IncreaseKarmaAction(10));
npc.add(
ConversationStates.QUEST_ITEM_BROUGHT,
ConversationPhrases.YES_MESSAGES,
new PlayerHasItemWithHimCondition("beer"),
ConversationStates.ATTENDING,
"*glug glug* Ah! That hit the spot. Let me know if you need anything, ok?",
new MultipleActions(reward));
npc.add(
ConversationStates.QUEST_ITEM_BROUGHT,
ConversationPhrases.NO_MESSAGES,
null,
ConversationStates.ATTENDING,
"Drat! You remembered that I asked you for one, right? I could really use it right now.",
null);
}
@Override
public void addToWorld() {
fillQuestInfo(
"Beer for Hayunn",
"Hayunn Naratha, the great warrior in Semos Guard House, wants a beer.",
false);
prepareRequestingStep();
prepareBringingStep();
}
@Override
public boolean removeFromWorld() {
final boolean res = ResetSpeakerNPC.reload(new RetiredAdventurerNPC(), getNPCName());
final boolean res = ResetSpeakerNPC.reload(new RetiredAdventurerNPC(), "Hayunn Naratha");
// reload other associated quests
SingletonRepository.getStendhalQuestSystem().reloadQuestSlots("meet_hayunn");
return res;
}
@Override
public String getSlotName() {
return QUEST_SLOT;
}
@Override
public String getName() {
return "BeerForHayunn";
}
public String getTitle() {
return "Beer for Hayunn";
}
@Override
public int getMinLevel() {
return 0;
}
@Override
public String getRegion() {
return Region.SEMOS_CITY;
}
@Override
public String getNPCName() {
return "Hayunn Naratha";
}
}

View file

@ -1,6 +1,5 @@
/* $Id$ */
/***************************************************************************
* (C) Copyright 2003-2010 - Stendhal *
* (C) Copyright 2003-2023 - Stendhal *
***************************************************************************
***************************************************************************
* *
@ -12,38 +11,12 @@
***************************************************************************/
package games.stendhal.server.maps.quests;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import games.stendhal.common.Rand;
import games.stendhal.common.parser.Sentence;
import games.stendhal.server.core.engine.SingletonRepository;
import games.stendhal.server.entity.item.StackableItem;
import games.stendhal.server.entity.npc.ChatAction;
import games.stendhal.server.entity.npc.ConversationPhrases;
import games.stendhal.server.entity.npc.ConversationStates;
import games.stendhal.server.entity.npc.EventRaiser;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.action.DropItemAction;
import games.stendhal.server.entity.npc.action.EquipItemAction;
import games.stendhal.server.entity.npc.action.EquipRandomItemAction;
import games.stendhal.server.entity.npc.action.IncreaseKarmaAction;
import games.stendhal.server.entity.npc.action.IncreaseXPAction;
import games.stendhal.server.entity.npc.action.MultipleActions;
import games.stendhal.server.entity.npc.action.SayTimeRemainingAction;
import games.stendhal.server.entity.npc.action.SetQuestAction;
import games.stendhal.server.entity.npc.action.SetQuestAndModifyKarmaAction;
import games.stendhal.server.entity.npc.action.SetQuestToTimeStampAction;
import games.stendhal.server.entity.npc.condition.AndCondition;
import games.stendhal.server.entity.npc.condition.GreetingMatchesNameCondition;
import games.stendhal.server.entity.npc.condition.NotCondition;
import games.stendhal.server.entity.npc.condition.PlayerHasItemWithHimCondition;
import games.stendhal.server.entity.npc.condition.QuestInStateCondition;
import games.stendhal.server.entity.npc.condition.QuestNotInStateCondition;
import games.stendhal.server.entity.npc.condition.QuestNotStartedCondition;
import games.stendhal.server.entity.npc.condition.QuestStartedCondition;
import games.stendhal.server.entity.npc.condition.TimePassedCondition;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.entity.npc.quest.BringItemQuestBuilder;
import games.stendhal.server.entity.npc.quest.QuestManuscript;
import games.stendhal.server.maps.Region;
/**
@ -74,222 +47,51 @@ import games.stendhal.server.maps.Region;
* <li> Unlimited, but 60 minutes of waiting are required between repetitions</li>
* </ul>
*/
public class Campfire extends AbstractQuest {
private static final int REQUIRED_WOOD = 10;
private static final int REWARDS = 10;
private static final int REQUIRED_MINUTES = 60;
private static final String QUEST_SLOT = "campfire";
public class Campfire implements QuestManuscript {
@Override
public String getSlotName() {
return QUEST_SLOT;
public BringItemQuestBuilder story() {
BringItemQuestBuilder quest = new BringItemQuestBuilder();
quest.info()
.name("Campfire")
.description("Sally wants to build a campfire, but she doesn't have any wood.")
.internalName("campfire")
.repeatableAfterMinutes(60)
.minLevel(0)
.region(Region.ORRIL)
.questGiverNpc("Sally");
quest.history()
.whenNpcWasMet("I have met Sally south of Orril Castle.")
.whenQuestWasRejected("But I do not want to help her.")
.whenQuestWasAccepted("She asked me to fetch 10 pieces of wood to keep her fire going.")
.whenTaskWasCompleted("I found the wood needed for the fire.")
.whenQuestWasCompleted("I have given the wood to Sally. She gave me some food and charcoal in return. I also gained 50 xp")
.whenQuestCanBeRepeated("Sally's fire needs some wood again.");
quest.offer()
.respondToRequest("I need more wood to keep my campfire running, But I can't leave it unattended to go get some! Could you please get some from the forest for me? I need ten pieces.")
.respondToUnrepeatableRequest("Thanks, but I think the wood, you brought, will last [remaining_time].")
.respondToRepeatedRequest("My campfire needs wood again, ten pieces of #wood will be enough. Could you please get those #wood pieces from the forest for me? Please say yes!")
.respondToAccept("Okay. You can find wood in the forest north of here. Come back when you get ten pieces of wood!")
.respondToReject("Oh dear, how am I going to cook all this meat? Perhaps I'll just have to feed it to the animals...")
.rejectionKarmaPenalty(5.0)
.remind("Please don't forget that you promised to collect ten pieces of wood for me!");
quest.task()
.requestItem(10, "wood");
quest.complete()
.greet("Hi again! You've got wood, I see; do you have those 10 pieces of wood I asked about earlier?")
.respondToReject("Oh... well, I hope you find some quickly; this fire's going to burn out soon!")
.respondToAccept(null)
.rewardWith(new IncreaseXPAction(50))
.rewardWith(new IncreaseKarmaAction(10))
.rewardWith(new EquipItemAction("charcoal", 10))
.rewardWith(new EquipRandomItemAction("meat=10;ham=10", false, "Thank you! Here, take [this_these] [number_item] and charcoal!"));
return quest;
}
@Override
public boolean isCompleted(final Player player) {
return player.hasQuest(QUEST_SLOT) && !"start".equals(player.getQuest(QUEST_SLOT)) && !"rejected".equals(player.getQuest(QUEST_SLOT));
}
@Override
public boolean isRepeatable(final Player player) {
return new AndCondition(new QuestNotInStateCondition(QUEST_SLOT, "start"), new QuestStartedCondition(QUEST_SLOT), new TimePassedCondition(QUEST_SLOT,REQUIRED_MINUTES)).fire(player, null, null);
}
@Override
public List<String> getHistory(final Player player) {
final List<String> res = new ArrayList<String>();
if (!player.hasQuest(QUEST_SLOT)) {
return res;
}
res.add("I have met Sally");
final String questState = player.getQuest(QUEST_SLOT);
if ("rejected".equals(questState)) {
res.add("I do not want to help Sally");
return res;
}
res.add("I do want to help Sally");
if (player.isEquipped("wood", REQUIRED_WOOD) || isCompleted(player)) {
res.add("I have found the 10 wood needed to start the fire");
}
if (isCompleted(player)) {
res.add("I have given Sally the wood. She gave me some food and charcoal in return. I also gained 50 xp");
}
if(isRepeatable(player)){
res.add("Sally's fire needs some wood again.");
}
return res;
}
private void prepareRequestingStep() {
final SpeakerNPC npc = npcs.get("Sally");
// player returns with the promised wood
npc.add(ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(npc.getName()),
new QuestInStateCondition(QUEST_SLOT, "start"), new PlayerHasItemWithHimCondition("wood", REQUIRED_WOOD)),
ConversationStates.QUEST_ITEM_BROUGHT,
"Hi again! You've got wood, I see; do you have those 10 pieces of wood I asked about earlier?",
null);
//player returns without promised wood
npc.add(ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(npc.getName()),
new QuestInStateCondition(QUEST_SLOT, "start"), new NotCondition(new PlayerHasItemWithHimCondition("wood", REQUIRED_WOOD))),
ConversationStates.ATTENDING,
"You're back already? Don't forget that you promised to collect ten pieces of wood for me!",
null);
// first chat of player with sally
npc.add(ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(npc.getName()),
new QuestNotStartedCondition(QUEST_SLOT)),
ConversationStates.ATTENDING, "Hi! I need a little #favor ... ",
null);
// player who is rejected or 'done' but waiting to start again, returns
npc.add(ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(npc.getName()),
new QuestNotInStateCondition(QUEST_SLOT, "start"),
new QuestStartedCondition(QUEST_SLOT)),
ConversationStates.ATTENDING,
"Hi again!",
null);
// if they ask for quest while on it, remind them
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new QuestInStateCondition(QUEST_SLOT, "start"),
ConversationStates.ATTENDING,
"You already promised me to bring me some wood! Ten pieces, remember?",
null);
// first time player asks/ player had rejected
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new QuestNotStartedCondition(QUEST_SLOT),
ConversationStates.QUEST_OFFERED,
"I need more wood to keep my campfire running, But I can't leave it unattended to go get some! Could you please get some from the forest for me? I need ten pieces.",
null);
// player returns - enough time has passed
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new AndCondition(new QuestNotInStateCondition(QUEST_SLOT, "start"), new QuestStartedCondition(QUEST_SLOT), new TimePassedCondition(QUEST_SLOT,REQUIRED_MINUTES)),
ConversationStates.QUEST_OFFERED,
"My campfire needs wood again, ten pieces of #wood will be enough. Could you please get those #wood pieces from the forest for me? Please say yes!",
null);
// player returns - enough time has passed
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new AndCondition(new QuestNotInStateCondition(QUEST_SLOT, "start"), new QuestStartedCondition(QUEST_SLOT), new NotCondition(new TimePassedCondition(QUEST_SLOT,REQUIRED_MINUTES))),
ConversationStates.ATTENDING,
null,
new SayTimeRemainingAction(QUEST_SLOT,REQUIRED_MINUTES,"Thanks, but I think the wood you brought already will last me"));
// player is willing to help
npc.add(ConversationStates.QUEST_OFFERED,
ConversationPhrases.YES_MESSAGES,
null,
ConversationStates.ATTENDING,
"Okay. You can find wood in the forest north of here. Come back when you get ten pieces of wood!",
new SetQuestAction(QUEST_SLOT, "start"));
// player is not willing to help
npc.add(ConversationStates.QUEST_OFFERED,
ConversationPhrases.NO_MESSAGES,
null,
ConversationStates.ATTENDING,
"Oh dear, how am I going to cook all this meat? Perhaps I'll just have to feed it to the animals...",
new SetQuestAndModifyKarmaAction(QUEST_SLOT, "rejected", -5.0));
}
private void prepareBringingStep() {
final SpeakerNPC npc = npcs.get("Sally");
// player has wood and tells sally, yes, it is for her
final List<ChatAction> reward = new LinkedList<ChatAction>();
reward.add(new DropItemAction("wood", REQUIRED_WOOD));
reward.add(new EquipItemAction("charcoal", REWARDS));
reward.add(new IncreaseXPAction(50));
reward.add(new SetQuestToTimeStampAction(QUEST_SLOT));
reward.add(new IncreaseKarmaAction(10));
reward.add(new ChatAction() {
@Override
public void fire(final Player player, final Sentence sentence, final EventRaiser npc) {
String rewardClass;
if (Rand.throwCoin() == 1) {
rewardClass = "meat";
} else {
rewardClass = "ham";
}
npc.say("Thank you! Here, take some " + rewardClass + " and charcoal!");
final StackableItem reward = (StackableItem) SingletonRepository.getEntityManager().getItem(rewardClass);
reward.setQuantity(REWARDS);
player.equipOrPutOnGround(reward);
player.notifyWorldAboutChanges();
}
});
npc.add(ConversationStates.QUEST_ITEM_BROUGHT,
ConversationPhrases.YES_MESSAGES,
new PlayerHasItemWithHimCondition("wood", REQUIRED_WOOD),
ConversationStates.ATTENDING, null,
new MultipleActions(reward));
//player said the wood was for her but has dropped it from his bag or hands
npc.add(ConversationStates.QUEST_ITEM_BROUGHT,
ConversationPhrases.YES_MESSAGES,
new NotCondition(new PlayerHasItemWithHimCondition("wood", REQUIRED_WOOD)),
ConversationStates.ATTENDING,
"Hey! Where did you put the wood?",
null);
// player had wood but said it is not for sally
npc.add(
ConversationStates.QUEST_ITEM_BROUGHT,
ConversationPhrases.NO_MESSAGES,
null,
ConversationStates.ATTENDING,
"Oh... well, I hope you find some quickly; this fire's going to burn out soon!",
null);
}
@Override
public void addToWorld() {
fillQuestInfo(
"Campfire",
"Sally wants to build a campfire, but she doesn't have any wood.",
true);
prepareRequestingStep();
prepareBringingStep();
}
@Override
public String getName() {
return "Campfire";
}
@Override
public int getMinLevel() {
return 0;
}
@Override
public String getNPCName() {
return "Sally";
}
@Override
public String getRegion() {
return Region.ORRIL;
}
}

View file

@ -1,6 +1,5 @@
/* $Id$ */
/***************************************************************************
* (C) Copyright 2019 - Stendhal *
* (C) Copyright 2019-2023 - Stendhal *
***************************************************************************
***************************************************************************
* *
@ -12,37 +11,11 @@
***************************************************************************/
package games.stendhal.server.maps.quests;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import games.stendhal.common.Rand;
import games.stendhal.common.parser.Sentence;
import games.stendhal.server.core.engine.SingletonRepository;
import games.stendhal.server.entity.item.StackableItem;
import games.stendhal.server.entity.npc.ChatAction;
import games.stendhal.server.entity.npc.ConversationPhrases;
import games.stendhal.server.entity.npc.ConversationStates;
import games.stendhal.server.entity.npc.EventRaiser;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.action.DropItemAction;
import games.stendhal.server.entity.npc.action.EquipRandomItemAction;
import games.stendhal.server.entity.npc.action.IncreaseKarmaAction;
import games.stendhal.server.entity.npc.action.IncreaseXPAction;
import games.stendhal.server.entity.npc.action.MultipleActions;
import games.stendhal.server.entity.npc.action.SayTimeRemainingAction;
import games.stendhal.server.entity.npc.action.SetQuestAction;
import games.stendhal.server.entity.npc.action.SetQuestAndModifyKarmaAction;
import games.stendhal.server.entity.npc.action.SetQuestToTimeStampAction;
import games.stendhal.server.entity.npc.condition.AndCondition;
import games.stendhal.server.entity.npc.condition.GreetingMatchesNameCondition;
import games.stendhal.server.entity.npc.condition.NotCondition;
import games.stendhal.server.entity.npc.condition.PlayerHasItemWithHimCondition;
import games.stendhal.server.entity.npc.condition.QuestInStateCondition;
import games.stendhal.server.entity.npc.condition.QuestNotInStateCondition;
import games.stendhal.server.entity.npc.condition.QuestNotStartedCondition;
import games.stendhal.server.entity.npc.condition.QuestStartedCondition;
import games.stendhal.server.entity.npc.condition.TimePassedCondition;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.entity.npc.quest.BringItemQuestBuilder;
import games.stendhal.server.entity.npc.quest.QuestManuscript;
import games.stendhal.server.maps.Region;
/**
@ -73,250 +46,58 @@ import games.stendhal.server.maps.Region;
* <li> Unlimited, at least 60 minutes have to elapse before repeating</li>
* </ul>
*/
public class EggsForMarianne extends AbstractQuest {
//a dozen of eggs
private static final int REQUIRED_EGGS = 12;
//60 minutes before quest can be repeated
private static final int REQUIRED_MINUTES = 60;
private static final String QUEST_SLOT = "eggs_for_marianne";
public class EggsForMarianne implements QuestManuscript {
@Override
public String getSlotName() {
return QUEST_SLOT;
public BringItemQuestBuilder story() {
BringItemQuestBuilder quest = new BringItemQuestBuilder();
quest.info()
.name("Eggs for Marianne")
.description("Marianne's mom is going to make some pancakes and she needs some eggs.")
.internalName("eggs_for_marianne")
.repeatableAfterMinutes(60)
.minLevel(0)
.region(Region.DENIRAN)
.questGiverNpc("Marianne");
quest.history()
.whenNpcWasMet("I have met Marianne in Deniran City.")
.whenQuestWasRejected("She asked me to fetch some eggs, but I do not want to help her.")
.whenQuestWasAccepted("She asked me to fetch 12 eggs")
.whenTaskWasCompleted("I have found the eggs for Marianne.")
.whenQuestWasCompleted("I have given Marianne the eggs. She gave me some flowers in return.")
.whenQuestCanBeRepeated("Marianne needs more eggs again.");
quest.offer()
.respondToRequest(
"I need a dozen of eggs. " +
"My mom asked me to collect eggs and she is going to make me pancakes! " +
"I'm afraid of getting close to those chickens! " +
"Could you please get eggs for me?")
.respondToUnrepeatableRequest("Thanks! I think the eggs you already brought me will be enough for another while...")
.respondToRepeatedRequest("My mom needs eggs again! Could you please get a dozen more for me?")
.respondToAccept(
"Okay. You can find eggs hunting chickens... I am so afraid of getting near those pesky chickens! " +
"Please come back when you found enough eggs for me!")
.respondToReject(
"Oh dear, what am I going to do with all these flowers? " +
"Perhaps I'll just leave them around some graves...")
.rejectionKarmaPenalty(5.0)
.remind("You promised to collect a dozen of eggs for me ... ");
quest.task()
.requestItem(12, "egg");
quest.complete()
.greet("Hi again! You've got several eggs, I see. Do you have 12 eggs for me?")
.respondToReject("Oh... well, I hope you find some quickly. I'm getting hungry!")
.respondToAccept(null)
.rewardWith(new IncreaseXPAction(50))
.rewardWith(new IncreaseKarmaAction(50))
.rewardWith(new EquipRandomItemAction("pansy=12;daisies=12", false, "Thank you! Here, take [this_these] [number_item]!"));
return quest;
}
@Override
public boolean isCompleted(final Player player) {
return player.hasQuest(QUEST_SLOT) && !"start".equals(player.getQuest(QUEST_SLOT)) && !"rejected".equals(player.getQuest(QUEST_SLOT));
}
@Override
public boolean isRepeatable(final Player player) {
return new AndCondition(
new QuestNotInStateCondition(QUEST_SLOT, "start"),
new QuestStartedCondition(QUEST_SLOT),
new TimePassedCondition(QUEST_SLOT,REQUIRED_MINUTES)).fire(player, null, null);
}
@Override
public List<String> getHistory(final Player player) {
final List<String> res = new ArrayList<String>();
if (!player.hasQuest(QUEST_SLOT)) {
return res;
}
res.add("I have met Marianne");
final String questState = player.getQuest(QUEST_SLOT);
if ("rejected".equals(questState)) {
res.add("I do not want to help Marianne");
return res;
}
res.add("I do want to help Marianne");
if (player.isEquipped("egg", REQUIRED_EGGS) || isCompleted(player)) {
res.add("I have found some eggs for Marianne");
}
if (isCompleted(player)) {
res.add("I have given Marianne the eggs. " +
"She gave me some flowers in return. " +
"I also gained some xp!");
}
if(isRepeatable(player)){
res.add("Marianne needs more eggs again.");
}
return res;
}
private void prepareRequestingStep() {
final SpeakerNPC npc = npcs.get("Marianne");
// player returns with the promised eggs
npc.add(ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new AndCondition(
new GreetingMatchesNameCondition(npc.getName()),
new QuestInStateCondition(QUEST_SLOT, "start"),
new PlayerHasItemWithHimCondition("egg", REQUIRED_EGGS)),
ConversationStates.QUEST_ITEM_BROUGHT,
"Hi again! You've got several eggs I see; " +
"Do you have as many eggs as I asked earlier?",
null);
//player returns without promised eggs
npc.add(ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(npc.getName()),
new QuestInStateCondition(QUEST_SLOT, "start"),
new NotCondition(
new PlayerHasItemWithHimCondition("egg", REQUIRED_EGGS))),
ConversationStates.ATTENDING,
"You're back already? " +
"You promised to collect a dozen of eggs for me ... " +
"But it does not seem that you carry enough eggs with you!",
null);
// first chat of player with Marianne
npc.add(ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(npc.getName()),
new QuestNotStartedCondition(QUEST_SLOT)),
ConversationStates.ATTENDING, "Hello you ... " +
"I need a little #favor if you please, you look so kind ... ",
null);
// player who is rejected or 'done' but waiting to start again, returns
npc.add(ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(npc.getName()),
new QuestNotInStateCondition(QUEST_SLOT, "start"),
new QuestStartedCondition(QUEST_SLOT)),
ConversationStates.ATTENDING,
"Hello again, you!",
null);
// if they ask for quest while on it, remind them
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new QuestInStateCondition(QUEST_SLOT, "start"),
ConversationStates.ATTENDING,
"You already promised me to bring me some eggs, do you not remember?",
null);
// first time player asks/ player had rejected
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new QuestNotStartedCondition(QUEST_SLOT),
ConversationStates.QUEST_OFFERED,
"I need a dozen of eggs. " +
"My mom asked me to collect eggs and she is going to make me pancakes! " +
"I'm afraid of getting close to those chickens! " +
"Could you please get eggs for me?",
null);
// player returns - enough time has passed
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new AndCondition(
new QuestNotInStateCondition(QUEST_SLOT, "start"),
new QuestStartedCondition(QUEST_SLOT),
new TimePassedCondition(QUEST_SLOT,REQUIRED_MINUTES)),
ConversationStates.QUEST_OFFERED,
"My mom needs eggs again! " +
"Could you please get a dozen more for me?",
null);
// player returns - enough time has passed
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new AndCondition(new QuestNotInStateCondition(QUEST_SLOT, "start"),
new QuestStartedCondition(QUEST_SLOT),
new NotCondition(new TimePassedCondition(QUEST_SLOT,REQUIRED_MINUTES))),
ConversationStates.ATTENDING,
null,
new SayTimeRemainingAction(QUEST_SLOT,REQUIRED_MINUTES,
"Thanks! " +
"I think the eggs you already brought me " +
"will be enough for another while ..."));
// player is willing to help
npc.add(ConversationStates.QUEST_OFFERED,
ConversationPhrases.YES_MESSAGES,
null,
ConversationStates.ATTENDING,
"Okay. " +
"You can find eggs hunting chickens... I am so afraid of getting near those pesky chickens! " +
"Please come back when you found enough eggs for me!",
new SetQuestAction(QUEST_SLOT, "start"));
// player is not willing to help
npc.add(ConversationStates.QUEST_OFFERED,
ConversationPhrases.NO_MESSAGES,
null,
ConversationStates.ATTENDING,
"Oh dear, what am I going to do with all these flowers? " +
"Perhaps I'll just leave them around some graves...",
new SetQuestAndModifyKarmaAction(QUEST_SLOT, "rejected", -5.0));
}
private void prepareBringingStep() {
final SpeakerNPC npc = npcs.get("Marianne");
// player has eggs and tells Marianne, yes, it is for her
final List<ChatAction> reward = new LinkedList<ChatAction>();
reward.add(new DropItemAction("egg", REQUIRED_EGGS));
reward.add(new IncreaseXPAction(50));
reward.add(new SetQuestToTimeStampAction(QUEST_SLOT));
reward.add(new IncreaseKarmaAction(50));
reward.add(new ChatAction() {
@Override
public void fire(final Player player, final Sentence sentence, final EventRaiser npc) {
String rewardClass;
if (Rand.throwCoin() == 1) {
rewardClass = "pansy";
} else {
rewardClass = "daisies";
}
npc.say("Thank you! Here, take some " + rewardClass + "!");
final StackableItem reward = (StackableItem) SingletonRepository.getEntityManager().getItem(rewardClass);
reward.setQuantity(REQUIRED_EGGS);
player.equipOrPutOnGround(reward);
player.notifyWorldAboutChanges();
}
});
npc.add(ConversationStates.QUEST_ITEM_BROUGHT,
ConversationPhrases.YES_MESSAGES,
new PlayerHasItemWithHimCondition("egg", REQUIRED_EGGS),
ConversationStates.ATTENDING, null,
new MultipleActions(reward));
//player said the eggs was for her but has dropped it from his bag or hands
npc.add(ConversationStates.QUEST_ITEM_BROUGHT,
ConversationPhrases.YES_MESSAGES,
new NotCondition(new PlayerHasItemWithHimCondition("egg", REQUIRED_EGGS)),
ConversationStates.ATTENDING,
"Hey! Where did you put the eggs?",
null);
// player had eggs but said it is not for Marianne
npc.add(
ConversationStates.QUEST_ITEM_BROUGHT,
ConversationPhrases.NO_MESSAGES,
null,
ConversationStates.ATTENDING,
"Oh... well, I hope you find some quickly;" +
"I'm getting hungry!",
null);
}
@Override
public void addToWorld() {
fillQuestInfo(
"Eggs for Marianne",
"Marianne's mom is going to make some pancakes and she needs some eggs.",
true);
prepareRequestingStep();
prepareBringingStep();
}
@Override
public String getName() {
return "EggsForMarianne";
}
@Override
public int getMinLevel() {
return 0;
}
@Override
public String getNPCName() {
return "Marianne";
}
@Override
public String getRegion() {
return Region.DENIRAN;
}
}

View file

@ -1,4 +1,3 @@
/* $Id$ */
/***************************************************************************
* (C) Copyright 2003-2023 - Stendhal *
***************************************************************************
@ -12,29 +11,11 @@
***************************************************************************/
package games.stendhal.server.maps.quests;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import games.stendhal.server.core.engine.SingletonRepository;
import games.stendhal.server.entity.npc.ChatAction;
import games.stendhal.server.entity.npc.ConversationPhrases;
import games.stendhal.server.entity.npc.ConversationStates;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.action.DropItemAction;
import games.stendhal.server.entity.npc.action.IncreaseKarmaAction;
import games.stendhal.server.entity.npc.action.IncreaseXPAction;
import games.stendhal.server.entity.npc.action.MultipleActions;
import games.stendhal.server.entity.npc.action.SetQuestAction;
import games.stendhal.server.entity.npc.action.SetQuestAndModifyKarmaAction;
import games.stendhal.server.entity.npc.condition.AndCondition;
import games.stendhal.server.entity.npc.condition.GreetingMatchesNameCondition;
import games.stendhal.server.entity.npc.condition.NotCondition;
import games.stendhal.server.entity.npc.condition.PlayerHasItemWithHimCondition;
import games.stendhal.server.entity.npc.condition.QuestCompletedCondition;
import games.stendhal.server.entity.npc.condition.QuestInStateCondition;
import games.stendhal.server.entity.npc.condition.QuestNotCompletedCondition;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.entity.npc.quest.BringItemQuestBuilder;
import games.stendhal.server.entity.npc.quest.QuestManuscript;
import games.stendhal.server.maps.Region;
import games.stendhal.server.maps.semos.city.GreeterNPC;
import games.stendhal.server.util.ResetSpeakerNPC;
@ -62,151 +43,55 @@ import games.stendhal.server.util.ResetSpeakerNPC;
*
* REPETITIONS: - None.
*/
public class HatForMonogenes extends AbstractQuest {
private static final String QUEST_SLOT = "hat_monogenes";
public class HatForMonogenes implements QuestManuscript {
@Override
public String getSlotName() {
return QUEST_SLOT;
}
@Override
public List<String> getHistory(final Player player) {
final List<String> res = new ArrayList<String>();
if (player.hasQuest(QUEST_SLOT)) {
res.add("I have met Monogenes at the spring in Semos village");
}
if (!player.hasQuest(QUEST_SLOT)) {
return res;
}
res.add("I have to find a hat, something leather to keep his head warm.");
if (player.isQuestInState(QUEST_SLOT, "start")
&& player.isEquipped("leather helmet")
|| player.isQuestCompleted(QUEST_SLOT)) {
res.add("I have found a hat.");
}
if (player.isQuestCompleted(QUEST_SLOT)) {
res.add("I gave the hat to Monogenes to keep his bald head warm.");
}
return res;
public BringItemQuestBuilder story() {
BringItemQuestBuilder quest = new BringItemQuestBuilder();
quest.info()
.name("Hat for Monogenes")
.description("Monogenes wants a hat to help him keep warm during the winter.")
.internalName("hat_monogenes")
.notRepeatable()
.minLevel(0)
.region(Region.SEMOS_CITY)
.questGiverNpc("Monogenes");
quest.history()
.whenNpcWasMet("I have met Monogenes at the spring in Semos village.")
.whenQuestWasRejected("He asked me for a hat, but I don't want to help.")
.whenQuestWasAccepted("I have to find a hat, something leather to keep his head warm.")
.whenTaskWasCompleted("I have found a hat.")
.whenQuestWasCompleted("I gave the hat to Monogenes to keep his bald head warm.");
quest.offer()
.respondToRequest("Could you bring me a #hat to cover my bald head? Brrrrr! The days here in Semos are really getting colder...")
.respondToUnrepeatableRequest("Thanks for the offer, good friend, but this hat will last me five winters at least, and it's not like I need more than one.")
.respondToAccept("Thanks, my good friend. I'll be waiting here for your return!")
.respondToReject("You surely have more importants things to do, and little time to do them in. I'll just stay here and freeze to death, I guess... *sniff*")
.rejectionKarmaPenalty(5.0)
.remind("Hey, my good friend, remember that leather hat I asked you about before? It's still pretty chilly here...")
.respondTo("hat").saying("You don't know what a hat is?! Anything light that can cover my head; like leather, for instance. Now, will you do it?");
quest.task()
.requestItem(1, "leather helmet");
quest.complete()
.greet("Hey! Is that leather hat for me?")
.respondToReject("I guess someone more fortunate will get his hat today... *sneeze*")
.respondToAccept("Bless you, my good friend! Now my head will stay nice and warm.")
.rewardWith(new IncreaseXPAction(50))
.rewardWith(new IncreaseKarmaAction(10));
return quest;
}
private void createRequestingStep() {
final SpeakerNPC monogenes = npcs.get("Monogenes");
monogenes.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new QuestNotCompletedCondition(QUEST_SLOT),
ConversationStates.QUEST_OFFERED,
"Could you bring me a #hat to cover my bald head? Brrrrr! The days here in Semos are really getting colder...",
null);
monogenes.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new QuestCompletedCondition(QUEST_SLOT),
ConversationStates.ATTENDING,
"Thanks for the offer, good friend, but this hat will last me five winters at least, and it's not like I need more than one.",
null);
monogenes.add(
ConversationStates.QUEST_OFFERED,
ConversationPhrases.YES_MESSAGES,
null,
ConversationStates.ATTENDING,
"Thanks, my good friend. I'll be waiting here for your return!",
new SetQuestAction(QUEST_SLOT, "start"));
monogenes.add(
ConversationStates.QUEST_OFFERED,
ConversationPhrases.NO_MESSAGES,
null,
ConversationStates.ATTENDING,
"You surely have more importants things to do, and little time to do them in. I'll just stay here and freeze to death, I guess... *sniff*",
new SetQuestAndModifyKarmaAction(QUEST_SLOT, "rejected", -5.0));
monogenes.add(
ConversationStates.QUEST_OFFERED,
"hat",
null,
ConversationStates.QUEST_OFFERED,
"You don't know what a hat is?! Anything light that can cover my head; like leather, for instance. Now, will you do it?",
null);
}
private void createBringingStep() {
final SpeakerNPC monogenes = npcs.get("Monogenes");
monogenes.add(ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(monogenes.getName()),
new QuestInStateCondition(QUEST_SLOT, "start"),
new PlayerHasItemWithHimCondition("leather helmet")),
ConversationStates.QUEST_ITEM_BROUGHT,
"Hey! Is that leather hat for me?", null);
monogenes.add(ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(monogenes.getName()),
new QuestInStateCondition(QUEST_SLOT, "start"),
new NotCondition(new PlayerHasItemWithHimCondition("leather helmet"))),
ConversationStates.ATTENDING,
"Hey, my good friend, remember that leather hat I asked you about before? It's still pretty chilly here...",
null);
final List<ChatAction> reward = new LinkedList<ChatAction>();
reward.add(new DropItemAction("leather helmet"));
reward.add(new IncreaseXPAction(50));
reward.add(new IncreaseKarmaAction(10));
reward.add(new SetQuestAction(QUEST_SLOT, "done"));
// make sure the player isn't cheating by putting the
// helmet away and then saying "yes"
monogenes.add(
ConversationStates.QUEST_ITEM_BROUGHT,
ConversationPhrases.YES_MESSAGES,
new PlayerHasItemWithHimCondition("leather helmet"),
ConversationStates.ATTENDING,
"Bless you, my good friend! Now my head will stay nice and warm.",
new MultipleActions(reward));
monogenes.add(
ConversationStates.QUEST_ITEM_BROUGHT,
ConversationPhrases.NO_MESSAGES,
null,
ConversationStates.ATTENDING,
"I guess someone more fortunate will get his hat today... *sneeze*",
null);
}
@Override
public void addToWorld() {
fillQuestInfo(
"Hat for Monogenes",
"Monogenes wants a hat to help him keep warm during the winter.",
false);
createRequestingStep();
createBringingStep();
}
@Override
public boolean removeFromWorld() {
final boolean res = ResetSpeakerNPC.reload(new GreeterNPC(), getNPCName());
final boolean res = ResetSpeakerNPC.reload(new GreeterNPC(), "Monogenes");
// reload other quests associated with Monogenes
SingletonRepository.getStendhalQuestSystem().reloadQuestSlots("Monogenes");
return res;
}
@Override
public String getName() {
return "HatForMonogenes";
}
@Override
public String getRegion() {
return Region.SEMOS_CITY;
}
@Override
public String getNPCName() {
return "Monogenes";
}
}

View file

@ -1,4 +1,3 @@
/* $Id$ */
/***************************************************************************
* (C) Copyright 2003-2023 - Stendhal *
***************************************************************************
@ -12,30 +11,24 @@
***************************************************************************/
package games.stendhal.server.maps.quests;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import games.stendhal.server.core.engine.SingletonRepository;
import games.stendhal.server.entity.npc.ChatAction;
import games.stendhal.server.entity.npc.ConversationPhrases;
import games.stendhal.server.entity.npc.ConversationStates;
import games.stendhal.server.entity.npc.NPCList;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.action.DropItemAction;
import games.stendhal.server.entity.npc.action.EquipItemAction;
import games.stendhal.server.entity.npc.action.IncreaseKarmaAction;
import games.stendhal.server.entity.npc.action.IncreaseXPAction;
import games.stendhal.server.entity.npc.action.MultipleActions;
import games.stendhal.server.entity.npc.action.SetQuestAction;
import games.stendhal.server.entity.npc.action.SetQuestAndModifyKarmaAction;
import games.stendhal.server.entity.npc.condition.AndCondition;
import games.stendhal.server.entity.npc.condition.GreetingMatchesNameCondition;
import games.stendhal.server.entity.npc.condition.NotCondition;
import games.stendhal.server.entity.npc.condition.PlayerHasItemWithHimCondition;
import games.stendhal.server.entity.npc.condition.QuestCompletedCondition;
import games.stendhal.server.entity.npc.condition.QuestInStateCondition;
import games.stendhal.server.entity.npc.condition.QuestNotStartedCondition;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.entity.npc.quest.BringItemQuestBuilder;
import games.stendhal.server.entity.npc.quest.QuestManuscript;
import games.stendhal.server.maps.Region;
import games.stendhal.server.maps.orril.magician_house.WitchNPC;
import games.stendhal.server.maps.semos.library.LibrarianNPC;
@ -66,84 +59,75 @@ import games.stendhal.server.util.ResetSpeakerNPC;
*
* REPETITIONS: None
*/
public class LookBookforCeryl extends AbstractQuest {
private static final String QUEST_SLOT = "ceryl_book";
public class LookBookforCeryl implements QuestManuscript {
private final static String QUEST_SLOT = "ceryl_book";
@Override
public String getSlotName() {
return QUEST_SLOT;
}
public BringItemQuestBuilder story() {
BringItemQuestBuilder quest = new BringItemQuestBuilder();
private void step1LearnAboutQuest() {
quest.info()
.name("Look for a Book for Ceryl")
.description("Ceryl wants an old book that was checked out.")
.internalName(QUEST_SLOT)
.notRepeatable()
.minLevel(0)
.region(Region.SEMOS_CITY)
.questGiverNpc("Ceryl");
final SpeakerNPC npc = npcs.get("Ceryl");
quest.history()
.whenNpcWasMet("I have met Ceryl at the library, he's the librarian there.")
.whenQuestWasRejected("I do not want to find the book.")
.whenQuestWasAccepted("I promised to fetch the black book from Jynath.")
.whenTaskWasCompleted("I have talked to Jynath and got the book.")
.whenQuestWasCompleted("I have returned the book to Ceryl and got a little reward.");
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new QuestNotStartedCondition(QUEST_SLOT),
ConversationStates.ATTENDING,
"I am looking for a very special #book.", null);
quest.offer()
.respondToRequest("I am looking for a very special book. Could you ask #Jynath to return it? She has had it for months now, and people are looking for it.")
.respondToUnrepeatableRequest("I have nothing for you now.")
.respondToAccept("Great! Please get me it as quickly as possible... there's a huge waiting list!")
.respondTo("jynath").saying("Jynath is the witch who lives south of Or'ril castle, southwest of here. So, will you get me the book?")
.respondToReject("Oh... I suppose I will have to get somebody else to do it, then.")
.rejectionKarmaPenalty(5.0)
.remind("I really need that book now! Go to talk with #Jynath.");
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new QuestCompletedCondition(QUEST_SLOT),
ConversationStates.ATTENDING,
"I have nothing for you now.", null);
SpeakerNPC npc = NPCList.get().get("Ceryl");
npc.addReply("jynath", "Jynath is the witch who lives south of Or'ril castle, southwest of here.");
/** Other conditions not met e.g. quest completed */
npc.addReply("book","If you want to learn more, chat to my friend Wikipedian in Ados library.", null);
step2getBook();
quest.task()
.requestItem(1, "black book");
/** If quest is not started yet, start it. */
quest.complete()
.greet("Hi, did you get the book from Jynath?")
.respondToReject("Oh... I suppose I will have to get somebody else to fetch it, then.")
.respondToAccept("Oh, you got the book back! Phew, thanks!")
.rewardWith(new IncreaseXPAction(100))
.rewardWith(new IncreaseKarmaAction(10))
.rewardWith(new EquipItemAction("money", 50));
// There is no other way to get the book.
// Remove that quest slot so that the player can get
// it again from Jynath
// As the book is both bound and useless outside the
// quest, this is not a problem
npc.add(
ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(npc.getName()),
new QuestInStateCondition(QUEST_SLOT, "jynath"),
new NotCondition(new PlayerHasItemWithHimCondition("black book"))),
ConversationStates.ATTENDING,
"book", new QuestNotStartedCondition(QUEST_SLOT),
ConversationStates.QUEST_OFFERED,
"Could you ask #Jynath to return her book? She's had it for months now, and people are looking for it.",
null);
npc.add(
ConversationStates.QUEST_OFFERED,
ConversationPhrases.YES_MESSAGES,
null,
ConversationStates.ATTENDING,
"Great! Please get me it as quickly as possible... there's a huge waiting list!",
"Haven't you got that #book back from #Jynath? Please go look for it, quickly!",
new SetQuestAction(QUEST_SLOT, "start"));
npc.add(
ConversationStates.QUEST_OFFERED,
ConversationPhrases.NO_MESSAGES,
null,
ConversationStates.ATTENDING,
"Oh... I suppose I will have to get somebody else to do it, then.",
new SetQuestAndModifyKarmaAction(QUEST_SLOT, "rejected", -5.0));
npc.add(
ConversationStates.QUEST_OFFERED,
"jynath",
null,
ConversationStates.QUEST_OFFERED,
"Jynath is the witch who lives south of Or'ril castle, southwest of here. So, will you get me the book?",
null);
/** Remind player about the quest */
npc.add(ConversationStates.ATTENDING, "book",
new QuestInStateCondition(QUEST_SLOT, "start"),
ConversationStates.ATTENDING,
"I really need that book now! Go to talk with #Jynath.", null);
npc.add(
ConversationStates.ATTENDING,
"jynath",
null,
ConversationStates.ATTENDING,
"Jynath is the witch who lives south of Or'ril castle, southwest of here.",
null);
return quest;
}
private void step2getBook() {
final SpeakerNPC npc = npcs.get("Jynath");
final SpeakerNPC npc = NPCList.get().get("Jynath");
/**
* If player has quest and is in the correct state, just give him the
@ -182,103 +166,12 @@ public class LookBookforCeryl extends AbstractQuest {
null);
}
private void step3returnBook() {
final SpeakerNPC npc = npcs.get("Ceryl");
/** Complete the quest */
final List<ChatAction> reward = new LinkedList<ChatAction>();
reward.add(new DropItemAction("black book"));
reward.add(new EquipItemAction("money", 50));
reward.add(new IncreaseXPAction(100));
reward.add(new IncreaseKarmaAction(10.0));
reward.add(new SetQuestAction(QUEST_SLOT, "done"));
npc.add(
ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(npc.getName()),
new QuestInStateCondition(QUEST_SLOT, "jynath"),
new PlayerHasItemWithHimCondition("black book")),
ConversationStates.ATTENDING,
"Oh, you got the book back! Phew, thanks!",
new MultipleActions(reward));
// There is no other way to get the book.
// Remove that quest slot so that the player can get
// it again from Jynath
// As the book is both bound and useless outside the
// quest, this is not a problem
npc.add(
ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(npc.getName()),
new QuestInStateCondition(QUEST_SLOT, "jynath"),
new NotCondition(new PlayerHasItemWithHimCondition("black book"))),
ConversationStates.ATTENDING,
"Haven't you got that #book back from #Jynath? Please go look for it, quickly!",
new SetQuestAction(QUEST_SLOT, "start"));
}
@Override
public List<String> getHistory(final Player player) {
final List<String> res = new ArrayList<String>();
if (!player.hasQuest(QUEST_SLOT)) {
return res;
}
res.add("I have met Ceryl at the library, he's the librarian there.");
final String questState = player.getQuest(QUEST_SLOT);
if (questState.equals("rejected")) {
res.add("I do not want to find the book.");
}
if (player.isQuestInState(QUEST_SLOT, "start", "jynath", "done")) {
res.add("I promised to fetch the black book from Jynath.");
}
if (questState.equals("jynath") && player.isEquipped("black book")
|| questState.equals("done")) {
res.add("I have talked to Jynath, and have the book.");
}
if (questState.equals("jynath") && !player.isEquipped("black book")) {
res.add("I do not have the black book Jynath has.");
}
if (questState.equals("done")) {
res.add("I have returned the book to Ceryl and got a little reward.");
}
return res;
}
@Override
public void addToWorld() {
fillQuestInfo(
"Look for a Book for Ceryl",
"Ceryl wants an old book that was checked out.",
false);
step1LearnAboutQuest();
step2getBook();
step3returnBook();
}
@Override
public boolean removeFromWorld() {
final boolean res = ResetSpeakerNPC.reload(new LibrarianNPC(), getNPCName())
final boolean res = ResetSpeakerNPC.reload(new LibrarianNPC(), "Ceryl")
&& ResetSpeakerNPC.reload(new WitchNPC(), "Jynath");
// reload other quests associated with Ceryl
SingletonRepository.getStendhalQuestSystem().reloadQuestSlots("obsidian_knife");
return res;
}
@Override
public String getName() {
return "LookBookforCeryl";
}
@Override
public String getRegion() {
return Region.SEMOS_CITY;
}
@Override
public String getNPCName() {
return "Ceryl";
}
}

View file

@ -1,6 +1,5 @@
/* $Id$ */
/***************************************************************************
* (C) Copyright 2003-2010 - Stendhal *
* (C) Copyright 2003-2023 - Stendhal *
***************************************************************************
***************************************************************************
* *
@ -12,32 +11,17 @@
***************************************************************************/
package games.stendhal.server.maps.quests;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import games.stendhal.server.core.engine.SingletonRepository;
import games.stendhal.server.core.engine.StendhalRPZone;
import games.stendhal.server.entity.mapstuff.spawner.PassiveEntityRespawnPoint;
import games.stendhal.server.entity.npc.ChatAction;
import games.stendhal.server.entity.npc.ConversationPhrases;
import games.stendhal.server.entity.npc.ConversationStates;
import games.stendhal.server.entity.npc.NPCList;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.action.DropItemAction;
import games.stendhal.server.entity.npc.action.IncreaseKarmaAction;
import games.stendhal.server.entity.npc.action.IncreaseXPAction;
import games.stendhal.server.entity.npc.action.MultipleActions;
import games.stendhal.server.entity.npc.action.SetQuestAction;
import games.stendhal.server.entity.npc.condition.AndCondition;
import games.stendhal.server.entity.npc.condition.GreetingMatchesNameCondition;
import games.stendhal.server.entity.npc.condition.NotCondition;
import games.stendhal.server.entity.npc.condition.OrCondition;
import games.stendhal.server.entity.npc.condition.PlayerHasItemWithHimCondition;
import games.stendhal.server.entity.npc.condition.QuestCompletedCondition;
import games.stendhal.server.entity.npc.condition.QuestNotCompletedCondition;
import games.stendhal.server.entity.npc.condition.QuestNotStartedCondition;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.entity.npc.quest.BringItemQuestBuilder;
import games.stendhal.server.entity.npc.quest.QuestManuscript;
import games.stendhal.server.maps.Region;
/**
@ -53,85 +37,60 @@ import games.stendhal.server.maps.Region;
*
* REPETITIONS: <ul><li> None. </ul>
*/
public class PlinksToy extends AbstractQuest {
private static final String QUEST_SLOT = "plinks_toy";
public class PlinksToy implements QuestManuscript {
@Override
public String getSlotName() {
return QUEST_SLOT;
public BringItemQuestBuilder story() {
BringItemQuestBuilder quest = new BringItemQuestBuilder();
quest.info()
.name("Plink's Toy")
.description("Plink is a sweet little boy, and like many little boys, is frightened of wolves")
.internalName("plinks_toy")
.notRepeatable()
.minLevel(0)
.region(Region.SEMOS_SURROUNDS)
.questGiverNpc("Plink");
quest.history()
.whenNpcWasMet("I have met Plink.")
.whenQuestWasRejected("I do not want to find Plink's toy bear.")
.whenQuestWasAccepted("Plink begged me to look for his teddy in a garden with lots of wolves.")
.whenTaskWasCompleted("I have found Plink's toy bear.")
.whenQuestWasCompleted("I gave the bear to Plink and he was extremly happy.");
quest.offer()
.begOnGreeting("*cries* There were wolves in the #park! *sniff* I ran away, but I dropped my #teddy! Please will you get it for me? *sniff* Please?")
.respondToRequest("*cries* There were wolves in the #park! *sniff* I ran away, but I dropped my #teddy! Please will you get it for me? *sniff* Please?")
.respondToUnrepeatableRequest("You found my teddy already near by the wolves! I still squeeze and hug it :)")
.respondToAccept("*sniff* Thanks a lot! *smile*")
.respondToReject("*sniff* But... but... PLEASE! *cries*")
.rejectionKarmaPenalty(10.0)
.remind("I lost my teddy in the #park over east, where all those #wolves are hanging about.")
.respondTo("wolf", "wolves").saying("They came in from the plains, and now they're hanging around the #park over to the east a little ways. I'm not allowed to go near them, they're dangerous.")
.respondTo("park").saying("My parents told me not to go to the park by myself, but I got lost when I was playing... Please don't tell them! Can you bring my #teddy back?")
.respondTo("teddy").saying("Teddy is my favourite toy! Please will you bring him back?");
final SpeakerNPC npc = NPCList.get().get("Plink");
npc.addReply(Arrays.asList("wolf", "wolves"), "They came in from the plains, and now they're hanging around the #park over to the east a little ways. I'm not allowed to go near them, they're dangerous.");
npc.addReply("park", "My parents told me not to go to the park by myself, but I got lost when I was playing... Please don't tell them!");
npc.addReply("teddy", "Teddy is my favourite toy! Please bring him back to me.");
quest.task()
.requestItem(1, "teddy");
step2();
quest.complete()
.greet("Ah, I see, you have enough coal to keep my BBQ on! Is it for me?")
.respondToReject("Well then, hopefully someone else will help me before my BBQ goes out.")
.respondToAccept("You found him! *hugs teddy* Thank you, thank you! *smile*")
.rewardWith(new IncreaseXPAction(20))
.rewardWith(new IncreaseKarmaAction(10));
return quest;
}
@Override
public List<String> getHistory(final Player player) {
final List<String> res = new ArrayList<String>();
if (!player.hasQuest(QUEST_SLOT)) {
if (player.isEquipped("teddy")) {
res.add("I found a bear which might belong to someone else.");
}
return res;
}
res.add("I have met Plink");
final String questState = player.getQuest(QUEST_SLOT);
if (questState.equals("rejected")) {
res.add("I do not want to find Plink's toy bear.");
return res;
}
res.add("Plink begged me to look for his teddy in a garden with lots of wolves.");
if (player.isEquipped("teddy") || isCompleted(player)) {
res.add("I have found Plink's toy bear");
}
if (isCompleted(player)) {
res.add("I gave Plink his bear.");
}
return res;
}
private void step_1() {
final SpeakerNPC npc = npcs.get("Plink");
npc.add(
ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(npc.getName()),
new QuestNotCompletedCondition(QUEST_SLOT),
new NotCondition(new PlayerHasItemWithHimCondition("teddy"))),
ConversationStates.QUEST_OFFERED,
"*cries* There were wolves in the #park! *sniff* I ran away, but I dropped my #teddy! Please will you get it for me? *sniff* Please?",
null);
npc.add(ConversationStates.QUEST_OFFERED,
ConversationPhrases.YES_MESSAGES, null,
ConversationStates.IDLE, "*sniff* Thanks a lot! *smile*",
new SetQuestAction(QUEST_SLOT, "start"));
npc.add(ConversationStates.QUEST_OFFERED, ConversationPhrases.NO_MESSAGES, null,
ConversationStates.QUEST_OFFERED,
"*sniff* But... but... PLEASE! *cries*", null);
npc.add(
ConversationStates.QUEST_OFFERED,
Arrays.asList("wolf", "wolves"),
null,
ConversationStates.QUEST_OFFERED,
"They came in from the plains, and now they're hanging around the #park over to the east a little ways. I'm not allowed to go near them, they're dangerous.",
null);
npc.add(
ConversationStates.QUEST_OFFERED,
"park",
null,
ConversationStates.QUEST_OFFERED,
"My parents told me not to go to the park by myself, but I got lost when I was playing... Please don't tell them! Can you bring my #teddy back?",
null);
npc.add(ConversationStates.QUEST_OFFERED, "teddy", null,
ConversationStates.QUEST_OFFERED,
"Teddy is my favourite toy! Please will you bring him back?",
null);
}
private void step_2() {
private void step2() {
final StendhalRPZone zone = SingletonRepository.getRPWorld().getZone("0_semos_plains_n");
final PassiveEntityRespawnPoint teddyRespawner = new PassiveEntityRespawnPoint("teddy", 1500);
teddyRespawner.setPosition(107, 84);
@ -140,66 +99,4 @@ public class PlinksToy extends AbstractQuest {
teddyRespawner.setToFullGrowth();
}
private void step_3() {
final SpeakerNPC npc = npcs.get("Plink");
final List<ChatAction> reward = new LinkedList<ChatAction>();
reward.add(new DropItemAction("teddy"));
reward.add(new IncreaseXPAction(20));
reward.add(new SetQuestAction(QUEST_SLOT, "done"));
reward.add(new IncreaseKarmaAction(10));
npc.add(ConversationStates.IDLE, ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(npc.getName()),
new OrCondition(
new QuestNotStartedCondition(QUEST_SLOT),
new QuestNotCompletedCondition(QUEST_SLOT)),
new PlayerHasItemWithHimCondition("teddy")),
ConversationStates.ATTENDING,
"You found him! *hugs teddy* Thank you, thank you! *smile*",
new MultipleActions(reward));
npc.add(
ConversationStates.ATTENDING,
"teddy",
new AndCondition(new QuestNotCompletedCondition(QUEST_SLOT), new NotCondition(new PlayerHasItemWithHimCondition("teddy"))),
ConversationStates.ATTENDING,
"I lost my teddy in the #park over east, where all those #wolves are hanging about.",
null);
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(npc.getName()),
new QuestCompletedCondition(QUEST_SLOT)),
ConversationStates.ATTENDING,
"You found my teddy already near by the wolves! I still squeeze and hug it :)", null);
}
@Override
public void addToWorld() {
fillQuestInfo(
"Plink's Toy",
"Plink is a sweet little boy, and like many little boys, is frightened of wolves.",
false);
step_1();
step_2();
step_3();
}
@Override
public String getName() {
return "PlinksToy";
}
@Override
public String getNPCName() {
return "Plink";
}
@Override
public String getRegion() {
return Region.SEMOS_SURROUNDS;
}
}

View file

@ -1,5 +1,5 @@
/***************************************************************************
* (C) Copyright 2003-2010 - Stendhal *
* (C) Copyright 2003-2023 - Stendhal *
***************************************************************************
***************************************************************************
* *
@ -11,10 +11,7 @@
***************************************************************************/
package games.stendhal.server.maps.quests;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import games.stendhal.common.parser.Sentence;
import games.stendhal.server.core.engine.SingletonRepository;
@ -25,27 +22,24 @@ import games.stendhal.server.entity.npc.ChatCondition;
import games.stendhal.server.entity.npc.ConversationPhrases;
import games.stendhal.server.entity.npc.ConversationStates;
import games.stendhal.server.entity.npc.EventRaiser;
import games.stendhal.server.entity.npc.NPCList;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.action.DropItemAction;
import games.stendhal.server.entity.npc.action.ConditionalAction;
import games.stendhal.server.entity.npc.action.EquipItemAction;
import games.stendhal.server.entity.npc.action.IncreaseKarmaAction;
import games.stendhal.server.entity.npc.action.IncreaseXPAction;
import games.stendhal.server.entity.npc.action.MultipleActions;
import games.stendhal.server.entity.npc.action.SayTimeRemainingAction;
import games.stendhal.server.entity.npc.action.SetQuestAction;
import games.stendhal.server.entity.npc.action.SetQuestAndModifyKarmaAction;
import games.stendhal.server.entity.npc.action.SetQuestToTimeStampAction;
import games.stendhal.server.entity.npc.action.SayTextAction;
import games.stendhal.server.entity.npc.condition.AndCondition;
import games.stendhal.server.entity.npc.condition.GreetingMatchesNameCondition;
import games.stendhal.server.entity.npc.condition.NotCondition;
import games.stendhal.server.entity.npc.condition.PlayerCanEquipItemCondition;
import games.stendhal.server.entity.npc.condition.PlayerHasItemWithHimCondition;
import games.stendhal.server.entity.npc.condition.PlayerHasItemdataItemWithHimCondition;
import games.stendhal.server.entity.npc.condition.QuestActiveCondition;
import games.stendhal.server.entity.npc.condition.QuestCompletedCondition;
import games.stendhal.server.entity.npc.condition.QuestNotStartedCondition;
import games.stendhal.server.entity.npc.condition.QuestRegisteredCondition;
import games.stendhal.server.entity.npc.condition.TimePassedCondition;
import games.stendhal.server.entity.npc.quest.BringItemQuestBuilder;
import games.stendhal.server.entity.npc.quest.QuestManuscript;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.maps.Region;
@ -75,207 +69,64 @@ import games.stendhal.server.maps.Region;
* <li>Every 24 hours</li>
* </ul>
*/
public class TrapsForKlaas extends AbstractQuest {
public final int REQUIRED_TRAPS = 20;
// Time player must wait to repeat quest (1 day)
private static final int WAIT_TIME = 60 * 24;
private static final String QUEST_SLOT = "traps_for_klaas";
private static final String info_string = "note to apothecary";
public class TrapsForKlaas implements QuestManuscript {
private final static String QUEST_SLOT = "traps_for_klaas";
@Override
public List<String> getHistory(final Player player) {
final List<String> res = new ArrayList<String>();
if (!player.hasQuest(QUEST_SLOT)) {
return res;
}
res.add("I have talked to Klaas.");
final String questState = player.getQuest(QUEST_SLOT);
if ("rejected".equals(questState)) {
res.add("I do not care to deal with rodents.");
}
if (player.isQuestInState(QUEST_SLOT, "start", "done")) {
res.add("I promised to gather " + REQUIRED_TRAPS + " rodent traps and bring them to Klaas.");
}
if (player.isQuestInState(QUEST_SLOT, 0, "done")) {
res.add("I gave the rodent traps to Klaas. I got some experience and antidotes.");
}
if (isRepeatable(player)) {
res.add("I should check if Klaas needs my help again.");
}
return res;
}
public BringItemQuestBuilder story() {
BringItemQuestBuilder quest = new BringItemQuestBuilder();
private void prepareRequestingStep() {
final SpeakerNPC npc = npcs.get("Klaas");
quest.info()
.name("Traps for Klaas")
.description("Klaas, the cargo caretaker on the Athor ferry, is in need of some rodent traps.")
.internalName(QUEST_SLOT)
.repeatableAfterMinutes(24 * 60)
.minLevel(0)
.region(Region.ATHOR_ISLAND)
.questGiverNpc("Klaas");
// Player asks for quest
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new AndCondition(
new NotCondition(new QuestActiveCondition(QUEST_SLOT)),
new TimePassedCondition(QUEST_SLOT, 1, WAIT_TIME)
),
ConversationStates.QUEST_OFFERED,
"The rats down here have been getting into the food storage. Would you help me rid us of the varmints?",
null);
quest.history()
.whenNpcWasMet("I have talked to Klaas on the ship to Athor.")
.whenQuestWasRejected("I do not care about dealing with rodents.")
.whenQuestWasAccepted("I promised to gather 20 rodent traps and bring them to Klaas.")
.whenTaskWasCompleted("I got enough traps.")
.whenQuestWasCompleted("I gave the rodent traps to Klaas. I got some experience and antidotes.")
.whenQuestCanBeRepeated("I should check if Klaas needs my help again.");
// Player requests quest before wait period ended
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new NotCondition(new TimePassedCondition(QUEST_SLOT, 1, WAIT_TIME)),
ConversationStates.ATTENDING,
null,
new SayTimeRemainingAction(QUEST_SLOT, 1, WAIT_TIME, "Thanks for the traps. Now the food will be safe. But I may need your help again in"));
quest.offer()
.respondToRequest("The rats down here have been getting into the food storage. Would you help me rid us of the varmints?")
.respondToUnrepeatableRequest("Thanks for the traps. Now the food will be safe. But I may need your help again soon.")
.respondToRepeatedRequest("The rats down here have been getting into the food storage. Would you help me rid us of the varmints?")
.respondToAccept("Thanks, I need you to bring me bring me 20 #rodent #traps. Please hurry! We can't afford to lose anymore food.")
.respondToReject("Don't waste my time. I've got to protect the cargo.")
.rejectionKarmaPenalty(5.0)
.remind("I believe, I already asked you to get me 20 rodent traps.");
// Player asks for quest after already started
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
new QuestActiveCondition(QUEST_SLOT),
ConversationStates.ATTENDING,
"I believe I already asked you to get me " + REQUIRED_TRAPS + " rodent traps.",
null);
// Player accepts quest
final SpeakerNPC npc = NPCList.get().get("Klaas");
npc.add(
ConversationStates.QUEST_OFFERED,
ConversationPhrases.YES_MESSAGES,
null,
ConversationStates.ATTENDING,
"Thanks, I need you to bring me bring me " + REQUIRED_TRAPS + " #rodent #traps. Please hurry! We can't afford to lose anymore food.",
new SetQuestAction(QUEST_SLOT, "start"));
// Player rejects quest
npc.add(
ConversationStates.QUEST_OFFERED,
ConversationPhrases.NO_MESSAGES,
null,
// Klaas walks away
ConversationStates.IDLE,
"Don't waste my time. I've got to protect the cargo.",
new SetQuestAndModifyKarmaAction(QUEST_SLOT, "rejected", -5.0));
// Player asks about rodent traps
npc.add(
ConversationStates.ATTENDING,
Arrays.asList("rodent trap", "trap", "rodent traps", "traps"),
new QuestActiveCondition(QUEST_SLOT),
ConversationStates.ATTENDING,
"I don't know of anyone who sells 'em. But I did hear a story once about a fella who killed a large rat and discovered a trap snapped shut on its foot.",
null);
}
private void prepareBringingStep() {
final SpeakerNPC npc = npcs.get("Klaas");
final ChatCondition giveNoteRewardCondition = new ChatCondition() {
private final String avrQuestSlot = "antivenom_ring";
@Override
public boolean fire(final Player player, final Sentence sentence, final Entity npc) {
if (!new QuestRegisteredCondition(avrQuestSlot).fire(player, sentence, npc)) {
return false;
}
// note has already been given to Jameson & Antivenom Ring quest has already been started or completed
if (player.getQuest(avrQuestSlot) != null) {
return false;
}
// player already has a note
// FIXME: PlayerOwnsItemIncludingBankCondition currently doesn't support itemdata items
if (player.isEquippedWithItemdata("note", info_string)) {
return false;
}
return true;
}
};
// Reward
final List<ChatAction> reward = new LinkedList<ChatAction>();
reward.add(new DropItemAction("rodent trap", 20));
reward.add(new EquipItemAction("greater antidote", 5));
reward.add(new IncreaseXPAction(1000));
reward.add(new IncreaseKarmaAction(10));
reward.add(new SetQuestAction(QUEST_SLOT, "done"));
reward.add(new SetQuestToTimeStampAction(QUEST_SLOT, 1));
// action that gives player note to apothecary
final ChatAction equipNoteAction = new ChatAction() {
@Override
public void fire(final Player player, final Sentence sentence, final EventRaiser npc) {
final Item note = SingletonRepository.getEntityManager().getItem("note");
note.setItemData(info_string);
note.setDescription("You see a note written to an apothecary. It is a recommendation from Klaas.");
note.setBoundTo(player.getName());
player.equipOrPutOnGround(note);
}
};
// Player has all 20 traps
npc.add(ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(npc.getName()),
new QuestActiveCondition(QUEST_SLOT),
new PlayerHasItemWithHimCondition("rodent trap")),
ConversationStates.QUEST_ITEM_BROUGHT,
"Did you bring any traps?",
ConversationStates.ATTENDING,
Arrays.asList("rodent trap", "trap", "rodent traps", "traps"),
new QuestActiveCondition("traps_for_klaas"),
ConversationStates.ATTENDING,
"I don't know of anyone who sells 'em. But I did hear a story once about a fella who killed a large rat and discovered a trap snapped shut on its foot.",
null);
// Player is not carrying any traps
npc.add(ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
new AndCondition(new GreetingMatchesNameCondition(npc.getName()),
new QuestActiveCondition(QUEST_SLOT),
new NotCondition(new PlayerHasItemWithHimCondition("rodent trap"))),
ConversationStates.ATTENDING,
"I could really use those #traps. How can I help you?",
null);
quest.task()
.requestItem(20, "rodent trap");
// Player is not carrying 20 traps
npc.add(ConversationStates.QUEST_ITEM_BROUGHT,
ConversationPhrases.YES_MESSAGES,
new AndCondition(new PlayerHasItemWithHimCondition("rodent trap"),
new NotCondition(new PlayerHasItemWithHimCondition("rodent trap", 20))),
ConversationStates.ATTENDING,
"I'm sorry but I need 20 #rodent #traps",
null);
// brings traps & has already started/completed antivenom ring quest
npc.add(ConversationStates.QUEST_ITEM_BROUGHT,
ConversationPhrases.YES_MESSAGES,
new AndCondition(
new NotCondition(giveNoteRewardCondition),
new PlayerHasItemWithHimCondition("rodent trap", 20)),
ConversationStates.ATTENDING,
"Thanks! I've got to get these set up as quickly as possible. Take these antidotes as a reward.",
new MultipleActions(reward));
// brings traps & has not started antivenom ring quest
npc.add(ConversationStates.QUEST_ITEM_BROUGHT,
ConversationPhrases.YES_MESSAGES,
new AndCondition(
giveNoteRewardCondition,
new PlayerHasItemWithHimCondition("rodent trap", 20)),
ConversationStates.ATTENDING,
"Thanks! I've got to get these set up as quickly as possible. Take these antidotes as a reward. I used to know an old #apothecary. Take this note to him. Maybe he can help you out with something.",
new MultipleActions(
new MultipleActions(reward),
equipNoteAction));
// Player says did not bring items
npc.add(
ConversationStates.QUEST_ITEM_BROUGHT,
ConversationPhrases.NO_MESSAGES,
null,
ConversationStates.ATTENDING,
"Please hurry! I just found another box of food that's been chewed through.",
null);
quest.complete()
.greet("Did you bring any traps?")
.respondToReject("Please hurry! I just found another box of food that's been chewed through.")
.respondToAccept("Thanks! I've got to get these set up as quickly as possible. Take these antidotes as a reward.")
.rewardWith(new IncreaseXPAction(1000))
.rewardWith(new IncreaseKarmaAction(10))
.rewardWith(new EquipItemAction("greater antidote", 5))
.rewardWith(new ConditionalAction(
giveNoteRewardCondition,
new MultipleActions(
equipNoteAction,
new SayTextAction("I used to know an old #apothecary. Take this note to him. Maybe he can help you out with something."))));
// Player has lost note
npc.add(ConversationStates.IDLE,
@ -291,6 +142,7 @@ public class TrapsForKlaas extends AbstractQuest {
+ " Remember to ask around about an #apothecary.",
equipNoteAction);
// player lost note, but doesn't have room in inventory
npc.add(ConversationStates.IDLE,
ConversationPhrases.GREETING_MESSAGES,
@ -302,52 +154,46 @@ public class TrapsForKlaas extends AbstractQuest {
ConversationStates.ATTENDING,
"You lost the note? Well, I could write another one. But it doesn't look like you have room to carry it.",
null);
return quest;
}
@Override
public void addToWorld() {
fillQuestInfo(
"Traps for Klaas",
"Klaas, the cargo caretaker on the Athor ferry, is in need of some rodent traps.",
false);
prepareRequestingStep();
prepareBringingStep();
}
// action that gives player note to apothecary
private static final String info_string = "note to apothecary";
final ChatAction equipNoteAction = new ChatAction() {
@Override
public void fire(final Player player, final Sentence sentence, final EventRaiser npc) {
final Item note = SingletonRepository.getEntityManager().getItem("note");
note.setItemData(info_string);
note.setDescription("You see a note written to an apothecary. It is a recommendation from Klaas.");
note.setBoundTo(player.getName());
player.equipOrPutOnGround(note);
}
};
final ChatCondition giveNoteRewardCondition = new ChatCondition() {
private final String avrQuestSlot = "antivenom_ring";
@Override
public String getSlotName() {
return QUEST_SLOT;
}
@Override
public boolean fire(final Player player, final Sentence sentence, final Entity npc) {
if (!new QuestRegisteredCondition(avrQuestSlot).fire(player, sentence, npc)) {
return false;
}
@Override
public String getName() {
return "TrapsForKlaas";
}
// note has already been given to Jameson & Antivenom Ring quest has already been started or completed
if (player.getQuest(avrQuestSlot) != null) {
return false;
}
public String getTitle() {
// player already has a note
// FIXME: PlayerOwnsItemIncludingBankCondition currently doesn't support itemdata items
if (player.isEquippedWithItemdata("note", info_string)) {
return false;
}
return "TrapsForKlaas";
}
return true;
}
};
@Override
public int getMinLevel() {
return 0;
}
@Override
public String getRegion() {
return Region.ATHOR_ISLAND;
}
@Override
public String getNPCName() {
return "Klaas";
}
@Override
public boolean isRepeatable(final Player player) {
return new AndCondition(
new QuestCompletedCondition(QUEST_SLOT),
new TimePassedCondition(QUEST_SLOT, 1, WAIT_TIME)).fire(player, null, null);
}
}

View file

@ -35,6 +35,7 @@ import games.stendhal.server.entity.npc.NPC;
import games.stendhal.server.entity.npc.NPCList;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.fsm.Engine;
import games.stendhal.server.entity.npc.quest.BuiltQuest;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.maps.MockStendlRPWorld;
import games.stendhal.server.maps.quests.AGrandfathersWish;
@ -175,7 +176,7 @@ public class FriendAchievementFactoryTest extends AchievementTestHelper {
// Plink
loadConfigurators(new games.stendhal.server.maps.semos.plains.LittleBoyNPC());
addZones("0_semos_plains_n");
loadQuests(new PlinksToy());
loadQuests(new BuiltQuest(new PlinksToy().story()));
ChildrensFriendStub.doQuestPlink(player);
assertFalse(achievementReached(player, id));
@ -187,7 +188,7 @@ public class FriendAchievementFactoryTest extends AchievementTestHelper {
// Sally
loadConfigurators(new games.stendhal.server.maps.orril.river.CampingGirlNPC());
loadQuests(new Campfire());
loadQuests(new BuiltQuest(new Campfire().story()));
ChildrensFriendStub.doQuestSally(player);
assertFalse(achievementReached(player, id));
@ -233,7 +234,7 @@ public class FriendAchievementFactoryTest extends AchievementTestHelper {
// Marianne
loadConfigurators(new games.stendhal.server.maps.deniran.cityoutside.LittleGirlNPC());
loadQuests(new EggsForMarianne());
loadQuests(new BuiltQuest(new EggsForMarianne().story()));
ChildrensFriendStub.doQuestMarianne(player);
assertTrue(achievementReached(player, id));

View file

@ -48,7 +48,6 @@ import utilities.AchievementTestHelper;
import utilities.PlayerTestHelper;
import utilities.ZonePlayerAndNPCTestImpl;
public class KillBlordroughsAchievementFactoryTest extends ZonePlayerAndNPCTestImpl {
private static final Logger logger = Logger.getLogger(KillBlordroughsAchievementFactoryTest.class);

View file

@ -14,6 +14,7 @@ package games.stendhal.server.core.rp.achievement.factory;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static utilities.SpeakerNPCTestHelper.getSpeakerNPC;
import static utilities.ZoneAndPlayerTestImpl.setupZone;
@ -21,6 +22,7 @@ import static utilities.ZoneAndPlayerTestImpl.setupZone;
import java.util.ArrayList;
import java.util.List;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
@ -35,6 +37,7 @@ import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.fsm.Engine;
import games.stendhal.server.entity.npc.quest.BuiltQuest;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.maps.Region;
import games.stendhal.server.maps.quests.AbstractQuest;
import games.stendhal.server.maps.quests.BalloonForBobby;
import games.stendhal.server.maps.quests.BeerForHayunn;
@ -90,7 +93,11 @@ public class QuestAchievementFactoryTest extends AchievementTestHelper {
QuestHelper.unloadQuests(qloaded);
for (int idx = qloaded.size()-1; idx >= 0; idx--) {
// TODO: QuestManuscripts should support unloading
if (!qloaded.get(idx).getName().equals("pizza_delivery")) {
if (!qloaded.get(idx).getName().equals("pizza_delivery")
&& !qloaded.get(idx).getName().equals("ceryl_book")
&& !qloaded.get(idx).getName().equals("hat_monogenes")
&& !qloaded.get(idx).getName().equals("beer_hayunn")
) {
assertFalse(qloaded.get(idx).getName(), QuestHelper.isLoaded(qloaded.get(idx)));
}
qloaded.remove(idx);
@ -318,9 +325,9 @@ public class QuestAchievementFactoryTest extends AchievementTestHelper {
final GoodiesForRudolph questRudolph = new GoodiesForRudolph();
loadQuests(
new MeetHayunn(),
new BeerForHayunn(),
new BuiltQuest(new BeerForHayunn().story()),
new MeetMonogenes(),
new HatForMonogenes(),
new BuiltQuest(new HatForMonogenes().story()),
new SheepGrowing(),
new MedicineForTad(),
new MeetIo(),
@ -328,7 +335,7 @@ public class QuestAchievementFactoryTest extends AchievementTestHelper {
new NewsFromHackim(),
new BowsForOuchit(),
new HungryJoshua(),
new LookBookforCeryl(),
new BuiltQuest(new LookBookforCeryl().story()),
new MeetKetteh(),
new BuiltQuest(new PizzaDelivery().story()),
new HerbsForCarmen(),
@ -474,6 +481,7 @@ public class QuestAchievementFactoryTest extends AchievementTestHelper {
QuestRunner.doQuestGoodiesForRudolph(player);
*/
assertThat(SingletonRepository.getStendhalQuestSystem().getIncompleteQuests(player, Region.SEMOS_CITY), Matchers.empty());
assertTrue(achievementReached(player, id));
}

View file

@ -1,6 +1,5 @@
/* $Id$ */
/***************************************************************************
* (C) Copyright 2003-2010 - Stendhal *
* (C) Copyright 2003-2023 - Stendhal *
***************************************************************************
***************************************************************************
* *
@ -28,6 +27,7 @@ import games.stendhal.server.entity.item.Item;
import games.stendhal.server.entity.npc.ConversationStates;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.fsm.Engine;
import games.stendhal.server.entity.npc.quest.BuiltQuest;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.maps.MockStendlRPWorld;
import games.stendhal.server.maps.amazon.hut.PrincessNPC;
@ -40,6 +40,7 @@ public class AmazonPrincessTest {
private Player player = null;
private SpeakerNPC npc = null;
private Engine en = null;
private AbstractQuest quest = null;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
@ -54,7 +55,7 @@ public class AmazonPrincessTest {
npc = SingletonRepository.getNPCList().get("Princess Esclara");
en = npc.getEngine();
final AbstractQuest quest = new AmazonPrincess();
quest = new BuiltQuest(new AmazonPrincess().story());
quest.addToWorld();
player = PlayerTestHelper.createPlayer("player");
@ -69,7 +70,7 @@ public class AmazonPrincessTest {
*/
@Test
public void testGetSlotname() {
assertEquals("amazon_princess", new AmazonPrincess().getSlotName());
assertEquals("amazon_princess", quest.getSlotName());
}
/**
@ -78,12 +79,12 @@ public class AmazonPrincessTest {
@Test
public void testhasRecovered() {
en.setCurrentState(ConversationStates.ATTENDING);
player.setQuest(new AmazonPrincess().getSlotName(), "drinking;0");
player.setQuest(quest.getSlotName(), "done;0");
en.step(player, "task");
assertEquals("The last cocktail you brought me was so lovely. Will you bring me another?", getReply(npc));
assertEquals(ConversationStates.QUEST_OFFERED, en.getCurrentState());
en.step(player, "yes");
assertEquals("start", player.getQuest(new AmazonPrincess().getSlotName()));
assertEquals("start", player.getQuest(quest.getSlotName(), 0));
}
@ -100,7 +101,7 @@ public class AmazonPrincessTest {
en.step(player, "task");
assertEquals("I'm looking for a drink, should be an exotic one. Can you bring me one?", getReply(npc));
en.step(player, "yes");
assertEquals("Thank you! If you have found some, say #drink to me so I know you have it. I'll be sure to give you a nice reward.", getReply(npc));
assertEquals("Thank you! If you have found some, I'll be sure to give you a nice reward.", getReply(npc));
en.step(player, "bye");
assertEquals("Goodbye, and beware of the barbarians.", getReply(npc));
@ -112,17 +113,8 @@ public class AmazonPrincessTest {
assertEquals("I like these exotic drinks, I forget the name of my favourite one.", getReply(npc));
en.step(player, "help");
assertEquals("Beware of my sisters on the island, they do not like strangers.", getReply(npc));
en.step(player, "pinacolada");
assertEquals("You don't have any drink I like yet. Go, and you better get an exotic one!", getReply(npc));
en.step(player, "exotic drink");
en.step(player, "pinacolad");
assertEquals("You don't have any drink I like yet. Go, and you better get an exotic one!", getReply(npc));
en.step(player, "help");
assertEquals("Beware of my sisters on the island, they do not like strangers.", getReply(npc));
en.step(player, "favor");
assertEquals("I like these exotic drinks, I forget the name of my favourite one.", getReply(npc));
en.step(player, "pinacolada");
assertEquals("You don't have any drink I like yet. Go, and you better get an exotic one!", getReply(npc));
en.step(player, "bye");
assertEquals("Goodbye, and beware of the barbarians.", getReply(npc));
@ -134,9 +126,6 @@ public class AmazonPrincessTest {
assertEquals("Beware of my sisters on the island, they do not like strangers.", getReply(npc));
en.step(player, "quest");
assertEquals("I like these exotic drinks, I forget the name of my favourite one.", getReply(npc));
en.step(player, "done");
en.step(player, "drink");
assertEquals("You don't have any drink I like yet. Go, and you better get an exotic one!", getReply(npc));
en.step(player, "bye");
assertEquals("Goodbye, and beware of the barbarians.", getReply(npc));
@ -145,9 +134,9 @@ public class AmazonPrincessTest {
player.getSlot("bag").add(item);
en.step(player, "hi");
assertEquals("Huh, what are you doing here?", getReply(npc));
en.step(player, "pina colada");
assertTrue(getReply(npc).startsWith("Thank you!! Take th"));
assertEquals("Ah, I see, you have a §'pina colada' Is it for me?", getReply(npc));
en.step(player, "yes");
assertTrue(getReply(npc).startsWith("Thank you! Take th"));
assertTrue(player.isEquipped("fish pie"));
en.step(player, "bye");
assertEquals("Goodbye, and beware of the barbarians.", getReply(npc));
@ -157,19 +146,9 @@ public class AmazonPrincessTest {
en.step(player, "hi");
assertEquals("Huh, what are you doing here?", getReply(npc));
en.step(player, "task");
assertTrue(getReply(npc).startsWith("I'm sure I'll be too drunk to have another for at least"));
assertTrue(getReply(npc).startsWith("I'm sure I'll be too drunk to have another one now."));
en.step(player, "bye");
assertEquals("Goodbye, and beware of the barbarians.", getReply(npc));
// -----------------------------------------------
en.step(player, "hi");
assertEquals("Huh, what are you doing here?", getReply(npc));
en.step(player, "pina colada");
assertEquals("Sometime you could do me a #favour ...", getReply(npc));
en.step(player, "favour");
assertTrue(getReply(npc).startsWith("I'm sure I'll be too drunk to have another for at least "));
en.step(player, "bye");
assertEquals("Goodbye, and beware of the barbarians.", getReply(npc));
}
}

View file

@ -1,5 +1,5 @@
/***************************************************************************
* (C) Copyright 2019 - Arianne *
* (C) Copyright 2019-2023 - Arianne *
***************************************************************************
***************************************************************************
* *
@ -139,7 +139,7 @@ public class AntivenomRingTest extends ZonePlayerAndNPCTestImpl {
new MakeRings(new MarriageQuestInfo()).addToWorld(); // marriage quest
new RingMaker().addToWorld();
// Klaas
new TrapsForKlaas().addToWorld();
new BuiltQuest(new TrapsForKlaas().story()).addToWorld();
// Julius
new EmotionCrystals().addToWorld();
// Haizen

View file

@ -1,6 +1,5 @@
/* $Id$ */
/***************************************************************************
* (C) Copyright 2003-2010 - Stendhal *
* (C) Copyright 2003-2023 - Stendhal *
***************************************************************************
***************************************************************************
* *
@ -29,6 +28,7 @@ import games.stendhal.server.core.engine.StendhalRPZone;
import games.stendhal.server.entity.item.StackableItem;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.fsm.Engine;
import games.stendhal.server.entity.npc.quest.BuiltQuest;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.maps.MockStendhalRPRuleProcessor;
import games.stendhal.server.maps.MockStendlRPWorld;
@ -41,7 +41,7 @@ public class BeerForHayunnTest {
private SpeakerNPC hayunn;
private BeerForHayunn bfh;
private AbstractQuest bfh;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
@ -60,7 +60,7 @@ public class BeerForHayunnTest {
new RetiredAdventurerNPC().configureZone(zone, null);
hayunn = SingletonRepository.getNPCList().get("Hayunn Naratha") ;
bfh = new BeerForHayunn();
bfh = new BuiltQuest(new BeerForHayunn().story());
bfh.addToWorld();
}
@ -96,7 +96,7 @@ public class BeerForHayunnTest {
assertEquals(1, player.getNumberOfEquipped("beer"));
en.step(player, "hi");
en.step(player, "yes");
assertEquals("done", player.getQuest("beer_hayunn"));
assertEquals("done", player.getQuest("beer_hayunn", 0));
en.step(player, "bye");
// reject
final Player player2 = PlayerTestHelper.createPlayer("player");
@ -125,10 +125,9 @@ public class BeerForHayunnTest {
public void testgetHistory() {
final Player player = PlayerTestHelper.createPlayer("bob");
assertTrue(bfh.getHistory(player).isEmpty());
player.setQuest("beer_hayunn", "");
player.setQuest("beer_hayunn", null);
final List<String> history = new LinkedList<String>();
history.add("I have talked to Hayunn.");
assertEquals(history, bfh.getHistory(player));
history.add("I have talked to Hayunn Naratha.");
player.setQuest("beer_hayunn", "rejected");
history.add("I do not want to make Hayunn drunk.");

View file

@ -1,6 +1,5 @@
/* $Id$ */
/***************************************************************************
* (C) Copyright 2003-2010 - Stendhal *
* (C) Copyright 2003-2023 - Stendhal *
***************************************************************************
***************************************************************************
* *
@ -20,7 +19,6 @@ import static utilities.SpeakerNPCTestHelper.getReply;
import java.util.Date;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@ -33,6 +31,7 @@ import games.stendhal.server.entity.npc.ConversationStates;
import games.stendhal.server.entity.npc.NPCList;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.fsm.Engine;
import games.stendhal.server.entity.npc.quest.BuiltQuest;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.maps.MockStendhalRPRuleProcessor;
import games.stendhal.server.maps.MockStendlRPWorld;
@ -60,19 +59,14 @@ public class CampfireTest {
MockStendlRPWorld.get();
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
}
@Before
public void setUp() {
player = PlayerTestHelper.createPlayer("player");
zone = new StendhalRPZone("zone");
new CampingGirlNPC().configureZone(zone, null);
npc = NPCList.get().get("Sally");
final Campfire cf = new Campfire();
cf.addToWorld();
final AbstractQuest quest = new BuiltQuest(new Campfire().story());
quest.addToWorld();
}
@After
@ -90,46 +84,30 @@ public class CampfireTest {
final Engine en = npc.getEngine();
assertTrue(en.step(player, "hi"));
assertEquals("Hi! I need a little #favor ... ", getReply(npc));
assertEquals("Hi, how are you?", getReply(npc));
assertTrue(en.step(player, "bye"));
player.setQuest(CampfireTest.CAMPFIRE, "start");
player.setQuest(CampfireTest.CAMPFIRE, 0, "start");
assertTrue(en.step(player, "hi"));
assertEquals(
"You're back already? Don't forget that you promised to collect ten pieces of wood for me!",
"Hi, how are you?",
getReply(npc));
assertTrue(en.step(player, "bye"));
player.setQuest(CampfireTest.CAMPFIRE, String.valueOf(System.currentTimeMillis()));
player.setQuest(CampfireTest.CAMPFIRE, 1, String.valueOf(System.currentTimeMillis()));
en.step(player, "hi");
assertEquals(
"Hi again!",
"Hi, how are you?",
getReply(npc));
assertTrue(en.step(player, "bye"));
final long SIXMINUTESAGO = System.currentTimeMillis() - 6 * MathHelper.MILLISECONDS_IN_ONE_MINUTE;
player.setQuest(CampfireTest.CAMPFIRE, String.valueOf(SIXMINUTESAGO));
player.setQuest(CampfireTest.CAMPFIRE, 1, String.valueOf(SIXMINUTESAGO));
en.step(player, "hi");
assertEquals("delay is 5 minutes, so 6 minutes should be enough", "Hi again!", getReply(npc));
assertEquals("delay is 5 minutes, so 6 minutes should be enough", "Hi, how are you?", getReply(npc));
assertTrue(en.step(player, "bye"));
}
/**
* Tests for hiAndbye.
*/
@Test
public void testHiAndbye() {
final Engine en = npc.getEngine();
assertTrue(en.step(player, "hi"));
assertTrue(npc.isTalking());
assertEquals("Hi! I need a little #favor ... ", getReply(npc));
assertTrue(en.step(player, "bye"));
assertFalse(npc.isTalking());
assertEquals("Bye.", getReply(npc));
}
/**
* Tests for doQuest.
*/
@ -140,7 +118,7 @@ public class CampfireTest {
assertTrue(en.step(player, "hi"));
assertTrue(npc.isTalking());
assertEquals("Hi! I need a little #favor ... ", getReply(npc));
assertEquals("Hi, how are you?", getReply(npc));
assertTrue(en.step(player, "favor"));
assertEquals(
@ -164,8 +142,7 @@ public class CampfireTest {
assertTrue(en.step(player, "yes"));
assertEquals(0, player.getNumberOfEquipped("wood"));
String reply = getReply(npc);
assertTrue("Thank you! Here, take some meat and charcoal!".equals(reply)
|| "Thank you! Here, take some ham and charcoal!".equals(reply));
assertTrue(reply.contains("Thank you! Here, take "));
assertTrue((10 == player.getNumberOfEquipped("meat"))
|| (10 == player.getNumberOfEquipped("ham")));
assertTrue(en.step(player, "bye"));
@ -174,38 +151,6 @@ public class CampfireTest {
}
/**
* Tests for isRepeatable.
*/
@Test
public void testIsRepeatable() {
player.setQuest(CAMPFIRE, "start");
assertFalse(new Campfire().isRepeatable(player));
player.setQuest(CAMPFIRE, "rejected");
assertFalse(new Campfire().isRepeatable(player));
player.setQuest(CAMPFIRE, System.currentTimeMillis() + "");
assertFalse(new Campfire().isRepeatable(player));
player.setQuest(CAMPFIRE, "1");
assertTrue(new Campfire().isRepeatable(player));
}
/**
* Tests for isCompleted.
*/
@Test
public void testIsCompleted() {
assertFalse(new Campfire().isCompleted(player));
player.setQuest(CAMPFIRE, "start");
assertFalse(new Campfire().isCompleted(player));
player.setQuest(CAMPFIRE, "rejected");
assertFalse(new Campfire().isCompleted(player));
player.setQuest(CAMPFIRE, "notStartorRejected");
assertTrue(new Campfire().isCompleted(player));
}
/**
* Tests for jobAndOffer.
*/
@ -215,7 +160,7 @@ public class CampfireTest {
assertTrue(en.step(player, "hi"));
assertTrue(npc.isTalking());
assertEquals("Hi! I need a little #favor ... ", getReply(npc));
assertEquals("Hi, how are you?", getReply(npc));
assertTrue(en.step(player, "job"));
assertEquals("Work? I'm just a little girl! I'm a scout, you know.",
getReply(npc));
@ -240,14 +185,15 @@ public class CampfireTest {
for (String request : ConversationPhrases.QUEST_MESSAGES) {
final Engine en = npc.getEngine();
player.setQuest(CAMPFIRE, questState);
player.setQuest(CAMPFIRE, 0, "done");
player.setQuest(CAMPFIRE, 1, questState);
en.setCurrentState(ConversationStates.ATTENDING);
en.step(player, request);
String reply = getReply(npc);
assertTrue("Thanks, but I think the wood you brought already will last me 60 minutes.".equals(reply) || "Thanks, but I think the wood you brought already will last me 1 hour.".equals(reply));
assertTrue("Thanks, but I think the wood, you brought, will last 60 minutes.".equals(reply) || "Thanks, but I think the wood, you brought, will last 1 hour.".equals(reply));
assertEquals(ConversationStates.ATTENDING, en.getCurrentState());
assertEquals("quest state unchanged", questState, player.getQuest(CAMPFIRE));
assertEquals("quest state unchanged", questState, player.getQuest(CAMPFIRE, 1));
}
}
@ -259,13 +205,14 @@ public class CampfireTest {
final String questState = Long.toString(new Date().getTime() - 61 * 60 * 1000);
for (String request : ConversationPhrases.QUEST_MESSAGES) {
final Engine en = npc.getEngine();
player.setQuest(CAMPFIRE, questState);
player.setQuest(CAMPFIRE, 0, "done");
player.setQuest(CAMPFIRE, 1, questState);
en.setCurrentState(ConversationStates.ATTENDING);
en.step(player, request);
assertEquals("My campfire needs wood again, ten pieces of #wood will be enough. Could you please get those #wood pieces from the forest for me? Please say yes!", getReply(npc));
assertEquals(ConversationStates.QUEST_OFFERED, en.getCurrentState());
assertEquals("quest state unchanged", questState, player.getQuest(CAMPFIRE));
assertEquals("quest state unchanged", questState, player.getQuest(CAMPFIRE, 1));
}
}
@ -276,13 +223,13 @@ public class CampfireTest {
public void testAllowRestartAfterRejecting() {
for (String request : ConversationPhrases.QUEST_MESSAGES) {
final Engine en = npc.getEngine();
player.setQuest(CAMPFIRE, "rejected");
player.setQuest(CAMPFIRE, 0, "rejected");
en.setCurrentState(ConversationStates.ATTENDING);
en.step(player, request);
assertEquals("I need more wood to keep my campfire running, But I can't leave it unattended to go get some! Could you please get some from the forest for me? I need ten pieces.", getReply(npc));
assertEquals(ConversationStates.QUEST_OFFERED, en.getCurrentState());
assertEquals("quest state unchanged", "rejected", player.getQuest(CAMPFIRE));
assertEquals("quest state unchanged", "rejected", player.getQuest(CAMPFIRE, 0));
}
}
@ -300,7 +247,7 @@ public class CampfireTest {
assertEquals("Oh dear, how am I going to cook all this meat? Perhaps I'll just have to feed it to the animals..."
, getReply(npc));
assertEquals(ConversationStates.ATTENDING, en.getCurrentState());
assertEquals("quest state 'rejected'", "rejected", player.getQuest(CAMPFIRE));
assertEquals("quest state 'rejected'", "rejected", player.getQuest(CAMPFIRE, 0 ));
assertEquals("karma penalty", karma - 5.0, player.getKarma(), 0.01);
}
}

View file

@ -1,4 +1,3 @@
/* $Id$ */
/***************************************************************************
* (C) Copyright 2003-2023 - Stendhal *
***************************************************************************
@ -30,6 +29,7 @@ import games.stendhal.server.core.engine.StendhalRPZone;
import games.stendhal.server.entity.item.Item;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.fsm.Engine;
import games.stendhal.server.entity.npc.quest.BuiltQuest;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.maps.semos.city.GreeterNPC;
import games.stendhal.server.maps.semos.tavern.TraderNPC;
@ -76,7 +76,7 @@ public class HatForMonogenesTest {
quest = new MeetMonogenes();
quest.addToWorld();
quest = new HatForMonogenes();
quest = new BuiltQuest(new HatForMonogenes().story());
quest.addToWorld();
}
@ -167,6 +167,10 @@ public class HatForMonogenesTest {
// -----------------------------------------------
en.step(player, "hi");
assertEquals(
"Hi again, player. How can I #help you this time?",
getReply(npc));
en.step(player, "quest");
assertEquals(
"Hey, my good friend, remember that leather hat I asked you about before? It's still pretty chilly here...",
getReply(npc));
@ -199,7 +203,7 @@ public class HatForMonogenesTest {
assertEquals(history, quest.getHistory(player));
player.setQuest("hat_monogenes", "");
history.add("I have met Monogenes at the spring in Semos village");
history.add("I have met Monogenes at the spring in Semos village.");
history.add("I have to find a hat, something leather to keep his head warm.");
assertEquals(history, quest.getHistory(player));

View file

@ -1,6 +1,5 @@
/* $Id$ */
/***************************************************************************
* (C) Copyright 2003-2010 - Stendhal *
* (C) Copyright 2003-2023 - Stendhal *
***************************************************************************
***************************************************************************
* *
@ -24,6 +23,7 @@ import games.stendhal.server.core.engine.StendhalRPZone;
import games.stendhal.server.entity.item.Item;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.fsm.Engine;
import games.stendhal.server.entity.npc.quest.BuiltQuest;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.maps.MockStendlRPWorld;
import games.stendhal.server.maps.amazon.hut.JailedBarbNPC;
@ -54,7 +54,7 @@ public class JailedBarbarianTest {
final AbstractQuest quest = new JailedBarbarian();
// princess Esclara's greeting response is defined in her quest
final AbstractQuest quest2 = new AmazonPrincess();
final AbstractQuest quest2 = new BuiltQuest(new AmazonPrincess().story());
quest.addToWorld();
quest2.addToWorld();
@ -119,6 +119,7 @@ public class JailedBarbarianTest {
assertEquals("I'm looking for a drink, should be an exotic one. Can you bring me one?", getReply(npc));
en.step(player, "no");
assertEquals("Oh, never mind. Bye then.", getReply(npc));
en.step(player, "bye");
en.step(player, "hi");
assertEquals("Huh, what are you doing here?", getReply(npc));

View file

@ -1,6 +1,5 @@
/* $Id$ */
/***************************************************************************
* (C) Copyright 2003-2010 - Stendhal *
* (C) Copyright 2003-2023 - Stendhal *
***************************************************************************
***************************************************************************
* *
@ -12,9 +11,11 @@
***************************************************************************/
package games.stendhal.server.maps.quests;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static utilities.SpeakerNPCTestHelper.getReply;
@ -31,6 +32,7 @@ import games.stendhal.server.entity.item.Item;
import games.stendhal.server.entity.npc.ConversationPhrases;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.fsm.Engine;
import games.stendhal.server.entity.npc.quest.BuiltQuest;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.maps.MockStendhalRPRuleProcessor;
import games.stendhal.server.maps.MockStendlRPWorld;
@ -70,7 +72,7 @@ public class LookBookforCerylTest {
@Test
public final void askJynathWithoutQuest() {
final LookBookforCeryl quest = new LookBookforCeryl();
final AbstractQuest quest = new BuiltQuest(new LookBookforCeryl().story());
quest.addToWorld();
final Player pl = PlayerTestHelper.createPlayer("joe");
@ -94,7 +96,7 @@ public class LookBookforCerylTest {
@Test
public final void comeBackFromJynathWithoutBook() {
final LookBookforCeryl quest = new LookBookforCeryl();
final AbstractQuest quest = new BuiltQuest(new LookBookforCeryl().story());
quest.addToWorld();
final Player pl = PlayerTestHelper.createPlayer("joe");
@ -112,7 +114,7 @@ public class LookBookforCerylTest {
@Test
public void doQuest() throws Exception {
final LookBookforCeryl quest = new LookBookforCeryl();
final AbstractQuest quest = new BuiltQuest(new LookBookforCeryl().story());
quest.addToWorld();
final Player pl = PlayerTestHelper.createPlayer("player");
@ -124,12 +126,7 @@ public class LookBookforCerylTest {
assertEquals("Greetings! How may I help you?", getReply(ceryl));
cerylEngine.step(pl, ConversationPhrases.QUEST_MESSAGES.get(0));
assertTrue(ceryl.isTalking());
assertEquals("I am looking for a very special #book.",
getReply(ceryl));
cerylEngine.step(pl, "book");
assertTrue(ceryl.isTalking());
assertEquals(
"Could you ask #Jynath to return her book? She's had it for months now, and people are looking for it.",
assertEquals("I am looking for a very special book. Could you ask #Jynath to return it? She has had it for months now, and people are looking for it.",
getReply(ceryl));
cerylEngine.step(pl, ConversationPhrases.YES_MESSAGES.get(0));
assertTrue(ceryl.isTalking());
@ -137,10 +134,6 @@ public class LookBookforCerylTest {
"Great! Please get me it as quickly as possible... there's a huge waiting list!",
getReply(ceryl));
assertEquals("start", pl.getQuest(LookBookforCerylTest.CERYL_BOOK));
cerylEngine.step(pl, "book");
assertTrue(ceryl.isTalking());
assertEquals("I really need that book now! Go to talk with #Jynath.",
getReply(ceryl));
cerylEngine.step(pl, ConversationPhrases.GOODBYE_MESSAGES.get(0));
assertFalse(ceryl.isTalking());
final Engine jynathEngine = jynath.getEngine();
@ -164,8 +157,9 @@ public class LookBookforCerylTest {
cerylEngine.step(pl, "Hi");
assertTrue(ceryl.isTalking());
assertEquals("Oh, you got the book back! Phew, thanks!",
getReply(ceryl));
assertEquals("Hi, did you get the book from Jynath?", getReply(ceryl));
cerylEngine.step(pl, "yes");
assertEquals("Oh, you got the book back! Phew, thanks!", getReply(ceryl));
cerylEngine.step(pl, "bye");
cerylEngine.step(pl, "Hi");
@ -181,8 +175,7 @@ public class LookBookforCerylTest {
*/
@Test
public final void testAddToWorld() {
LookBookforCeryl quest;
quest = new LookBookforCeryl();
final AbstractQuest quest = new BuiltQuest(new LookBookforCeryl().story());
quest.addToWorld();
}
@ -192,54 +185,38 @@ public class LookBookforCerylTest {
@Test
public final void testGetHistory() {
final Player pl = PlayerTestHelper.createPlayer("player");
LookBookforCeryl quest;
quest = new LookBookforCeryl();
final AbstractQuest quest = new BuiltQuest(new LookBookforCeryl().story());
quest.addToWorld();
assertTrue(quest.getHistory(pl).isEmpty());
pl.setQuest(CERYL_BOOK, "rejected");
assertEquals(2, quest.getHistory(pl).size());
assertEquals(Arrays.asList(
assertThat(quest.getHistory(pl), equalTo(Arrays.asList(
"I have met Ceryl at the library, he's the librarian there.",
"I do not want to find the book."),
quest.getHistory(pl));
"I do not want to find the book.")));
pl.setQuest(CERYL_BOOK, "start");
assertEquals(2, quest.getHistory(pl).size());
assertEquals(Arrays.asList(
assertThat(quest.getHistory(pl), equalTo(Arrays.asList(
"I have met Ceryl at the library, he's the librarian there.",
"I promised to fetch the black book from Jynath."),
quest.getHistory(pl));
"I promised to fetch the black book from Jynath.")));
pl.setQuest(CERYL_BOOK, "jynath");
assertEquals(3, quest.getHistory(pl).size());
assertEquals(Arrays.asList(
"I have met Ceryl at the library, he's the librarian there.",
"I promised to fetch the black book from Jynath.",
"I do not have the black book Jynath has."),
quest.getHistory(pl));
final Item item = SingletonRepository.getEntityManager().getItem(
"black book");
final Item item = SingletonRepository.getEntityManager().getItem("black book");
assertNotNull(item);
item.setBoundTo(pl.getName());
pl.equipOrPutOnGround(item);
assertEquals(3, quest.getHistory(pl).size());
assertEquals(Arrays.asList(
assertThat(quest.getHistory(pl), equalTo(Arrays.asList(
"I have met Ceryl at the library, he's the librarian there.",
"I promised to fetch the black book from Jynath.",
"I have talked to Jynath, and have the book."),
quest.getHistory(pl));
"I have talked to Jynath and got the book.")));
pl.setQuest(CERYL_BOOK, "done");
assertEquals(4, quest.getHistory(pl).size());
assertEquals(Arrays.asList(
assertThat(quest.getHistory(pl), equalTo(Arrays.asList(
"I have met Ceryl at the library, he's the librarian there.",
"I promised to fetch the black book from Jynath.",
"I have talked to Jynath, and have the book.",
"I have returned the book to Ceryl and got a little reward."),
quest.getHistory(pl));
"I have talked to Jynath and got the book.",
"I have returned the book to Ceryl and got a little reward.")));
}
/**
@ -247,8 +224,7 @@ public class LookBookforCerylTest {
*/
@Test
public final void testIsCompleted() {
LookBookforCeryl quest;
quest = new LookBookforCeryl();
final AbstractQuest quest = new BuiltQuest(new LookBookforCeryl().story());
quest.addToWorld();
final Player pl = PlayerTestHelper.createPlayer("player");
@ -264,7 +240,7 @@ public class LookBookforCerylTest {
*/
@Test
public final void testIsRepeatable() {
final LookBookforCeryl quest = new LookBookforCeryl();
final AbstractQuest quest = new BuiltQuest(new LookBookforCeryl().story());
assertFalse(quest.isRepeatable(null));
}
@ -273,7 +249,7 @@ public class LookBookforCerylTest {
*/
@Test
public final void testIsStarted() {
final LookBookforCeryl quest = new LookBookforCeryl();
final AbstractQuest quest = new BuiltQuest(new LookBookforCeryl().story());
final Player bob = PlayerTestHelper.createPlayer("bob");
assertFalse(bob.hasQuest(LookBookforCerylTest.CERYL_BOOK));

View file

@ -1,6 +1,5 @@
/* $Id$ */
/***************************************************************************
* (C) Copyright 2003-2010 - Stendhal *
* (C) Copyright 2003-2023 - Stendhal *
***************************************************************************
***************************************************************************
* *
@ -13,27 +12,22 @@
package games.stendhal.server.maps.quests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static utilities.SpeakerNPCTestHelper.getReply;
import java.util.Arrays;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import games.stendhal.server.core.engine.SingletonRepository;
import games.stendhal.server.core.engine.StendhalRPZone;
import games.stendhal.server.entity.item.Item;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.fsm.Engine;
import games.stendhal.server.entity.npc.quest.BuiltQuest;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.maps.MockStendlRPWorld;
import games.stendhal.server.maps.semos.plains.LittleBoyNPC;
import utilities.PlayerTestHelper;
import utilities.QuestHelper;
import utilities.RPClass.ItemTestHelper;
import utilities.RPClass.PassiveEntityRespawnPointTestHelper;
public class PlinksToyTest {
@ -54,7 +48,7 @@ public class PlinksToyTest {
MockStendlRPWorld.get().addRPZone(zone);
new LittleBoyNPC().configureZone(zone, null);
final PlinksToy quest = new PlinksToy();
final AbstractQuest quest = new BuiltQuest(new PlinksToy().story());
quest.addToWorld();
player = PlayerTestHelper.createPlayer("player");
@ -74,6 +68,7 @@ public class PlinksToyTest {
assertEquals("My parents told me not to go to the park by myself, but I got lost when I was playing... Please don't tell them! Can you bring my #teddy back?", getReply(npc));
en.step(player, "yes");
assertEquals("*sniff* Thanks a lot! *smile*", getReply(npc));
en.step(player, "bye");
// -----------------------------------------------
@ -85,21 +80,17 @@ public class PlinksToyTest {
assertEquals("*sniff* But... but... PLEASE! *cries*", getReply(npc));
en.step(player, "teddy bear");
assertEquals("Teddy is my favourite toy! Please will you bring him back?", getReply(npc));
en.step(player, "yes");
assertEquals("*sniff* Thanks a lot! *smile*", getReply(npc));
assertEquals("Teddy is my favourite toy! Please bring him back to me.", getReply(npc));
en.step(player, "bye");
// -----------------------------------------------
/* TODO: Re-implement support for early quest completion
final Item teddy = ItemTestHelper.createItem("teddy");
teddy.setEquipableSlots(Arrays.asList("bag"));
player.equipToInventoryOnly(teddy);
assertTrue(player.isEquipped("teddy"));
System.out.println(player.getSlot("!quests"));
System.out.println(player.getSlot("lhand"));
System.out.println(player.getSlot("rhand"));
en.step(player, "hi");
// [21:25] player earns 10 experience points.
assertEquals("You found him! *hugs teddy* Thank you, thank you! *smile*", getReply(npc));
@ -112,5 +103,6 @@ public class PlinksToyTest {
assertEquals("I play all day.", getReply(npc));
en.step(player, "bye");
assertEquals("Bye.", getReply(npc));
*/
}
}

View file

@ -1,5 +1,5 @@
/***************************************************************************
* (C) Copyright 2019 - Arianne *
* (C) Copyright 2019-2023 - Arianne *
***************************************************************************
***************************************************************************
* *
@ -30,6 +30,7 @@ import games.stendhal.server.core.rp.StendhalQuestSystem;
import games.stendhal.server.entity.npc.ConversationStates;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.fsm.Engine;
import games.stendhal.server.entity.npc.quest.BuiltQuest;
import games.stendhal.server.maps.ados.animal_sanctuary.ZoologistNPC;
import games.stendhal.server.maps.ados.church.HealerNPC;
import games.stendhal.server.maps.ados.magician_house.WizardNPC;
@ -51,7 +52,7 @@ public class TrapsForKlaasTest extends ZonePlayerAndNPCTestImpl {
private SpeakerNPC klaas;
private TrapsForKlaas quest;
private AbstractQuest quest;
private AntivenomRing avrQuest;
private String questName;
private String avrQuestName;
@ -91,7 +92,7 @@ public class TrapsForKlaasTest extends ZonePlayerAndNPCTestImpl {
klaas = getNPC(npcName);
quest = new TrapsForKlaas();
quest = new BuiltQuest(new TrapsForKlaas().story());
avrQuest = new AntivenomRing();
questName = quest.getSlotName();
avrQuestName = avrQuest.getSlotName();
@ -130,7 +131,6 @@ public class TrapsForKlaasTest extends ZonePlayerAndNPCTestImpl {
"The rats down here have been getting into the food storage. Would you help me rid us of the varmints?",
getReply(klaas));
en.step(player, "no");
assertEquals(ConversationStates.IDLE, en.getCurrentState());
assertEquals("Don't waste my time. I've got to protect the cargo.", getReply(klaas));
// player loses some karma
assertEquals(karma - 5.0, player.getKarma(), 0);
@ -162,33 +162,14 @@ public class TrapsForKlaasTest extends ZonePlayerAndNPCTestImpl {
en.step(player, "hi");
assertEquals(ConversationStates.ATTENDING, en.getCurrentState());
assertEquals("I could really use those #traps. How can I help you?", getReply(klaas));
en.step(player, "bye");
assertEquals(ConversationStates.IDLE, en.getCurrentState());
// player does not have enough traps
PlayerTestHelper.equipWithStackableItem(player, "rodent trap", 19);
assertTrue(player.isEquipped("rodent trap"));
assertFalse(player.isEquipped("rodent trap", 20));
en.step(player, "hi");
assertEquals(ConversationStates.QUEST_ITEM_BROUGHT, en.getCurrentState());
assertEquals("Did you bring any traps?", getReply(klaas));
en.step(player, "no");
assertEquals(ConversationStates.ATTENDING, en.getCurrentState());
assertEquals("Please hurry! I just found another box of food that's been chewed through.", getReply(klaas));
en.step(player, "bye");
assertEquals(ConversationStates.IDLE, en.getCurrentState());
en.step(player, "hi");
assertEquals(ConversationStates.QUEST_ITEM_BROUGHT, en.getCurrentState());
en.step(player, "yes");
assertEquals(ConversationStates.ATTENDING, en.getCurrentState());
assertEquals("I'm sorry but I need 20 #rodent #traps", getReply(klaas));
assertEquals("Ahoy! Nice to see you in the cargo hold!", getReply(klaas));
en.step(player, "quest");
assertEquals("I believe, I already asked you to get me 20 rodent traps.", getReply(klaas));
en.step(player, "bye");
assertEquals(ConversationStates.IDLE, en.getCurrentState());
// player has enough traps
PlayerTestHelper.equipWithStackableItem(player, "rodent trap", 1);
PlayerTestHelper.equipWithStackableItem(player, "rodent trap", 20);
assertTrue(player.isEquipped("rodent trap", 20));
en.step(player, "hi");
@ -214,10 +195,10 @@ public class TrapsForKlaasTest extends ZonePlayerAndNPCTestImpl {
// player asks for quest before cooldown period is up
en.step(player, "quest");
assertEquals(ConversationStates.ATTENDING, en.getCurrentState());
assertTrue(getReply(klaas).startsWith("Thanks for the traps. Now the food will be safe. But I may need your help again in"));
assertTrue(getReply(klaas).startsWith("Thanks for the traps. Now the food will be safe. But I may need your help again soon."));
// player asks for quest after cooldown period is up
player.setQuest(questName, "done;0");
player.setQuest(questName, 1, "0");
en.step(player, "quest");
assertEquals(ConversationStates.QUEST_OFFERED, en.getCurrentState());
assertEquals("The rats down here have been getting into the food storage. Would you help me rid us of the varmints?", getReply(klaas));
@ -250,8 +231,7 @@ public class TrapsForKlaasTest extends ZonePlayerAndNPCTestImpl {
assertEquals(ConversationStates.QUEST_ITEM_BROUGHT, en.getCurrentState());
assertEquals("Did you bring any traps?", getReply(klaas));
en.step(player, "yes");
assertEquals("Thanks! I've got to get these set up as quickly as possible. Take these antidotes as a reward."
+ " I used to know an old #apothecary. Take this note to him. Maybe he can help you out with something.",
assertEquals("I used to know an old #apothecary. Take this note to him. Maybe he can help you out with something.",
getReply(klaas));
assertEquals("done", player.getQuest(questName, 0));
assertFalse(player.isEquipped("rodent trap"));

View file

@ -265,6 +265,7 @@ public class QuestRunner {
en.step(player, "bye");
en = ceryl.getEngine();
en.step(player, "hi");
en.step(player, "yes");
en.step(player, "bye");
assertEquals("done", player.getQuest(questSlot, 0));
}

View file

@ -86,13 +86,12 @@ public class ChildrensFriendStub {
en.step(player, "hi");
en.step(player, "yes");
// don't need to say "bye"
assertEquals(ConversationStates.IDLE, en.getCurrentState());
en.step(player, "bye");
equipWithItem(player, "teddy");
en.step(player, "hi");
en.step(player, "yes");
en.step(player, "bye");
assertEquals("done", player.getQuest(questSlot, 0));