Page 1 of 2
Multiple Player Controlled Characters
Posted: Tue Apr 02, 2019 11:49 pm
by Thoranar
I'm looking to utilize Quest Machine in a squad based RPG game where the player controls multiple characters. The ideal state is that when any character interacts with a quest giver and is given a quest, it goes to game wide quest journal instead of an individual player character. Any other characters that the player controls can complete the quests, and which ever character turns in the quest, will receive the associated reward.
In some initial testing, I'm able to pickup and complete quests with multiple characters as intended, however I'm having difficulty displaying the associated UI elements (Alerts work fine, but not Journal/HUD). In my testing, I gave each character the Quest Journal component.
Is there a "delivered" way of achieving something like this or will I need to create new classes extending QuestListContainer? My initial thought was to have a quest journal like component that sits on a playermanager and each time a character picks up a quest, it adds it to the quest journal component sitting on the playermanager. The UI's would then be hooked up to the playermanager to display all quests.
Re: Multiple Player Controlled Characters
Posted: Wed Apr 03, 2019 8:32 am
by Tony Li
Hi,
No need for any custom scripting. Just put the Quest Journal component on your player manager.
That should be all you need to do. If you have quests that check for specific quester IDs, give it an ID of "Player". Give each player GameObject a Quest Entity component and assign an EntityType asset whose Display Name is "Player". You can assign the same asset to all of them.
Re: Multiple Player Controlled Characters
Posted: Wed Apr 03, 2019 6:35 pm
by Thoranar
That was my original thought as well, but I'm also creating custom actions to grant Item rewards on certain quests. The intended behavior would be to grant the character interacting with the quest giver, the reward, not all characters.
How would I go about doing this without having a Quest Journal component on that particular character? In addition, how would Quest machine tell me which character interacted with the quest giver (in order to know which player's inventory to add the quest reward for example).
Re: Multiple Player Controlled Characters
Posted: Wed Apr 03, 2019 9:28 pm
by Tony Li
In that case you will need to make a subclass of QuestGiver that can handle the player GameObject separately from the Quest Journal GameObject. Here's an example:
QM_MultiplePlayerSharedJournalExample_2019-04-03.unitypackage
You can probably just use the ExampleCustomQuestGiver.cs script as-is, although you may want to rename the class to something better than "ExampleCustomQuestGiver".
I included a dummy action that reports "give item to player 1" or "give item to player 2" depending on which player you use to complete the quest.
(Exported from Unity 2018.2.0, Quest Machine 1.1.6.)
Re: Multiple Player Controlled Characters
Posted: Wed Apr 03, 2019 10:48 pm
by Thoranar
Thank you very much for that. This certainly helps. I'll need to modify things slightly to handle NPC interaction (I won't be able to define ahead of time the player objects in the inspector), but this points me in a direction for sure.
Since there will be procedural generated characters the player can "Recruit", I'll need to create new player entities at runtime. Is there in issue with my instantiating a copy of the player entity scriptable object? That's the method I use for inventory items as well.
Also again thank you for the example on giving an item. I see you have string reference to the questor ID, are there built in methods for returning the associated gameobject from that string? (so I can get the appropriate player inventory component). Or is this a utility style function I'll need to create myself?
Re: Multiple Player Controlled Characters
Posted: Wed Apr 03, 2019 11:33 pm
by Tony Li
Thoranar wrote: ↑Wed Apr 03, 2019 10:48 pmSince there will be procedural generated characters the player can "Recruit", I'll need to create new player entities at runtime. Is there in issue with my instantiating a copy of the player entity scriptable object? That's the method I use for inventory items as well.
There's no issue instantiating a copy of player entity ScriptableObject. Just remember to Destroy it when you're done with it.
Alternatively, if you don't want to bother with instantiating a copy, there's another way to assign a unique ID & Display Name to a GameObject. Make a subclass of
IdentifiableQuestListContainer. It can be an empty subclass, just to make it accessible in the editor. It can be a one-line script, such as:
PlayerDummyIdentifiableQuestListContainer.cs
Code: Select all
public class PlayerDummyIdentifiableQuestListContainer : PixelCrushers.QuestMachine.IdentifiableQuestListContainer { }
When Quest Machine looks for a GameObject's ID, it checks if the GameObject has a QuestEntity or an IdentifiableQuestListContainer. (Subclasses of IdentifiableQuestListContainer include QuestGiver and QuestJournal.) In this case, we're only going to use it for its 'id' and 'displayName' properties. We won't actually use its quest list.
Then assign StringFields to the id and displayName properties:
Code: Select all
var newPlayer = new GameObject("Adam");
var dummyList = newPlayer.AddComponent<PlayerDummyIdentifiableQuestListContainer>();
dummyList.id = new StringField("adam");
dummyList.displayName = new StringField("Adam the Adventurer");
This way you don't need to deal with ScriptableObject instances.
Thoranar wrote: ↑Wed Apr 03, 2019 10:48 pmAlso again thank you for the example on giving an item. I see you have string reference to the questor ID, are there built in methods for returning the associated gameobject from that string? (so I can get the appropriate player inventory component). Or is this a utility style function I'll need to create myself?
If you use QuestEntity, call
QuestMachineMessages.FindGameObjectWithID:
Code: Select all
var player = QuestMachineMessages.FindGameObjectWithID(quest.questerID);
If you use a subclass of IdentifiableQuestListContainer, first register it with
QuestMachine.RegisterQuestListContainer. So the code above would turn into:
Code: Select all
var newPlayer = new GameObject("Adam");
var dummyList = newPlayer.AddComponent<PlayerDummyIdentifiableQuestListContainer>();
dummyList.id = new StringField("adam");
dummyList.displayName = new StringField("Adam the Adventurer");
QuestMachine.RegisterQuestListContainer(dummyList); //<-- ADD THIS LINE.
This adds it to a lookup table so Quest Machine can quickly look it up by ID. Then you can use QuestMachineMessages.FindGameObjectWithID as above.
When you destroy the player, unregister the IdentifiableQuestListContainer using
QuestMachine.UnregisterQuestListContainer.
---
As an alternative to all that, you could always grab the quest giver instead of the quester. (quest.questGiverID) Then use the quest giver's 'player' property, which points to the player GameObject.
Re: Multiple Player Controlled Characters
Posted: Thu Apr 04, 2019 12:10 am
by Thoranar
Simply perfect. All integrated in and working nicely.
Thank you Tony for the amazing response time.
Re: Multiple Player Controlled Characters
Posted: Thu Apr 04, 2019 7:58 am
by Tony Li
Glad to help!
Re: Multiple Player Controlled Characters
Posted: Thu Apr 04, 2019 8:36 pm
by Thoranar
In a related question. I've create custom UI list templates and item templates to show the specific item quest reward content types. However I'm unable to reference the new classes in the UnityUIBaseUI class and associate Dialogue/Journal classes. (The classes just can't seem to find/reference them) and thus unable to add those elements.
Is this not the process for creating new UIs or is there some method I'm missing? The documentation was a bit vague in this area.
Re: Multiple Player Controlled Characters
Posted: Thu Apr 04, 2019 9:11 pm
by Tony Li
Hi,
I'm not sure what you're trying to do. Can you provide a sketch or mock-up image?
If you only want to define new UI content types, copy QuestContentTemplate.cs to make new subclasses of QuestContent. Your new subclasses should show up when you click "+" in the lower right of a content section such as Offer Text or States > Active > Dialogue Text.
If 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.