I was able to implement the chosen reward system easier than I expected. Happy to share the related code files if you'd like but what I ended up doing was to first create a new quest content ("RewardQuestContent") that holds a reference to the possible item reward as well as a static method called SelectReward and a static UnityEvent called OnRewardSelected.
I then created a OnDoubleClickEvent to the UI icon that displays the item in the dialogue UI. The static SelectReward method listens for that event and stores the currently chosen award in a public static variable called currentChosenReward.
Next I created a quest condition that sets the quest state to true whenever a reward is selected by listening to the OnRewardSelected static event.
Finally, a new action that simply calls up the static currentChosenReward and adds that particular item to the players inventory.
ItemQuestContent:
Code: Select all
public class ItemQuestContent : QuestContent
{
[Serializable] public class OnRewardSelected : UnityEvent { }
public static OnRewardSelected onRewardSelected = new OnRewardSelected();
public static Item currentChosenReward;
public static void SelectReward(Item item)
{
currentChosenReward = item;
onRewardSelected?.Invoke();
}
[Tooltip("The item.")]
[SerializeField]
private Item m_item;
[Tooltip("The count to show on the count label. If 0 or 1, count is not shown.")]
[SerializeField]
private int m_count;
public Item item
{
get { return m_item; }
set { m_item = value; }
}
public int count
{
get { return m_count; }
set { m_count = value; }
}
}
RewardChosenQuestCondition:
Code: Select all
public class RewardChosenQuestCondition : QuestCondition
{
public override void StartChecking(System.Action trueAction)
{
base.StartChecking(trueAction);
// Add your code here to start checking your condition.
// When the condition is true, call SetTrue().
ItemQuestContent.onRewardSelected.AddListener(SetTrue);
}
public override void StopChecking()
{
base.StopChecking();
ItemQuestContent.onRewardSelected.RemoveListener(SetTrue);
// Add your code here to stop checking your condition.
}
}
QuestItemRewardtemplate:
Code: Select all
public class UIQuestItemRewardTemplate : UnityUIContentTemplate
{
[SerializeField] private UIItemSlot itemSlot;
public virtual void Assign(Item item)
{
itemSlot.Assign(item);
itemSlot.onDoubleClick.AddListener(ChooseReward);
}
public virtual void ChooseReward(UIItemSlot slot)
{
if(itemSlot.GetItemInfo() is Item)
ItemQuestContent.SelectReward(itemSlot.GetItemInfo() as Item);
}
public override void Despawn()
{
if (itemSlot != null)
itemSlot.onDoubleClick.RemoveListener(ChooseReward);
base.Despawn();
}
}
InventoryItemQuestAction - This action is pretty specific to my game, and I also chose to just have one action instead of two. It assumes that if the quest setup with the Item field blank, then check for a chosen reward.
Code: Select all
public class InventoryItemQuestAction : QuestAction
{
[SerializeField]
private Item m_item;
public Item item
{
get { return m_item; }
set { m_item = value; }
}
public override void Execute()
{
base.Execute();
Inventory inventory = QuestMachineMessages.FindGameObjectWithID(quest.questerID).GetComponent<Inventory>();
if(inventory != null)
{
if (ItemQuestContent.currentChosenReward != null)
{
inventory.AddItem(ItemQuestContent.currentChosenReward.GetCopy());
ItemQuestContent.currentChosenReward = null;
}
else if (m_item != null)
{
inventory.AddItem(item.GetCopy());
}
else
Debug.LogError("No chosen reward or item identified to add");
}
}
}
The only minor issue I have right now is that the quest window does not automatically close when a reward is chosen and the item is added. It doesn't allow you to add multiple rewards, but I could see that as being confusing to the player if the window stays up. Minor issue that I'm sure I'll figure out shortly after posting this.
On a side note, I recognize I probably could have used QuestMachine messaging for this, instead of custom events, I just am more familiar with standard unity events.