Dialog conditionals help
#1
Posté 21 décembre 2009 - 05:53
The problem I have right now is how to make the plot flag system check for multiple conditions.
Example: I have a simple quest, a guard asks the player to clear out some rats from 2 places. I have 3 plot flags (main, not defined ... not sure the difference ... HAS_RATQUEST, RATS_KILLED1, RATS_KILLED2). If you do the quest, it works. BUT, the line the NPC speaks for the old parts of the quest always appears, which looks silly.
Here are the NPCs 3 lines of text (simplified)
** Help me kill rats (conditional checks to see if quest has been accepted)
** You killed that first rat, good job, please help me kill another rat (conditional checks to see rat1 is dead)
** Great, you killed both sets of rats, have Starfang as my thanks (conditional checks to see if rat 2 is dead)
The problem is that the last 2 two lines appear if the quest is complete ... is there any way to check for multiple conditions using plot flags? Or do you have to set up a separate plot flag that combines those conditions?
Do I need a another flag and set it to true if both sets of rats are dead? If so, that seems like extra work ... and just writing your own conditionals would be easier. If you had 5 groups of rats, it would be chaos!
Or am I missing something simple?
Thanks.
#2
Posté 21 décembre 2009 - 06:31
The simplest way is have the rat groups only be killable in a specific order. Then, use different NPC conversation branches in inverse chronological order. Each one only needs to check for one group killed, since they have to be killed in order.
If they can be killed in any order, and what's significant is if you've killed one or if you've killed both, there are two ways to do that.
One is to put the logic in the team death scripts. Have a plot flag for team A being dead, a flag for team B being dead, a flag for at least one team being dead and a flag for both teams being dead. In the team death event after setting the A or B flag, check if the other team's flag has already been set. If not, set the at least one flag. If so, set the both flag. If for some reason ordering the NPC lines in inverse chronological order is not sufficient, you could rename the at least one flag to exactly one and unset it when you set the both flag.
The other way is to put the logic in defined conditions. I think this is what you've been missing. To make a defined condition, make a defined flag instead of a main flag. Defined flags cannot be set, and the flag itself has no true/false value. Instead, checking a defined flag runs the plot script, and within the appropriate case statement you put whatever logic you want and return TRUE or FALSE.
The easiest way to see how plot scripts work, if you're having trouble, is to open an existing one. There should be a few examples in the cores scripts, including ones with defined conditions. You can also look at the plot script template. The defined conditions are in the second half of the script, after the actions.
#3
Posté 21 décembre 2009 - 07:14
BioSpirit wrote...
I am not sure does this work but how about someting like this:switch(nFlag)
{
case PLOT_KILLED_SOME_RATS:
{
UT_IncLocalInt(RATS_KILLED); // Increment number of rats killed
if (GetLocalInt(RATS_KILLED)=5) WR_SetPlotFlag(PLOT_KILLED_ALL_RATS);
}
}
Now if you set the plot flag PLOT_KILLED_SOME_RATS every time you kill a rat (evenif it's already set) it could fire the plot script and count the rats.
I see a few potential problems with the above script. One is that UT_IncLocalInt must be using OBJECT_SELF because no object parameter is specified. You have no idea what OBJECT_SELF is going to be when running a plot script, since the flag could be set from anywhere. Second, RATS_KILLED is not a variable defined in any default variables list. You'd have to make a new variables 2da or add it to an existing one. You could use a default variable like CREATURE_COUNTER_1, but then you have to be careful you're not using that variable for anything else.
If you want to detect when 5 rats are dead, the easiest thing to do is put them in a team, and when they are all dead a TEAM_DESTROYED event will be fired to the area. The player would be forced to kill all the rats rather than just some of them, and you're limited to one area, but otherwise it's a very easy way to script this.
Due to the limitations of local variables I would only use that method as a last resort. Instead, if I needed to overcome the above limitations, I would make 5 plot flags and use them as a counter. Plot flags don't rely on OBJECT_SELF, they don't require variables be declared in a 2da, there's no risk of double purposing an existing variable and they can be set/checked in any area.
Modifié par DavidSims, 21 décembre 2009 - 07:15 .
#4
Posté 21 décembre 2009 - 10:59
FalloutBoy wrote...
DavidSims wrote...
Due to the limitations of local variables I would only use that method as a last resort. Instead, if I needed to overcome the above limitations, I would make 5 plot flags and use them as a counter. Plot flags don't rely on OBJECT_SELF, they don't require variables be declared in a 2da, there's no risk of double purposing an existing variable and they can be set/checked in any area.
So let's say you made 5 plot flags, one per rat. Would you also make a defined flag called ALL_RATS_DEAD and in your plot script for this flag, return TRUE if your 5 plot flags are all TRUE?
I think maybe I finally understand what a defined flag is. :happy:
Yes, that's a common use for a defined flag, and that's certainly one way to implement the quest; to make each flag represent a different and unique rat. If you've only got 5 rats, I'd probably do it that way*. If there were many rats and you just wanted to know if the player has killed at least 5, you could run something like the following when any rat dies:
if (WR_GetPlotFlag(PLT_RATS, RATS_DEAD_4) WR_SetPlotFlag(PLT_RATS, RATS_DEAD_5, TRUE);
else if (WR_GetPlotFlag(PLT_RATS, RATS_DEAD_3) WR_SetPlotFlag(PLT_RATS, RATS_DEAD_4, TRUE);
else if (WR_GetPlotFlag(PLT_RATS, RATS_DEAD_2) WR_SetPlotFlag(PLT_RATS, RATS_DEAD_3, TRUE);
else if (WR_GetPlotFlag(PLT_RATS, RATS_DEAD_1) WR_SetPlotFlag(PLT_RATS, RATS_DEAD_2, TRUE);
else WR_SetPlotFlag(PLT_RATS, RATS_DEAD_1, TRUE);
*Assuming I wasn't using a single team, probably because the rats are split up in different areas, or because I want the journal to update every kill rather than only when they are all dead. If all of the rats are in one place, the team would definitely be the easier way to do it.
#5
Posté 22 décembre 2009 - 06:24
Axe_Murderer wrote...
Just read that wiki from Sunjammer and I can't help agreeing that "defined" flag is a misnomer of a name for them. In truth, they are exactly opposite of defined...they are computed dynamically. There is nothing about them that is defined other than their ID. The fact that you can't set them also means that you cannot define them. Oh I guess you could say they are defined by code rather than values, but I don't think that way. I would have called them computed flags or computing flags or maybe evaluating flags since their value is determined by a computational evaluation made in code on the fly at the time they are examined (Get). They are basically just a function call invoked thru event signals rather than direct execution. I like them muchly they are incredibly elegant. but the name chosen is confusing because its really completely opposite...to me anyway.
Function flags?
Does the toolset call them defined flags? I've always called them defined conditions. I think name comes from the fact that the condition is defined by the script, rather than the value of the flag. I agree it's not the best naming, but the system works quite well once you wrap your head around it.





Retour en haut






