Quest Machine Tutorials: Dialogue System Integration, Procedural Quests
Re: Quest Machine Tutorials: Dialogue System Integration, Procedural Quests
I just PM'ed you the beta version of 1.1.0. Please import it or the patch above. This is almost certainly the bug I mentioned above. After importing, check your Quest Machine GameObject. Make sure Generator Settings > Default Player Domain Type is assigned a value. It should default to the asset Plugins / Pixel Crushers / Quest Machine / Data / Domains / PlayerDomain.
-
- Posts: 178
- Joined: Fri Sep 21, 2018 8:38 pm
Re: Quest Machine Tutorials: Dialogue System Integration, Procedural Quests
ok, solved, I eliminated the polimorfism action, as I didn't set up anything for that, and the giver choose the kill quest
Re: Quest Machine Tutorials: Dialogue System Integration, Procedural Quests
With the patch or 1.1.0b1, the polymorph action should work again.
-
- Posts: 178
- Joined: Fri Sep 21, 2018 8:38 pm
Re: Quest Machine Tutorials: Dialogue System Integration, Procedural Quests
Starting to create procedural quests....
I'm a bit lost trying to figure out how to design the elements () for getting a treasure in a chest in a wreck.
I have set up the entities, domain, etc... but not sure how to set up the Urgency, drives (wealth?), factions, etc....
Thanks,
I'm a bit lost trying to figure out how to design the elements () for getting a treasure in a chest in a wreck.
I have set up the entities, domain, etc... but not sure how to set up the Urgency, drives (wealth?), factions, etc....
Thanks,
Re: Quest Machine Tutorials: Dialogue System Integration, Procedural Quests
Hi,
Procedural quests are a little complicated to get started with. I added an example to the tutorial assets:
QuestMachineTutorialAssets_WithProceduralChestQuest.unitypackage
To play it, you must also import some free assets from the Asset Store:
The quest giver will generate a quest to bring him the chest of gold from the mysterious circle.
It uses these assets:
The second step is to run urgency functions on all of the entities. The NPC's faction relationship to the chest is -100. The chest has a Threat urgency function. You can think of it like this: The fact that the chest is out there in the world, and not in the NPC's possession, is a "threat" to the NPC's happiness. So the NPC will choose to make a quest about the chest.
The third step is to choose an action. The NPC will choose the Retrieve action, which removes the chest from the world -- that is, it removes the "threat" to his happiness.
Quest Machine doesn't have an inventory system, so the example action is simplified. In your game, you could define a new action to actually give the chest to the NPC. The action could listen for a message like "GaveToNPC"+"Chest".
The quest giver's Greed drive is +100. Action_Retrieve has a Motive whose Greed is +100. The quest giver will choose this motive because it's similar to his Greed drive.
The last step is to make the plan. The Retrieve action has no requirements, so the plan is only one step.
Once you get the basic quest working, you can make it more complicated. For example, maybe the Retrieve action only works if there is an open chest. To change from a closed chest to an open chest, the player must complete a "Cast Spell" action. To cast the spell, the player must first get the spell scroll. To get the spell scroll, the player must defeat a wizard. Then the plan might consist of these actions:
Procedural quests are a little complicated to get started with. I added an example to the tutorial assets:
QuestMachineTutorialAssets_WithProceduralChestQuest.unitypackage
To play it, you must also import some free assets from the Asset Store:
- A Piece of Nature: https://assetstore.unity.com/packages/3 ... ture-40538
- Toon RTS Units - Demo: https://assetstore.unity.com/packages/3 ... demo-69687
- Toon RTS Units - Orcs Demo: https://assetstore.unity.com/packages/3 ... emo-101359
The quest giver will generate a quest to bring him the chest of gold from the mysterious circle.
It uses these assets:
- DomainType_Circle: Represents the mysterious circle.
- EntityType_Chest: Represents a chest of gold.
- Faction_Chest: Represents the chest's faction.
- Action_Retrieve: The action to move the chest from its current domain to the player's inventory domain.
- EntityType_QuestGiver: Represents the quest giver.
- Greed: Drive type.
The second step is to run urgency functions on all of the entities. The NPC's faction relationship to the chest is -100. The chest has a Threat urgency function. You can think of it like this: The fact that the chest is out there in the world, and not in the NPC's possession, is a "threat" to the NPC's happiness. So the NPC will choose to make a quest about the chest.
The third step is to choose an action. The NPC will choose the Retrieve action, which removes the chest from the world -- that is, it removes the "threat" to his happiness.
Quest Machine doesn't have an inventory system, so the example action is simplified. In your game, you could define a new action to actually give the chest to the NPC. The action could listen for a message like "GaveToNPC"+"Chest".
The quest giver's Greed drive is +100. Action_Retrieve has a Motive whose Greed is +100. The quest giver will choose this motive because it's similar to his Greed drive.
The last step is to make the plan. The Retrieve action has no requirements, so the plan is only one step.
Once you get the basic quest working, you can make it more complicated. For example, maybe the Retrieve action only works if there is an open chest. To change from a closed chest to an open chest, the player must complete a "Cast Spell" action. To cast the spell, the player must first get the spell scroll. To get the spell scroll, the player must defeat a wizard. Then the plan might consist of these actions:
- Defeat: Wizard (Effect: adds scroll to world)
- Get: Scroll (Requirement: scroll is in world. Effect: adds scroll to player)
- Cast: Scroll (Requirement: player has scroll. Effect: remove closed chest; add open chest)
- Retrieve: Chest
-
- Posts: 178
- Joined: Fri Sep 21, 2018 8:38 pm
Re: Quest Machine Tutorials: Dialogue System Integration, Procedural Quests
Thanks very much for the detailed explanation and demo!!! I'll start to study it
PS: I sent you an PM this afternoon related to the save system, please tell me if you received it, as I saw it on the outbox for long time before leaving to sent messages.
PS: I sent you an PM this afternoon related to the save system, please tell me if you received it, as I saw it on the outbox for long time before leaving to sent messages.
Re: Quest Machine Tutorials: Dialogue System Integration, Procedural Quests
Hi,
I forgot to mention that "threat" isn't the only way to compute urgency. You can make a copy of UrgencyFunctionTemplate.cs and define your own urgency function. For example, it could return the value of the item multiplied by the NPC's Greed drive value.
"If you’re using an Invector controller that has an inventory, such as the Shooter Template, define the scripting symbol USE_INVECTOR_INVENTORY. To do this, select Edit > Project Settings > Player and scroll down to Other Settings.
This will make it available. Not all Invector templates have inventory, so it has to be enabled like this or it could cause compiler errors for other customers."
I forgot to mention that "threat" isn't the only way to compute urgency. You can make a copy of UrgencyFunctionTemplate.cs and define your own urgency function. For example, it could return the value of the item multiplied by the NPC's Greed drive value.
I think it was related to saving Invector inventory. Did you get this reply?GorkaGames wrote: ↑Wed Nov 21, 2018 7:30 pmPS: I sent you an PM this afternoon related to the save system, please tell me if you received it, as I saw it on the outbox for long time before leaving to sent messages.
"If you’re using an Invector controller that has an inventory, such as the Shooter Template, define the scripting symbol USE_INVECTOR_INVENTORY. To do this, select Edit > Project Settings > Player and scroll down to Other Settings.
This will make it available. Not all Invector templates have inventory, so it has to be enabled like this or it could cause compiler errors for other customers."
-
- Posts: 178
- Joined: Fri Sep 21, 2018 8:38 pm
Re: Quest Machine Tutorials: Dialogue System Integration, Procedural Quests
Yes I did, but I replayed again . I'll put here the message:
OK, everything works fine and the Invector inventory saves and loads fine...
But related to saving and loading the procedural states.....
--------------------------------------------------------------------------------------------
I get this error when anytime I have saved any procedural quest with this code You gave me one month ago to save automatically the quest states: (At the end of the message)
And once the scene restarts and loads, i get the following error: and whats worst, I lose all the quest on my journal (I guess is because it loads empty or wrong because this error)
ArgumentNullException: Value cannot be null.
Parameter name: key
System.Collections.Generic.Dictionary`2[TKey,TValue].FindEntry (TKey key) (at <f2e6809acb14476a81f399aeb800f8f2>:0)
System.Collections.Generic.Dictionary`2[TKey,TValue].ContainsKey (TKey key) (at <f2e6809acb14476a81f399aeb800f8f2>:0)
PixelCrushers.QuestMachine.QuestMachine.GetImage (System.String imageName) (at Assets/Plugins/Pixel Crushers/Quest Machine/Scripts/Quest Machine/QuestMachine.cs:503)
PixelCrushers.QuestMachine.IconQuestContent.OnAfterProxyDeserialization () (at Assets/Plugins/Pixel Crushers/Quest Machine/Scripts/Quest/Quest Subasset/Quest Content/IconQuestContent.cs:82)
PixelCrushers.QuestMachine.QuestContentProxy.CreateList (PixelCrushers.QuestMachine.QuestContentProxy[] contentListProxy) (at Assets/Plugins/Pixel Crushers/Quest Machine/Scripts/Quest/Quest Serialization/QuestProxy.cs:518)
PixelCrushers.QuestMachine.QuestProxy.CopyTo (PixelCrushers.QuestMachine.Quest quest) (at Assets/Plugins/Pixel Crushers/Quest Machine/Scripts/Quest/Quest Serialization/QuestProxy.cs:114)
PixelCrushers.QuestMachine.QuestListContainer.ApplyData (System.String data) (at Assets/Plugins/Pixel Crushers/Quest Machine/Scripts/Quest MonoBehaviours/Quest List/QuestListContainer.cs:332)
PixelCrushers.QuestMachine.QuestJournal.ApplyData (System.String data) (at Assets/Plugins/Pixel Crushers/Quest Machine/Scripts/Quest MonoBehaviours/Quest List/QuestJournal.cs:128)
PixelCrushers.SaveSystem.ApplySavedGameData (PixelCrushers.SavedGameData savedGameData) (at Assets/Plugins/Pixel Crushers/Common/Scripts/Save System/SaveSystem.cs:497)
UnityEngine.Debug:LogException(Exception)
PixelCrushers.SaveSystem:ApplySavedGameData(SavedGameData) (at Assets/Plugins/Pixel Crushers/Common/Scripts/Save System/SaveSystem.cs:502)
PixelCrushers.<LoadSceneCoroutine>c__Iterator4:MoveNext() (at Assets/Plugins/Pixel Crushers/Common/Scripts/Save System/SaveSystem.cs:599)
--------------------------------------------- code -------------------
using UnityEngine;
using PixelCrushers;
using PixelCrushers.QuestMachine;
public class QuestNodeControllerSaver : MonoBehaviour, PixelCrushers.IMessageHandler
{
public int Slot = 0;
void OnEnable()
{ // Let me know when quest states change.
MessageSystem.AddListener(this, QuestMachineMessages.QuestStateChangedMessage, string.Empty);
}
void OnDisable()
{ // Unregister when disabling script.
MessageSystem.RemoveListener(this);
}
public void OnMessage(MessageArgs messageArgs)
{
//Recoge Cambio en el estado de una Quest
//QuestState state = (QuestState)messageArgs.values[1];
//Recoge Cambio en el estado del nodo de una Quest
QuestNodeState state = (QuestNodeState)messageArgs.values[1];
StringField nodeID = messageArgs.values[0] as StringField;
if (nodeID == null)
{
return; // Is main quest.
}
//Comprueba si es activa la quest
//if (state == QuestState.Active)
//Comprueba si es activa el nodo de la quest
if (state == QuestNodeState.Active)
{ // Quest Node became active. Save game.
//Guardamos en el slot 0, que lo reservamos para guardar los estados de cambios de Nodos / quests
int SlotPrincipal = 0;
PlayerPrefs.SetString("slot_saveName_" + SlotPrincipal, System.DateTime.Now.ToString());
PlayerPrefs.SetInt("slot_" + SlotPrincipal, SlotPrincipal);
PlayerPrefs.SetString("slot_sceneName_" + SlotPrincipal, "CrazyPiratesOpenWorld");
//Save
SaveSystem.SaveToSlot(SlotPrincipal);
//Y además Grabación de BackUp:
Slot +=1; // Use 5 slots, wrapping around back to 1.
if (Slot > 5) Slot = 1;
//Pone la fecha
PlayerPrefs.SetString("slot_saveName_" + Slot, System.DateTime.Now.ToString());
//POne el numero de slot
PlayerPrefs.SetInt("slot_" + Slot, Slot);
//Nombre de escena
PlayerPrefs.SetString("slot_sceneName_" + Slot, "CrazyPiratesOpenWorld");
//Save
SaveSystem.SaveToSlot(Slot);
Debug.Log("Save Quest Node");
if (Invector.vCharacterController.vHUDController.instance)
Invector.vCharacterController.vHUDController.instance.ShowText("Save Quest Node");
}
}
}
UPDATE:
After some research.....
- The error fires always when I REload the scene, so I think is not the origin of the issue.
- We may need to filter the nodeID not to save when is a Procedural Quest, as when I load the game its empty, but I don't know how to do it. Can you help me to filter it?
Should be on the above code somehow.
OK, everything works fine and the Invector inventory saves and loads fine...
But related to saving and loading the procedural states.....
--------------------------------------------------------------------------------------------
I get this error when anytime I have saved any procedural quest with this code You gave me one month ago to save automatically the quest states: (At the end of the message)
And once the scene restarts and loads, i get the following error: and whats worst, I lose all the quest on my journal (I guess is because it loads empty or wrong because this error)
ArgumentNullException: Value cannot be null.
Parameter name: key
System.Collections.Generic.Dictionary`2[TKey,TValue].FindEntry (TKey key) (at <f2e6809acb14476a81f399aeb800f8f2>:0)
System.Collections.Generic.Dictionary`2[TKey,TValue].ContainsKey (TKey key) (at <f2e6809acb14476a81f399aeb800f8f2>:0)
PixelCrushers.QuestMachine.QuestMachine.GetImage (System.String imageName) (at Assets/Plugins/Pixel Crushers/Quest Machine/Scripts/Quest Machine/QuestMachine.cs:503)
PixelCrushers.QuestMachine.IconQuestContent.OnAfterProxyDeserialization () (at Assets/Plugins/Pixel Crushers/Quest Machine/Scripts/Quest/Quest Subasset/Quest Content/IconQuestContent.cs:82)
PixelCrushers.QuestMachine.QuestContentProxy.CreateList (PixelCrushers.QuestMachine.QuestContentProxy[] contentListProxy) (at Assets/Plugins/Pixel Crushers/Quest Machine/Scripts/Quest/Quest Serialization/QuestProxy.cs:518)
PixelCrushers.QuestMachine.QuestProxy.CopyTo (PixelCrushers.QuestMachine.Quest quest) (at Assets/Plugins/Pixel Crushers/Quest Machine/Scripts/Quest/Quest Serialization/QuestProxy.cs:114)
PixelCrushers.QuestMachine.QuestListContainer.ApplyData (System.String data) (at Assets/Plugins/Pixel Crushers/Quest Machine/Scripts/Quest MonoBehaviours/Quest List/QuestListContainer.cs:332)
PixelCrushers.QuestMachine.QuestJournal.ApplyData (System.String data) (at Assets/Plugins/Pixel Crushers/Quest Machine/Scripts/Quest MonoBehaviours/Quest List/QuestJournal.cs:128)
PixelCrushers.SaveSystem.ApplySavedGameData (PixelCrushers.SavedGameData savedGameData) (at Assets/Plugins/Pixel Crushers/Common/Scripts/Save System/SaveSystem.cs:497)
UnityEngine.Debug:LogException(Exception)
PixelCrushers.SaveSystem:ApplySavedGameData(SavedGameData) (at Assets/Plugins/Pixel Crushers/Common/Scripts/Save System/SaveSystem.cs:502)
PixelCrushers.<LoadSceneCoroutine>c__Iterator4:MoveNext() (at Assets/Plugins/Pixel Crushers/Common/Scripts/Save System/SaveSystem.cs:599)
--------------------------------------------- code -------------------
using UnityEngine;
using PixelCrushers;
using PixelCrushers.QuestMachine;
public class QuestNodeControllerSaver : MonoBehaviour, PixelCrushers.IMessageHandler
{
public int Slot = 0;
void OnEnable()
{ // Let me know when quest states change.
MessageSystem.AddListener(this, QuestMachineMessages.QuestStateChangedMessage, string.Empty);
}
void OnDisable()
{ // Unregister when disabling script.
MessageSystem.RemoveListener(this);
}
public void OnMessage(MessageArgs messageArgs)
{
//Recoge Cambio en el estado de una Quest
//QuestState state = (QuestState)messageArgs.values[1];
//Recoge Cambio en el estado del nodo de una Quest
QuestNodeState state = (QuestNodeState)messageArgs.values[1];
StringField nodeID = messageArgs.values[0] as StringField;
if (nodeID == null)
{
return; // Is main quest.
}
//Comprueba si es activa la quest
//if (state == QuestState.Active)
//Comprueba si es activa el nodo de la quest
if (state == QuestNodeState.Active)
{ // Quest Node became active. Save game.
//Guardamos en el slot 0, que lo reservamos para guardar los estados de cambios de Nodos / quests
int SlotPrincipal = 0;
PlayerPrefs.SetString("slot_saveName_" + SlotPrincipal, System.DateTime.Now.ToString());
PlayerPrefs.SetInt("slot_" + SlotPrincipal, SlotPrincipal);
PlayerPrefs.SetString("slot_sceneName_" + SlotPrincipal, "CrazyPiratesOpenWorld");
//Save
SaveSystem.SaveToSlot(SlotPrincipal);
//Y además Grabación de BackUp:
Slot +=1; // Use 5 slots, wrapping around back to 1.
if (Slot > 5) Slot = 1;
//Pone la fecha
PlayerPrefs.SetString("slot_saveName_" + Slot, System.DateTime.Now.ToString());
//POne el numero de slot
PlayerPrefs.SetInt("slot_" + Slot, Slot);
//Nombre de escena
PlayerPrefs.SetString("slot_sceneName_" + Slot, "CrazyPiratesOpenWorld");
//Save
SaveSystem.SaveToSlot(Slot);
Debug.Log("Save Quest Node");
if (Invector.vCharacterController.vHUDController.instance)
Invector.vCharacterController.vHUDController.instance.ShowText("Save Quest Node");
}
}
}
UPDATE:
After some research.....
- The error fires always when I REload the scene, so I think is not the origin of the issue.
- We may need to filter the nodeID not to save when is a Procedural Quest, as when I load the game its empty, but I don't know how to do it. Can you help me to filter it?
Should be on the above code somehow.
Re: Quest Machine Tutorials: Dialogue System Integration, Procedural Quests
Hi,
This is a bug. I will try to have it fixed by tomorrow.
In the meantime, this should prevent the error: QM109_Patch2018-11-21.unitypackage
This is a bug. I will try to have it fixed by tomorrow.
In the meantime, this should prevent the error: QM109_Patch2018-11-21.unitypackage
-
- Posts: 178
- Joined: Fri Sep 21, 2018 8:38 pm
Re: Quest Machine Tutorials: Dialogue System Integration, Procedural Quests
Ok, I'll wait till the fix, please let me know when is done to test it.Tony Li wrote: ↑Wed Nov 21, 2018 9:58 pm Hi,
This is a bug. I will try to have it fixed by tomorrow.
In the meantime, this should prevent the error: QM109_Patch2018-11-21.unitypackage