Aller au contenu

Photo

Easy question about scripting from a noob


  • Veuillez vous connecter pour répondre
11 réponses à ce sujet

#1
Petunien

Petunien
  • Members
  • 6 messages
Hello everyone,

I want to learn scripting with the toolset and therefore I'm reading and trying a lot of tutorials and example codes,
but I don't understand some of the basics.

I want to use the "if/then"-system to start a conversation after a cutscene ends.
The cutscene starts with "placeable_onclick".

Here is my current code:

#include "events_h"
#include "utility_h"
#include "wrappers_h"
#include "log_h"

void main()
{
    int bEventHandled = FALSE;

    event evCurrent = GetCurrentEvent();
    int nEventType = GetEventType(evCurrent);

    switch(nEventType)
    {
        case EVENT_TYPE_PLACEABLE_ONCLICK:
        {

            CS_LoadCutscene(R"level1_cutscene1.cut");
            PlayCutscene();

            bEventHandled = TRUE;
            break;

        }
    }

    if(!bEventHandled)
    {
        HandleEvent(evCurrent, RESOURCE_SCRIPT_TRIGGER_CORE);
    }
}

But how can I create an "If-Cutscene-Ended-Then-Start-Conversation" part?

It would be very nice if someone could take the time and help a desperate noob. :blush:

#2
Sunjammer

Sunjammer
  • Members
  • 925 messages
You should be able to do it by passing the tag of the NPC who owns the conversation in as one of the optional parameters to the CS_LoadCutscene function. Personally I haven't tested this approach. Or you could set a plot flag (see this example which starts the conversation. Note both these approaches require gen00cs_cutscene_end to be referenced in the cutscene's End Script property.

Alternatively write a second script that starts the conversation and reference that in the cutscene's End Script property.

Modifié par Sunjammer, 28 décembre 2011 - 01:12 .


#3
Petunien

Petunien
  • Members
  • 6 messages
Thank you a lot for the answer... I will try those solutions.

After I did some thinking I got an idea.
Because of the overall view and general simplicity I want to ask whether it's possible to set a (global?) variable to "TRUE" after the cutscene ends. Then another scripts check the variable and if it's "TRUE" starts the conversation.

Is that possibile? Would be a good solution, or?

By the way, sorry for my bad english, I'm from Italy and i speak mostly italian and german.

:)

#4
Sunjammer

Sunjammer
  • Members
  • 925 messages
Dragon Age doesn't really have the concept of a global variable.

In the past, Neverwinter Nights, it was very simple to create a variable on an object and set, check or delete the variable's value as required. However in Dragon Age such variables have to be listed in a 2da file which in turn has to be compiled and associated with a template. You can still use this approach but it tends to be more hassle than it is worth to create a new one. You could of course use an existing variable but there is always a chance that one of Dragon Age's existing systems (or a mod) is already using it.

Consequently in Dragon Age, instead of using "global" variables we tend to use plot flags. There are two types of flags (main and defined) and they can be set (true) or unset (false). Main flags are can be checked and updated (read/write) while defined flags can only be checked (read only). Moreover defined flag's value is determined by a snippet of code. You might find this old article helpful to distinguish the two types.

#5
Petunien

Petunien
  • Members
  • 6 messages
Thank you for your effort.

Now I want to test whether I have understood the "if function" and therefore I wrote a little script that set the status of a door at 0 after the cutscene starts/ends. But it says that there's an error in line 29:
"Variable defined without type (while compiling var_constants_h.nss)"

I searched the error long but I can't find it.
 

Here's my code:

void main()
{
    int bEventHandled;

    event evCurrent = GetCurrentEvent();
    int nEventType = GetEventType(evCurrent);
    object oClosed_door = GetObjectByTag("closed_door");
    switch(nEventType)
    {
        case EVENT_TYPE_PLACEABLE_ONCLICK:
        {

            CS_LoadCutscene(R"level1_cutscene1.cut");
            PlayCutscene();

            bEventHandled = TRUE;
            break;

        }
    }

    if(!bEventHandled)
        {
            WR_SetPlotFlag("TEST", CUTSCENE1_BEENDET, TRUE); // Allegedly the error should be here
        }
    if(WR_GetPlotFlag("haupthandlung", CUTSCENE1_BEENDET))
        {
            SetPlaceableState(oClosed_door, 0);
        }

}

May I waste your time again?

#6
Sunjammer

Sunjammer
  • Members
  • 925 messages
The reason why you are getting an error is probably because you aren't including the plot's support script. Whenever you create a plot resource a support script is created (and maintained) by the toolset. The support script has the base name as the plot but with a "plt_" prefix and simply contains constants for the plot's GUID and each of the plot's flags.

If you don't include this support script then you have to use the literal value for the plot (either it's name or GUID) and the literal value for it's flags. If you do include it then you can use constants for these values which can make your script a little easier to read.

There error you are seeing is a little bit misleading: it has nothing to do with var_constants_h. What it is actually telling you is that the compiler has recursively searched all of the include files for this script and couldn't find the CUTSCENE1_BEENDET constant anywhere so it doesn't know what literal value to replace it with.

Unfortunately, while the syntax of you if statements is correct, I'm afraid the logic appears to be all wrong.

The first condition checks to see bEventHandled is still false. Since this is only set to true by the Click event it will remain false for all other placeable events. This means that as soon as the door spawns the plot flag would be set which is not what you want.

The second condition checks a different plot ("TEST" vs. "haupthandlung") so unless the value is being modified elsewhere that condition will always evaluate to false and will never run which again is not what you want.

The final thing I wanted to say is that cutscenes are not run in line. That means that although we use the PlayCutscene function to tell the game to play a cutscene "immediately" it doesn't actually do that. The script is allowed to finish and then the client switches game mode to "cutscene mode" (triggering its own event to fire and event script to run) and then the cutscene plays. This is why, for example, we tend to use the other parameters in the PlayCutscene function or use cutscene's End Script to call another script.

Modifié par Sunjammer, 29 décembre 2011 - 01:26 .


#7
Petunien

Petunien
  • Members
  • 6 messages

Sunjammer wrote...

The reason why you are getting an error is probably because you aren't including the plot's support script. Whenever you create a plot resource a support script is created (and maintained) by the toolset. The support script has the base name as the plot but with a "plt_" prefix and simply contains constants for the plot's GUID and each of the plot's flags.

If you don't include this support script then you have to use the literal value for the plot (either it's name or GUID) and the literal value for it's flags. If you do include it then you can use constants for these values which can make your script a little easier to read.

There error you are seeing is a little bit misleading: it has nothing to do with var_constants_h. What it is actually telling you is that the compiler has recursively searched all of the include files for this script and couldn't find the CUTSCENE1_BEENDET constant anywhere so it doesn't know what literal value to replace it with.


OK, now a dumb question: How do I include that plot's support script?

Sunjammer wrote...
Unfortunately, while the syntax of you if statements is correct, I'm afraid the logic appears to be all wrong.

The first condition checks to see bEventHandled is still false. Since this is only set to true by the Click event it will remain false for all other placeable events. This means that as soon as the door spawns the plot flag would be set which is not what you want.

The second condition checks a different plot ("TEST" vs. "haupthandlung") so unless the value is being modified elsewhere that condition will always evaluate to false and will never run which again is not what you want.


That's a bit embarrassing...
"TEST" is the plot I created to test things like this, "haupthandlung" (german for: main action) is the plot I want to working with finally. I forgot to change "haupthandlung" into "TEST", sry.

By the way, is it allowed to use lower case letters in the name of the plot?

Sunjammer wrote...
The final thing I wanted to say is that cutscenes are not run in line. That means that although we use the PlayCutscene function to tell the game to play a cutscene "immediately" it doesn't actually do that. The script is allowed to finish and then the client switches game mode to "cutscene mode" (triggering its own event to fire and event script to run) and then the cutscene plays. This is why, for example, we tend to use the other parameters in the PlayCutscene function or use cutscene's End Script to call another script.


Would be very nice, if you write the "endscript-part" so I can see how it works.

You notice possibly that I haven't many experience with coding (a few lines php/html) and I expect that my project will ends bad without releases, but it's very nice from you to write those helping posts.

:)

#8
Sunjammer

Sunjammer
  • Members
  • 925 messages

Petunien wrote...

OK, now a dumb question: How do I include that plot's support script?

Assuming your plot resource was "first_quest" the support script would be "plt_first_quest" and you would included it by adding the following line on or near the top of your script (before the void main() or int StartingConditional() line):
#include "plt_first_quest"

Petunien wrote...

By the way, is it allowed to use lower case letters in the name of the plot?

I believe all resource names are forced to lower case (though that might just be a habit of mine from NWN). Conversely all plot flag names are forced to upper case.

Petunien wrote...

Would be very nice, if you write the "endscript-part" so I can see how it works.

I'll try to throw something together for you. What is the resource name/tag of the NPC that will start the conversation and what is the resource name/tag of the conversation to start?

Modifié par Sunjammer, 30 décembre 2011 - 04:15 .


#9
Petunien

Petunien
  • Members
  • 6 messages

Sunjammer wrote...
I'll try to throw something together for you. What is the resource name/tag of the NPC that will start the conversation and what is the resource name/tag of the conversation to start?


I named the resource for the npc "bote" and the conversation I simply named "level1_bote".

I'm also new to the designation from resources, conversations etc. therefore the eventually bad names.

Thanks again for your answer.

#10
Sunjammer

Sunjammer
  • Members
  • 925 messages
Create a new script resource, give it an appropriate name, paste the following code into it and then save it:

#include "utility_h"

void main()
{
    object oHero = GetHero();
    object oBote = UT_GetNearestCreatureByTag(oHero, "bote");

    if(IsObjectValid(oBote))
    {
        UT_Talk(oBote, oHero, R"level1_bote.dlg");
    }
}
Then open the cutscene, click on the ellipsis (...) button in its End Script property and select your newly created script.

Export all new/updated resources and test.

Note you may want to add a stage to the conversation to force the player and NPC into the right positions. A lot will depend on where the player is in releation to the NPC when cutscene is triggered.

Modifié par Sunjammer, 31 décembre 2011 - 11:36 .


#11
Petunien

Petunien
  • Members
  • 6 messages
It works!

There are still some little things, but I'll solve them by myself...

But one question does remaining.

Suppose that I want to start a script after another one ends, is there only the possibility with the plots?
Or exists another possible solution in the form of code in the first script or something like that?

Anyway, thank you a lot!

And a good New Year!

:)

#12
Sunjammer

Sunjammer
  • Members
  • 925 messages
It really depends what you are wanting to do.

Normally scripts are triggered by objects, for example, creatures being spawned, placeables being used, triggers being entered; or by game systems, for example, conversation nodes being chosen, cutscenes ending, game modes changing, the UI used, etc.

However, if we want to run one script from another we can set a plot flag which will run the associated plot script or we generate a (standard or custom) event and use the SignalEvent function or, more commonly, the DelayEvent function.

Ultimately there are many ways to skin this particular cat!

Modifié par Sunjammer, 06 janvier 2012 - 12:34 .