I have a base struct that every one of my quest objectives inherits from, and a bunch of child structs which enumerate the logic for specific types of objectives, like kill quests vs. fetch quests. I’m trying to set it up now so that every action that a quest could possibly want to know about messages the quest system, which in term informs any quest objectives that need the information. As an example, this is the prototype for a kill quest:
USTRUCT(BlueprintType)
struct FQuestGoalBase{ //Base struct that all quest objectives inherit
GENERATED_USTRUCT_BODY()
bool EvaluateMyself(); //Check if this goal has been met
void Notify_Kill(int8 enemyID); //This fires every time an enemy is killed
};
USTRUCT(BlueprintType)
struct FQuestGoalKill : public FQuestGoalBase{
GENERATED_USTRUCT_BODY()
int8 numberToKill; //Number of enemy that needs to be killed to finish objective
int8 numberKilled; //Number of enemy already killed
int8 enemyTypeID; //Type of enemy to kill
bool EvaluateMyself(){ //Resolve to true iff the player has killed as many or more enemies than required
if (numberKilled >= numberToKill){
return true;
}
else
{
return false;
}
}
void Notify_Kill(int8 enemyID){
if (enemyID == enemyTypeID){ //If the player killed the type of enemy this objective is counting, increment kill count by one
numberKilled++;
}
}
};
Extending this logic to every possible objective type, the idea is that the logic manager class would have its own version of each notification: Notify_Kill, Notify_Talk, Notify_Loot, and so forth. Whenever the player performs an action it would inform the logic manager, which in turn informs every quest. It’s pretty straightforward, but I’m worried about how cumbersome it’s going to get when I have 40-50 notifications, and the need to clone my functions (one in FQuestGoalBase, one in the logic manager) seems like poor design to me. Is there an obvious way to clean this up, or am I going about it in more-or-less the logical way?
How do delegates work with structs? Do I need to manually add some kind of unbinding method to the struct’s destructor, or can I bind a method, forget about it, and rest assured that if the invoking struct gets destroyed, unreal will handle unbinding it independently?
It is always better to be sure and undo everything you’ve done.
I don’t think that structs handle unbinding automatically. If you want automatic unbinding, use UObjects.
Alright, that seems pretty straightforward- thank you for the advice
Edit: Quick followup I belatedly thought up- it’s safe to pass delegates by value, right? So I could bind some method in FQuestObjective objectiveA to a delegate, then say FQuestObjective objectiveB = objectiveA and trust that objectiveB will now be correctly bound to the desired delegate?
Hm, no I don’t think that this is how it works. The method you bind is just a method and it doesn’t have any information about delegates it is bound to. So when you copy your objective, you have to bind new objective’s methods in your copy constructor if you want it to work in that way.