Convert Unicorn Horns for Zelan to QuestManuscript

This commit is contained in:
Jordan Irwin 2023-01-09 19:05:18 -08:00
parent 29bad6ce2e
commit fac1d43535
7 changed files with 215 additions and 82 deletions

View file

@ -1033,6 +1033,7 @@ Entrance fee is 10 money</attribute>
<!-- NPCs -->
<configurator class-name="games.stendhal.server.maps.atlantis.cityoutside.GreeterNPC"/>
<configurator class-name="games.stendhal.server.maps.atlantis.cityoutside.ZelanNPC"/>
<portal x="104" y="41" ref="potions_shop">
<destination zone="int_atlantis_potions_shop" ref="entrance"/>

View file

@ -1,63 +0,0 @@
--[[
***************************************************************************
* Copyright © 2020 - Arianne *
***************************************************************************
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
]]
local zoneName = "-7_deniran_atlantis"
if game:setZone(zoneName) then
local zelan = entities:createSpeakerNPC("Zelan")
-- NPC appearance & behavior
zelan:setEntityClass("atlantismale01npc")
zelan:setCollisionAction(CollisionAction.STOP)
-- NPC location & path
local nodes = {
{63, 66},
{75, 66},
}
zelan:setPathAndPosition(nodes, true)
-- NPC dialog
zelan:addGreeting()
zelan:addGoodbye()
-- add Zelan to the world
game:add(zelan)
-- quest
local quest = quests.simple:create("unicorn_horns_for_zelan", "Unicorn Horns for Zelan", "Zelan")
quest:setDescription("Zelan needs help gathering unicorn horns.")
quest:setReply(quests.simple.ID_REQUEST,
"Hello! I'm in need of some unicorn horns to make some daggers."
.. " It is really dangerous in the woods surrounding Atlantis. If you are a brave sort"
.. " I could really use some help gathering unicorn horns. Will you help me?")
quest:setReply(quests.simple.ID_ACCEPT,
"Great! Be careful out there lots of large monsters, and those centaurs are really nasty")
quest:setReply(quests.simple.ID_REWARD, "Thanks a bunch!")
quest:setReply(quests.simple.ID_REJECT, "Thats ok, I will find someone else to help me.")
quest:setItemToCollect("unicorn horn", 10)
quest:setXPReward(50000)
quest:setKarmaReward(5.0)
quest:addItemReward("soup", 3)
quest:addItemReward("money", 20000)
quest:setRegion(Region.ATLANTIS)
quests:register(quest)
else
logger:error("Could not set zone: " .. zoneName)
end

View file

@ -186,6 +186,7 @@ public class StendhalQuestSystem {
loadQuest(new TrapsForKlaas());
//loadQuest(new TutorialIsland());
loadQuest(new UltimateCollector());
loadQuest(new UnicornHornsForZelan());
loadQuest(new VampireSword());
loadQuest(new WaterForXhiphin());
loadQuest(new WeaponsCollector());

View file

@ -552,6 +552,15 @@ public abstract class UpdateConverter {
}
}
// 1.43: Unicorn Horns for Zelan converted to QuestManuscript
final String zelanQName = "unicorn_horns_for_zelan";
if (player.hasQuest(zelanQName)) {
final String[] zelanSlots = player.getQuest(zelanQName).split(";");
if (zelanSlots.length == 2) {
player.setQuest(zelanQName, zelanSlots[0] + ";;" + zelanSlots[1]);
}
}
// fix quest slots for kills quests.
fixKillQuestsSlots(player);

View file

@ -0,0 +1,49 @@
/***************************************************************************
* (C) Copyright 2003-2022 - Stendhal *
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation; either version 3 of the *
* License, or (at your option) any later version. *
* *
***************************************************************************/
package games.stendhal.server.maps.atlantis.cityoutside;
import java.util.Arrays;
import java.util.Map;
import games.stendhal.server.core.config.ZoneConfigurator;
import games.stendhal.server.core.engine.StendhalRPZone;
import games.stendhal.server.core.pathfinder.FixedPath;
import games.stendhal.server.core.pathfinder.Node;
import games.stendhal.server.entity.CollisionAction;
import games.stendhal.server.entity.npc.SpeakerNPC;
public class ZelanNPC implements ZoneConfigurator {
@Override
public void configureZone(final StendhalRPZone zone, final Map<String, String> attributes) {
zone.add(buildNPC());
}
private SpeakerNPC buildNPC() {
final SpeakerNPC zelan = new SpeakerNPC("Zelan");
// appearance & behavior
zelan.setEntityClass("atlantismale01npc");
zelan.setCollisionAction(CollisionAction.STOP);
// location & path
zelan.setPathAndPosition(new FixedPath(Arrays.asList(
new Node(63, 66),
new Node(75, 66)), true));
// dialog
zelan.addGreeting();
zelan.addGoodbye();
return zelan;
}
}

View file

@ -0,0 +1,113 @@
/***************************************************************************
* Copyright © 2003-2023 - Arianne *
***************************************************************************
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
package games.stendhal.server.maps.quests;
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.quest.BringItemTask;
import games.stendhal.server.entity.npc.quest.QuestBuilder;
import games.stendhal.server.entity.npc.quest.QuestManuscript;
import games.stendhal.server.maps.Region;
/**
* QUEST: Unicorn Horns for Zelan
*
* PARTICIPANTS:
* <ul>
* <li>Zelan</li>
* </ul>
*
* STEPS:
* <ul>
* <li>Zelan needs 10 unicorn horns.</li>
* <li>Bring the unicorn horns to him for a reward.</li>
* </ul>
*
* REWARD:
* <ul>
* <li>50000 xp</li>
* <li>5 karma</li>
* <li>3 soup</li>
* <li>20000 money</li>
* </ul>
*
* REPETITIONS:
* <ul>
* <li>never</li>
* </ul>
*/
public class UnicornHornsForZelan implements QuestManuscript {
@Override
public QuestBuilder<?> story() {
QuestBuilder<BringItemTask> quest = new QuestBuilder<>(new BringItemTask());
final String npcName = "Zelan";
final int quantity = 10;
final String itemName = "unicorn horn";
final String plItemName = itemName + "s";
final int rewardSoup = 3;
final int rewardMoney = 20000;
quest.info()
.name("Unicorn Horns for Zelan")
.internalName("unicorn_horns_for_zelan")
.description("Zelan needs help gathering unicorn horns.")
.region(Region.ATLANTIS)
.questGiverNpc(npcName)
.notRepeatable();
quest.history()
.whenNpcWasMet(npcName + " asked me to get " + quantity
+ " " + plItemName + ".")
.whenQuestWasRejected("I do not want to help " + npcName + ".")
.whenQuestWasAccepted("I have not found what I am looking for yet.")
.whenTaskWasCompleted("I have what " + npcName + " asked for.")
.whenQuestWasCompleted("I found " + quantity
+ " " + plItemName + " for " + npcName + ".");
quest.offer()
.respondToRequest("Hello! I'm in need of some unicorn horns to"
+ " make some daggers. It is really dangerous in the woods"
+ " surrounding Atlantis. If you are a brave sort I could"
+ " really use some help gathering unicorn horns. Will you"
+ " help me?")
.respondToUnrepeatableRequest("Thanks, but I don't need any more"
+ " help.")
.respondToAccept("Great! Be careful out there lots of large"
+ " monsters, and those centaurs are really nasty.")
.respondToReject("Thats ok, I will find someone else to help me.")
.rejectionKarmaPenalty(0)
//~ .remind("I have already asked you to get " + quantity
//~ + " " + plItemName + ". Are you #done?");
.remind("I asked you to bring me " + quantity + " " + plItemName
+ ".");
quest.task()
.requestItem(quantity, itemName);
quest.complete()
.greet("Did you find the " + plItemName + "?")
.respondToReject("I asked you to bring me " + quantity + " "
+ plItemName + ".")
.respondToAccept("Thanks a bunch! As a reward I will give you "
+ rewardSoup + " soups and " + rewardMoney + " money.")
.rewardWith(new IncreaseXPAction(50000))
.rewardWith(new IncreaseKarmaAction(5.0))
.rewardWith(new EquipItemAction("soup", rewardSoup))
.rewardWith(new EquipItemAction("money", rewardMoney));
return quest;
}
}

View file

@ -1,5 +1,5 @@
/***************************************************************************
* (C) Copyright 2003-2022 - Arianne *
* Copyright © 2003-2023 - Arianne *
***************************************************************************
***************************************************************************
* *
@ -9,7 +9,7 @@
* (at your option) any later version. *
* *
***************************************************************************/
package scripts.quest;
package games.stendhal.server.maps.quests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@ -21,28 +21,31 @@ import org.junit.Before;
import org.junit.Test;
import games.stendhal.server.core.engine.SingletonRepository;
import games.stendhal.server.core.engine.StendhalRPZone;
import games.stendhal.server.entity.npc.ConversationStates;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.fsm.Engine;
import utilities.LuaTestHelper;
import utilities.PlayerTestHelper;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.maps.atlantis.cityoutside.ZelanNPC;
import utilities.QuestHelper;
public class UnicornHornsForZelanTest extends LuaTestHelper {
public class UnicornHornsForZelanTest extends QuestHelper {
private SpeakerNPC zelan;
private Player player;
private final String slot = "unicorn_horns_for_zelan";
@Before
public void setUp() {
setUpZone("-7_deniran_atlantis");
load("data/script/region/atlantis/city/exterior/ZelanNPC.lua");
loadCachedQuests();
addPlayerToWorld();
player = createPlayer("tester");
// load Zelan
new ZelanNPC().configureZone(new StendhalRPZone("testzone"), null);
zelan = SingletonRepository.getNPCList().get("Zelan");
// load quest
quests.loadQuest(new UnicornHornsForZelan());
}
@Test
@ -57,6 +60,8 @@ public class UnicornHornsForZelanTest extends LuaTestHelper {
}
private void testQuest() {
assertTrue(quests.isLoaded(quests.getQuestFromSlot(slot)));
final Engine en = zelan.getEngine();
assertFalse(player.hasQuest(slot));
@ -72,11 +77,13 @@ public class UnicornHornsForZelanTest extends LuaTestHelper {
assertEquals(ConversationStates.ATTENDING, en.getCurrentState());
en.step(player, "quest");
assertEquals(ConversationStates.QUEST_OFFERED, en.getCurrentState());
assertEquals(ConversationStates.QUEST_OFFERED,
en.getCurrentState());
assertEquals(
"Hello! I'm in need of some unicorn horns to make some daggers."
+ " It is really dangerous in the woods surrounding Atlantis. If you are a brave sort"
+ " I could really use some help gathering unicorn horns. Will you help me?",
+ " It is really dangerous in the woods surrounding Atlantis. If"
+ " you are a brave sort I could really use some help gathering"
+ " unicorn horns. Will you help me?",
getReply(zelan));
en.step(player, "no");
assertEquals(ConversationStates.ATTENDING, en.getCurrentState());
@ -90,36 +97,52 @@ public class UnicornHornsForZelanTest extends LuaTestHelper {
en.step(player, "yes");
assertEquals(ConversationStates.ATTENDING, en.getCurrentState());
assertEquals(
"Great! Be careful out there lots of large monsters, and those centaurs are really nasty",
"Great! Be careful out there lots of large monsters, and those"
+ " centaurs are really nasty.",
getReply(zelan));
assertEquals("start", player.getQuest(slot, 0));
assertTrue(player.getKarma() == playerKarma);
en.step(player, "bye");
assertEquals(ConversationStates.IDLE, en.getCurrentState());
PlayerTestHelper.equipWithStackableItem(player, "unicorn horn", 9);
equipWithStackableItem(player, "unicorn horn", 9);
en.step(player, "hi");
assertEquals(ConversationStates.ATTENDING, en.getCurrentState());
en.step(player, "done");
assertEquals("I asked you to bring me 10 unicorn horns.", getReply(zelan));
assertEquals(
"I asked you to bring me 10 unicorn horns.",
getReply(zelan));
en.step(player, "bye");
PlayerTestHelper.equipWithStackableItem(player, "unicorn horn", 1);
equipWithStackableItem(player, "unicorn horn", 1);
en.step(player, "hi");
en.step(player, "done");
assertEquals(ConversationStates.QUEST_ITEM_BROUGHT,
en.getCurrentState());
assertEquals("Did you find the unicorn horns?", getReply(zelan));
en.step(player, "yes");
assertEquals(
"Thanks a bunch! As a reward I will give you 3 soups and 20000 money.",
"Thanks a bunch! As a reward I will give you 3 soups and 20000"
+ " money.",
getReply(zelan));
en.step(player, "bye");
assertEquals(ConversationStates.IDLE, en.getCurrentState());
assertEquals("done", player.getQuest(slot, 0));
assertEquals("1", player.getQuest(slot, 2));
assertTrue(player.getKarma() == playerKarma + 5);
assertEquals(playerXP + 50000, player.getXP());
assertEquals(0, player.getNumberOfEquipped("unicorn horn"));
assertEquals(3, player.getNumberOfEquipped("soup"));
assertEquals(20000, player.getNumberOfEquipped("money"));
en.step(player, "hi");
en.step(player, "quest");
assertEquals(ConversationStates.ATTENDING, en.getCurrentState());
assertEquals(
"Thanks, but I don't need any more help.",
getReply(zelan));
en.step(player, "bye");
}
}