Page 2 of 2

Re: Multiple Player Controlled Characters

Posted: Thu Apr 04, 2019 10:45 pm
by Thoranar
f you want to change how the UIs work -- such as adding a separate panel to show rewards -- make a subclass of the corresponding UI (e.g., UnityUIQuestDialogueUI or UnityUIQuestJournalUI). If you make a subclass of UnityUIQuestDialogueUI, override the AddContents and/or AddContent methods. If you make a subclass of UnityUIQuestJournalUI, override the RefreshNow and/or RepaintSelectedQuest method.
This is the part I am trying to do, but instead of making a new subclass, I was instead trying to modify the existing ones. However because all of quest machine's code is in a Plugins folder, it is compiled at different times and so cannot reference scripts created outside of the Plugins folder.

I've created now a new sublass of the UnityUIQuestDialogueUI but getting various reference errors when trying to accept new quests that have the new content types as well. Still working through it all.

Re: Multiple Player Controlled Characters

Posted: Fri Apr 05, 2019 1:07 am
by Thoranar
Was able to get everything working. I used the IconTemplate as an example and as such had to override a few methods from both UnityUIQuestionDialogueUI as well as UnityUIBaseUI. I now have a way of showing quest rewards that follow my item UI scripts I had previously built (which mainly show tooltip information whenever you mouse over).

The final piece would be a content type that allows for the player to choose a reward from a provided list within the dialogue UI. I was looking at the Button Quest Content and that looks like a good starting point. I'm thinking it would be an extension of the Item Content Type and UI I just made, but when the player clicks it, the associated action would be to highlight and flag in the script a field "selected". Then a new action type for "grant selected reward" that would reward the selected reward instead of one that was predefined by the quest.

Is this how you have seen other instances of having players choose reward or is there an easier solution?

Re: Multiple Player Controlled Characters

Posted: Fri Apr 05, 2019 8:28 am
by Tony Li
So far, I've seen other devs just use button content. When the player clicks on a reward button, it uses the message system to grant the reward and close the dialogue.

Selectable rewards is on the roadmap. May I use your idea above? I think that would be better than simply clicking a reward button to get a reward and close the dialogue. I'll try to get this into the next release.

Re: Multiple Player Controlled Characters

Posted: Fri Apr 05, 2019 11:35 pm
by Thoranar
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. :D

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.

Re: Multiple Player Controlled Characters

Posted: Sat Apr 06, 2019 8:38 am
by Tony Li
Hi,

Thanks for sharing that! To make it automatically close the window, you could add a line to the reward template's Assign method:

Code: Select all

public virtual void Assign(Item item)
{
    itemSlot.Assign(item);
    itemSlot.onDoubleClick.AddListener(ChooseReward);
    QuestMachine.defaultQuestJournalUI.Hide(); //<-- ADD THIS.
}

Re: Multiple Player Controlled Characters

Posted: Mon Apr 08, 2019 9:32 pm
by Tony Li
Hi,

Just letting you know that I sent you a PM with a patch to address some of the questions you had. The changes will also be in the upcoming Quest Machine version.