DMH-Online

Dungeon Masters Helper · Est. 2005

Npcs Scripts

NWN Script: barmaid003a.htm

Author Sticky: Post Working Scripts Here
ericksoa Posted: Tuesday, 16 July 12:59PM
NAME: Barmaid 1.1

USAGE: As described below. Make sure you have waypoints for "WP_<barmaidtag>_BAR" and "WP_<barmaidtag>_STA".

Use this on "onuserdefined":

NWScript:
//barmaid v1.1 - ericksoa, based on work by Rhodan.
//if you enhance this, and its useful, please post new version to nwn.bioware.com.  Thanx.
//also, it would be nice if you give credit to contributing authors as well :) 
//some behaviour consts
//drinking age switches
int NOMINORS_USE_DRINKING_AGE = FALSE;
int NOMINORS_DRINKING_AGE_HUMAN = 21;
int NOMINORS_DRINKING_AGE_ELF = 100;
int NOMINORS_DRINKING_AGE_HALFELF = 50;
int NOMINORS_DRINKING_AGE_GNOME = 50;
int NOMINORS_DRINKING_AGE_HALFLING = 50;
int NOMINORS_DRINKING_AGE_DWARF = 50;
int NOMINORS_DRINKING_AGE_HALFORC = 21;
string NOMINORS_GREETING = "Ah, what a cutie.  You know you are not old enough to drink the hard stuff now.";
//race service switches
int SERVE_HUMAN = TRUE;
int SERVE_ELF = TRUE;
int SERVE_HALFELF = TRUE;
int SERVE_GNOME = TRUE;
int SERVE_HALFLING = TRUE;
int SERVE_DWARF = TRUE;
int SERVE_HALFORC = FALSE;
string NO_SERVICE_RACE = "Sorry, this inn does not serve your race.  Begone!";
//reputation based service
int SERVE_ALL_REPUTATIONS = FALSE;
int REPUTATION_THRESHOLD = 30;
string NO_SERVICE_REPUTATION = "Please make yourself scarce.  You are not welcome here";
//sexual attraction switches
int WILL_FLIRT = TRUE; //determines whether barmaid/master will flirt w/customers
int ISA_HOMO = FALSE; //needs no explanation
int FLIRT_THRESHOLD1 = 15; //mild level flirting
int FLIRT_THRESHOLD2 = 18; //"wanna meet later tonight" - "meet me upstairs later" - "here's a key"
string FLIRT_HELLO1_1 = "Hello cutie :)   What can I do you for?";
string FLIRT_HELLO1_2 = "Nice to have you today.  Can I get you anything ::wink::?";
string FLIRT_HELLO1_3 = "It is my pleasure to serve you!  What would you like (besides me)?";
string FLIRT_HELLO2_1 = "Oh my god.  I have to say you are the best looking customer I have seen in these parts.  Your wish is my command.  ::whisper:: Meet me upstairs later... lets have some fun";
string FLIRT_HELLO2_2 = "I have a thing for people who look like you.  Lets meet tonight.  Can I get you a drink?";
string FLIRT_HELLO2_3 = ":::whisper::: for a good time, see me in my room tonight.  Can I get you anything?";
//repulsion switches
int WILL_BE_REPULSED = TRUE;
int REPULSION_THRESHOLD1 = 8; //ugh, can I get you a beer?
int REPULSION_THRESHOLD2 = 4; // ::barmaid throws up at the sight of you::
string REPULSED_1 = "Ugh, can I get you a drink?";
string REPULSED_2 = "Jeez, who hit you with the ugly wand.  I can see why you drink!  Let me help.";
//normal dialog
string GREETING_1 = "Is there anything I can get for you?";
string GREETING_2 = "How can I be of service?";
//available items
string ITEM1 = "Mosstone Ale";
string ITEM1_DESCRIPTION = "We have the local favorite, Mosstone Ale";
string ITEM1_TAG = "<custom item tag to be delivered>";
string ITEM2 = "Tethyrian Rum";
string ITEM2_DESCRIPTION = "If you can stand it, we also have Tethyrian Rum";
string ITEM2_TAG = "<custom item tag to be delivered>";
string ITEM3 = "Amnian Gin";
string ITEM3_DESCRIPTION = "And finally, we recommend the Amnian Gin if you are headed out adventuring";
string ITEM1_MINOR = "Milk";
string ITEM1_MINOR_DESCRIPTION = "For such a young adventurer, a nice glass of Milk";
string ITEM1_MINOR_TAG = "<custom item tag to be delivered>";
//function declarations
void main();
//object BarmaidAquireTarget(object oBarmaid, float fDistance=10.0);
//object BarmaidGetBar(object oBarmaid);
//object BarmaidGetStation(object oBarmaid);
string GetBarmaidsOrderQuery(object oBarmaid, object oTarget);
string GetBarmaidsOrderQuery(object oBarmaid, object oTarget)
{
    //based on faction/alignment/charisma/whatever, do different
    //  responses here.

    int iRace = GetRacialType(oTarget);
    int iRaceBarmaid = GetRacialType(oTarget);
    int iGender = GetGender(oTarget);
    int iBarmaidGender = GetGender(oBarmaid);
    int iRep = GetReputation(oBarmaid, oTarget);
    int iCharisma = GetAbilityScore(oTarget, ABILITY_CHARISMA);
    int iAge = GetAge(oTarget);
    int iGenderWorks = FALSE;
    if ((iGender == iBarmaidGender) && ISA_HOMO) iGenderWorks = TRUE;
    if ((iGender != iBarmaidGender) && (ISA_HOMO == FALSE)) iGenderWorks = TRUE;
    if ((SERVE_ALL_REPUTATIONS==FALSE) && (iRep < REPUTATION_THRESHOLD))
    {
        SetLocalInt(oBarmaid, "REFUSE_CURRENT_CUSTOMER", TRUE);
        return(NO_SERVICE_REPUTATION);
    }
    if ((iRace == RACIAL_TYPE_HUMAN) && (SERVE_HUMAN == FALSE))
    {
        SetLocalInt(oBarmaid, "REFUSE_CURRENT_CUSTOMER", TRUE);
        return(NO_SERVICE_RACE + "We don't serve humans.");
    }
    if ((iRace == RACIAL_TYPE_ELF) && (SERVE_ELF == FALSE))
    {
        SetLocalInt(oBarmaid, "REFUSE_CURRENT_CUSTOMER", TRUE);
        return(NO_SERVICE_RACE + "We don't serve elves.");
    }
    if ((iRace == RACIAL_TYPE_HALFELF) && (SERVE_HALFELF == FALSE))
    {
        SetLocalInt(oBarmaid, "REFUSE_CURRENT_CUSTOMER", TRUE);
        return(NO_SERVICE_RACE + "We don't serve half-elves.");
    }
    if ((iRace == RACIAL_TYPE_GNOME) && (SERVE_GNOME == FALSE))
    {
        SetLocalInt(oBarmaid, "REFUSE_CURRENT_CUSTOMER", TRUE);
        return(NO_SERVICE_RACE + "We don't serve gnomes.");
    }
    if ((iRace == RACIAL_TYPE_HALFLING) && (SERVE_HALFLING == FALSE))
    {
        SetLocalInt(oBarmaid, "REFUSE_CURRENT_CUSTOMER", TRUE);
        return(NO_SERVICE_RACE + "We don't serve halflings.");
    }
    if ((iRace == RACIAL_TYPE_DWARF) && (SERVE_DWARF == FALSE))
    {
        SetLocalInt(oBarmaid, "REFUSE_CURRENT_CUSTOMER", TRUE);
        return(NO_SERVICE_RACE + "We don't serve dwarves.");
    }
    if ((iRace == RACIAL_TYPE_HALFORC) && (SERVE_HALFORC == FALSE))
    {
        SetLocalInt(oBarmaid, "REFUSE_CURRENT_CUSTOMER", TRUE);
        return(NO_SERVICE_RACE + "We don't serve halforcs.");
    }
    if(NOMINORS_USE_DRINKING_AGE)
    {
        if ((iRace == RACIAL_TYPE_HUMAN) && (iAge < NOMINORS_DRINKING_AGE_HUMAN))
        {
            SetLocalInt(oBarmaid, "KIDMENU_CURRENT_CUSTOMER", TRUE);
            return(NOMINORS_GREETING);
        }
        if ((iRace == RACIAL_TYPE_ELF) && (iAge < NOMINORS_DRINKING_AGE_ELF))
        {
            SetLocalInt(oBarmaid, "KIDMENU_CURRENT_CUSTOMER", TRUE);
            return(NOMINORS_GREETING);
        }
        if ((iRace == RACIAL_TYPE_HALFELF) && (iAge < NOMINORS_DRINKING_AGE_HALFELF))
        {
            SetLocalInt(oBarmaid, "KIDMENU_CURRENT_CUSTOMER", TRUE);
            return(NOMINORS_GREETING);
        }
        if ((iRace == RACIAL_TYPE_GNOME) && (iAge < NOMINORS_DRINKING_AGE_GNOME))
        {
            SetLocalInt(oBarmaid, "KIDMENU_CURRENT_CUSTOMER", TRUE);
            return(NOMINORS_GREETING);
        }
        if ((iRace == RACIAL_TYPE_HALFLING) && (iAge < NOMINORS_DRINKING_AGE_HALFLING))
        {
            SetLocalInt(oBarmaid, "KIDMENU_CURRENT_CUSTOMER", TRUE);
            return(NOMINORS_GREETING);
        }
        if ((iRace == RACIAL_TYPE_DWARF) && (iAge < NOMINORS_DRINKING_AGE_DWARF))
        {
            SetLocalInt(oBarmaid, "KIDMENU_CURRENT_CUSTOMER", TRUE);
            return(NOMINORS_GREETING);
        }
        if ((iRace == RACIAL_TYPE_HALFORC) && (iAge < NOMINORS_DRINKING_AGE_HALFORC))
        {
            SetLocalInt(oBarmaid, "KIDMENU_CURRENT_CUSTOMER", TRUE);
            return(NOMINORS_GREETING);
        }
    }
    if (WILL_FLIRT && (iCharisma >= FLIRT_THRESHOLD1) && (iRace == iRaceBarmaid) && iGenderWorks)
    {
        if (WILL_FLIRT && (iCharisma >= FLIRT_THRESHOLD2) && (iRace == iRaceBarmaid) && iGenderWorks)
        {
            int iRespNum = Random(2);
            switch(iRespNum)
            {
                case 0:
                    return(FLIRT_HELLO2_1);
                    break;
                case 1:
                    return(FLIRT_HELLO2_2);
                    break;
                case 2:
                    return(FLIRT_HELLO2_3);
                    break;
            }
        }
        else
        {
            //ok, perhaps we are repulsed
            if (WILL_BE_REPULSED && (iCharisma <= REPULSION_THRESHOLD2))
            {
                 return(REPULSED_2);
            }
            else
            {
                if (WILL_BE_REPULSED && (iCharisma <= REPULSION_THRESHOLD1))
                {
                    return(REPULSED_1);
                }
            }
        }
    }
    int iGreet = Random(1);
    switch(iGreet)
    {
        case 0:
            return(GREETING_1);
        case 1:
            return(GREETING_2);
    }
    return(GREETING_1);
}
/* from failed attempt to "non-heartbeaat" this script
object BarmaidGetBar(object oBarmaid)
{
    object oBarWP = GetObjectByTag("WP_" + GetTag(oBarmaid) + "_BAR");
    return(oBarWP);
}
object BarmaidGetStation(object oBarmaid)
{
    object oBarWP = GetObjectByTag("WP_" + GetTag(oBarmaid) + "_STA");
    return(oBarWP);
}
object BarmaidAquireTarget(object oBarmaid, float fDistance=10.0)
{
    int iNth = GetLocalInt(oBarmaid, "NTH_PATRON");
    object oInvalid;
    iNth++;
    //Get this gets the iNth nearest NPC
    object oTarget = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_NOT_PC, oBarmaid, iNth);
    //SpeakString("I am looking for the " + IntToString(iNth) + " potential customer");
    //do not take orders from other barmaids
    if (GetStringLeft(GetTag(oTarget), 7) == "BARMAID")
    {
        //SpeakString("arrgh, cant serve to miself");
        //do not take orders from other barmaids
        iNth++;
        oTarget = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, oBarmaid, iNth);
    }
    //other cases like this (e.g. dont serve to the inkeep, etc.) are possible...
    //left out for simplicity the first time around
    if (GetIsObjectValid(oTarget) && (GetDistanceBetween(oBarmaid, oTarget) <= fDistance))
    {
        //SpeakString("Ahh, found a customer, the " + IntToString(iNth) + "th one");
        //iAquired = TRUE;
        //SetLocalObject(oBarmaid,"MAID_TARGET",oTarget);
        SetLocalInt(oBarmaid, "NTH_PATRON", iNth);
        return(oTarget);
                            //ActionMoveToObject(oTarget);
    }
    else
    {
        //try setting iNth back to 1, cycling
        //SpeakString("Starting from the beginning");
        iNth = 1;
        oTarget = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, oBarmaid, iNth);
        if (GetIsObjectValid(oTarget) && (GetDistanceBetween(oBarmaid, oTarget) <= fDistance))
        {
              //special case, we have cycled through all patrons
              //iAquired = TRUE;
              //SetLocalObject(OBJECT_SELF,"MAID_TARGET",oTarget);
              SetLocalInt(oBarmaid, "NTH_PATRON", iNth);
              return(oTarget);
              //ActionMoveToObject(oTarget);
        }
        else
        {
              //Ok, so there is nobody here :) 
              //SpeakString("Beer here...  beer here...");
              SetLocalInt(oBarmaid, "NTH_PATRON", 0);
              return(oInvalid);
        }
    }
    //if you got to here, you got too far!
    return(oInvalid);
}
*/
void main()
{
    // You need these outside the nEvent switch
    // So you can use the varnames in other signal events
    string sMe = GetTag(OBJECT_SELF);
    int STATUS_READY =10;
    int STATUS_BUSY=20; // do nothing-she's busy with actions
    int STATUS_FINISHED=30;
    int STAGE_AQUIRE =10; //case doesn't use vars
    int STAGE_GETORDER =20; //but put these here to
    int STAGE_WALKBAR =30; //remind you which values
    int STAGE_GETDRINK =40; //mean what
    int STAGE_DELIVERDRINK =50;
    int STAGE_GOSTATION =60;
    float BARMAID_DISTANCE_THRESHOLD=1000.0; //set this to the range you want the barmaid to work
    int IS_BARMAID_EFFICIENT = TRUE;
    object oTarget;
    object oBarWP;
    object oStaWP;
    int nEvent=GetUserDefinedEventNumber();
    switch (nEvent)
    {
        case 2005:
            //set state ready
            //SendMessageToPC(GetFirstPC(), "BARMAID - Status is ready");
            SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_READY);
            break;
        case 2006:
            //set state busy
            //SendMessageToPC(GetFirstPC(), "BARMAID - Status is busy");
            SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_BUSY);
            break;
        case 2007:
            //set state finished
            //SendMessageToPC(GetFirstPC(), "BARMAID - Status is done");
            SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_FINISHED);
            break;

        /*  if you can get this to work, w/o heartbeat, re-post!
        case 2100:
            SendMessageToPC(GetFirstPC(), "BARMAID - Aquire Target");
            //start stage 1 - Get to the next customer
            //Set busy state
            ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2006)));
            //Set the stage
            ActionDoCommand(SetLocalInt(OBJECT_SELF,"MAID_STAGE",STAGE_AQUIRE));
            //Find the customer
            oTarget = BarmaidAquireTarget(OBJECT_SELF, BARMAID_DISTANCE_THRESHOLD);
            //If valid customer is found?
            if (GetIsObjectValid(oTarget))
            {
                SendMessageToPC(GetFirstPC(), "BARMAID - Found customer");
                //we found a valid customer... set a flag saying we found one
                SetLocalInt(OBJECT_SELF,"FOUND_FIRST_CUSTOMER", TRUE);
                //Set the current target
                SetLocalObject(OBJECT_SELF,"MAID_TARGET",oTarget);
                //Move to the target
                ActionMoveToObject(oTarget, IS_BARMAID_EFFICIENT);
                //Face the target
                ActionDoCommand(SetFacingPoint(GetPositionFromLocation(GetLocation(oTarget))));
            }
            //Signal that we are finished once she clears her queue
            DelayCommand(4.0, SignalEvent(OBJECT_SELF, EventUserDefined(2007)));
            //ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2007)));
            //After signaling finished, signal that we are ready for the next phase
            ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2005)));
            //Start the next phase if the oTarget was valid
            if (GetIsObjectValid(oTarget))
            {
                ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2101)));
            }
            //Done and done
            break;
        case 2101:
            SendMessageToPC(GetFirstPC(), "BARMAID - Get Order");
            //start stage 2 - GetOrder
            //Set busy state
            ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2006)));
            //Set the stage
            ActionDoCommand(SetLocalInt(OBJECT_SELF,"MAID_STAGE",STAGE_GETORDER));
            //Start talking
            DelayCommand(4.0, ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL, 1.0, 2.0));
            //Say some words
            ActionDoCommand(SpeakString("Can I take your order, sir?"));
            //Signal that we are finished once she clears her queue
            DelayCommand(4.0, SignalEvent(OBJECT_SELF, EventUserDefined(2007)));
            //ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2007)));
            //After signaling finished, signal that we are ready for the next phase
            ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2005)));
            //After taking the order, start the next phase
            ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2102)));
            //Done and done
            break;
        case 2102:
            SendMessageToPC(GetFirstPC(), "BARMAID - Walk Bar");
            //start stage 3 - WalkBar
            //Set busy state
            ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2006)));
            //Set the stage
            ActionDoCommand(SetLocalInt(OBJECT_SELF,"MAID_STAGE",STAGE_WALKBAR));
            //Get the bar
            oBarWP = BarmaidGetBar(OBJECT_SELF);
            if (GetIsObjectValid(oBarWP))
            {
                ActionMoveToObject(oBarWP, IS_BARMAID_EFFICIENT);
                SendMessageToPC(GetFirstPC(), "BARMAID - Walk Bar");
            }
            else
            {
                ActionDoCommand(SpeakString("Perhaps the owner should buy a bar for this inn... and tag it WP_" + GetTag(OBJECT_SELF) + "_BAR"));
                //ActionDoCommand(SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_FINISHED));
            }
            //Signal that we are finished once she clears her queue
            DelayCommand(4.0, SignalEvent(OBJECT_SELF, EventUserDefined(2007)));
            //ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2007)));
            //After signaling finished, signal that we are ready for the next phase
            ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2005)));
            //After taking the order, start the next phase
            ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2103)));
            //Done and done
            break;
        case 2103:
            SendMessageToPC(GetFirstPC(), "BARMAID - Get Drink");
            //start stage 4 - GetDrink
            //Set busy state
            ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2006)));
            //Set the stage
            ActionDoCommand(SetLocalInt(OBJECT_SELF,"MAID_STAGE",STAGE_GETDRINK));
            //Say something witty at the bar
            ActionDoCommand(SpeakString("Gimme a beer, bartender (or not)"));
            //Signal that we are finished once she clears her queue
            DelayCommand(4.0, SignalEvent(OBJECT_SELF, EventUserDefined(2007)));
            //ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2007)));
            //After signaling finished, signal that we are ready for the next phase
            ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2005)));
            //After taking the order, start the next phase
            ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2104)));
            //Done and done
            break;
        case 2104:
            SendMessageToPC(GetFirstPC(), "BARMAID - Deliver Drink");
            //start stage 5 - DeliverDrink
            //Set busy state
            ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2006)));
            //Set the stage
            ActionDoCommand(SetLocalInt(OBJECT_SELF,"MAID_STAGE",STAGE_DELIVERDRINK));
            //Get the customer
            oTarget = GetLocalObject(OBJECT_SELF, "MAID_TARGET");
            //Go to the target (dont run, you have beer)
            ActionMoveToObject(oTarget);
            //Face the target
            ActionDoCommand(SetFacingPoint(GetPositionFromLocation(GetLocation(oTarget))));
            //Play a "give stuff" animation
            ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 1.0, 2.0);
            // update to actually base the selection on what was selected...
            ActionDoCommand(SpeakString("Here's your beer."));
            //Signal that we are finished once she clears her queue
            DelayCommand(4.0, SignalEvent(OBJECT_SELF, EventUserDefined(2007)));
            //ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2007)));
            //After signaling finished, signal that we are ready for the next phase
            ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2005)));
            //After taking the order, start the next phase
            ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2105)));
            //Done and done
            break;
        case 2105:
            //start stage 6 - GoBackToStation
            //Set busy state
            ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2006)));
            //Set the stage
            ActionDoCommand(SetLocalInt(OBJECT_SELF,"MAID_STAGE",STAGE_GOSTATION));
            //Get the station
            oStaWP = BarmaidGetStation(OBJECT_SELF);
            if (GetIsObjectValid(oStaWP))
            {
                ActionMoveToObject(oStaWP, IS_BARMAID_EFFICIENT);
                SendMessageToPC(GetFirstPC(), "BARMAID - Go Station");
            }
            else
            {
                ActionDoCommand(SpeakString("Perhaps the owner should place a station for this inn... and tag it WP_" + GetTag(OBJECT_SELF) + "_STA"));
                //ActionDoCommand(SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_FINISHED));
            }
            //Signal that we are finished once she clears her queue
            DelayCommand(4.0, SignalEvent(OBJECT_SELF, EventUserDefined(2007)));
            //ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2007)));
            //After signaling finished, signal that we are ready for the next phase
            ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2005)));
            //ClearAllActions();
            //After taking the order, start the next phase
            ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2100)));
            //Done and done
            break;
        */
        case 1001: // heartbeats
            int nStatus=GetLocalInt(OBJECT_SELF,"MAID_STATUS");
            int nStage=GetLocalInt(OBJECT_SELF,"MAID_STAGE");
            int iAquired = FALSE; //default, perhaps there is nobody to aquire
            if (nStatus==0) // Just started new module
            {
                nStatus=STATUS_READY;
                SetLocalInt(OBJECT_SELF,"MAID_STAGE",nStatus);
                nStage=STAGE_AQUIRE;
                SetLocalInt(OBJECT_SELF,"MAID_STAGE",nStage);
            }
            switch(nStage)
            {
                case 10: // STAGE_AQUIRE
                    if (nStatus==STATUS_READY)
                    {
                        SetLocalInt(OBJECT_SELF, "REFUSE_CURRENT_CUSTOMER", FALSE);
                        SetLocalInt(OBJECT_SELF, "KIDMENU_CURRENT_CUSTOMER", FALSE);
                        SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_BUSY);
                        int iNth = GetLocalInt(OBJECT_SELF, "NTH_PATRON");
                        iNth++;
                        object oTarget = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_NOT_PC, OBJECT_SELF, iNth);
                        //SpeakString("I am looking for the " + IntToString(iNth) + " potential customer");
                        if (GetStringLeft(GetTag(oTarget), 7) == "BARMAID")
                        {
                            //SpeakString("arrgh, cant serve to miself");
                            //do not take orders from other barmaids
                            iNth++;
                            oTarget = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, OBJECT_SELF, iNth);
                        }
                        if (GetStringLeft(GetTag(oTarget), 9) == "BARTENDER")
                        {
                            //SpeakString("arrgh, cant serve to miself");
                            //do not take orders from other barmaids
                            iNth++;
                            oTarget = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, OBJECT_SELF, iNth);
                        }
                        //other cases like this (e.g. dont serve to the inkeep, etc.) are possible...
                        //left out for simplicity the first time around
                        /*
                        if (GetIsObjectValid(oTarget))
                        {
                            SpeakString("Master, object is valid");
                        }
                        else
                        {
                            SpeakString("Master, nearest object is not valid in my view");
                        }
                        */
                        if (GetIsObjectValid(oTarget) && (GetDistanceToObject(oTarget) <= BARMAID_DISTANCE_THRESHOLD))
                        {
                            //SpeakString("Ahh, found a customer, the " + IntToString(iNth) + "th one");
                            iAquired = TRUE;
                            SetLocalObject(OBJECT_SELF,"MAID_TARGET",oTarget);
                            SetLocalInt(OBJECT_SELF, "NTH_PATRON", iNth);
                            ActionForceMoveToObject(oTarget, IS_BARMAID_EFFICIENT);
                            ActionDoCommand(SetFacingPoint(GetPositionFromLocation(GetLocation(oTarget))));
                            AssignCommand(oTarget, ActionWait(5.0));
                            AssignCommand(oTarget, SetFacingPoint(GetPositionFromLocation(GetLocation(GetObjectByTag(sMe)))));
                        }
                        else
                        {
                            //try setting iNth back to 1, cycling
                            //SpeakString("Starting from the beginning");
                            iNth = 1;
                            oTarget = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, OBJECT_SELF, iNth);
                            if (GetIsObjectValid(oTarget) && (GetDistanceToObject(oTarget) <= BARMAID_DISTANCE_THRESHOLD))
                            {
                                //special case, we have cycled through all patrons
                                iAquired = TRUE;
                                SetLocalObject(OBJECT_SELF,"MAID_TARGET",oTarget);
                                SetLocalInt(OBJECT_SELF, "NTH_PATRON", iNth);
                                ActionForceMoveToObject(oTarget, IS_BARMAID_EFFICIENT);
                                ActionDoCommand(SetFacingPoint(GetPositionFromLocation(GetLocation(oTarget))));
                                AssignCommand(oTarget, ActionWait(5.0));
                                AssignCommand(oTarget, SetFacingPoint(GetPositionFromLocation(GetLocation(GetObjectByTag(sMe)))));
                            }
                            else
                            {
                                //Ok, so there is nobody here :) 
                                //SpeakString("Beer here...  beer here...");
                                SetLocalInt(OBJECT_SELF, "NTH_PATRON", 0);
                            }
                        }
                        if (iAquired)
                            // we can move to finished and start serving someone only if there is
                            // someone to serve
                            ActionDoCommand(SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_FINISHED));
                        else
                            //otherwise, reset to ready and try again in 6 seconds
                            ActionDoCommand(SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_READY));
                    }
                    if (nStatus==STATUS_FINISHED)
                    {
                        SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_READY);
                        SetLocalInt(OBJECT_SELF,"MAID_STAGE",STAGE_GETORDER);
                    }
                    break;
                case 20: // STAGE_GETORDER
                    if (nStatus==STATUS_READY)
                    {
                        SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_BUSY);
                        object oTarget = GetLocalObject(OBJECT_SELF, "MAID_TARGET");
                        //do your animations etc
                        ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL, 1.0, 2.0);
                        ActionDoCommand(SpeakString(GetBarmaidsOrderQuery(OBJECT_SELF, oTarget)));
                        //mention the items as appropriate
                        if (GetLocalInt(OBJECT_SELF,"REFUSE_CURRENT_CUSTOMER"))
                        {
                            //set it up as if we already delivered the drink
                            ActionDoCommand(SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_READY));
                            ActionDoCommand(SetLocalInt(OBJECT_SELF,"MAID_STAGE",STAGE_DELIVERDRINK));
                        }
                        else
                        {
                            //do more stuff
                            //mention the items as appropriate
                            if (GetLocalInt(OBJECT_SELF,"KIDMENU_CURRENT_CUSTOMER"))
                            {
                                ActionDoCommand(SpeakString(ITEM1_MINOR_DESCRIPTION));
                            }
                            else
                            {
                                ActionWait(3.0);
                                ActionDoCommand(SpeakString(ITEM1_DESCRIPTION));
                                ActionWait(3.0);
                                ActionDoCommand(SpeakString(ITEM2_DESCRIPTION));
                                ActionWait(3.0);
                                ActionDoCommand(SpeakString(ITEM3_DESCRIPTION));
                                ActionWait(3.0);
                                int iDrink = Random(2);
                                AssignCommand(oTarget, ActionWait(8.0));
                                switch(iDrink)
                                {
                                    case 0:
                                        AssignCommand(oTarget, DelayCommand(8.0, SpeakString("I'll have " + ITEM1)));
                                        break;
                                    case 1:
                                        AssignCommand(oTarget, DelayCommand(8.0, SpeakString("A " + ITEM2 + " sounds good!")));
                                        break;
                                    case 2:
                                        AssignCommand(oTarget, DelayCommand(8.0, SpeakString("Please bring me a " + ITEM3)));
                                        break;
                                }
                                SetLocalInt(OBJECT_SELF, "DRINK_CHOSEN", iDrink);
                                ActionWait(3.0);
                                ActionDoCommand(SpeakString("Coming right up!"));
                            }
                            ActionDoCommand(SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_FINISHED));
                        }
                    }
                    if (nStatus==STATUS_FINISHED)
                    {
                        SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_READY);
                        SetLocalInt(OBJECT_SELF,"MAID_STAGE",STAGE_WALKBAR);
                    }
                    break;
                case 30: // STATE WALKBAR
                    if (nStatus==STATUS_READY)
                    {
                        SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_BUSY);
                        //Get a Waypoint for going to the bar, or if "object invalid", say that there is no bar, and that
                        //  perhaps the owner of the place should buy one
                        //if you make your bar waypoint in the manner of WP_<your waitresstag>_BAR you are in good shape
                        object oBarWP = GetObjectByTag("WP_" + GetTag(OBJECT_SELF) + "_BAR");
                        if (GetIsObjectValid(oBarWP)==FALSE)
                        {
                            ActionDoCommand(SpeakString("Perhaps the owner should buy a bar for this inn... and tag it WP_" + GetTag(OBJECT_SELF) + "_BAR"));
                        }
                        else
                        {
                            ActionForceMoveToObject(oBarWP, IS_BARMAID_EFFICIENT);
                            ActionDoCommand(SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_FINISHED));
                        }
                    }
                    if (nStatus==STATUS_FINISHED)
                    {
                        SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_READY);
                        SetLocalInt(OBJECT_SELF,"MAID_STAGE",STAGE_GETDRINK);
                    }
                    break;
                case 40: //STAGE_GETDRINK
                    if (nStatus==STATUS_READY)
                    {
                        SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_BUSY);
                        object oTarget = GetLocalObject(OBJECT_SELF, "MAID_TARGET");
                        //do your animations etc
                        //at some point, this should do something like say "give me a <what they ordered>"
                        int iDrinkChosen = GetLocalInt(OBJECT_SELF, "DRINK_CHOSEN");
                        switch(iDrinkChosen)
                        {
                            case 0:
                                ActionDoCommand(SpeakString("Please give me a " + ITEM1));
                                break;
                            case 1:
                                ActionDoCommand(SpeakString("I need a " + ITEM2));
                                break;
                            case 2:
                                ActionDoCommand(SpeakString("Load me up with a " + ITEM3));
                                break;
                        }
                        ActionWait(2.0);
                        ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 1.0, 2.0);
                        ActionDoCommand(SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_FINISHED));
                    }
                    if (nStatus==STATUS_FINISHED)
                    {
                        SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_READY);
                        SetLocalInt(OBJECT_SELF,"MAID_STAGE",STAGE_DELIVERDRINK);
                    }
                    break;
                case 50: //STAGE_DELIVER_DRINK
                    if (nStatus==STATUS_READY)
                    {
                        SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_BUSY);
                        object oTarget = GetLocalObject(OBJECT_SELF, "MAID_TARGET");
                        ActionForceMoveToObject(oTarget);
                        // update to actually base the selection on what was selected...
                        ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 1.0, 2.0);
                        int iDrinkChosen = GetLocalInt(OBJECT_SELF, "DRINK_CHOSEN");
                        switch(iDrinkChosen)
                        {
                            case 0:
                                ActionDoCommand(SpeakString("Here's your " + ITEM1));
                                break;
                            case 1:
                                ActionDoCommand(SpeakString("Enjoy your " + ITEM2));
                                break;
                            case 2:
                                ActionDoCommand(SpeakString("Your " + ITEM3 + " is ready!"));
                                break;
                        }
                        int iTargetSits = GetLocalInt(oTarget, "SITS_DOWN");
                        if (iTargetSits)
                        {
                            object oMychair = GetNearestObjectByTag("chair", oTarget);
                            AssignCommand(oTarget, DelayCommand(4.0, ActionSit(oMychair)));
                        }
                        ActionDoCommand(SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_FINISHED));
                    }
                    if (nStatus==STATUS_FINISHED)
                    {
                        SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_READY);
                        SetLocalInt(OBJECT_SELF,"MAID_STAGE",STAGE_GOSTATION);
                    }
                    break;
                case 60: //STAGE_GO_STATION
                    if (nStatus==STATUS_READY)
                    {
                        //Get a Waypoint for going to the station, or if "object invalid", say that there is no station, and that
                        //  perhaps the owner of the place should set one
                        //if you make your station waypoint in the manner of WP_<your waitresstag>_STA you are in good shape
                        object oStaWP = GetObjectByTag("WP_" + GetTag(OBJECT_SELF) + "_STA");
                        SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_BUSY);
                        if (GetIsObjectValid(oStaWP)==FALSE)
                        {
                            ActionDoCommand(SpeakString("Perhaps the owner should give me a station in this inn... and tag it WP_" + GetTag(OBJECT_SELF) + "_STA"));
                        }
                        else
                        {
                            ActionForceMoveToObject(oStaWP);
                            ActionDoCommand(SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_FINISHED));
                        }
                    }
                    if (nStatus==STATUS_FINISHED)
                    {
                        SetLocalInt(OBJECT_SELF,"MAID_STATUS",STATUS_READY);
                        SetLocalInt(OBJECT_SELF,"MAID_STAGE",STAGE_AQUIRE);
                    }
                    break;
        }
        break;
   }
}



Use this on "onspawn":

NWScript:
//::///////////////////////////////////////////////
//:: Default: On Spawn In
//:: NW_C2_DEFAULT9
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
    Determines the course of action to be taken
    after having just been spawned in
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Oct 25, 2001
//:://////////////////////////////////////////////
#include "NW_O2_CONINCLUDE"
#include "NW_I0_GENERIC"
void main()
{
// OPTIONAL BEHAVIORS (Comment In or Out to Activate ) ****************************************************************************
     //SetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION);
     //SetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION);
                // This causes the creature to say a special greeting in their conversation file
                // upon Perceiving the player. Attach the [NW_D2_GenCheck.nss] script to the desired
                // greeting in order to designate it. As the creature is actually saying this to
                // himself, don't attach any player responses to the greeting.
     //SetSpawnInCondition(NW_FLAG_SHOUT_ATTACK_MY_TARGET);
                // This will set the listening pattern on the NPC to attack when allies call
     //SetSpawnInCondition(NW_FLAG_STEALTH);
                // If the NPC has stealth and they are a rogue go into stealth mode
     //SetSpawnInCondition(NW_FLAG_SEARCH);
                // If the NPC has Search go into Search Mode
     //SetSpawnInCondition(NW_FLAG_SET_WARNINGS);
                // This will set the NPC to give a warning to non-enemies before attacking
     //SetSpawnInCondition(NW_FLAG_SLEEP);
                //Creatures that spawn in during the night will be asleep.
     //SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
     //SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
     //SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
     //SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
                //This will play Ambient Animations until the NPC sees an enemy or is cleared.
                //NOTE that these animations will play automatically for Encounter Creatures.
    // NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
    //SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN);    // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
    //SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE);     // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
    //SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE);   // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
    //SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN);  // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
// CUSTOM USER DEFINED EVENTS
/*
    The following settings will allow the user to fire one of the blank user defined events in the NW_D2_DefaultD.  Like the
    On Spawn In script this script is meant to be customized by the end user to allow for unique behaviors.  The user defined
    events user 1000 - 1010
*/
    SetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT);        //OPTIONAL BEHAVIOR - Fire User Defined Event 1001
    //SetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT);         //OPTIONAL BEHAVIOR - Fire User Defined Event 1002
    //SetSpawnInCondition(NW_FLAG_ATTACK_EVENT);           //OPTIONAL BEHAVIOR - Fire User Defined Event 1005
    //SetSpawnInCondition(NW_FLAG_DAMAGED_EVENT);          //OPTIONAL BEHAVIOR - Fire User Defined Event 1006
    //SetSpawnInCondition(NW_FLAG_DISTURBED_EVENT);        //OPTIONAL BEHAVIOR - Fire User Defined Event 1008
    //SetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1003
    //SetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT);      //OPTIONAL BEHAVIOR - Fire User Defined Event 1004
    //SetSpawnInCondition(NW_FLAG_DEATH_EVENT);            //OPTIONAL BEHAVIOR - Fire User Defined Event 1007
    SetSpawnInCondition(2005); // for "barmaid is ready" event after some *** bothers her.
    SetSpawnInCondition(2006);
    SetSpawnInCondition(2007);
    //SetSpawnInCondition(2100);
    //SetSpawnInCondition(2101);
    //SetSpawnInCondition(2102);
    //SetSpawnInCondition(2103);
    //SetSpawnInCondition(2104);
    //SetSpawnInCondition(2105);
// DEFAULT GENERIC BEHAVIOR (DO NOT TOUCH) *****************************************************************************************
    SetListeningPatterns();    // Goes through and sets up which shouts the NPC will listen to.
    WalkWayPoints();           // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
                               // 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
                               // 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
                               //    combat.
    GenerateNPCTreasure();     //* Use this to create a small amount of treasure on the creature
    //DelayCommand(5.0, ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2005))));
    //ActionDoCommand(SignalEvent(OBJECT_SELF, EventUserDefined(2100)));
}



And this in the abort and end conversation events in the barmaids dialog:

NWScript:
void main()
{
    SignalEvent(OBJECT_SELF, EventUserDefined(2005));
}



And that should do it. Please excuse the cheesy dialog.

⌂ All Scripts ← PreviousNext → 👁 Category List

All Npcs Scripts

📄 ambient_animations 📄 barmaid 📄 barmaid002 📄 barmaid003 📄 barmaid003a 📄 barmaid004 📄 bitch_slap 📄 blacksmith 📄 blacksmith_001 📄 blacksmith_002 📄 blacksmith_003 📄 bounty_hunter 📄 check 📄 check_pc_item 📄 check_pc_item_002 📄 cheer_pcs 📄 cook 📄 daily_activity 📄 day_merchant 📄 determine_armed 📄 drunk 📄 equip_dequip 📄 equip_dequip_002 📄 escort 📄 flee 📄 flee_001 📄 force_pc_sit 📄 gate_guard 📄 get_nearest 📄 guard_dog_002 📄 guard_patrol 📄 healer 📄 impersonation 📄 item_guardian 📄 item_guardian_002 📄 jail_cell 📄 janitor 📄 janitor_002 📄 living_statues 📄 misc_activity 📄 monolouge 📄 multi_converse 📄 night_watch 📄 npc_brawls 📄 npc_pick_pocket 📄 npc_speak_onperception 📄 npc_start_conv 📄 npc_start_conv_002 📄 npc_start_conv_003 📄 npc_start_conv_004 📄 npc_start_conv_005 📄 open_door 📄 polymorph 📄 prostitute 📄 protect_items 📄 protect_items_002 📄 random_speak 📄 random_speak_002 📄 random_speak_003 📄 random_speak_004 📄 random_speak_005 📄 random_walk2 📄 reinforcements 📄 reinforcements_002 📄 remember_conv 📄 rowdy 📄 sheath_weapons 📄 sit_and_talk 📄 sit_and_talk_002 📄 sit_in_nearest_chair 📄 smart_npc 📄 smart_sitting 📄 streetfight 📄 tag 📄 tag_001a 📄 teleport_away 📄 teleport_away_002 📄 teleport_away_003 📄 town_crier 📄 trivia_bot 📄 walk_after 📄 woodcutter 📄 worker 📄 worker_002 📄 workstation 📄 wrestling_game