// Script Name : kjs_worker_npc // Author : Kurt Jaegers (NWN Account : Krebbs) // Version : 1.10 // Date : June 22, 2002 // Description : A working routine script for shopkeepers or any other // type of NPC that can perform a fairly random set of // tasks. // // Usage : Put this script on an NPC in the OnHeartbeat code. // For each workstation the NPC will work at, you need // *BOTH* a Placeable Object and a Waypoint. // The waypoints should face the placable objects (ie, they // should be where the NPC is going to be standing while // interacting with the placeable object. // Both placables and waypoints should be named by these // standards: // // Placeable objects (workstations) : ws_NPCTAG_# // Waypoints : wsp_NPCTAG_# // // Where NPCTAG is the tag of the NPC that will follow // this routine, and # is a number starting with 1 and // incrementing upwards with no gaps (ie, 1,2,3,4,5 if you // have 5 workstations). // // Other Info : If you wish to deactivate the routine for any period of // time, simply set a local integer on the NPC called // KJ_WKS_DEACTIVATE to 1. That will disable the // process. To reactivate the process, set the local // variable back to 0. The script now detects if the NPC // is in conversation and doesn't do anything if so. // // If you wish to alter how often the NPC switches workstations // or how often the NPC performs interactions/animations, // set integers on the NPC named KJ_WKS_CHANGE_CHANCE and // KJ_WKS_ANIM_CHANCE. Both are percentage values. They // Can be set both in OnSpawn or at any time as needed. // // To make custom animations, set the following variables // in your OnSpawn script for the NPC: // Local Int : KJ_WKS_CUSTOM_ANIM set to 1 // Local Int : KJ_WKS_ANIM_COUNT set to # of animations // Local Ints: KJ_WKS_ANIM_# set to animation numbers. // Note that you can use constants to set these. // For example, : // SetLocalInt(OBJECT_SELF, "KJ_WKS_ANIM_1", ANIMATION_FIREFORGET_TAUNT); // // Versions : 1.10 - Updated to automatically not activate during conversation // 1.00 - Initial Script void main() { // Check to see if setup has already been done for this NPC. if (!(GetLocalInt(OBJECT_SELF, "KJ_WKS_SETUP")==1)) { // Determine the number of workstations int iWksCounter=0; // Counts the number of workstations object oWorkstation; // Temporary object to hold workstation info string sBuildName; // Temporary string to build workstatio names in // Assemble the first workstation name from it's parts sBuildName = "ws_" + GetTag(OBJECT_SELF) + "_" + IntToString(iWksCounter+1); // Get the first workstation oWorkstation = GetObjectByTag(sBuildName); while (GetIsObjectValid(oWorkstation)) { // Loop until we find a non-existant workstation iWksCounter++; sBuildName = "ws_" + GetTag(OBJECT_SELF) + "_" + IntToString(iWksCounter+1); oWorkstation = GetObjectByTag(sBuildName); } if (iWksCounter==0) { // No workstations were found, so shut off the routine SetLocalInt(OBJECT_SELF, "KJ_WKS_DEACTIVATE", 1); } else { // Put the number of Workstations into a local variable on the NPC SetLocalInt(OBJECT_SELF, "KJ_WKS_COUNT", iWksCounter); // Check to see if a custom workstation change chance is set. // if not, set the default. if (GetLocalInt(OBJECT_SELF, "KJ_WKS_CHANGE_CHANCE")==0) { SetLocalInt(OBJECT_SELF, "KJ_WKS_CHANGE_CHANCE", 30); } // Check to see if a custom animation chance is set. // if not, set the default. if (GetLocalInt(OBJECT_SELF, "KJ_WKS_ANIM_CHANCE")==0) { SetLocalInt(OBJECT_SELF, "KJ_WKS_ANIM_CHANCE", 55); } // Check to see if custom animations are set up. if (!(GetLocalInt(OBJECT_SELF, "KJ_WKS_CUSTOM_ANIM")==1)) { // if not, set up the defaults. They are: // 3 Animations : Steal, Get Middle, and Pause Tired SetLocalInt(OBJECT_SELF, "KJ_WKS_ANIM_COUNT",3); SetLocalInt(OBJECT_SELF, "KJ_WKS_ANIM_1", ANIMATION_FIREFORGET_STEAL); SetLocalInt(OBJECT_SELF, "KJ_WKS_ANIM_2", ANIMATION_LOOPING_GET_MID); SetLocalInt(OBJECT_SELF, "KJ_WKS_ANIM_3", ANIMATION_LOOPING_PAUSE_TIRED); } } // Indicate that setup has been completed. SetLocalInt(OBJECT_SELF, "KJ_WKS_SETUP", 1); } // If we are deactivated, don't do anything at all. if ((!(GetLocalInt(OBJECT_SELF, "KJ_WKS_DEACTIVATE")==1)) && !(IsInConversation(OBJECT_SELF))) { // Roll the dice to see if we should change workstations if (d100()<=GetLocalInt(OBJECT_SELF, "KJ_WKS_CHANGE_CHANCE")) { object oWayPoint; // Working variable to store the new waypoint if we move. string sWPtag; // String to build the tag for the new waypoint. int iCurObj; // Integer representing the Workspace # we want to use. string sInterObj; // The Workspace object we are interacting with. // Pick a random workstation to move to. iCurObj = Random(GetLocalInt(OBJECT_SELF, "KJ_WKS_COUNT"))+1; // Assemble tags for the workstation and the waypoint. sWPtag = "wsp_" + GetTag(OBJECT_SELF) + "_" + IntToString(iCurObj); sInterObj = "ws_" + GetTag(OBJECT_SELF) + "_" + IntToString(iCurObj); // Debugging info. Uncomment to see NPC talk about what they are doing. //ActionSpeakString("Changing Jobs to : " + sInterObj); // Get the waypoint and move the NPC to it. oWayPoint = GetObjectByTag(sWPtag); if ( GetIsObjectValid(oWayPoint)) { AssignCommand(OBJECT_SELF, ActionMoveToLocation(GetLocation(oWayPoint))); AssignCommand(OBJECT_SELF, ActionInteractObject(GetObjectByTag(sInterObj))); // Store the name of the workstation object as a local string on the NPC // This is used in later heartbeats to play animations. SetLocalString(OBJECT_SELF, "KJ_WKS_CURRENT", sInterObj); } } else { if (d100() <= GetLocalInt(OBJECT_SELF, "KJ_WKS_ANIM_CHANCE")) { int iAction; // The action/animation to play. int iAnimCount = GetLocalInt(OBJECT_SELF, "KJ_WKS_ANIM_COUNT"); int iRValue = iAnimCount; // What to actually roll agains. // If the workstation is a usable placeable, allow one of the // animations to be to use it via ActionInteractObject. if (GetIsPlaceableObjectActionPossible(GetObjectByTag(GetLocalString(OBJECT_SELF, "KJ_WKS_CURRENT")), PLACEABLE_ACTION_USE)) { iRValue++; } // Roll the dice. Equal chance of each animation. iAction=Random(iRValue) + 1; // Debugging info. Uncomment to see the NPC talk about animations. //ActionSpeakString("Playing Animation " + IntToString(iAction) + " of " + IntToString(iAnimCount)); if (iAction==iAnimCount+1) { // Did we roll the action to interact with the workstation? // If so, execute ActionInteractObject AssignCommand(OBJECT_SELF, ActionInteractObject(GetObjectByTag(GetLocalString(OBJECT_SELF, "KJ_WKS_CURRENT")))); } else { // If not, play the appropriate animation. AssignCommand(OBJECT_SELF, ActionPlayAnimation(GetLocalInt(OBJECT_SELF, "KJ_WKS_ANIM_" + IntToString(iAction)))); } } } } }