Aller au contenu

Photo

sitting script


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

#1
Groove Widdit

Groove Widdit
  • Members
  • 378 messages
I used the sitting script in NWN1, in which the chair tag is identified in the sitting script, which is in the creature's on-heartbeat property. How do you do this in NWN2? Is the sitting script in the list? Thanks.

#2
Tchos

Tchos
  • Members
  • 5 042 messages

The NWN1 sitting scripts don't work in NWN2, and there's not a built-in script you can call for it.  You can get a replacement sitting system on the Vault, or you can just play any of the sitting animations directly and jump the character to the location of a chair, which you can get by a unique tag, or by getting the nearest object with a chair-type tag you choose, etc.  Just keep the sitting animation playing in the character's heartbeat.

 

You can see several sitting animations and sittable chairs in use in my campaign if you want an example (there's one in the starting room, and many downstairs in the inn), and check out the scripts on them.



#3
kamal_

kamal_
  • Members
  • 5 240 messages

You might like my commoner ai package.  http://neverwinterva...ric-commoner-ai

videos of it in action:

defenders getting up to protect the pc, then sitting back down in their chairs once combat is over

day/night schedules, including selecting a home for the night.



#4
Groove Widdit

Groove Widdit
  • Members
  • 378 messages
What are the sitting animations called and where do I find them?

#5
kamal_

kamal_
  • Members
  • 5 240 messages

What are the sitting animations called and where do I find them?

may as well give you the list of animations for reference.

http://nwn2.wikia.co...t_of_animations



#6
Groove Widdit

Groove Widdit
  • Members
  • 378 messages
Thanks man. I found nw_c2_sitting. It doesn't seem to be working. I made a unique tag for the chair. What are the prefixes for the sitting animations? I assume they're on the script list.

#7
Tchos

Tchos
  • Members
  • 5 042 messages

You don't need a prefix for those.  Use the PlayCustomAnimation function and just pass in the name of the animation in that list, such as "sitidle".  Keep that list handy.  I have a copy saved.



#8
Groove Widdit

Groove Widdit
  • Members
  • 378 messages
How do you give the function sitidle? I found the functions, but I'm stalled on passing it an argument. I assume you do this in the onheartbeat script.

#9
Groove Widdit

Groove Widdit
  • Members
  • 378 messages
How do you give the function sitidle? I found the functions, but I'm stalled on passing it an argument. I assume you do this in the onheartbeat script.

#10
Groove Widdit

Groove Widdit
  • Members
  • 378 messages
Is this in script assistant?

#11
Groove Widdit

Groove Widdit
  • Members
  • 378 messages
Is this in script assistant?

#12
kevL

kevL
  • Members
  • 4 056 messages

yes.
if you put "PlayCustomAnimation" into Script Assist filter, and click 'functions' (or whatever it is), this should come up:

// FAK - OEI 5/16/05
// Returns TRUE if it found an object to play a custom animation one
// oObject is the object to play the animation on
// sAnimationName is the name of the gr2 to play
// nLooping is 0 for one-off, 1 for loop
// fSpeed is the playback speed: 1.0 is default, < 0 is backwards
int PlayCustomAnimation( object oObject, string sAnimationName, int nLooping, float fSpeed = 1.0f );

eg:

PlayCustomAnimation(oNPC, "sitidle", 1);


(there might be tricks needed, like writing a wrapper if you want to delay the command, or using "*" before the anim-string when using a combat related animation - see the link )

#13
kevL

kevL
  • Members
  • 4 056 messages

once you've assigned a looping animation, you *might* not have to recall PlayCustomAnimation each heartbeat

 

instead, when the animation should stop, call the function again and use "%" as the string - I think that means 'no animation'



#14
Tchos

Tchos
  • Members
  • 5 042 messages

I didn't know that about the "no animation" string.  I'd been telling it to play "idle" when I want the custom animation to stop.  :)

 

You don't need to call PlayCustomAnimation each heartbeat if it's looping, unless something interrupts the playback.  For instance, walking past the NPC and bumping it, or perhaps talking to it (assuming nodes are set to the default "idle" animation).  Or if it senses a hostile creature nearby.  Some of these things are solved by making the NPC unbumpable, immobile, and setting them not to turn to face the PC on dialogue.



#15
rjshae

rjshae
  • Members
  • 4 485 messages

For what it's use, here's a heartbeat script I used for seated bar patrons.

// ms_pub_sit_hb
/*
    This is a custom heartbeat script adopted from
    3030_fplace_dwarf_hb in the original campaign.
    It is used by seated, non-bark stringing NPCs.
*/
// 25apr12 RJH

#include "ginc_misc"
#include "ginc_math"
#include "ginc_wp"

const string CURR_ANIM = "CurrAnim";
const int ANIM_IDLE = 0;
const int ANIM_DRINK = 1;
const int ANIM_TALK = 2;

void PlayCustomLoopingAnimation(object oObject, string sAnimationName)
{
    PlayCustomAnimation(oObject, sAnimationName, 1);
}

void PlayCustomOneShotAnimation(object oObject, string sAnimationName)
{
    PlayCustomAnimation(oObject, sAnimationName, 0);
}

// Perform an animation of the same type
void RepeatAnim( object oActor )
{
    int nLastAnim = GetLocalInt( oActor, CURR_ANIM );
    switch ( nLastAnim ) {
        case ANIM_IDLE:
        default:
            if ( d2(1) == 1 ) {
                PlayCustomLoopingAnimation(oActor, "sitidle");
            } else {
                PlayCustomLoopingAnimation(oActor, "sitfidget");
            }
            break;
        case ANIM_DRINK:
            if ( d2(1) == 1 ) {
                PlayCustomLoopingAnimation(oActor, "sitdrink");
            } else {
                PlayCustomLoopingAnimation(oActor, "sitdrinkidle");
            }
            break;
        case ANIM_TALK:
            if ( d2(1) == 1 ) {
                PlayCustomLoopingAnimation(oActor, "sittalk01");
            } else {
                PlayCustomLoopingAnimation(oActor, "sittalk02");
            }
            break;
    }
}

// Perform a random animation
void RandomAnim( object oActor )
{
    int nNextAnim = ANIM_IDLE;
    int nRandom = d10(1);
    switch( nRandom ) {
        case 0:
            PlayCustomLoopingAnimation(oActor, "sitidle");
            break;
        case 1:
            PlayCustomLoopingAnimation(oActor, "sitfidget");
            break;
        case 2:
        case 3:
            PlayCustomLoopingAnimation(oActor, "sitdrink");
            nNextAnim = ANIM_DRINK;
            break;
        case 4:
        case 5:
            PlayCustomLoopingAnimation(oActor, "sitdrinkidle");
            nNextAnim = ANIM_DRINK;
            break;
        case 6:
        case 7:
            PlayCustomLoopingAnimation(oActor, "sittalk01");
            nNextAnim = ANIM_TALK;
            break;
        case 8:
        case 9:
            PlayCustomLoopingAnimation(oActor, "sittalk02");
            nNextAnim = ANIM_TALK;
            break;
        default:
            PlayCustomLoopingAnimation(oActor, "sitidle");
            break;
    }
    SetLocalInt( oActor, CURR_ANIM, nNextAnim );
}

void main()
{
    if (GetAILevel(OBJECT_SELF) == AI_LEVEL_VERY_LOW)
    {
        return;
    }
    
    object oActor = OBJECT_SELF;
    
    if (GetLocalInt(oActor, "SetDefaultAnimation") == 0)
    {
        AssignCommand(oActor, PlayCustomLoopingAnimation(oActor, "sitidle"));
        SetLocalInt(oActor, "SetDefaultAnimation", 1);
    }
    
    if ( d10(1) < 6 ) {
        RepeatAnim( oActor );
    } else {
        RandomAnim( oActor );
    }
}

Probably redundant at this point.



#16
4760

4760
  • Members
  • 1 204 messages

instead, when the animation should stop, call the function again and use "%" as the string - I think that means 'no animation'

I found a comment in a script (but I can't remember if that was custom or stock) explaining 

 

percent sign to set the looping animations to defaults



#17
Groove Widdit

Groove Widdit
  • Members
  • 378 messages
Okay this what I got: void main() { int PlayCustomAnimation( object oObject, "sitdrink", int nLooping, float fSpeed = 1.0f ); } When I try to compile it it gives me ERRROR PARSING VARIABLE LIST

#18
kevL

kevL
  • Members
  • 4 056 messages

void main()
{
    object oMrDrunk = OBJECT_SELF;
    PlayCustomAnimation(oMrDrunk, "sitdrink", 1);
}

see what i did thar?
that doesn't mean it'll work, but you should really look up some NwScript tutorials/ basics.

#19
Groove Widdit

Groove Widdit
  • Members
  • 378 messages
I just cut and pasted your code and...it worked! Yeah, I haven't used the 2 toolset that much, and I think the toolset manuals are not perfect in their descriptions of the proceedures to do things. I'm looking for a Teach Yourself NWN Toolset in 24 Hours book, but I can't believe there's one out there.

#20
Groove Widdit

Groove Widdit
  • Members
  • 378 messages

For what it's use, here's a heartbeat script I used for seated bar patrons.

// ms_pub_sit_hb
/*
    This is a custom heartbeat script adopted from
    3030_fplace_dwarf_hb in the original campaign.
    It is used by seated, non-bark stringing NPCs.
*/
// 25apr12 RJH

#include "ginc_misc"
#include "ginc_math"
#include "ginc_wp"

const string CURR_ANIM = "CurrAnim";
const int ANIM_IDLE = 0;
const int ANIM_DRINK = 1;
const int ANIM_TALK = 2;

void PlayCustomLoopingAnimation(object oObject, string sAnimationName)
{
    PlayCustomAnimation(oObject, sAnimationName, 1);
}

void PlayCustomOneShotAnimation(object oObject, string sAnimationName)
{
    PlayCustomAnimation(oObject, sAnimationName, 0);
}

// Perform an animation of the same type
void RepeatAnim( object oActor )
{
    int nLastAnim = GetLocalInt( oActor, CURR_ANIM );
    switch ( nLastAnim ) {
        case ANIM_IDLE:
        default:
            if ( d2(1) == 1 ) {
                PlayCustomLoopingAnimation(oActor, "sitidle");
            } else {
                PlayCustomLoopingAnimation(oActor, "sitfidget");
            }
            break;
        case ANIM_DRINK:
            if ( d2(1) == 1 ) {
                PlayCustomLoopingAnimation(oActor, "sitdrink");
            } else {
                PlayCustomLoopingAnimation(oActor, "sitdrinkidle");
            }
            break;
        case ANIM_TALK:
            if ( d2(1) == 1 ) {
                PlayCustomLoopingAnimation(oActor, "sittalk01");
            } else {
                PlayCustomLoopingAnimation(oActor, "sittalk02");
            }
            break;
    }
}

// Perform a random animation
void RandomAnim( object oActor )
{
    int nNextAnim = ANIM_IDLE;
    int nRandom = d10(1);
    switch( nRandom ) {
        case 0:
            PlayCustomLoopingAnimation(oActor, "sitidle");
            break;
        case 1:
            PlayCustomLoopingAnimation(oActor, "sitfidget");
            break;
        case 2:
        case 3:
            PlayCustomLoopingAnimation(oActor, "sitdrink");
            nNextAnim = ANIM_DRINK;
            break;
        case 4:
        case 5:
            PlayCustomLoopingAnimation(oActor, "sitdrinkidle");
            nNextAnim = ANIM_DRINK;
            break;
        case 6:
        case 7:
            PlayCustomLoopingAnimation(oActor, "sittalk01");
            nNextAnim = ANIM_TALK;
            break;
        case 8:
        case 9:
            PlayCustomLoopingAnimation(oActor, "sittalk02");
            nNextAnim = ANIM_TALK;
            break;
        default:
            PlayCustomLoopingAnimation(oActor, "sitidle");
            break;
    }
    SetLocalInt( oActor, CURR_ANIM, nNextAnim );
}

void main()
{
    if (GetAILevel(OBJECT_SELF) == AI_LEVEL_VERY_LOW)
    {
        return;
    }
    
    object oActor = OBJECT_SELF;
    
    if (GetLocalInt(oActor, "SetDefaultAnimation") == 0)
    {
        AssignCommand(oActor, PlayCustomLoopingAnimation(oActor, "sitidle"));
        SetLocalInt(oActor, "SetDefaultAnimation", 1);
    }
    
    if ( d10(1) < 6 ) {
        RepeatAnim( oActor );
    } else {
        RandomAnim( oActor );
    }
}

Probably redundant at this point.

This is useful. I want to do something like this. Now I'm trying to figure out how to get him to grab a chair.



#21
kamal_

kamal_
  • Members
  • 5 240 messages

This is useful. I want to do something like this. Now I'm trying to figure out how to get him to grab a chair.

In my commoner AI, they can establish an origin and facing on their first heartbeat. They will then return to their origin, facing, and activity automatically if they are not busy doing something else (seen for instance in the video where the elf returns to his seat once his combat is over). I did this all in heartbeat to make it as easy as possible for an inexperience builder to implement, you could also set up the origin point etc in the OnSpawn script. My ai assumes the chairs are environmental objects, they are not active objects for the player to use, however the npc is in the spot so the pc can't walk through the environmental chair, as the pc bumps into the npc who is in that space. It may not do exactly what you want, but feel free to pillage from it (with attribution of course :-) ).



#22
Groove Widdit

Groove Widdit
  • Members
  • 378 messages
Okay I will if I use it. Your village looks pretty cool. It sounds too complicated, though. I just want him to sit in the chair. The way it is, he stands up if bumped, then just sits down wherever he is, including through a barrel. Isn't there a line of code for assigning the chair's tag in the guy's script for him to sit in? Do you have to change the chair's properties, like making it usable? Thanks everybody for helping me.

#23
Tchos

Tchos
  • Members
  • 5 042 messages

You can set him to be unbumpable in his character properties.  If/when you get more comfortable with scripting, you can toggle whether he's bumpable or not, for instance to make him unbumpable only when he's in the chair.

 

The chair doesn't have to be (and shouldn't be) usable if you intend to have the NPC in that chair all the time, or else the PC may accidentally click on the chair instead of the NPC.  It would need to be a placeable and not an environmental object if you want to refer to it by its tag in a script, in which case the chair should be set to "walkable" in its properties so that the NPC can occupy the same space as the chair and sit in it.

 

There are dozens of different ways of handling sitting in a chair, and we're all giving you methods that work, but which may not necessarily work together.



#24
kevL

kevL
  • Members
  • 4 056 messages

take 2: assumes you're placing the NPC in the toolset (not spawning).

- place him in the chair with proper orientation
- on his Properties page:
    - give him an int_variable "NX2_NO_ORIENT_ON_DIALOG", set it to TRUE ( or "1")
    - make him unbumpable, in the Bumpable dropdown

you might want to clear some/most of his AI script-slots, so he just sits there drinking.*

 

 

 

* not the onSpawn or onHB, but pretty much all the others can be blank



#25
Tchos

Tchos
  • Members
  • 5 042 messages

* not the onSpawn or onHB, but pretty much all the others can be blank

 

Should keep the On Conversation, too, if you want to talk to him.