# Create a new quest type

## Summary

1. [The structure](#the-structure)
2. [How to create your quest](#how-to-create-your-quest)
   1. [Step 1: Create a quest object](#step-1-create-a-quest-object)
   2. [Step 2: Create the listener](#step-2-create-the-listener)
   3. [Step 3: Register quest and event](#step-3-register-quest-and-event)

## The structure

The structure of how quests work is relatively simple.&#x20;

The basis of the quest is contained in an [AbstractQuest](https://odailyquests.ordwen-dev.com/javadoc/com/ordwen/odailyquests/quests/types/AbstractQuest.html) class, which contains all the information common to all quests: the name, the description, the item menu... Each quest class inherits from the AbstractQuest class and implements its own settings. The quest class also adds a [`canProgress()`](https://odailyquests.ordwen-dev.com/javadoc/com/ordwen/odailyquests/quests/types/shared/BasicQuest.html#canProgress\(org.bukkit.event.Event,com.ordwen.odailyquests.quests.player.progression.Progression\)) method, which returns a `boolean` and performs any necessary checks depending on the quest parameters.

Each type of quest is associated with a game event. For example, [`BREAK`](https://odailyquests.ordwen-dev.com/javadoc/com/ordwen/odailyquests/quests/types/item/BreakQuest.html) type quests are associated with the `BlockBreakEvent` event.&#x20;

The class that listens the event inherits from a PlayerProgressor class, which:

* &#x20;checks if the player has an active quest of the same type,
* &#x20;if yes, calls the quest's [`canProgress()`](https://odailyquests.ordwen-dev.com/javadoc/com/ordwen/odailyquests/quests/types/shared/BasicQuest.html#canProgress\(org.bukkit.event.Event,com.ordwen.odailyquests.quests.player.progression.Progression\)) method,
* if the method returns true, make the quest progress.

Finally, quests are saved in the [`QuestTypeRegistry`](https://odailyquests.ordwen-dev.com/javadoc/com/ordwen/odailyquests/api/quests/QuestTypeRegistry.html).

## How to create your quest

Here, you'll learn step-by-step how to create your new quest type. For this example, we'll use the PyroFishingPro API to create a quest of type `PYRO_FISH`.

### Step 1: Create a quest object

To begin with, you need to create a class to represent your quest object. \
This class must inherit from the [`AbstractQuest`](https://odailyquests.ordwen-dev.com/javadoc/com/ordwen/odailyquests/quests/types/AbstractQuest.html) class.

```java
public class PyroFishQuest extends AbstractQuest {}
```

Now you need to implement the constructor to instantiate the AbstractQuest, passing as parameter a [BasicQuest](https://odailyquests.ordwen-dev.com/javadoc/com/ordwen/odailyquests/quests/types/shared/BasicQuest.html) object, which represents a quest with no prerequisites.

<pre class="language-java"><code class="lang-java"><strong>protected PyroFishQuest(BasicQuest basicQuest) { super(basicQuest); }
</strong></code></pre>

Now you need to implement the three methods of the [`IQuest`](https://odailyquests.ordwen-dev.com/javadoc/com/ordwen/odailyquests/api/quests/IQuest.html) interface.

#### The [getType()](https://odailyquests.ordwen-dev.com/javadoc/com/ordwen/odailyquests/api/quests/IQuest.html#getType\(\)) method

This method simply returns the quest type as a String.

```java
@Override
public String getType() {
    return "PYRO_FISH";
}
```

#### The [loadParameters()](https://odailyquests.ordwen-dev.com/javadoc/com/ordwen/odailyquests/api/quests/IQuest.html#loadParameters\(org.bukkit.configuration.ConfigurationSection,java.lang.String,java.lang.String\)) method

This method takes the quest's section, file and index as parameters and loads your quest's attributes. For example, for a quest of type `PYRO_FISH`, we need two attributes: an `integer` representing the item number, and a `String` for the tier.

```java
private String tier;
private int id;
```

Let's suppose we have the following quest:

```yaml
1:
  name: "Get a custom fish"
  menu_item: COD
  description:
    - "&6Get a custom fish."
    - "&6Win &b5000 &6$."
  quest_type: PYRO_FISH
  pyro_fish_tier: "Bronze"
  pyro_fish_id: 2
  required_amount: 1
  reward:
    reward_type: MONEY
    amount: 5000
```

Here, we have a `PYRO_FISH` quest that takes two new parameters: `pyro_fish_tier` and `pyro_fish_id`. We now need to load them into our `loadParameters()` method. To do this, we have the `section` parameter in the method, which corresponds exactly to the quest. We can then check for the presence of the required parameters in the quest configuration, and trigger an error if this is not the case, using the [`PluginLogger#configurationError()`](https://odailyquests.ordwen-dev.com/javadoc/com/ordwen/odailyquests/tools/PluginLogger.html) method.

Here is the result. Of course, you can add additional checks, such as checking the parameter type.&#x20;

Returning `false` when the parameters are not correct is important, as it tells the plugin that the quest is invalid and won't be added to the list, thus avoiding errors.

```java
@Override
public boolean loadParameters(ConfigurationSection section, String file, int index) {
    if (!section.contains("pyro_fish_tier")) {
        PluginLogger.configurationError(file, index, "pyro_fish_tier", "You must specify the tier of the Pyro Fish.");
        return false;
    }

    if (!section.contains("pyro_fish_id")) {
        PluginLogger.configurationError(file, index, "pyro_fish_id", "You must specify the id of the Pyro Fish.");
        return false;
    }

    this.tier = section.getString("pyro_fish_tier");
    this.id = section.getInt("pyro_fish_id");

    return true;
}
```

{% hint style="info" %}
You don't need to call the method, the plugin will do it automatically!
{% endhint %}

#### The [canProgress()](https://odailyquests.ordwen-dev.com/javadoc/com/ordwen/odailyquests/api/quests/IQuest.html#canProgress\(org.bukkit.event.Event,com.ordwen.odailyquests.quests.player.progression.Progression\)) method

Finally, we need to implement a method for checking that the conditions are met for the quest to progress. This method takes an `Event` object as parameter. The first step is to check that the event corresponds to the one used by the quest, in order to retrieve its instance. Then we can check our parameters.

```java
@Override
public boolean canProgress(Event provided) {
    if (provided instanceof PyroFishCatchEvent event) {
        return event.getTier().equals(this.tier) && event.getFishNumber() == this.id;
    }

    return false;
}
```

Here, we're using the `PyroFishCatchEvent` and its associated methods. It's as simple as that!

{% hint style="info" %}
You don't need to call the method, the plugin will do it automatically!
{% endhint %}

{% hint style="info" %}
You don't need to check by yourself whether the player is in a forbidden world or an unauthorized region. If the parameter is present in your config.yml file, the plugin already checks this at the time of progression!
{% endhint %}

After implementing all the methods, here's the complete result.

<details>

<summary>PyroFishQuest class</summary>

```java
package com.ordwen.odailyquests.quests.types.custom.items;

import com.ordwen.odailyquests.quests.types.AbstractQuest;
import com.ordwen.odailyquests.quests.types.shared.BasicQuest;
import com.ordwen.odailyquests.tools.PluginLogger;
import me.arsmagica.API.PyroFishCatchEvent;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.Event;

public class PyroFishQuest extends AbstractQuest {

    private String tier;
    private int id;

    protected PyroFishQuest(BasicQuest basicQuest) {
        super(basicQuest);
    }

    @Override
    public String getType() {
        return "PYRO_FISH";
    }

    @Override
    public boolean canProgress(Event provided) {
        if (provided instanceof PyroFishCatchEvent event) {
            return event.getTier().equals(this.tier) && event.getFishNumber() == this.id;
        }

        return false;
    }

    @Override
    public boolean loadParameters(ConfigurationSection section, String file, int index) {
        if (!section.contains("pyro_fish_tier")) {
            PluginLogger.configurationError(file, index, "pyro_fish_tier", "You must specify the tier of the Pyro Fish.");
            return false;
        }

        if (!section.contains("pyro_fish_id")) {
            PluginLogger.configurationError(file, index, "pyro_fish_id", "You must specify the id of the Pyro Fish.");
            return false;
        }

        this.tier = section.getString("pyro_fish_tier");
        this.id = section.getInt("pyro_fish_id");

        return true;
    }
}

```

</details>

Now that our quest object is ready, we can move on to the next step.

### Step 2: Create the listener

To trigger quest progression, we need to create a class that inherits from [`PlayerProgressor`](https://odailyquests.ordwen-dev.com/javadoc/com/ordwen/odailyquests/quests/player/progression/PlayerProgressor.html) and implements `Listener`. Then define the method that listens for the desired event.

When the event is triggered, simply call `PlayerProgressor`'s [`setPlayerQuestProgression()`](https://odailyquests.ordwen-dev.com/javadoc/com/ordwen/odailyquests/quests/player/progression/PlayerProgressor.html#setPlayerQuestProgression\(org.bukkit.event.Event,org.bukkit.entity.Player,int,java.lang.String\)) method, which takes as its parameters the event in question, the player involved, the amount to be added to the progression, and the type of quest.

```java
package com.ordwen.odailyquests.events.listeners.item.custom;

import com.ordwen.odailyquests.quests.player.progression.PlayerProgressor;
import me.arsmagica.API.PyroFishCatchEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

public class PyroFishCatchListener extends PlayerProgressor implements Listener {

    @EventHandler(ignoreCancelled = true)
    public void onPyroFishCatch(PyroFishCatchEvent event) {
        setPlayerQuestProgression(event, event.getPlayer(), 1, "PYRO_FISH");
    }
}
```

For the `PyroFishCatchEvent`, the method used to retrieve the player is `getPlayer()`, and as the player receives only one item per event, the amount is 1. Then we specify the `PYRO_FISH` quest type.&#x20;

Of course, you'll need to adapt to the needs of the event you're listening to.

{% hint style="info" %}
You can add to this method any pre-checks that would not be taken into account by your quest. For example, if the API of the target plugin allows it, the type of ocean, the distance from the shore, or a defined region...
{% endhint %}

### Step 3: Register quest and event

Now all you have to do is register the quest in the [QuestTypeRegistry](https://odailyquests.ordwen-dev.com/javadoc/com/ordwen/odailyquests/api/quests/QuestTypeRegistry.html) and the event, so that it can be listened to.&#x20;

An event must be registered in the same way as any other event, as with any other plugin.

```java
Bukkit.getPluginManager().registerEvents(new PyroFishCatchListener(), oDailyQuests);
```

The quest type must be registered in the `onLoad()` method of your main class.

```java
@Override
public void onLoad() {
    ODailyQuestsAPI.registerQuestType("PYRO_FISH", PyroFishQuest.class);
}
```

And that's it! Now all you have to do is compile and add your plugin to your server. When it starts up, O'DailyQuests should write you logs showing that your quests are loading correctly.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ordwenplugins.gitbook.io/odailyquests/api/create-a-new-quest-type.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
