Page 1 of 1
Reward System?
Posted: Tue Jan 23, 2024 7:27 pm
by aallenfx
Hey, is there a reward system functionality? I wanted to add it on the "Success" node under "Actions". I didn't see any option for auto-triggering reward functionality.
I tried adding a "Unity Event" action and assigning my function under "OnExecute" though that's less than ideal since it's really nested in there and I would need to do this for every quest. And if a script rename happened, I'd need to fix this on every quest ever (if i could even find the unity event i created incase it turns into multiples).
There's also a lack of multi-object editing which makes it difficult to bulk edit things as well. Trying to find ways to streamline or automate the process of adding rewards. Any ideas on how to resolve this?
Re: Reward System?
Posted: Tue Jan 23, 2024 7:30 pm
by aallenfx
Re: Reward System?
Posted: Tue Jan 23, 2024 8:29 pm
by Tony Li
Hi,
I recommend writing a custom quest action instead of using the UnityEvent quest action. You can find a starter script in Plugins / Pixel Crushers / Quest Machine / Templates. Just duplicate QuestActionTemplate.cs, rename it and move it into your scripts folder, and add your reward code where the comments indicate.
Alternatively, you can add a script that implements IMessageHandler to listen for quest state change messages (see
this post) to the player or Quest Machine GameObject. When the quest changes to success, give the reward. If you plan to give the same reward(s) with every quest, you could create counters for them. For example, if you plan to give gold and XP with each quest, you can add "gold" and "xp" counters to each quest. In your IMessageHandler script's OnMessage() method, look up the quest's gold and xp counter values and give those rewards to the player.
Re: Reward System?
Posted: Mon Mar 04, 2024 1:21 pm
by TrueHumanSoul
Good day!
I'm writing a reward system and encountered a similar problem.
From Actions at some quest state I send a Message:
Sender: Quest Giver
Target: Any
Message: Give
Parameter: Coins
Value: int 50
How should I subscribe my MessageSystemListener to actually listen this action messages I send? I`ve spend all day but couldn`t figure it out. What should I add instead of QuestMachineMessages.QuestStateChangedMessage?
Code: Select all
public class RewardSystemController : MonoBehaviour, IMessageHandler
{
[SerializeField] private RewardSystemDatabase _rewardsDatabase;
private void OnEnable()
{
// Listen for Quest State Changed messages:
MessageSystem.AddListener(this, QuestMachineMessages.QuestStateChangedMessage, string.Empty);
}
private void OnDisable()
{
// Stop listening:
MessageSystem.RemoveListener(this);
}
public void OnMessage(MessageArgs messageArgs)
{
string parameter = messageArgs.parameter;
string message = messageArgs.message;
object[] value = messageArgs.values;
Debug.Log("Message Recieved: Parameter: " + parameter + ". Message: " + message + ". Value: " + value[0].ToString());
}
public void RecieveMessageFromQuest(string message, string parameter, int value)
{
switch (message)
{
case "Give":
RewardSystemDatabase.Reward reward = _rewardsDatabase.SeekForRewardByName(parameter);
if (reward != null)
{
Debug.Log("GIVE!");
}
break;
case "Remove":
break;
}
}
}
Re: Reward System?
Posted: Mon Mar 04, 2024 8:18 pm
by Tony Li
Hi,
Try this:
Code: Select all
public class RewardSystemController : MonoBehaviour, IMessageHandler
{
[SerializeField] private RewardSystemDatabase _rewardsDatabase;
private void OnEnable()
{
// Listen for "Give" + (reward) messages: (first value will be amount to give)
MessageSystem.AddListener(this, "Give", string.Empty);
// Listen for "Remove" + (reward) messages: (first value will be amount to remove)
MessageSystem.AddListener(this, "Remove", string.Empty);
}
private void OnDisable()
{
// Stop listening:
MessageSystem.RemoveListener(this);
}
public void OnMessage(MessageArgs messageArgs)
{
string rewardName = messageArgs.parameter;
int amount = messageArgs.intValue;
switch (messageArgs.message)
{
case "Give":
RewardSystemDatabase.Reward reward = _rewardsDatabase.SeekForRewardByName(rewardName);
if (reward != null)
{
Debug.Log($"GIVE {amount} {rewardName}!");
}
break;
case "Remove":
Debug.Log($"REMOVE {amount} {rewardName}!");
break;
}
}
}
Alternatively, if you're giving rewards in a quest, it's better to make a new quest action:
- Duplicate QuestActionTemplate.cs
- Move the duplicate to your own scripts folder
- Rename it to something like GiveRewardQuestAction.cs
- Fill in your code where the comments indicate
- In the quest's Success node (for example), in the True state > Actions section, add your Give Reward action.