diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 2.3.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 2.3.lsl new file mode 100644 index 00000000..dc2c350f --- /dev/null +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 2.3.lsl @@ -0,0 +1,1686 @@ +// :SHOW:1 +// :CATEGORY:NPC +// :NAME:All In One NPC Recorder and Player +// :AUTHOR:Ferd Frederix +// :KEYWORDS: +// :CREATED:2013-09-08 18:27:47 +// :EDITED:2015-05-29 11:25:14 +// :ID:27 +// :NUM:1612 +// :REV:2.3 +// :WORLD:OpenSim +// :DESCRIPTION: +// All in one NPC recorder player. +// Supports both absolute and relative paths and many new commands +// Add animations named "Fly, Walk, Stand and Run" +// Click Prim to use. +// Should be worn as a HUD to record. +// Put it on the ground and click Sensor or Start NPC when done. +// :CODE: +// This is Rev 2.2 5/17/2015 + +// Revision History +// Rev 1.1 10-2-2014 @Sit did not work. Minor tweaks to casting for lslEditor +// Rev 1.2 10-14-2014 @ sit had wrong type. +// Rev 1.3 relative movement fixed for @fly +// Rev 1.4 4-3-2014 allow anyone to use this, non owners and non group members can only start and stop. +// Rev 1.5 5-17-2014 set sensor to auto start on reboot of sim +// Rev 1.6 5-24-2014 move menu so you can get it by touching, removed many of the KeyValues to RAM for efficiency +// Rev 1.7 CHANGED_REGION_RESTART, not CHANGED_REGION_START (Opensim difference) +// Rev 1.8 tuned up Kill NPC, added more flexible upgrader +// Rev 1.9 Better script injection by link message// Rev 2.0 Added osSetSpeed so you can speed up or slow down an NPC. +// Rev 2.1 No laggy sensor used exept to sit on stuff +// Rev 2.2 Various sensor fixes +// Rev 2.3 Sets No Sensorin menu, must be started by hand +//*******************************************************************// + +// Instructions on how to use this is at http://www.outworldz.com/opensim/posts/NPC/ +// This is an OpenSim-only script. +// Author: Ferd Frederix aka Fred Beckhusen - fred@mitsi.com + +//////////////////////////////////////////////////////////////////////////////////////////// +// Original code was Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // +/////////////////////////////////////////////////////////////////////////////////////////// +// Please see: http://www.gnu.org/licenses/gpl.html for legal details, // +// rights of fair usage, the disclaimer and warranty conditions. // +/////////////////////////////////////////////////////////////////////////////////////////// +// The original NPC controller was from http://was.fm/opensim:npc +// Extensive additions and bug fixes by Fred Beckhusem, aka Ferd Frederix, fred@mitsi.com +// llSensor had two params swapped +// @Wander would wander where it had rezzed, not where it was. +// There was no 'no_sensor' event in sit, so if a @sit failed, the NPC got stuck +// The animation and walks always stopped old, then started new. It should be start new, then stop old so the default stand would be suppressed. +// New code: +// Merged with new Route recorder and notecard writer +// If the NPC failed to reach a destination it never moved on. Added WAIT global to tune this +// Exposed many tunable variables and ported the code to LSLEditor. +// Added floating point to times in notecard. + +// Added @sound, @randsound, @whisper, @shout, and @cmd controls. +// +// notecards integers are not floats for better control +// +// Link Messages may be used to perform external control by injecting @commands into the stream of actions +// Example: +// To chat something, such as with a chat robot +// llMessageLinked(LINK_SET,0,"@npc_say=Hello",""); + +// This script assumes that NPCs and OSSl scripting is enabled in the OpenSim configuration. +// In order to enable them, the following changes must be made in the OpenSim.ini configuration file: +// +// ; Turn on OSSL +// AllowOSFunctions = true +// OSFunctionThreatLevel = Severe + +//[NPC] +// ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} +// Enabled = true +// +// and then the server has to be restarted. + + +// Commands: All commands begin with an @ sign. All other lines are ignored +// @commands may have optional parameters. The syntax is always: +// @cmd=parm1|parm2 +// NaN in the table below meand Not a Number. This means there is no parameter + +//Command First Parameter Second Parameter Description +//@spawn name location (vector) Rezzes an NPC with name at a location. +//@walk destination (vector) NaN Makes the NPC walk to destination. +//@fly destination (vector) NaN Makes the NPC fly to destination. +//@land destination (vector) NaN Makes the NPC land at destination. +//@say string NaN Makes the NPC speak a phrase. +//@whisper string NaN Makes the NPC whisper a phrase. +//@shout string NaN Makes the NPC shout a phrase. +//@pause seconds (float) NaN Makes the NPC wait for a multiple of seconds. +//@wander radius (float) cycles (integer) Makes the NPC wander in radius, for cycles seconds. +//@delete NaN NaN Removes the NPC. Rerquires a link message of @npc_start to continue +//@npc_start NaN NaN Starts the NPC at the beginning +//@animate animation (string) time (float) Makes the NPC trigger the animation animation for time seconds. +//@goto label (string) NaN Jump to the label label in the script. +//@rotate degrees (float) NaN Rotate the NPC degrees around the Z axis. +//@sit primitive name NaN Sit on a primitive with a given name. +//@stand NaN NaN If sitting on a primitive, stand up. +//@sound sound_name NaN plays a sound from inventory +//@randsound NaN NaN Plays a random sound from inventory +//@cmd channel (integer) string Says string on channel, for controlling external gadgets + +//@stop NaN NaN Halts the NPC script indefinitely. Can be started with a link message +//@go NaN NaN Continues on next notecard line, for use in link messages + + +////////////////////////////////////////////////////////// +// DEBUG // +////////////////////////////////////////////////////////// +integer debug = FALSE; // set to TRUE or FALSE for debug chat on various actions +integer Editor = FALSE; // set to to TRUE to working in LSLEditor, FALSE for in-world. + // you must also include the NPC commands found in the other script since LSLEditor does not support OpenSim +integer iTitleText = TRUE; // set to TRUE to see debug info in text above the controller + +////////////////////////////////////////////////////////// +// TUNABLE CONFIGURATION // +////////////////////////////////////////////////////////// +integer allowUsers = FALSE; // If true, any user can get a Start NPC and Stop NPC menu. Only groups and owners can get all commands if TRUE, or FALSE +float MAXDIST = 2.0; // how close a NPC has to get to a dest pos to continue to next state. Do not lower this too much, as it may miss the target +float TIMER = 0.5; // how often the system checks the distance traveled. Fastest you can go is 0.5 seconds +integer WANDERRAND = TRUE; // set to TRUE and they will pause during wanders a random number of seconds +float WANDERTIME = 10.0; // how long they stand after each @wander,if WANDERRAND is FALSE. If WANDERRAND is TRUE, this is the max time +integer WAIT = 20; // wait for this number of seconds for the NPC to reach a destination (for safety). If it fails to reach a target, it will move on after this time. +float RANGE = 96.0; // 1 to N meters - anyone this close to the controller will start NPCS if Sensor button is clicked +float REZTIME = 10.0; // wait this long for NPC to rez in, then start the process +string STAND = "Stand"; // the name of the default Stand animation +string WALK = "Walk"; // the name of the default Walk animation +string FLY = "Fly"; // the name of the default Fly animation +string RUN = "Run"; // the name of the default Run animation +string LAND = "Land"; // the name of the default land animation ( for birds only) +float OffsetZ = 0.5; // appear 0.5 meter above ground, this is added to all destinations to keep them from sinking in. For fun, make this large and watch them fall out of the sky +float SPEEDMULT = 0.8; // 1.0 = regular vatar speed. Smaller numbers slow down walks. Large numbers speed them up. + + +// DESCRIPTIONS FIELDS HAVE TO SURVIVE A RESET +// These vars are stored by saving them with KeyValueSet +// "pr" is a 0 if it is set for Owner Only, 1 for Group control +// "se" is "on" if Started +// "co" = "R" or "A" for relative or absolute addressing mode +// "key" = NPC key + +// These Globals used to be stored in description. Moved to RAM in V1.6 +float RAMPause; // @pause param +float RAMwd ; // @wander distance +integer RAMwc; // @wander count +float RAMrot; // @rotate +string RAMsit; // @sit primname +string RAManimationName; // @animate animation (string) time (float) +float RAManimationTime; + +// other globals section +integer iChannel; // a listen channel, randomly assigned +integer iHandle; // the handle to it + +// NPC controls +vector newDest ; // tmp storage for the walks +integer iWaitCounter ; // wait for this number of seconds for the NPC to reach a desrtination +string sNPCName; // the name of the NPC that may be in world. So we can remove it. +integer bNPC_STOP = FALSE; // boolean to reuse a listener +integer bForget = FALSE; // set to TRUE by link messages so we do not remember them +float fTimerVal ; // how long we wait when wandering (calculated) + +// OS_NPC_CREATOR_OWNED will create an 'owned' NPC that will only respond to osNpc* commands issued from scripts that have the same owner as the one that created the NPC. +// OS_NPC_NOT_OWNED will create an 'unowned' NPC that will respond to any script that has OSSL permissions to call osNpc* commands. +integer NPCOptions = OS_NPC_CREATOR_OWNED; // only yhe owner of this box can control this NPC. + +integer walkstate = 0; // helps us reshare the walk state for run, fly and land - a bit of a hack, but it saves RAM. Has to be done this way because some bits of NPCWalkOption are asserted as 0 + +integer NPCWalkOption; // Some notes for what happens to NPCWalkOption: +// OS_NPC_FLY - Fly the avatar to the given position. The avatar will not land unless the OS_NPC_LAND_AT_TARGET option is also given. +// OS_NPC_NO_FLY - Do not fly to the target. The NPC will attempt to walk to the location. If it's up in the air then the avatar will keep bouncing hopeless until another move target is given or the move is stopped +//OS_NPC_LAND_AT_TARGET - If given and the avatar is flying, then it will land when it reaches the target. If OS_NPC_NO_FLY is given then this option has no effect. +// OS_NPC_RUNNING - if given, NPC avatar moves at running/fast flying speed, otherwise moves at walking/slow flying speed. + +// menus +string mSensor="Sensor"; // Sensor or "No Sensor" +integer showMenu = FALSE; // when we switch states, we need to bring up a menu +list lAtButtons = ["Menu","-", "More", "@run","@walk","@fly", "@land","@wander","@sit", "@stand","@animate","@rotate"]; +list lMenu2 = ["<<", "@comment", "@stop", "@say","@whisper","@shout", "@sound","@randsound", "-", "@cmd", "@pause", "@delete" ]; +string sCommand; // place to store a command for two-prompted ones +string sParam2; // place to store a prompt for two-prompted ones +string priPub = "Owner Only"; // Private or Group +key kUserKey; // the person who is controlling the avatar, not the Owner + +// the command lists +list lCommands; // commands are stored here +list lNPCScript; // Storage for the NPC script. +string npcAction; // Storage for the next action. @cmd=0|hello, this becomes @cmd +string npcParams; // Storage for the param, @cmd=0|hello, this becomes 0|hello + +// misc vars +string sNotecard; // commands are stored here temporarily for dumping +vector vWanderPos; // a place to wander to +string lastANIM ; // last animation run +// Sensor +integer avatarPresent; // Sensor sets this flag when people are within Range. + +// Coordinate control +vector vInitialPos ; // Vector that will be filled by the script with the initial starting position in region coordinates. +vector vDestPos = ZERO_VECTOR; // Storage for destination position. +string relAbs = "Relative"; // absolute vs relative positioning + +/////////////////////////////////////////////////////////////////////////// +// FUNCTIONS // +/////////////////////////////////////////////////////////////////////////// + + +// DEBUG(string) will chat a string or display it as hovertext if debug == TRUE +DEBUG(string str) +{ + if (debug) + llOwnerSay( str); // Send the owner debug info so you can chase NPCS + if (iTitleText) + { + llSleep(0.1); + llSetText(str,<1.0,1.0,1.0>,1.0); // show hovertext + } +} + +integer SenseAvatar() +{ + //Returns a strided list of the UUID, position, and name of each avatar in the region except the owner. + list avatars = llGetAgentList(AGENT_LIST_REGION ,[]); + integer numOfAvatars = llGetListLength(avatars); + if (numOfAvatars == 0) + { + DEBUG("No people"); + return 0; + } + DEBUG("Located " + (string)numOfAvatars + " avatars"); + + integer nAvatars; + integer i; + for( i = 0;i < numOfAvatars; i++) { + key aviKey = llList2Key(avatars,i); + if (!osIsNpc(aviKey)) { + list detail = llGetObjectDetails(aviKey,[OBJECT_POS]); + vector pos = llList2Vector(detail,0); + float dist = llVecDist(pos, llGetPos()); + if (dist < RANGE) + { + nAvatars++; + DEBUG("In range:" + llKey2Name(aviKey)); + } + } + } + DEBUG("Located " + (string) nAvatars + " avatars"); + return nAvatars; +} + +// return TRUE if the avatar is owner when private is set, or TRUE if the avatar is in th same group and GROUP is set. +integer checkPerms() { + + integer group = (integer) KeyValueGet("pr"); + if (! group) + priPub = "Owner Only"; + else + priPub = "Group"; + + + if (llDetectedKey(0) == llGetOwner()){ + kUserKey = llDetectedKey(0); + return TRUE; + } + + if ( group && llDetectedGroup(0)) { + kUserKey = llDetectedKey(0); + return TRUE; + } + kUserKey = llDetectedKey(0); + return FALSE; +} + + + +NPCStart(string anim) +{ + DEBUG(" Start Anim: " + anim); + if (llGetInventoryType(anim) == INVENTORY_ANIMATION ) { + + if (lastANIM != anim) { + osNpcPlayAnimation(NPCKey(), anim); + + if(llStringLength(lastANIM) && llGetInventoryType(lastANIM) == INVENTORY_ANIMATION) { + osNpcStopAnimation(NPCKey(), lastANIM) ; + } + + lastANIM = anim; + } + } else { + llSay(DEBUG_CHANNEL, "No animation named " + anim); + } +} + + +TimerEvent(float timesent) +{ + //DEBUG("Setting timer: " + (string) timesent); + llSetTimerEvent(timesent); +} + + + +ProcessLink(string str) +{ + // DEBUG("Processing exern cmd : " + str); + bForget = TRUE; // tell the NPCProcess state to forget this command after processing it. + lNPCScript = llListInsertList(lNPCScript,[str],0); // add this command to the beginning of the list of commands + NPCStart(STAND); +} + +// Kill a NPC by Name +Kill(string param) +{ + + integer count; + + list avatars = osGetAvatarList(); // Returns a strided list of the UUID, position, and name of each avatar in the region except the owner. + + integer i; + integer j = llGetListLength(avatars); + for (i=0 ; i <= j; i+=3){ + + string desired = llList2String(avatars,i+2); + desired = llStringTrim(desired,STRING_TRIM); // should not be needed but is needed + + if (desired == param){ + vector v = llList2Vector(avatars,i+1); + key target = llList2Key(avatars,i); // get the UUID of the avatar + osNpcRemove(target); + KeyValueSet("key", NULL_KEY ); + llOwnerSay("Removed " + param+ " at location " + (string) v); + count++; + } + } + if (count) + llOwnerSay("Removed " + (string) count + " NPC's"); + else + llOwnerSay("Could not locate " + param); +} + + +// return a String for the position we are at. Strings used as the caller wants strings +string Pos() +{ + vector where = llGetPos(); // find the box position + + where.z += OffsetZ; // use the ground position + an offset + + if (Editor) + where = <128,128,31 + llFrand(1)>; // center of sim for editing + + // if attached the height will be too high by 1/2 the agent size + if (llGetAttached()) { + vector size = llGetAgentSize(llGetOwner()); + float Z = size.z; + where.z -= Z/2; + } + + // DEBUG("Pos= " + (string) where); + return (string) where; +} + +Expire() +{ + llOwnerSay("Menu expired"); + iHandle = 0; + TimerEvent(0.0); +} + +// setup a menu with a timer for timeouts, called by all make*() +menu() +{ + llListenRemove(iHandle); + iChannel = llCeil(llFrand(100000) + 20000); + iHandle = llListen(iChannel,"","",""); + TimerEvent(120.0); +} + + +// make a text box +makeText(string Param) +{ + menu(); + llTextBox(kUserKey, Param, iChannel); +} + +// top level menu +makeMainMenu() +{ + menu(); + list buttons = ["Appearance","Recording","Save","Help","-","Erase RAM", priPub,relAbs,"-","Stop NPC",mSensor,"Start NPC"]; + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Recordings",buttons,iChannel); +} + + +// Rev 1.4 +// top level menu for non group/ non owners +makeUserMenu() +{ + if (!allowUsers) + return; + menu(); + list buttons = ["Start NPC","Stop NPC"]; + llDialog(kUserKey,"Choose",buttons,iChannel); +} + + + +// programmable menu for @commands +makeMenu(list buttons) +{ + menu(); + llDialog(kUserKey,(string) llGetListLength(lCommands) + "Recordings",buttons,iChannel); +} + + + + +// make one or two text boxes with prompts +Text(string cmd, string p1, string p2) +{ + sCommand = cmd; + sParam2 = ""; + if (llStringLength(p2)) + sParam2 = p2; + + makeText(p1); +} + +// Set the Avatar Present flag - if sensors are off and we are forece run, there will be one present. +ProcessSensor() +{ + integer SensorOn; + if ("on" == KeyValueGet("se")) + { + SensorOn = TRUE; // we need to scan for avatars + } else { + SensorOn = FALSE; // we need to scan for avatars + } + DEBUG("Sensor:" + (string) SensorOn); + + integer n = SenseAvatar(); + + if (SensorOn && n) + avatarPresent = TRUE; // someone is here and we need to tell the system to run + else if (SensorOn && !n) + avatarPresent = FALSE; // someone is not here and we need to tell the system to stop + else + avatarPresent = TRUE; // someone is effectivley always here when sensor is off and we are running + + DEBUG("Avatar Present: " + (string) avatarPresent); +} + +vector CirclePoint(float radius) { + float x = llFrand(radius *2) - radius; // +/- radius, randomized + float y = llFrand(radius *2) - radius; // +/- radius, randomized + return ; // so this should always happen +} + +string KeyValueGet(string var) { + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k != var) jump continue; + //DEBUG("got " + var + " = " + llList2String(data, 1)); + return llList2String(data, 1); + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + return ""; +} + +KeyValueSet(string var, string val) { + + //DEBUG("set " + var + " = " + val); + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + if(llGetListLength(dVars) == 0) + { + llSetObjectDesc(var + "=" + val); + return; + } + list result = []; + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k == "") jump continue; + if(k == var && val == "") jump continue; + if(k == var) { + result += k + "=" + val; + val = ""; + jump continue; + } + string v = llList2String(data, 1); + if(v == "") jump continue; + result += k + "=" + v; + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + if(val != "") result += var + "=" + val; + llSetObjectDesc(llDumpList2String(result, "&")); +} + + +// clear RAM +Clr() { + + lCommands = []; + llOwnerSay("RAM Memory cleared. Notecards, if any, are not modified."); + makeMainMenu(); +} + +integer checkNoteCards() +{ + // Check that they have saved an Appeaance and Path notecard + integer num = llGetInventoryNumber(INVENTORY_NOTECARD); // how many notecards overall + + integer i; + integer count; + for (; i < num; i++){ + if (llGetInventoryName(INVENTORY_NOTECARD,i) == "!Path") + count++; + if (llGetInventoryName(INVENTORY_NOTECARD,i) == "!Appearance") + count++; + } + // if we have both, run the NPC + return count; +} +// saves a few bytes per call +key NPCKey() +{ + return KeyValueGet("key"); +} + +// Notes: +// No llResetScript() used so we can retain memory between rezzes and sim restarts. NPC info and stateful info is held in the Description +// + + +// This state is the first main menu +default +{ + state_entry() + { + llSetText("",<1,1,1>,1.0); // clr all hovertext- we may not be using it. + + // delete all NPC*scripts except myself + integer i; + integer j = llGetInventoryNumber(INVENTORY_SCRIPT); + for (i = 0; i < j; i++) { + string name = llGetInventoryName(INVENTORY_SCRIPT,i); + string match = llGetSubString(name,0,2); + if (match == "NPC" && llGetScriptName() != name) + { + llRemoveInventory(name); + llOwnerSay("Upgraded"); + } + } + + + string rA = KeyValueGet("co"); // Get the remembered menu setting for Abs Vs Relative + if (rA == "A") + relAbs = "Absolute"; + else if (rA == "R") + relAbs = "Relative"; + else + relAbs = "Absolute"; + + // menu reentrance + if (showMenu) { + makeMainMenu(); + return; + } + + // reenable NPC is sensor is on. + if ("on" == KeyValueGet("se")) + { + mSensor = "Sensor"; + ProcessSensor(); // fake 1 avatar to get it rezzed + state NPCGo; + } else { + mSensor = "No Sensor"; + } + } + + + touch_start(integer n) { // if touched, make a menu + if (checkPerms()) + makeMainMenu(); + else + makeUserMenu(); + } + + // no changed event needed + + // menu listener + listen(integer iChannel, string name, key id, string message) { + TimerEvent(0.0); /// kill the menu expiration timer + + if (message == "Stop NPC") + { + if (llStringLength(sNPCName)){ + Kill(sNPCName); + sNPCName = ""; + } else { + bNPC_STOP = TRUE; + makeText("Enter name of an NPC to stop"); + } + } + else if (message == "Erase RAM"){ + Clr(); + } + else if (message == "Relative"){ + relAbs = "Absolute"; + KeyValueSet("co","A"); // remember coordinates = A + Clr(); + } + else if (message == "Absolute"){ + relAbs = "Relative"; + KeyValueSet("co","R"); // remember coordinates = R + Clr(); + } + else if (message == "Recording"){ + state Commands; // show them the recording menu + } + else if (message == "Owner Only") { + priPub = "Group"; + KeyValueSet("pr","1"); + + llOwnerSay("Group members have control"); + makeMainMenu(); + } + else if (message == "Group") { + priPub = "Owner Only"; + KeyValueSet("pr","0"); + llOwnerSay("Only you have control"); + makeMainMenu(); + } + else if (message == "Sensor") { + mSensor ="No Sensor"; + KeyValueSet("se", "off"); + llOwnerSay("Sensors now Off"); + makeMainMenu(); + } + else if (message == "No Sensor") { + mSensor ="Sensor"; + llOwnerSay("Sensors now On"); + KeyValueSet("se", "on"); + + integer count = checkNoteCards(); + if (count >= 2) { + state NPCGo; + } + + // lslEditor does not handle the above, so I hack it in + if (Editor) { + state NPCGo; + } + + llOwnerSay("You have not saved a recording and/or appearance, so you cannot start a NPC"); + makeMainMenu(); + } + else if (message == "Appearance") { + llRemoveInventory("!Appearance"); // delete the notecard + osAgentSaveAppearance(kUserKey, "!Appearance"); // make the ntecard + llOwnerSay("Your Appearance has been recorded in notecard '!Appearance'"); + makeMainMenu(); + } + else if (message == "Save") { + if (llGetListLength(lCommands) == 0) { + llOwnerSay("Nothing recorded, you need to make some Recodings first"); + makeMainMenu(); + return; + } + state Save; + } + else if (message == "Help"){ + llLoadURL(kUserKey,"Click to view help","http://www.outworldz.com/opensim/posts/NPC/"); + makeMainMenu(); + } + else if (message == "Start NPC") { + integer count = checkNoteCards(); + if (Editor) state NPCGo; + if (count == 2) + state NPCGo; + + llOwnerSay("You have not saved a either recording or and appearance, so we cannot start a NPC"); + + } + else if (bNPC_STOP){ + bNPC_STOP = FALSE; + Kill(message); + } + } + timer(){ + Expire(); + } +} + + +// This state is used to save a Path notecard +state Save +{ + state_entry(){ + makeText("Stand where you want the NPC to appear, and enter the NPC Name"); + } + listen(integer iChannel, string name, key id, string message) { + TimerEvent(0.0); /// kill the menu expiration timer + + sNPCName = message; // in case we need to kill it. + vector vDest = (vector) Pos(); + + if (relAbs == "Relative") + { + vDest -= llGetPos(); // just an offset for relative + } + sNotecard = "@spawn=" + message + "|" + (string) vDest + "\n"; + integer i; + integer j = llGetListLength(lCommands); + for (; i < j; i++){ + // get the command to save to the notecard + string line = llList2String(lCommands,i); + if (relAbs == "Absolute") { + sNotecard += line; // add the un-modified string to the notecard + } else { + // since we have to record absolute coords since we do not know where the box goes until they press Save, + // we process the absolute to relative conversion for walks here + list parts = llParseString2List(line,["="],[]); //get the @command + + if (llList2String(parts,0) == "@walk") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@walk=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@fly") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@fly=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@run") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@run=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@land") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@land=" + (string) vec + "\n"; + } + else { + sNotecard += line; // add the un-modified string to the notecard + } + } + } + llRemoveInventory("!Path"); // delete the old notecard + osMakeNotecard("!Path",sNotecard); // Makes the notecard. + llOwnerSay("'!Path' notecard has been written"); + state default; + } + timer(){ + Expire(); + } + +} + +// This state is used to record the path for the NPC +// Each command can take 0, 1, or 2 params +state Commands +{ + state_entry() { + makeMenu(lAtButtons); + } + + on_rez(integer p) { + showMenu= TRUE; + state default; + } + touch_start(integer n){ + if (checkPerms()) + makeMenu(lAtButtons); + else + makeUserMenu(); + + } + + listen(integer iChannel, string name, key id, string message) + { + TimerEvent(0.0); /// kill the menu expiration timer + + if (message == "Menu"){ + showMenu= TRUE; + state default; + } + else if (message == "More"){ + makeMenu(lMenu2); + } + else if (message == "<<") { + makeMenu(lAtButtons); + } + else if (message == "@comment"){ + Text("# ","Enter a comment",""); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@run"){ + lCommands += "@run=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@fly"){ + lCommands += "@fly=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@land"){ + lCommands += "@land=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@walk") { + lCommands += "@walk=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@sound"){ + Text("@sound=","Enter a sound name or UUID to trigger",""); + } + else if (message == "@randsound"){ + lCommands += "@randsound"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@say") { + Text("@say=","Enter what the NPC will say",""); + } + else if (message == "@whisper"){ + Text("@whisper=","Enter what the NPC will whisper",""); + } else if (message == "@shout"){ + Text("@shout=","Enter what the NPC will shout",""); + } + else if (message == "@wander") { + Text("@wander=","Enter radius to wander","Enter number of wanders"); + } + else if (message == "@pause") { + Text("@pause=","Enter time to pause",""); + } + else if (message == "@rotate") { + Text("@rotate=","Enter degrees to rotate",""); + } + else if (message == "@sit"){ + Text("@sit=","Enter name of object to sit on",""); + } + else if (message == "@cmd"){ + Text("@cmd=","Enter cjhannel to speak on","Enter text to speak"); + } + else if (message == "@stand"){ + lCommands += "@stand\n"; + llOwnerSay("Stand Recorded"); + makeMenu(lAtButtons); + } + else if (message == "@animate"){ + Text("@animate=","Enter animation name to play","Enter time to play the animation"); + } + else if (! llStringLength(sParam2)) { + lCommands += sCommand + message + "\n"; + llOwnerSay("Recorded"); + makeMenu(lAtButtons); + } + else if (llStringLength(sParam2)){ + sCommand = sCommand + message + "|"; + llOwnerSay("Recorded"); + makeText(sParam2); + sParam2 = ""; + } + } + timer() { + Expire(); + } + + + +} + + +// This state will create an NPC in world +state NPCGo { + state_entry() { + DEBUG("NPCGo"); + + ProcessSensor(); // Set the flags + + lNPCScript = llParseString2List(osGetNotecard("!Path"), ["\n"], []); + if(llGetListLength(lNPCScript) == 0) { + llSay(DEBUG_CHANNEL, "No !Path notecard found."); + return; + } + state ProcessNPCLine; + } + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state ProcessNPCLine; + } + on_rez(integer num) { + llResetScript(); + } + state_exit() { + TimerEvent(0.0); + } +} + + +// This state loops over the notecard, processing each command +state ProcessNPCLine +{ + state_entry() + { + // DEBUG("ProcessNPCLine"); + @ignore; + + string next = llList2String(lNPCScript, 0); // get the next command + // DEBUG("Cmd:" + next); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); // delete it + if (! bForget) { + lNPCScript += next; // put it on the end unless we are told to forget it from a Link Message + bForget = FALSE; + } + if(llGetSubString(next, 0, 0) != "@") jump ignore; // ignore non-@ commands + list data = llParseString2List(next, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data, 0), STRING_TRIM)); + npcParams = llStringTrim(llList2String(data, 1), STRING_TRIM); + + @commands; + + if (! avatarPresent){ + state nobodyHome; + } + if(npcAction == "@spawn") { + // DEBUG("Spawning"); + integer lastIdx = llGetListLength(lNPCScript)-1; + lNPCScript = llDeleteSubList(lNPCScript, lastIdx, lastIdx); // remove spawn commands, we do them only once + list spawnData = llParseString2List(npcParams, ["|"], []); + sNPCName =llList2String(spawnData, 0); // V 1.6 name in RAM + + list spawnDest = llParseString2List(llList2String(spawnData, 1), ["<", ",", ">"], []); + vInitialPos.x = llList2Float(spawnDest, 0); + vInitialPos.y = llList2Float(spawnDest, 1); + vInitialPos.z = llList2Float(spawnDest, 2); + state spawn; + } + if(npcAction == "@stop") { + state stop; + } + if(npcAction == "@goto") { + // DEBUG("goto"); + integer lastIdx = llGetListLength(lNPCScript)-1; + lNPCScript = llDeleteSubList(lNPCScript, lastIdx, lastIdx); + // Wind commands till goto label. + @wind; + string next1 = llList2String(lNPCScript, 0); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); + lNPCScript += next1; + if(next1 != npcParams) jump wind; + // Wind the label too. + next1 = llList2String(lNPCScript, 0); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); + lNPCScript += next1; + // Get next command. + list data1 = llParseString2List(next1, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data1, 0), STRING_TRIM)); + npcParams = llStringTrim(llList2String(data1, 1), STRING_TRIM); + // Reschedule. + jump commands; + } + + if(npcAction == "@sound") { + // DEBUG("sound"); + llTriggerSound(npcParams,1.0); + jump ignore; // process next line + } + if(npcAction == "@randsound") { + // DEBUG("random sound"); + integer N = llGetInventoryNumber(INVENTORY_SOUND); + integer rand = llCeil(llFrand(N)) -1; // pick a random sound + string toPlay = llGetInventoryName(INVENTORY_SOUND,rand); + llTriggerSound(toPlay,1.0); + jump ignore; // process next line + } + + if(npcAction == "@walk") { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); + + if (vDestPos == ZERO_VECTOR) { + llSay(DEBUG_CHANNEL,"Bad (zeros) position for @walk"); + state ProcessNPCLine; + } + walkstate = 1;// walking + NPCWalkOption = OS_NPC_NO_FLY ; + state walk; + } + + if(npcAction == "@fly") { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); + + if (vDestPos == ZERO_VECTOR) { + llSay(DEBUG_CHANNEL,"Bad (zeros) position for @fly"); + state ProcessNPCLine; + } + + walkstate = 2;// flying + NPCWalkOption = OS_NPC_FLY ; + state walk; + } + + if(npcAction == "@run") { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); + + if (vDestPos == ZERO_VECTOR) { + llSay(DEBUG_CHANNEL,"Bad (zeros) position for @walk"); + state ProcessNPCLine; + } + walkstate = 3;// running + NPCWalkOption = OS_NPC_NO_FLY | OS_NPC_RUNNING; + state walk; + } + + if(npcAction == "@land") { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); + + if (vDestPos == ZERO_VECTOR) { + llSay(DEBUG_CHANNEL,"Bad (zeros) position for @walk"); + state ProcessNPCLine; + } + + walkstate = 4;// landing + + + NPCWalkOption= OS_NPC_FLY | OS_NPC_LAND_AT_TARGET ; + state walk; + } + + + + // chat commands + // speak in white text + + if(npcAction == "@say") { + // DEBUG("say"); + osNpcSay(NPCKey(),0, npcParams); + jump ignore; // process next line + } + if(npcAction == "@shout") { + // DEBUG("shout"); + osNpcShout(NPCKey(),0, npcParams); + jump ignore; // process next line + } + if(npcAction == "@whisper") { + // DEBUG("whisper"); + osNpcWhisper(NPCKey(),0, npcParams); + jump ignore; // process next line + } + // speak a command on a channel, so you can open doors and control stuff. + if(npcAction == "@cmd") { + // DEBUG("cmd"); + list dataToSpeak = llParseString2List(npcParams, ["|"], []); + integer iChannel = (integer) llList2String(dataToSpeak,0); + string stringToSpeak = llList2String(dataToSpeak,1); + llRegionSay(iChannel, stringToSpeak); // V 1.2 + + jump ignore; // process next line + } + // stop everything + if(npcAction == "@pause") { + // DEBUG("pause"); + RAMPause = (float) npcParams; + state pause; + } + if(npcAction == "@wander") { + // DEBUG("wander"); + list wanderData = llParseString2List(npcParams, ["|"], []); + RAMwd = (float) llList2String(wanderData, 0); + RAMwc = (integer) llList2String(wanderData, 1); + + vDestPos = osNpcGetPos(NPCKey()); // set the wander start + DEBUG("Starting at " + (string) vDestPos); + state wander; + } + if(npcAction == "@rotate") { + // DEBUG("rotate"); + RAMrot = (float) npcParams; + state rotate; + } + if(npcAction == "@sit") { + // DEBUG("sit"); + RAMsit= npcParams; + state sit; + } + if(npcAction == "@stand") { + // DEBUG("stand"); + state stand; + } + if(npcAction == "@delete") { + state delete; + } + if(npcAction == "@animate") { + // DEBUG("animate"); + list animateData = llParseString2List(npcParams, ["|"], []); + RAManimationName = llList2String(animateData, 0); + RAManimationTime = (float) llList2String(animateData, 1); + state animate; + } + llSay(DEBUG_CHANNEL, "ERROR: Unrecognized script line: " + npcAction + "=" + npcParams); + jump ignore; + + } + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + on_rez(integer num) { + llResetScript(); + } + link_message(integer sender, integer num, string str, key id) { + ProcessLink(str); + state ProcessNPCLine; + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else { + makeUserMenu(); + } + + } +} + + +state nobodyHome +{ + state_entry() { + DEBUG("Nobody Home"); + if (NPCKey() != NULL_KEY) { + DEBUG("NPC Remove"); + osNpcRemove(NPCKey()); + KeyValueSet("key", NULL_KEY ); + } + + llSetTimerEvent(10); + } + timer() + { + if (llGetRegionAgentCount()) { + llSetTimerEvent(0); + state NPCGo; + } + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else { + makeUserMenu(); + } + } +} + +state spawn +{ + state_entry() { + // DEBUG("state spawn"); + list name = llParseString2List(sNPCName, [" "], []); + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + vInitialPos += llGetPos(); + } + + // DEBUG("rez:" + (string) vInitialPos); + key aKey = osNpcCreate(llList2String(name, 0), llList2String(name, 1), vInitialPos, "!Appearance", NPCOptions); + KeyValueSet("key", aKey ); + osSetSpeed(aKey,SPEEDMULT); // 1.9 speed multiplier + TimerEvent(REZTIME); + NPCStart(STAND); + } + link_message(integer sender, integer num, string str, key id) { + ProcessLink(str); + state ProcessNPCLine; + } + timer() { + state ProcessNPCLine; + } + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + on_rez(integer num) { + llResetScript(); + } + state_exit(){ + TimerEvent(0.0); + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + }else { + makeUserMenu(); + } + } +} + + +state rotate { + state_entry() { + // DEBUG("state rotate"); + osNpcSetRot(NPCKey(), llEuler2Rot(<0,0,RAMrot> * DEG_TO_RAD)); + TimerEvent(TIMER); + } + link_message(integer sender, integer num, string str, key id) { + ProcessLink(str); + state ProcessNPCLine; + } + timer() { + state ProcessNPCLine; + } + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + on_rez(integer num) { + llResetScript(); + } + state_exit() { + TimerEvent(0.0); + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + }else { + makeUserMenu(); + } + } +} + +state sit { + state_entry() { + // DEBUG ("state sit"); + llSensorRepeat(RAMsit, "", PASSIVE|ACTIVE, 96, TWO_PI, 1); + } + sensor(integer num) { + llSensorRemove(); + osNpcSit(NPCKey(), llDetectedKey(0), OS_NPC_SIT_NOW); //V1.2 + TimerEvent(TIMER); + } + no_sensor(){ + state ProcessNPCLine; + } + timer() { + state ProcessNPCLine; + } + link_message(integer sender, integer num, string str, key id) { + ProcessLink(str); + state ProcessNPCLine; + } + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + on_rez(integer num) { + llResetScript(); + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else { + makeUserMenu(); + } + + } + + + state_exit(){ + TimerEvent(0.0); + } + + +} + +state stand { + state_entry() { + // DEBUG("state stand"); + osNpcStand(NPCKey()); + state ProcessNPCLine; + } + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else { + makeUserMenu(); + } + + } + + + on_rez(integer num) { + llResetScript(); + } + +} + +state animate { + state_entry() { + // DEBUG("state animate"); + NPCStart(RAManimationName); + TimerEvent(RAManimationTime); + } + link_message(integer sender, integer num, string str, key id) { + ProcessLink(str); + state ProcessNPCLine; + } + timer() { + NPCStart(STAND); + state ProcessNPCLine; + } + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else { + makeUserMenu(); + } + + } + + + on_rez(integer num) { + llResetScript(); + } + state_exit() { + TimerEvent(0.0); + } + +} +state walk { + state_entry() { + + DEBUG("NPCWalkOption = " + (string) NPCWalkOption); + + // walk, fly, run, land + if (walkstate == 1) { + NPCStart(WALK); + } else if (walkstate == 2) { + llShout(299,"on"); + NPCStart(FLY); + } else if (walkstate == 3) { + NPCStart(RUN); + } else if (walkstate == 4) { + NPCStart(LAND); + } else { + state ProcessNPCLine; + } + + + ProcessSensor(); + + newDest = vDestPos ; + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + newDest += llGetPos(); + } + + DEBUG("Moveto:" + (string) newDest); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + osNpcMoveToTarget(NPCKey(), newDest, NPCWalkOption); + TimerEvent(TIMER); + } + link_message(integer sender, integer num, string str, key id) { + ProcessLink(str); + state ProcessNPCLine; + } + timer() { + if (--iWaitCounter) { + + if (llVecDist(osNpcGetPos(NPCKey()), newDest) > MAXDIST) { + return; + } + } + + // walk, fly, run, land + if (walkstate == 1) { + NPCStart(STAND); + } else if (walkstate == 2) { + // nothing + } else if (walkstate == 3) { + NPCStart(STAND); + } else if (walkstate == 4) { + llShout(299,"off"); + NPCStart(STAND); + } else { + state ProcessNPCLine; + } + + state ProcessNPCLine; + } + + + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else { + makeUserMenu(); + } + + } + + + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + on_rez(integer num) { + llResetScript(); + } + state_exit() { + TimerEvent(0.0); + } + +} + +state wander +{ + state_entry() { + DEBUG("state wander"); + + ProcessSensor(); + + vector point = CirclePoint(RAMwd); + DEBUG("CirclePoint:" + (string) point); + vWanderPos = vDestPos + point; + DEBUG("vWanderPos:" + (string) vWanderPos); + + fTimerVal = WANDERTIME; // default time to pause after each wander + if (WANDERRAND) + fTimerVal = llFrand(WANDERTIME); // override, they want random times + + NPCStart(WALK); + + DEBUG("Wander to:" + (string) vWanderPos); + + osNpcMoveToTarget(NPCKey(), vWanderPos, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + + TimerEvent(TIMER); // first time we wait for the short timer. + } + link_message(integer sender, integer num, string str, key id) { + ProcessLink(str); + NPCStart(STAND); + state ProcessNPCLine; + } + timer() { + + if (--iWaitCounter) // wait 60 seconds to get to a destination. + if (llVecDist(osNpcGetPos(NPCKey()), vWanderPos) > MAXDIST) return; + + + // see if wander counter == 0, if so, stop walking, go to stand and process next line + if(RAMwc == 0) { + NPCStart(STAND); + state ProcessNPCLine; + } + + // one less time to wander around + RAMwc--; + + NPCStart(STAND); + state wanderhold; + } + + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else { + makeUserMenu(); + } + } + + + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + on_rez(integer num) { + llResetScript(); + } + state_exit() { + TimerEvent(0.0); + } +} + + +state wanderhold +{ + state_entry(){ + // now that we have reached a wander spot, slow the timer down to the desired value + TimerEvent(fTimerVal); + + ProcessSensor(); + + } + timer() { + state wander; + } + + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else { + makeUserMenu(); + } + + } + + + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + on_rez(integer num) { + llResetScript(); + } + state_exit() { + TimerEvent(0.0); + } + + +} + + + +// @pause=10 will stand for 10 seconds +state pause { + state_entry() { + DEBUG("state pause"); + NPCStart(STAND); + + ProcessSensor(); + + llSetTimerEvent(RAMPause); + } + link_message(integer sender, integer num, string str, key id){ + ProcessLink(str); + state ProcessNPCLine; + } + timer() { + NPCStart(STAND); + state ProcessNPCLine; + } + + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else + makeUserMenu(); + + } + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + on_rez(integer num) { + llResetScript(); + } + state_exit() + { + TimerEvent(0.0); + } +} + +// @stop makes the NPC stand there. You have to linkmessage to get moving again +state stop { + state_entry() { + NPCStart(STAND); + } + link_message(integer sender, integer num, string str, key id){ + if (str=="@go") + state ProcessNPCLine; + ProcessLink(str); + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else + makeUserMenu(); + + } + + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + on_rez(integer num) { + llResetScript(); + } +} + + + +state delete { + state_entry() { + // DEBUG("state delete"); + if (NPCKey() != NULL_KEY) { + DEBUG("NPC Remove"); + osNpcRemove(NPCKey()); + KeyValueSet("key", NULL_KEY ); + } + } + link_message(integer sender, integer num, string str, key id) { + if(str == "@npc_start") + { + state NPCGo; + } + + } + + // No on_rez or changed event needed, the only way out is a link message +} + diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.2.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.2.lsl new file mode 100644 index 00000000..1c1a3437 --- /dev/null +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.2.lsl @@ -0,0 +1,1476 @@ +// :SHOW:0 +// :CATEGORY:NPC +// :NAME:All In One NPC Recorder and Player +// :AUTHOR:Ferd Frederix +// :KEYWORDS:NPC, Puppeteer +// :CREATED:2013-09-08 18:27:47 +// :EDITED:2015-09-04 19:33:55 +// :ID:27 +// :NUM:1812 +// :REV:3.2 +// :WORLD:OpenSim +// :DESCRIPTION: +// All in one NPC recorder player. +// Supports both absolute and relative paths and many new commands +// Add animations named "Fly, Walk, Stand and Run" +// Click Prim to use. +// Should be worn as a HUD to record. +// Put it on the ground and click Sensor or Start NPC when done. +// :CODE: + +FOR DEBUG PURPOSES - DO NOT USE - USE LATER VERSIONS ONLY!!! + + +// This is Rev 3.2 07/19/2015 + +// Revision History +// Rev 1.1 10-2-2014 @Sit did not work. Minor tweaks to casting for lslEditor +// Rev 1.2 10-14-2014 @ sit had wrong type. +// Rev 1.3 relative movement fixed for @fly +// Rev 1.4 4-3-2014 allow anyone to use this, non owners and non group members can only start and stop. +// Rev 1.5 5-17-2014 set sensor to auto start on reboot of sim +// Rev 1.6 5-24-2014 move menu so you can get it by touching, removed many of the KeyValues to RAM for efficiency +// Rev 1.7 CHANGED_REGION_START, not CHANGED_REGION_START (Opensim difference) +// Rev 1.8 tuned up Kill NPC, added more flexible upgrader +// Rev 1.9 Better script injection by link message// Rev 2.0 Added osSetSpeed so you can speed up or slow down an NPC. +// Rev 2.1 No laggy sensor used exept to sit on stuff +// Rev 2.2 Various sensor fixes +// Rev 2.3 Sets No Sensor in menu, must be started by hand +// Rev 2.4 - reserved for patches to 2.3 if needed +// Rev 3.0 Refactor out into subs, not states to make command injection easier +// New command: @appearance=Notecardname so you can switch to a new notecard on the fly +// New command: @speed=1.0 which slows up ( < 1 ) or speeds up ( > 1) +// Rev 3.1 Commands are not interruptible by Link Message +// Rev 3.2 Sensor patches for consitency in removing the NPC +//*******************************************************************// + +// Instructions on how to use this is at http://www.outworldz.com/opensim/posts/NPC/ +// This is an OpenSim-only script. +// Author: Ferd Frederix aka Fred Beckhusen - fred@mitsi.com + +//////////////////////////////////////////////////////////////////////////////////////////// +// Original code was Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // +/////////////////////////////////////////////////////////////////////////////////////////// +// Please see: http://www.gnu.org/licenses/gpl.html for legal details, // +// rights of fair usage, the disclaimer and warranty conditions. // +/////////////////////////////////////////////////////////////////////////////////////////// +// The original NPC controller was from http://was.fm/opensim:npc +// Extensive additions and bug fixes by Fred Beckhusem, aka Ferd Frederix, fred@mitsi.com +// llSensor had two params swapped +// @Wander would wander where it had rezzed, not where it was. +// There was no 'no_sensor' event in sit, so if a @sit failed, the NPC got stuck +// The animation and walks always stopped old, then started new. It should be start new, then stop old so the default stand would be suppressed. +// New code: +// Merged with new Route recorder and notecard writer +// If the NPC failed to reach a destination it never moved on. Added WAIT global to tune this +// Exposed many tunable variables and ported the code to LSLEditor. +// Added floating point to times in notecard. + +// Added @sound, @randsound, @whisper, @shout, and @cmd controls. +// +// notecards integers are not floats for better control +// +// Link Messages may be used to perform external control by injecting @commands into the stream of actions +// Example: +// To chat something, such as with a chat robot +// llMessageLinked(LINK_SET,0,"@npc_say=Hello",""); + +// This script assumes that NPCs and OSSl scripting is enabled in the OpenSim configuration. +// In order to enable them, the following changes must be made in the OpenSim.ini configuration file: +// +// ; Turn on OSSL +// AllowOSFunctions = true +// OSFunctionThreatLevel = Severe + +//[NPC] +// ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} +// Enabled = true +// +// and then the server has to be restarted. + + +// Commands: All commands begin with an @ sign. All other lines are ignored +// @commands may have optional parameters. The syntax is always: +// @cmd=parm1|parm2 +// NaN in the table below meand Not a Number. This means there is no parameter + +//Command First Parameter Second Parameter Description +//@spawn name location (vector) Rezzes an NPC with name at a location. +//@appearance NoteCardName NaN switch the NPC appearance to a new notecard +//@walk destination (vector) NaN Makes the NPC walk to destination. +//@fly destination (vector) NaN Makes the NPC fly to destination. +//@land destination (vector) NaN Makes the NPC land at destination. +//@say string NaN Makes the NPC speak a phrase. +//@whisper string NaN Makes the NPC whisper a phrase. +//@shout string NaN Makes the NPC shout a phrase. +//@pause seconds (float) NaN Makes the NPC wait for a multiple of seconds. +//@wander radius (float) cycles (integer) Makes the NPC wander in radius, for cycles seconds. +//@delete NaN NaN Removes the NPC. Requires a link message to continue +//@goto label (string) NaN Jump to the label label in the script. +//@animate animation (string) time (float) Makes the NPC trigger the animation animation for time seconds. +//@sound sound_name NaN plays a sound from inventory +//@randsound NaN NaN Plays a random sound from inventory +//@rotate degrees (float) NaN Rotate the NPC degrees around the Z axis. +//@sit primitive name NaN Sit on a primitive with a given name. +//@stand NaN NaN If sitting on a primitive, stand up. +//@cmd channel (integer) string Says string on channel, for controlling external gadgets +//@stop NaN NaN Halts the NPC script indefinitely. Can be started with a link message +//@go NaN NaN Continues on next notecard line, for use in link messages +//@speed speed (float) NaN from 0 to N, where 1.0 ius a normal speed of an avatar. 0.2 is a turtle. +//@notecard notename (string) NaN load a new Path notecard + +////////////////////////////////////////////////////////// +// DEBUG // +////////////////////////////////////////////////////////// +integer debug = FALSE; // set to TRUE or FALSE for debug chat on various actions +integer Editor = FALSE; // set to to TRUE to working in LSLEditor, FALSE for in-world. + // you must also include the NPC commands found in the other script since LSLEditor does not support OpenSim +integer iTitleText = TRUE; // set to TRUE to see debug info in text above the controller + +////////////////////////////////////////////////////////// +// TUNABLE CONFIGURATION // +////////////////////////////////////////////////////////// +float TIMER = 0.5; // how often the system checks the distance traveled. Fastest you can go is 0.5 seconds +float QUICK = 0.020; // when we need to move to the next state, we use a QUICK timer +string Appearance = "!Appearance"; // The name of the recorded Appearance notecard +string Notecard = "!Path"; // The name of the recorded routes +integer allowUsers = FALSE; // If true, any user can get a Start NPC and Stop NPC menu. Only groups and owners can get all commands if TRUE, or FALSE +float MAXDIST = 2.0; // how close a NPC has to get to a dest pos to continue to next state. Do not lower this too much, as it may miss the target +integer WANDERRAND = TRUE; // set to TRUE and they will pause during wanders a random number of seconds +float WANDERTIME = 3.0; // how long they stand after each @wander,if WANDERRAND is FALSE. If WANDERRAND is TRUE, this is the max time +integer WAIT = 30; // wait for this number of seconds for the NPC to reach a destination (for safety). If it fails to reach a target, it will move on after this time. +float RANGE = 50; // 1 to N meters - anyone this close to the controller will start NPCS if Sensor button is clicked +float REZTIME = 5.0; // wait this long for NPC to rez in, then start the process +string STAND = "Stand"; // the name of the default Stand animation +string WALK = "Walk"; // the name of the default Walk animation +string FLY = "Fly"; // the name of the default Fly animation +string RUN = "Run"; // the name of the default Run animation +string LAND = "Land"; // the name of the default land animation ( for birds only) +float OffsetZ = 0.5; // appear 0.5 meter above ground, this is added to all destinations to keep them from sinking in. +float SPEEDMULT =1.0; // 1.0 = regular vatar speed. Smaller numbers slow down walks. Large numbers speed them up. +integer FLIGHT = 299; // For controllign wings. A channel that is shouted at when flight starts and ends. "flying" or "landing" + +// DESCRIPTIONS FIELDS HAVE TO SURVIVE A RESET +// These vars are stored by saving them with KeyValueSet +// "pr" is a 0 if it is set for Owner Only, 1 for Group control +// "se" is "on" if Started +// "co" = "R" or "A" for relative or absolute addressing mode +// "key" = NPC key + +// These Globals used to be stored in description. Moved to RAM in V1.6 +float RAMPause; // @pause param +float RAMwd ; // @wander distance +integer RAMwc; // @wander count +float RAMrot; // @rotate +string RAMsit; // @sit primname +string RAManimationName; // @animate animation (string) time (float) +float RAManimationTime; + +// other globals section +integer iChannel; // a listen channel, randomly assigned +integer iHandle; // the handle to it + +// NPC controls +vector newDest ; // tmp storage for the walks +integer iWaitCounter ; // wait for this number of seconds for the NPC to reach a desrtination +string sNPCName; // the name of the NPC that may be in world. So we can remove it. +integer bNPC_STOP = FALSE; // boolean to reuse a listener +integer Stopped = FALSE; // set to TRUE by link messages so we do not remember them +float fTimerVal ; // how long we wait when wandering (calculated) + +// OS_NPC_CREATOR_OWNED will create an 'owned' NPC that will only respond to osNpc* commands issued from scripts that have the same owner as the one that created the NPC. +// OS_NPC_NOT_OWNED will create an 'unowned' NPC that will respond to any script that has OSSL permissions to call osNpc* commands. +integer NPCOptions = OS_NPC_CREATOR_OWNED; // only yhe owner of this box can control this NPC. + +integer walkstate = 0; // helps us reshare the walk state for run, fly and land - a bit of a hack, but it saves RAM. Has to be done this way because some bits of NPCWalkOption are asserted as 0 + +integer NPCWalkOption; // Some notes for what happens to NPCWalkOption: +// OS_NPC_FLY - Fly the avatar to the given position. The avatar will not land unless the OS_NPC_LAND_AT_TARGET option is also given. +// OS_NPC_NO_FLY - Do not fly to the target. The NPC will attempt to walk to the location. If it's up in the air then the avatar will keep bouncing hopeless until another move target is given or the move is stopped +//OS_NPC_LAND_AT_TARGET - If given and the avatar is flying, then it will land when it reaches the target. If OS_NPC_NO_FLY is given then this option has no effect. +// OS_NPC_RUNNING - if given, NPC avatar moves at running/fast flying speed, otherwise moves at walking/slow flying speed. + +// menus +string mSensor="No Sensor"; // Sensor or "No Sensor" + +list lAtButtons = ["Menu","-", "More", "@run","@walk","@fly", "@land","@wander","@sit", "@stand","@animate","@rotate"]; +list lMenu2 = ["<<", "@comment", "@stop", "@say","@whisper","@shout", "@sound","@randsound", "@speed", "@cmd", "@pause", "@delete" ]; + +string sCommand; // place to store a command for two-prompted ones +string sParam2; // place to store a prompt for two-prompted ones +string priPub = "Owner Only"; // Private or Group +key kUserKey; // the person who is controlling the avatar, not the Owner +// the command lists +list lCommands; // commands are stored here +list lNPCScript; // Storage for the NPC script. +string npcAction; // Storage for the next action. @cmd=0|hello, this becomes @cmd +string npcParams; // Storage for the param, @cmd=0|hello, this becomes 0|hello + +// misc vars +string sNotecard; // commands are stored here temporarily for dumping +vector vWanderPos; // a place to wander to +string lastANIM ; // last animation run +// Sensor +integer avatarPresent; // Sensor sets this flag when people are within Range. + +// Coordinate control +vector vInitialPos ; // Vector that will be filled by the script with the initial starting position in region coordinates. +vector vDestPos = ZERO_VECTOR; // Storage for destination position. +string relAbs = "Relative"; // absolute vs relative positioning + + +// STATES +integer MENU ; // processing a dialog box state, may be concurrent with STATE +integer STATE; // state storage +integer MakeNotecard = 1; // displaying a text box for NPC name +integer RecordPath = 2; // displaying a path notecard menu +integer NobodyHome = 3; // looking for an avatar +integer Spawning = 4; // spawning an avatar +integer Animate = 5; // animation timer needed +integer Walking = 6; // Hey! I am walking here! +integer Wander = 7; // Wandering around neeeds a timer, too +integer WanderHold = 8; // We reached a wander point +integer DoProcess = 9; // Set this to make it process a new command + +key gNpcKey = NULL_KEY; // global key storage for the one NPC, to save CPU cycles +list Stack ; // a command stack from link message input + +/////////////////////////////////////////////////////////////////////////// +// FUNCTIONS // +/////////////////////////////////////////////////////////////////////////// + +// Do* functions are much like states from the old scripts. + +// Save a Path notecard +DoSave() +{ + STATE = MakeNotecard; + makeText("Stand where you want the NPC to appear, and enter the NPC Name"); +} + +// This function is used to record the path for the NPC +// Each command can take 0, 1, or 2 params +DoMenuForCommands() { + makeMenu(lAtButtons); +} + + +// No one is here when sensors were on, so we kill off the NPC +DoNobodyHome() +{ + DEBUG("Nobody Home"); + STATE = NobodyHome; + if (NPCKey() != NULL_KEY) { + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + } + TimerEvent(5); // keep ticking to sense avatars +} + +// Create a NPC +DoSpawn() { + DEBUG("state spawn"); + + // see if there is already one out there. + if (NPCKey() != NULL_KEY) + return; + + STATE = Spawning; + + list name = llParseString2List(sNPCName, [" "], []); + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + vInitialPos += llGetPos(); + } + + DEBUG("Rez NPC:" + (string) vInitialPos); + key aKey = osNpcCreate(llList2String(name, 0), llList2String(name, 1), vInitialPos, Appearance, NPCOptions); + + SaveKey(aKey ); // save in desceription and global, too + + osSetSpeed(aKey,SPEEDMULT); // 1.9 speed multiplier + TimerEvent(REZTIME); + NPCAnimate(STAND); +} + +DoRotate() { + DEBUG("state rotate"); + osNpcSetRot(NPCKey(), llEuler2Rot(<0,0,RAMrot> * DEG_TO_RAD)); +} + +DoSit() { + DEBUG ("state sit - looking for " + RAMsit); + llSensor(RAMsit, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +DoStand() { + + DEBUG("state stand"); + osNpcStand(NPCKey()); +} + + +DoAnimate() { + + DEBUG("state animate"); + STATE = Animate; + NPCAnimate(RAManimationName); + if (RAManimationTime < 1) + RAManimationTime = 1; + TimerEvent(RAManimationTime); +} + +DoWalk() { + + DEBUG("NPCWalkOption = " + (string) NPCWalkOption); + STATE = Walking; + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(WALK); + } else if (walkstate == 2) { + llShout(FLIGHT,"flying"); + NPCAnimate(FLY); + } else if (walkstate == 3) { + NPCAnimate(RUN); + } else if (walkstate == 4) { + NPCAnimate(LAND); + } + newDest = vDestPos ; + newDest.z += OffsetZ; + + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + newDest += llGetPos(); + } + + DEBUG("Moveto:" + (string) newDest); + osNpcMoveToTarget(NPCKey(), newDest, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + + +DoWander(){ + DEBUG("state wander"); + STATE = Wander; + + vector point = CirclePoint(RAMwd); + DEBUG("CirclePoint:" + (string) point); + vWanderPos = vDestPos + point; + DEBUG("vWanderPos:" + (string) vWanderPos); + + fTimerVal = WANDERTIME; // default time to pause after each wander + if (WANDERRAND) + fTimerVal = llFrand(WANDERTIME) + 1; // override, they want random times + + NPCAnimate(WALK); + + DEBUG("Wander to:" + (string) vWanderPos); + + osNpcMoveToTarget(NPCKey(), vWanderPos, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + +DoWanderhold() { + + DEBUG("Wander Hold"); + STATE = WanderHold; + + // now that we have reached a wander spot, slow the timer down to the desired value + TimerEvent(fTimerVal); +} + +// @pause=10 will do nothing for 10 seconds +DoPause() { + + DEBUG("state pause"); + if (RAMPause < 0.1) + RAMPause = 0.1; + + TimerEvent(RAMPause); +} + + +// @stop makes the NPC stop moving in whatever state it is in. You have to linkmessage to get moving again +DoStop() { + DEBUG("NPC is Stopped"); + Stopped = TRUE; // Link controlled - we mnust have a @go to continue with notecards + TimerEvent(0); +} + + +// @delete removes the NPC forever. Next command starts it up again at the beginning +DoDelete() { + DEBUG("state delete"); + + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + lNPCScript = []; // next command starts the NPC into action at the beginning + +} + +// change the appearance of the NPC +DoAppearance(string notecard) { + DEBUG("state appearance"); + if (llGetInventoryType(notecard) == INVENTORY_NOTECARD){ + DEBUG("Load appearance " + notecard); + osNpcLoadAppearance(NPCKey(),notecard); + } +} + +// Change the avatar speed +DoSpeed(string speed) { + float newspeed = (float) speed; + if (newspeed > 0.1 && newspeed < 5.0) // sanity check + osSetSpeed(NPCKey(),newspeed); +} +DoNewNote (string card) { + DEBUG("Load Notecard " + card); + NPCReadNoteCard(card); + Stopped = FALSE; +} + +// This loops over the notecard, processing each command +DoProcessNPCLine() { + DEBUG("ProcessNPCLine"); + STATE = 0; + + // auto load a notecard + if (! llGetListLength(lNPCScript)) { + DEBUG("Read Notecard"); + NPCReadNoteCard(Notecard); + Stopped = FALSE; + } + + // look for link messages on the stack + string next = llList2String(Stack,0); // lets see if there is anithing from a link message + if (llStringLength(next)) + { + Stack = llDeleteSubList(Stack,0,0); + ProcessCmd(next); //lets do this command instead. + return; + } + + // @stop issued? + if (Stopped) { + TimerEvent(0); + DEBUG("Waiting for input"); + return; + } + + // No, we have an @go for liftoff + next = llList2String(lNPCScript, 0); // get the next command + DEBUG("Execute:" + next); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); // delete it + + if (llGetListLength(lNPCScript) == 0) { + DEBUG("EOF"); + } + ProcessCmd(next); + +} + +ProcessCmd(string cmd) { + + DEBUG("ProcessCmd:" + cmd); + + if (llGetSubString(cmd, 0, 0) != "@") { + DEBUG("ignoring"); + STATE = DoProcess; + TimerEvent(QUICK); // this is so we do not recurse the stack + return; + } + + list data = llParseString2List(cmd, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data, 0), STRING_TRIM)); + + DEBUG("Action:" + npcAction); + npcParams = llStringTrim(llList2String(data, 1), STRING_TRIM); + + @commands; + + ProcessSensor(); + if (! avatarPresent){ + DoNobodyHome(); + DEBUG("No avatar nearby"); + return; + } else { + if (llStringLength(sNPCName)) { + DoSpawn(); + } + } + + if(npcAction == "@spawn") { + DEBUG("@spawn"); + list spawnData = llParseString2List(npcParams, ["|"], []); + sNPCName =llList2String(spawnData, 0); // V 1.6 name in RAM + + list spawnDest = llParseString2List(llList2String(spawnData, 1), ["<", ",", ">"], []); + vInitialPos.x = llList2Float(spawnDest, 0); + vInitialPos.y = llList2Float(spawnDest, 1); + vInitialPos.z = llList2Float(spawnDest, 2); + DoSpawn(); + + return; + } + else if(npcAction == "@stop") { + DEBUG("@stop"); + DoStop(); + return; + } + else if(npcAction == "@goto") { + DEBUG("goto"); + integer lastIdx = llGetListLength(lNPCScript)-1; + lNPCScript = llDeleteSubList(lNPCScript, lastIdx, lastIdx); + // Wind commands till goto label. + @wind; + string next1 = llList2String(lNPCScript, 0); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); + lNPCScript += next1; + if(next1 != npcParams) jump wind; + // Wind the label too. + next1 = llList2String(lNPCScript, 0); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); + lNPCScript += next1; + // Get next command. + list data1 = llParseString2List(next1, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data1, 0), STRING_TRIM)); + npcParams = llStringTrim(llList2String(data1, 1), STRING_TRIM); + // Reschedule. + jump commands; + } + else if(npcAction == "@sound") { + DEBUG("sound"); + llTriggerSound(npcParams,1.0); + } + else if(npcAction == "@randsound") { + DEBUG("@randsound"); + integer N = llGetInventoryNumber(INVENTORY_SOUND); + integer rand = llCeil(llFrand(N)) -1; // pick a random sound + string toPlay = llGetInventoryName(INVENTORY_SOUND,rand); + llTriggerSound(toPlay,1.0); + } + else if(npcAction == "@walk") { + DEBUG("@walk"); + GetDest(npcParams); + walkstate = 1;// walking + NPCWalkOption = OS_NPC_NO_FLY ; + DoWalk(); + return; + } + else if(npcAction == "@fly") { + GetDest(npcParams); + walkstate = 2;// flying + NPCWalkOption = OS_NPC_FLY ; + DoWalk(); + return; + } + else if(npcAction == "@run") { + DEBUG("@run"); + GetDest(npcParams); + walkstate = 3;// running + NPCWalkOption = OS_NPC_NO_FLY | OS_NPC_RUNNING; + DoWalk(); + return; + } + else if(npcAction == "@land") { + DEBUG("@land"); + GetDest(npcParams); + walkstate = 4;// landing + NPCWalkOption= OS_NPC_FLY | OS_NPC_LAND_AT_TARGET ; + DoWalk(); + return; + } + else if(npcAction == "@say") { + DEBUG("@say " + npcParams); + osNpcSay(NPCKey(), 0, npcParams); + } + else if(npcAction == "@shout") { + DEBUG("@shout"); + osNpcShout(NPCKey(),0, npcParams); + } + else if(npcAction == "@whisper") { + DEBUG("@whisper " + npcParams); + osNpcWhisper(NPCKey(),0, npcParams); + } + // speak a command on a channel, so you can open doors and control stuff. + else if(npcAction == "@cmd") { + DEBUG("@cmd"); + list dataToSpeak = llParseString2List(npcParams, ["|"], []); + string channel = llList2String(dataToSpeak,0); + DEBUG("Channel:"+(string) channel); + integer iChannel = (integer) channel; + string stringToSpeak = llList2String(dataToSpeak,1); + llSay(iChannel, stringToSpeak); + } + // stop everything + else if(npcAction == "@pause") { + DEBUG("@pause"); + RAMPause = (float) npcParams; + DoPause(); + return; + } + else if(npcAction == "@wander") { + DEBUG("@wander"); + list wanderData = llParseString2List(npcParams, ["|"], []); + RAMwd = (float) llList2String(wanderData, 0); + RAMwc = (integer) llList2String(wanderData, 1); + + vDestPos = osNpcGetPos(NPCKey()); // set the wander start + DEBUG("Starting at " + (string) vDestPos); + DoWander(); + return; + } + else if(npcAction == "@rotate") { + DEBUG("@rotate"); + RAMrot = (float) npcParams; + DoRotate(); + } + else if(npcAction == "@sit") { + DEBUG("@sit"); + RAMsit= npcParams; + DoSit(); + return; + } + else if(npcAction == "@stand") { + DEBUG("@stand"); + DoStand(); + } + else if(npcAction == "@delete") { + DEBUG("@delete"); + DoDelete(); + return; + } + else if(npcAction == "@animate") { + DEBUG("@animate"); + list animateData = llParseString2List(npcParams, ["|"], []); + RAManimationName = llList2String(animateData, 0); + RAManimationTime = (float) llList2String(animateData, 1); + DoAnimate(); + return; + } + else if(npcAction == "@appearance" ) + { + DEBUG("@appearance"); + DoAppearance(npcParams); + } + else if (npcAction =="@speed") { + DEBUG("@speed"); + DoSpeed(npcParams); + } + else if (npcAction =="@notecard") { + DEBUG("@notecard"); + DoNewNote(npcParams); + Notecard = npcParams; + } + + STATE = DoProcess; + TimerEvent(QUICK); // yeah I know, not possible this fast, we just go as fast as we can go - this is so we do not recurse the stack +} + + + +/////////////////// UTILITY Functions, not state-like ////////////////// + +// DEBUG(string) will chat a string or display it as hovertext if debug == TRUE +DEBUG(string str) { + if (debug) + llOwnerSay( str); // Send the owner debug info so you can chase NPCS + if (iTitleText) + llSetText(str,<1.0,1.0,1.0>,1.0); // show hovertext +} + +GetDest(string npcParams) { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); +} + +NPCReadNoteCard(string Note) { + DEBUG("NPCReadNoteCard"); + lNPCScript = llParseString2List(osGetNotecard(Note), ["\n"], []); +} + +integer SenseAvatar() +{ + //Returns a strided list of the UUID, position, and name of each avatar in the region + list avatars = llGetAgentList(AGENT_LIST_REGION ,[]); + integer numOfAvatars = llGetListLength(avatars); + if (numOfAvatars == 0) + { + DEBUG("No people"); + return 0; + } + //DEBUG("Located " + (string)numOfAvatars + " avatars and NPC's"); + + integer nAvatars; + integer i; + for( i = 0;i < numOfAvatars; i++) { + key aviKey = llList2Key(avatars,i); + if (!osIsNpc(aviKey)) { + list detail = llGetObjectDetails(aviKey,[OBJECT_POS]); + vector pos = llList2Vector(detail,0); + float dist = llVecDist(pos, llGetPos()); + if (dist < RANGE) + { + nAvatars++; + DEBUG("In range:" + llKey2Name(aviKey)); + } + } + } + //DEBUG("Located " + (string) nAvatars + " avatars"); + return nAvatars; +} + +// return TRUE if the avatar is owner when private is set, or TRUE if the avatar is in the same group and GROUP is set. +integer checkPerms() { + + integer group = (integer) KeyValueGet("pr"); + if (! group) + priPub = "Owner Only"; + else + priPub = "Group"; + + + if (llDetectedKey(0) == llGetOwner()){ + kUserKey = llDetectedKey(0); + return TRUE; + } + + if ( group && llDetectedGroup(0)) { + kUserKey = llDetectedKey(0); + return TRUE; + } + kUserKey = llDetectedKey(0); + return FALSE; +} + + + +NPCAnimate(string anim) +{ + DEBUG("Start Anim: " + anim); + if (llGetInventoryType(anim) == INVENTORY_ANIMATION ) { + + if (lastANIM != anim) { + if(llStringLength(lastANIM)) { + osNpcStopAnimation(NPCKey(), lastANIM); + } + osNpcPlayAnimation(NPCKey(), anim); + lastANIM = anim; + } + } else { + llSay(DEBUG_CHANNEL, "No animation named " + anim); + } +} + + +TimerEvent(float timesent) +{ + DEBUG("Setting timer: " + (string) timesent); + llSetTimerEvent(timesent); +} + +// Kill a NPC by Name +Kill(string param) +{ + integer count; + list avatars = osGetAvatarList(); // Returns a strided list of the UUID, position, and name of each avatar in the region except the owner.\ + integer i; + integer j = llGetListLength(avatars); + for (i=0 ; i <= j; i+=3){ + + string desired = llList2String(avatars,i+2); + desired = llStringTrim(desired,STRING_TRIM); // should not be needed but is needed + + if (desired == param){ + vector v = llList2Vector(avatars,i+1); + key target = llList2Key(avatars,i); // get the UUID of the avatar + osNpcRemove(target); + SaveKey(NULL_KEY ); + llOwnerSay("Removed " + param+ " at location " + (string) v); + count++; + } + } + if (count) + llOwnerSay("Removed " + (string) count + " NPC's"); + else + llOwnerSay("Could not locate " + param); +} + + +// return a String for the position we are at. Strings used as the caller wants strings +string Pos() +{ + vector where = llGetPos(); // find the box position + + where.z += OffsetZ; // use the ground position + an offset + + if (Editor) + where = <128,128,31 + llFrand(1)>; // center of sim for editing + + // if attached the height will be too high by 1/2 the agent size + if (llGetAttached()) { + vector size = llGetAgentSize(llGetOwner()); + float Z = size.z; + where.z -= Z/2; + } + + // DEBUG("Pos= " + (string) where); + return (string) where; +} + +// setup a menu with a timer for timeouts, called by all make*() +menu() +{ + llListenRemove(iHandle); + iChannel = llCeil(llFrand(100000) + 20000); + iHandle = llListen(iChannel,"","",""); + TimerEvent(30.0); + MENU = TRUE; +} + +// make a text box +makeText(string Param) +{ + menu(); + llTextBox(kUserKey, Param, iChannel); +} + +// top level menu +makeMainMenu() +{ + menu(); + list buttons = ["Appearance","Recording","Save","Help","-","Erase RAM", priPub,relAbs,"-","Stop NPC",mSensor,"Start NPC"]; + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Records",buttons,iChannel); +} + + +// Rev 1.4 +// top level menu for non group/ non owners +makeUserMenu() +{ + if (!allowUsers) return; + + menu(); + list buttons = ["Start NPC","Stop NPC"]; + llDialog(kUserKey,"Choose",buttons,iChannel); +} + + + +// programmable menu for @commands +makeMenu(list buttons) +{ + menu(); + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Record",buttons,iChannel); +} + + +// make one or two text boxes with prompts +Text(string cmd, string p1, string p2) +{ + sCommand = cmd; + sParam2 = ""; + if (llStringLength(p2)) + sParam2 = p2; + + makeText(p1); +} + +// Set the Avatar Present flag - if sensors are off and we are forece run, there will be one present. +ProcessSensor() +{ + integer SensorOn; + if ("on" == KeyValueGet("se")) + { + SensorOn = TRUE; // we need to scan for avatars + } else { + SensorOn = FALSE; // we need to scan for avatars + } + //DEBUG("Sensor:" + (string) SensorOn); + + integer n = SenseAvatar(); + + if (SensorOn && n) + avatarPresent = TRUE; // someone is here and we need to tell the system to run + else if (SensorOn && !n) + avatarPresent = FALSE; // someone is not here and we need to tell the system to stop + else + avatarPresent = TRUE; // someone is effectivley always here when sensor is off and we are running + + //DEBUG("Avatar Present: " + (string) avatarPresent); +} + +vector CirclePoint(float radius) { + float x = llFrand(radius *2) - radius; // +/- radius, randomized + float y = llFrand(radius *2) - radius; // +/- radius, randomized + return ; // so this should always happen +} + +string KeyValueGet(string var) { + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k != var) jump continue; + //DEBUG("got " + var + " = " + llList2String(data, 1)); + return llList2String(data, 1); + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + return ""; +} + +KeyValueSet(string var, string val) { + + //DEBUG("set " + var + " = " + val); + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + if(llGetListLength(dVars) == 0) + { + llSetObjectDesc(var + "=" + val); + return; + } + list result = []; + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k == "") jump continue; + if(k == var && val == "") jump continue; + if(k == var) { + result += k + "=" + val; + val = ""; + jump continue; + } + string v = llList2String(data, 1); + if(v == "") jump continue; + result += k + "=" + v; + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + if(val != "") result += var + "=" + val; + llSetObjectDesc(llDumpList2String(result, "&")); +} + + +// clear RAM +Clr() { + + lCommands = []; + llOwnerSay("RAM Memory cleared. Notecards, if any, are not modified."); + makeMainMenu(); +} + +integer checkNoteCards() +{ + // Check that they have saved an Appeaance and Path notecard + integer num = llGetInventoryNumber(INVENTORY_NOTECARD); // how many notecards overall + + integer i; + integer count; + for (; i < num; i++){ + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Notecard) + count++; + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Appearance) + count++; + } + DEBUG("Checked " + (string) count + " Notecards"); + // if we have both, run the NPC + return count; +} + +Update(string SName) { + + // delete all NPC*scripts except myself + integer i; + integer j = llGetInventoryNumber(INVENTORY_SCRIPT); + for (i = 0; i < j; i++) { + string name = llGetInventoryName(INVENTORY_SCRIPT,i); + string match = llGetSubString(name,0,2); + if (match == SName && llGetScriptName() != name) + { + llRemoveInventory(name); + llOwnerSay("Upgraded"); + } + } + +} + +// Get all default saved params from the Description +GetSwitches() +{ + string rA = KeyValueGet("co"); // Get the remembered menu setting for Abs Vs Relative + if (rA == "A") + relAbs = "Absolute"; + else if (rA == "R") + relAbs = "Relative"; + else + relAbs = "Absolute"; + + + // reenable NPC if sensor is on. + if ("on" == KeyValueGet("se")) + { + mSensor = "Sensor"; + ProcessSensor(); // fake 1 avatar to get it rezzed + } else { + mSensor = "No Sensor"; + } + } + + +SaveKey(key akey) +{ + DEBUG("Saving Key of " + (string) akey); + KeyValueSet("key", akey); + if (akey != (key) KeyValueGet("key") ) + { + DEBUG("Fatal error, cannot save key"); + } + gNpcKey = akey; +} + + +key NPCKey() +{ + key akey = gNpcKey; // from cached copy + // gNpcKey saves a lot of CPU processing by caching the key, if blank we get it from the description + if (gNpcKey == NULL_KEY) + { + DEBUG("Get DKey"); + akey = KeyValueGet("key"); // from Description of the prim + } + DEBUG("NPC KEY:" + (string) akey); + return akey; +} + + +/////////////////// CODE BEGINS ////////////////// + + +default +{ + changed(integer change) { + if(change & CHANGED_REGION_START) { + llResetScript(); + } + } + + on_rez(integer start_param) + { + llResetScript(); + } + + state_entry() { + + llSetText("",<1,1,1>,1.0); // clr all hovertext- we may not be using it. + DoDelete(); // kill any NPC that is out running + Update("NPC"); // If dragged and ropped into a prim with any script named "NPC...", this will replace it. + GetSwitches(); // Get all default saved params from the Description + llSetTimerEvent(TIMER); + } + + + touch_start(integer n) + { // if touched, make a menu + + if (checkPerms()) { + if (RecordPath == STATE) { + makeMenu(lAtButtons); + } else { + makeMainMenu(); + } + } else { + makeUserMenu(); + } + } + + // menu listener + listen(integer iChannel, string name, key id, string message) { + + if (MENU) { + llListenRemove(iHandle); + MENU = 0; // menu is off + iHandle = 0; + } + + if (message == "Stop NPC") + { + lNPCScript = []; // force reload of notecard + if (NPCKey() != NULL_KEY){ + Kill(sNPCName); + sNPCName = ""; + } else { + bNPC_STOP = TRUE; + makeText("Enter name of an NPC to stop"); + } + } + else if (message == "Menu" ) { + makeMainMenu(); + } + else if (message == "Erase RAM"){ + Clr(); + } + else if (message == "Relative"){ + relAbs = "Absolute"; + KeyValueSet("co","A"); // remember coordinates = A + Clr(); + } + else if (message == "Absolute"){ + relAbs = "Relative"; + KeyValueSet("co","R"); // remember coordinates = R + Clr(); + } + else if (message == "Recording"){ + DoMenuForCommands(); // show them the recording menu + } + else if (message == "Owner Only") { + priPub = "Group"; + KeyValueSet("pr","1"); + + llOwnerSay("Group members have control"); + makeMainMenu(); + } + else if (message == "Group") { + priPub = "Owner Only"; + KeyValueSet("pr","0"); + llOwnerSay("Only you have control"); + makeMainMenu(); + } + else if (message == "Sensor") { + mSensor ="No Sensor"; + KeyValueSet("se", "off"); + llOwnerSay("Sensors now Off"); + makeMainMenu(); + } + else if (message == "No Sensor") { + mSensor ="Sensor"; + llOwnerSay("Sensors now On"); + KeyValueSet("se", "on"); + + integer count = checkNoteCards(); + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + DoProcessNPCLine(); + return; + } + if (Editor) { + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording and/or appearance, so you cannot start a NPC"); + makeMainMenu(); + } + else if (message == "Appearance") { + llRemoveInventory(Appearance); // delete the notecard + osAgentSaveAppearance(kUserKey,Appearance); // make the ntecard + llOwnerSay("Your outfit has been saved"); + makeMainMenu(); + } + else if (message == "Save") { + if (llGetListLength(lCommands) == 0) { + llOwnerSay("Nothing recorded, you need to make a recording first"); + makeMainMenu(); + return; + } + DoSave(); + } + else if (message == "Help"){ + llLoadURL(kUserKey,"Click to view help","http://www.outworldz.com/opensim/posts/NPC/"); + makeMainMenu(); + } + else if (message == "Start NPC") { + integer count = checkNoteCards(); + Stopped = FALSE; // Let's run the notecard + + if (Editor) { + DoProcessNPCLine(); + return; + } + + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + Stopped = FALSE; // Let's run the notecard + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording or maybe an appearance, so we cannot start a NPC"); + + } + else if (bNPC_STOP){ + bNPC_STOP = FALSE; + Kill(message); + } + else if (message == "More"){ + makeMenu(lMenu2); + } + else if (message == "<<") { + makeMenu(lAtButtons); + } + else if (message == "@comment"){ + Text("# ","Enter a comment",""); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@run"){ + lCommands += "@run=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@fly"){ + lCommands += "@fly=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@land"){ + lCommands += "@land=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@walk") { + lCommands += "@walk=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@sound"){ + Text("@sound=","Enter a sound name or UUID to trigger",""); + } + else if (message == "@randsound"){ + lCommands += "@randsound"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@say") { + Text("@say=","Enter what the NPC will say",""); + } + else if (message == "@whisper"){ + Text("@whisper=","Enter what the NPC will whisper",""); + } + else if (message == "@shout"){ + Text("@shout=","Enter what the NPC will shout",""); + } + else if (message == "@wander") { + Text("@wander=","Enter radius to wander","Enter number of wanders"); + } + else if (message == "@pause") { + Text("@pause=","Enter time to pause",""); + } + else if (message == "@rotate") { + Text("@rotate=","Enter degrees to rotate",""); + } + else if (message == "@sit"){ + Text("@sit=","Enter name of object to sit on",""); + } + else if (message == "@cmd"){ + Text("@cmd=","Enter cjhannel to speak on","Enter text to speak"); + } + else if (message == "@stand"){ + lCommands += "@stand\n"; + llOwnerSay("Stand Recorded"); + makeMenu(lAtButtons); + } + else if (message == "@animate"){ + Text("@animate=","Enter animation name to play","Enter time to play the animation"); + } + else if (message == "@speed"){ + Text("@speed=","Enter a speed for the NPC, 1=100% normal speed, 0.5=50% speed",""); + } + else if (! llStringLength(sParam2)) { + lCommands += sCommand + message + "\n"; + llOwnerSay("Recorded"); + makeMenu(lAtButtons); + } + else if (llStringLength(sParam2)){ + sCommand = sCommand + message + "|"; + llOwnerSay("Recorded"); + makeText(sParam2); + sParam2 = ""; + } + + + // Save NPC name + else if (MakeNotecard == STATE) { + sNPCName = message; // in case we need to kill it. + + vector vDest = (vector) Pos(); + + if (relAbs == "Relative") + { + vDest -= llGetPos(); // just an offset for relative + } + sNotecard = "@spawn=" + message + "|" + (string) vDest + "\n"; + integer i; + integer j = llGetListLength(lCommands); + for (; i < j; i++){ + // get the command to save to the notecard + string line = llList2String(lCommands,i); + if (relAbs == "Absolute") { + sNotecard += line; // add the un-modified string to the notecard + } else { + // since we have to record absolute coords since we do not know where the box goes until they press Save, + // we process the absolute to relative conversion for walks here + list parts = llParseString2List(line,["="],[]); //get the @command + + if (llList2String(parts,0) == "@walk") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@walk=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@fly") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@fly=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@run") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@run=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@land") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@land=" + (string) vec + "\n"; + } + else { + sNotecard += line; // add the un-modified string to the notecard + } + } + } + llRemoveInventory(Notecard); // delete the old notecard + osMakeNotecard(Notecard,sNotecard); // Makes the notecard. + llOwnerSay("Commands notecard has been written"); + STATE = 0; + } // MakeNotecard + } + + + + timer(){ + DEBUG("tick"); + + // if llDialog is up, kill the listener for the dialog box. + if (iHandle) { + llOwnerSay("Menu timed out"); + llListenRemove(iHandle); + iHandle = 0; + return; // ^^^^^^^^^^^^^^^^^^^^^^^ + } + // if NoBodyHome, we are sensing for an avatar + else if (NobodyHome == STATE) { + if (! llGetRegionAgentCount()) { + DoNobodyHome(); + return; // ^^^^^^^^^^^^^^^^^^^^^^^ + } + } + // if we are spawning, we need time to rez the NPC, then start processing NPC Commands. + else if (Spawning == STATE) { + STATE = 0; + TimerEvent(TIMER); + } + // We end aniamtions with a timer + else if (Animate == STATE){ + NPCAnimate(STAND); + TimerEvent(TIMER); + } + + else if (Walking == STATE) { + if (--iWaitCounter) { + if (llVecDist(osNpcGetPos(NPCKey()), newDest) > MAXDIST) { + return; + } + } + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 2) { + // nothing + } else if (walkstate == 3) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 4) { + llShout(FLIGHT,"landing"); + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } + } + // Wandering timer + else if (Wander == STATE) { + if (--iWaitCounter) { // wait 60 seconds to get to a destination. + if (llVecDist(osNpcGetPos(NPCKey()), vWanderPos) > MAXDIST) + return; + } + + // see if wander counter == 0, if so, stop walking, go to stand and process next line + if(RAMwc == 0) { + NPCAnimate(STAND); + DEBUG("Wander ended, calling DoProcessNPCLine"); + STATE = 0; + DoProcessNPCLine(); + return; + } + // one less time to wander around + RAMwc--; + NPCAnimate(STAND); + TimerEvent(TIMER); + DoWanderhold(); + return; + } + // Wandering requires us to re-wander when we reach a destination + else if (WanderHold == STATE) { + DoWander(); + TimerEvent(TIMER); + return; + } + else if (DoProcess == STATE) { + TimerEvent(QUICK); + } + + STATE = 0; + + // We always process a NPC line at end of timer. + DEBUG("Tick end, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } + + // sensors are used for sitting on prims + sensor(integer num) { + osNpcSit(NPCKey(), llDetectedKey(0), OS_NPC_SIT_NOW); + DEBUG("Seated, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } + no_sensor(){ + DEBUG ("no seat located, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } + + + link_message(integer sender, integer num, string str, key id){ + DEBUG("Command In:" + str); + if (str=="@go") { + Stopped = FALSE; // Let's run the notecard + DEBUG("@go approved, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } else { + if (Stopped) + { + Stack += [str]; // take anything, the controller will filter away non @ stuff + DoProcessNPCLine(); + } else { + Stack += [str]; // take anything, the controller will filter away non @ stuff + TimerEvent(TIMER); + } + } + } + +} + + + diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.3.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.3.lsl new file mode 100644 index 00000000..a38e1f6e --- /dev/null +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.3.lsl @@ -0,0 +1,1515 @@ +// :SHOW:0 +// :CATEGORY:NPC +// :NAME:All In One NPC Recorder and Player +// :AUTHOR:Ferd Frederix +// :KEYWORDS:NPC, Puppeteer +// :CREATED:2013-09-08 18:27:47 +// :EDITED:2015-09-17 08:21:19 +// :ID:27 +// :NUM:1812 +// :REV:3.3 +// :WORLD:OpenSim +// :DESCRIPTION: +// All in one NPC recorder player. +// Supports both absolute and relative paths and many new commands +// Add animations named "Fly, Walk, Stand and Run" +// Click Prim to use. +// Should be worn as a HUD to record. +// Put it on the ground and click Sensor or Start NPC when done. +// :CODE: + +FOR DEBUG PURPOSES - DO NOT USE - USE LATER VERSIONS ONLY!!! + + +// This is Rev 3.3 07/19/2015 + +// Revision History +// Rev 1.1 10-2-2014 @Sit did not work. Minor tweaks to casting for lslEditor +// Rev 1.2 10-14-2014 @ sit had wrong type. +// Rev 1.3 relative movement fixed for @fly +// Rev 1.4 4-3-2014 allow anyone to use this, non owners and non group members can only start and stop. +// Rev 1.5 5-17-2014 set sensor to auto start on reboot of sim +// Rev 1.6 5-24-2014 move menu so you can get it by touching, removed many of the KeyValues to RAM for efficiency +// Rev 1.7 CHANGED_REGION_START, not CHANGED_REGION_START (Opensim difference) +// Rev 1.8 tuned up Kill NPC, added more flexible upgrader +// Rev 1.9 Better script injection by link message// Rev 2.0 Added osSetSpeed so you can speed up or slow down an NPC. +// Rev 2.1 No laggy sensor used exept to sit on stuff +// Rev 2.2 Various sensor fixes +// Rev 2.3 Sets No Sensor in menu, must be started by hand +// Rev 2.4 - reserved for patches to 2.3 if needed +// Rev 3.0 Refactor out into subs, not states to make command injection easier +// New command: @appearance=Notecardname so you can switch to a new notecard on the fly +// New command: @speed=1.0 which slows up ( < 1 ) or speeds up ( > 1) +// Rev 3.1 Commands are not interruptible by Link Message +// Rev 3.2 Sensor patches for consistency in removing the NPC +// Rev 3.3 Added Touch command by Neo.Cortex@hbase42/hopto/org:8002 +// Added Menu 3 for notecard and appearance commands +//*******************************************************************// + +// Instructions on how to use this is at http://www.outworldz.com/opensim/posts/NPC/ +// This is an OpenSim-only script. +// Author: Ferd Frederix aka Fred Beckhusen - fred@mitsi.com + +//////////////////////////////////////////////////////////////////////////////////////////// +// Original code was Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // +/////////////////////////////////////////////////////////////////////////////////////////// +// Please see: http://www.gnu.org/licenses/gpl.html for legal details, // +// rights of fair usage, the disclaimer and warranty conditions. // +/////////////////////////////////////////////////////////////////////////////////////////// +// The original NPC controller was from http://was.fm/opensim:npc +// Extensive additions and bug fixes by Fred Beckhusem, aka Ferd Frederix, fred@mitsi.com +// llSensor had two params swapped +// @Wander would wander where it had rezzed, not where it was. +// There was no 'no_sensor' event in sit, so if a @sit failed, the NPC got stuck +// The animation and walks always stopped old, then started new. It should be start new, then stop old so the default stand would be suppressed. +// New code: +// Merged with new Route recorder and notecard writer +// If the NPC failed to reach a destination it never moved on. Added WAIT global to tune this +// Exposed many tunable variables and ported the code to LSLEditor. +// Added floating point to times in notecard. + +// Added @sound, @randsound, @whisper, @shout, and @cmd controls. +// +// notecards integers are not floats for better control +// +// Link Messages may be used to perform external control by injecting @commands into the stream of actions +// Example: +// To chat something, such as with a chat robot +// llMessageLinked(LINK_SET,0,"@npc_say=Hello",""); + +// This script assumes that NPCs and OSSl scripting is enabled in the OpenSim configuration. +// In order to enable them, the following changes must be made in the OpenSim.ini configuration file: +// +// ; Turn on OSSL +// AllowOSFunctions = true +// OSFunctionThreatLevel = Severe + +//[NPC] +// ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} +// Enabled = true +// +// and then the server has to be restarted. + + +// Commands: All commands begin with an @ sign. All other lines are ignored +// @commands may have optional parameters. The syntax is always: +// @cmd=parm1|parm2 +// NaN in the table below meand Not a Number. This means there is no parameter + +//Command First Parameter Second Parameter Description +//@spawn name location (vector) Rezzes an NPC with name at a location. +//@appearance NoteCardName NaN switch the NPC appearance to a new notecard +//@walk destination (vector) NaN Makes the NPC walk to destination. +//@fly destination (vector) NaN Makes the NPC fly to destination. +//@land destination (vector) NaN Makes the NPC land at destination. +//@say string NaN Makes the NPC speak a phrase. +//@whisper string NaN Makes the NPC whisper a phrase. +//@shout string NaN Makes the NPC shout a phrase. +//@pause seconds (float) NaN Makes the NPC wait for a multiple of seconds. +//@wander radius (float) cycles (integer) Makes the NPC wander in radius, for cycles seconds. +//@delete NaN NaN Removes the NPC. Requires a link message to continue +//@goto label (string) NaN Jump to the label label in the script. +//@animate animation (string) time (float) Makes the NPC trigger the animation animation for time seconds. +//@sound sound_name NaN plays a sound from inventory +//@randsound NaN NaN Plays a random sound from inventory +//@rotate degrees (float) NaN Rotate the NPC degrees around the Z axis. +//@sit primitive name NaN Sit on a primitive with a given name. +//@touch primitive name NaN Touch on a primitive with a given name. +//@stand NaN NaN If sitting on a primitive, stand up. +//@cmd channel (integer) string Says string on channel, for controlling external gadgets +//@stop NaN NaN Halts the NPC script indefinitely. Can be started with a link message +//@go NaN NaN Continues on next notecard line, for use in link messages +//@speed speed (float) NaN from 0 to N, where 1.0 ius a normal speed of an avatar. 0.2 is a turtle. +//@notecard notename (string) NaN load a new Path notecard + + +////////////////////////////////////////////////////////// +// DEBUG // +////////////////////////////////////////////////////////// +integer debug = FALSE; // set to TRUE or FALSE for debug chat on various actions +integer Editor = FALSE; // set to to TRUE to working in LSLEditor, FALSE for in-world. + // you must also include the NPC commands found in the other script since LSLEditor does not support OpenSim +integer iTitleText = TRUE; // set to TRUE to see debug info in text above the controller + +////////////////////////////////////////////////////////// +// TUNABLE CONFIGURATION // +////////////////////////////////////////////////////////// +float TIMER = 0.5; // how often the system checks the distance traveled. Fastest you can go is 0.5 seconds +float QUICK = 0.020; // when we need to move to the next state, we use a QUICK timer +string Appearance = "!Appearance"; // The name of the recorded Appearance notecard +string Notecard = "!Path"; // The name of the recorded routes +integer allowUsers = FALSE; // If true, any user can get a Start NPC and Stop NPC menu. Only groups and owners can get all commands if TRUE, or FALSE +float MAXDIST = 2.0; // how close a NPC has to get to a dest pos to continue to next state. Do not lower this too much, as it may miss the target +integer WANDERRAND = TRUE; // set to TRUE and they will pause during wanders a random number of seconds +float WANDERTIME = 3.0; // how long they stand after each @wander,if WANDERRAND is FALSE. If WANDERRAND is TRUE, this is the max time +integer WAIT = 30; // wait for this number of seconds for the NPC to reach a destination (for safety). If it fails to reach a target, it will move on after this time. +float RANGE = 50; // 1 to N meters - anyone this close to the controller will start NPCS if Sensor button is clicked +float REZTIME = 5.0; // wait this long for NPC to rez in, then start the process +string STAND = "Stand"; // the name of the default Stand animation +string WALK = "Walk"; // the name of the default Walk animation +string FLY = "Fly"; // the name of the default Fly animation +string RUN = "Run"; // the name of the default Run animation +string LAND = "Land"; // the name of the default land animation ( for birds only) +float OffsetZ = 0.5; // appear 0.5 meter above ground, this is added to all destinations to keep them from sinking in. +float SPEEDMULT =1.0; // 1.0 = regular vatar speed. Smaller numbers slow down walks. Large numbers speed them up. +integer FLIGHT = 299; // For controllign wings. A channel that is shouted at when flight starts and ends. "flying" or "landing" + +// DESCRIPTIONS FIELDS HAVE TO SURVIVE A RESET +// These vars are stored by saving them with KeyValueSet +// "pr" is a 0 if it is set for Owner Only, 1 for Group control +// "se" is "on" if Started +// "co" = "R" or "A" for relative or absolute addressing mode +// "key" = NPC key + +// These Globals used to be stored in description. Moved to RAM in V1.6 +float RAMPause; // @pause param +float RAMwd ; // @wander distance +integer RAMwc; // @wander count +float RAMrot; // @rotate +string RAMsit; // @sit primname +string RAMtouch; // @touch primname +string RAManimationName; // @animate animation (string) time (float) +float RAManimationTime; + +// other globals section +integer iChannel; // a listen channel, randomly assigned +integer iHandle; // the handle to it + +// NPC controls +vector newDest ; // tmp storage for the walks +integer iWaitCounter ; // wait for this number of seconds for the NPC to reach a desrtination +string sNPCName; // the name of the NPC that may be in world. So we can remove it. +integer bNPC_STOP = FALSE; // boolean to reuse a listener +integer Stopped = FALSE; // set to TRUE by link messages so we do not remember them +float fTimerVal ; // how long we wait when wandering (calculated) + +// OS_NPC_CREATOR_OWNED will create an 'owned' NPC that will only respond to osNpc* commands issued from scripts that have the same owner as the one that created the NPC. +// OS_NPC_NOT_OWNED will create an 'unowned' NPC that will respond to any script that has OSSL permissions to call osNpc* commands. +integer NPCOptions = OS_NPC_CREATOR_OWNED; // only yhe owner of this box can control this NPC. + +integer walkstate = 0; // helps us reshare the walk state for run, fly and land - a bit of a hack, but it saves RAM. Has to be done this way because some bits of NPCWalkOption are asserted as 0 + +integer NPCWalkOption; // Some notes for what happens to NPCWalkOption: +// OS_NPC_FLY - Fly the avatar to the given position. The avatar will not land unless the OS_NPC_LAND_AT_TARGET option is also given. +// OS_NPC_NO_FLY - Do not fly to the target. The NPC will attempt to walk to the location. If it's up in the air then the avatar will keep bouncing hopeless until another move target is given or the move is stopped +//OS_NPC_LAND_AT_TARGET - If given and the avatar is flying, then it will land when it reaches the target. If OS_NPC_NO_FLY is given then this option has no effect. +// OS_NPC_RUNNING - if given, NPC avatar moves at running/fast flying speed, otherwise moves at walking/slow flying speed. + +// menus +string mSensor="Sense is Off"; // Sensor or "No Sensor" + +list lAtButtons = ["Menu","-", ">>", "@run", "@walk", "@fly", "@land", "@wander", "@sit", "@stand","@animate","@rotate"]; +list lMenu2 = ["<<", "@comment", ">>>", "@stop", "@say", "@whisper","@shout","@sound","@randsound","@cmd", "@pause", "@delete"]; +list lMenu3 = ["<<<","@notecard","@appearance", "@touch", "@speed", "-", "-","-", "-", "-", "-", "-" ]; + +string sCommand; // place to store a command for two-prompted ones +string sParam2; // place to store a prompt for two-prompted ones +string priPub = "Owner Only"; // Private or Group +key kUserKey; // the person who is controlling the avatar, not the Owner +// the command lists +list lCommands; // commands are stored here +list lNPCScript; // Storage for the NPC script. +string npcAction; // Storage for the next action. @cmd=0|hello, this becomes @cmd +string npcParams; // Storage for the param, @cmd=0|hello, this becomes 0|hello + +// misc vars +string sNotecard; // commands are stored here temporarily for dumping +vector vWanderPos; // a place to wander to +string lastANIM ; // last animation run +// Sensor +integer avatarPresent; // Sensor sets this flag when people are within Range. + +// Coordinate control +vector vInitialPos ; // Vector that will be filled by the script with the initial starting position in region coordinates. +vector vDestPos = ZERO_VECTOR; // Storage for destination position. +string relAbs = "Relative"; // absolute vs relative positioning + + +// STATES +integer MENU ; // processing a dialog box state, may be concurrent with STATE +integer STATE; // state storage +integer MakeNotecard = 1; // displaying a text box for NPC name +integer RecordPath = 2; // displaying a path notecard menu +integer NobodyHome = 3; // looking for an avatar +integer Spawning = 4; // spawning an avatar +integer Animate = 5; // animation timer needed +integer Walking = 6; // Hey! I am walking here! +integer Wander = 7; // Wandering around neeeds a timer, too +integer WanderHold = 8; // We reached a wander point +integer DoProcess = 9; // Set this to make it process a new command + +key gNpcKey = NULL_KEY; // global key storage for the one NPC, to save CPU cycles +list Stack ; // a command stack from link message input + +integer SensorFunc = 0; // define which function shall be triggered inside the sensor function + // 0 means none, 1 sit, 2 touch +/////////////////////////////////////////////////////////////////////////// +// FUNCTIONS // +/////////////////////////////////////////////////////////////////////////// + +// Do* functions are much like states from the old scripts. + +// Save a Path notecard +DoSave() +{ + STATE = MakeNotecard; + makeText("Stand where you want the NPC to appear, and enter the NPC Name"); +} + +// This function is used to record the path for the NPC +// Each command can take 0, 1, or 2 params +DoMenuForCommands() { + makeMenu(lAtButtons); +} + + +// No one is here when sensors were on, so we kill off the NPC +DoNobodyHome() +{ + DEBUG("Nobody Home"); + STATE = NobodyHome; + if (NPCKey() != NULL_KEY) { + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + } + TimerEvent(5); // keep ticking to sense avatars +} + +// Create a NPC +DoSpawn() { + DEBUG("state spawn"); + + // see if there is already one out there. + if (NPCKey() != NULL_KEY) + return; + + STATE = Spawning; + + list name = llParseString2List(sNPCName, [" "], []); + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + vInitialPos += llGetPos(); + } + + DEBUG("Rez NPC:" + (string) vInitialPos); + key aKey = osNpcCreate(llList2String(name, 0), llList2String(name, 1), vInitialPos, Appearance, NPCOptions); + + SaveKey(aKey ); // save in desceription and global, too + + osSetSpeed(aKey,SPEEDMULT); // 1.9 speed multiplier + TimerEvent(REZTIME); + NPCAnimate(STAND); +} + +DoRotate() { + DEBUG("state rotate"); + osNpcSetRot(NPCKey(), llEuler2Rot(<0,0,RAMrot> * DEG_TO_RAD)); +} + +DoSit() { + DEBUG ("state sit - looking for " + RAMsit); + SensorFunc = 1; //triggers osNpcSit + llSensor(RAMsit, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +DoTouch() { + DEBUG ("state touch - looking for " + RAMtouch); + SensorFunc = 2; //triggers osNpcTouch + llSensor(RAMtouch, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +DoStand() { + + DEBUG("state stand"); + osNpcStand(NPCKey()); +} + + +DoAnimate() { + + DEBUG("state animate"); + STATE = Animate; + NPCAnimate(RAManimationName); + if (RAManimationTime < 1) + RAManimationTime = 1; + TimerEvent(RAManimationTime); +} + +DoWalk() { + + DEBUG("NPCWalkOption = " + (string) NPCWalkOption); + STATE = Walking; + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(WALK); + } else if (walkstate == 2) { + llShout(FLIGHT,"flying"); + NPCAnimate(FLY); + } else if (walkstate == 3) { + NPCAnimate(RUN); + } else if (walkstate == 4) { + NPCAnimate(LAND); + } + newDest = vDestPos ; + newDest.z += OffsetZ; + + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + newDest += llGetPos(); + } + + DEBUG("Moveto:" + (string) newDest); + osNpcMoveToTarget(NPCKey(), newDest, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + + +DoWander(){ + DEBUG("state wander"); + STATE = Wander; + + vector point = CirclePoint(RAMwd); + DEBUG("CirclePoint:" + (string) point); + vWanderPos = vDestPos + point; + DEBUG("vWanderPos:" + (string) vWanderPos); + + fTimerVal = WANDERTIME; // default time to pause after each wander + if (WANDERRAND) + fTimerVal = llFrand(WANDERTIME) + 1; // override, they want random times + + NPCAnimate(WALK); + + DEBUG("Wander to:" + (string) vWanderPos); + + osNpcMoveToTarget(NPCKey(), vWanderPos, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + +DoWanderhold() { + + DEBUG("Wander Hold"); + STATE = WanderHold; + + // now that we have reached a wander spot, slow the timer down to the desired value + TimerEvent(fTimerVal); +} + +// @pause=10 will do nothing for 10 seconds +DoPause() { + + DEBUG("state pause"); + if (RAMPause < 0.1) + RAMPause = 0.1; + + TimerEvent(RAMPause); +} + + +// @stop makes the NPC stop moving in whatever state it is in. You have to linkmessage to get moving again +DoStop() { + DEBUG("NPC is Stopped"); + Stopped = TRUE; // Link controlled - we mnust have a @go to continue with notecards + TimerEvent(0); +} + + +// @delete removes the NPC forever. Next command starts it up again at the beginning +DoDelete() { + DEBUG("state delete"); + + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + lNPCScript = []; // next command starts the NPC into action at the beginning + +} + +// change the appearance of the NPC +DoAppearance(string notecard) { + DEBUG("state appearance"); + if (llGetInventoryType(notecard) == INVENTORY_NOTECARD){ + DEBUG("Load appearance " + notecard); + osNpcLoadAppearance(NPCKey(),notecard); + } +} + +// Change the avatar speed +DoSpeed(string speed) { + float newspeed = (float) speed; + if (newspeed > 0.1 && newspeed < 5.0) // sanity check + osSetSpeed(NPCKey(),newspeed); +} +DoNewNote (string card) { + DEBUG("Load Notecard " + card); + NPCReadNoteCard(card); + Stopped = FALSE; +} + +// This loops over the notecard, processing each command +DoProcessNPCLine() { + DEBUG("ProcessNPCLine"); + STATE = 0; + + // auto load a notecard + if (! llGetListLength(lNPCScript)) { + DEBUG("Read Notecard"); + NPCReadNoteCard(Notecard); + Stopped = FALSE; + } + + // look for link messages on the stack + string next = llList2String(Stack,0); // lets see if there is anithing from a link message + if (llStringLength(next)) + { + Stack = llDeleteSubList(Stack,0,0); + ProcessCmd(next); //lets do this command instead. + return; + } + + // @stop issued? + if (Stopped) { + TimerEvent(0); + DEBUG("Waiting for input"); + return; + } + + // No, we have an @go for liftoff + next = llList2String(lNPCScript, 0); // get the next command + DEBUG("Execute:" + next); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); // delete it + + if (llGetListLength(lNPCScript) == 0) { + DEBUG("EOF"); + } + ProcessCmd(next); + +} + +ProcessCmd(string cmd) { + + DEBUG("ProcessCmd:" + cmd); + + if (llGetSubString(cmd, 0, 0) != "@") { + DEBUG("ignoring"); + STATE = DoProcess; + TimerEvent(QUICK); // this is so we do not recurse the stack + return; + } + + list data = llParseString2List(cmd, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data, 0), STRING_TRIM)); + + DEBUG("Action:" + npcAction); + npcParams = llStringTrim(llList2String(data, 1), STRING_TRIM); + + @commands; + + ProcessSensor(); + if (! avatarPresent){ + DoNobodyHome(); + DEBUG("No avatar nearby"); + return; + } else { + if (llStringLength(sNPCName)) { + DoSpawn(); + } + } + + if(npcAction == "@spawn") { + DEBUG("@spawn"); + list spawnData = llParseString2List(npcParams, ["|"], []); + sNPCName =llList2String(spawnData, 0); // V 1.6 name in RAM + + list spawnDest = llParseString2List(llList2String(spawnData, 1), ["<", ",", ">"], []); + vInitialPos.x = llList2Float(spawnDest, 0); + vInitialPos.y = llList2Float(spawnDest, 1); + vInitialPos.z = llList2Float(spawnDest, 2); + DoSpawn(); + + return; + } + else if(npcAction == "@stop") { + DEBUG("@stop"); + DoStop(); + return; + } + else if(npcAction == "@goto") { + DEBUG("goto"); + integer lastIdx = llGetListLength(lNPCScript)-1; + lNPCScript = llDeleteSubList(lNPCScript, lastIdx, lastIdx); + // Wind commands till goto label. + @wind; + string next1 = llList2String(lNPCScript, 0); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); + lNPCScript += next1; + if(next1 != npcParams) jump wind; + // Wind the label too. + next1 = llList2String(lNPCScript, 0); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); + lNPCScript += next1; + // Get next command. + list data1 = llParseString2List(next1, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data1, 0), STRING_TRIM)); + npcParams = llStringTrim(llList2String(data1, 1), STRING_TRIM); + // Reschedule. + jump commands; + } + else if(npcAction == "@sound") { + DEBUG("sound"); + llTriggerSound(npcParams,1.0); + } + else if(npcAction == "@randsound") { + DEBUG("@randsound"); + integer N = llGetInventoryNumber(INVENTORY_SOUND); + integer rand = llCeil(llFrand(N)) -1; // pick a random sound + string toPlay = llGetInventoryName(INVENTORY_SOUND,rand); + llTriggerSound(toPlay,1.0); + } + else if(npcAction == "@walk") { + DEBUG("@walk"); + GetDest(npcParams); + walkstate = 1;// walking + NPCWalkOption = OS_NPC_NO_FLY ; + DoWalk(); + return; + } + else if(npcAction == "@fly") { + GetDest(npcParams); + walkstate = 2;// flying + NPCWalkOption = OS_NPC_FLY ; + DoWalk(); + return; + } + else if(npcAction == "@run") { + DEBUG("@run"); + GetDest(npcParams); + walkstate = 3;// running + NPCWalkOption = OS_NPC_NO_FLY | OS_NPC_RUNNING; + DoWalk(); + return; + } + else if(npcAction == "@land") { + DEBUG("@land"); + GetDest(npcParams); + walkstate = 4;// landing + NPCWalkOption= OS_NPC_FLY | OS_NPC_LAND_AT_TARGET ; + DoWalk(); + return; + } + else if(npcAction == "@say") { + DEBUG("@say " + npcParams); + osNpcSay(NPCKey(), 0, npcParams); + } + else if(npcAction == "@shout") { + DEBUG("@shout"); + osNpcShout(NPCKey(),0, npcParams); + } + else if(npcAction == "@whisper") { + DEBUG("@whisper " + npcParams); + osNpcWhisper(NPCKey(),0, npcParams); + } + // speak a command on a channel, so you can open doors and control stuff. + else if(npcAction == "@cmd") { + DEBUG("@cmd"); + list dataToSpeak = llParseString2List(npcParams, ["|"], []); + string channel = llList2String(dataToSpeak,0); + DEBUG("Channel:"+(string) channel); + integer iChannel = (integer) channel; + string stringToSpeak = llList2String(dataToSpeak,1); + llSay(iChannel, stringToSpeak); + } + // stop everything + else if(npcAction == "@pause") { + DEBUG("@pause"); + RAMPause = (float) npcParams; + DoPause(); + return; + } + else if(npcAction == "@wander") { + DEBUG("@wander"); + list wanderData = llParseString2List(npcParams, ["|"], []); + RAMwd = (float) llList2String(wanderData, 0); + RAMwc = (integer) llList2String(wanderData, 1); + + vDestPos = osNpcGetPos(NPCKey()); // set the wander start + DEBUG("Starting at " + (string) vDestPos); + DoWander(); + return; + } + else if(npcAction == "@rotate") { + DEBUG("@rotate"); + RAMrot = (float) npcParams; + DoRotate(); + } + else if(npcAction == "@sit") { + DEBUG("@sit"); + RAMsit= npcParams; + DoSit(); + return; + } + else if(npcAction == "@touch") { + DEBUG("@touch"); + RAMtouch= npcParams; + DoTouch(); + return; + } + else if(npcAction == "@stand") { + DEBUG("@stand"); + DoStand(); + } + else if(npcAction == "@delete") { + DEBUG("@delete"); + DoDelete(); + return; + } + else if(npcAction == "@animate") { + DEBUG("@animate"); + list animateData = llParseString2List(npcParams, ["|"], []); + RAManimationName = llList2String(animateData, 0); + RAManimationTime = (float) llList2String(animateData, 1); + DoAnimate(); + return; + } + else if(npcAction == "@appearance" ) + { + DEBUG("@appearance"); + DoAppearance(npcParams); + } + else if (npcAction =="@speed") { + DEBUG("@speed"); + DoSpeed(npcParams); + } + else if (npcAction =="@notecard") { + DEBUG("@notecard"); + DoNewNote(npcParams); + Notecard = npcParams; + } + + STATE = DoProcess; + TimerEvent(QUICK); // yeah I know, not possible this fast, we just go as fast as we can go - this is so we do not recurse the stack +} + + + +/////////////////// UTILITY Functions, not state-like ////////////////// + +// DEBUG(string) will chat a string or display it as hovertext if debug == TRUE +DEBUG(string str) { + if (debug) + llOwnerSay( str); // Send the owner debug info so you can chase NPCS + if (iTitleText) + llSetText(str,<1.0,1.0,1.0>,1.0); // show hovertext +} + +GetDest(string npcParams) { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); +} + +NPCReadNoteCard(string Note) { + DEBUG("NPCReadNoteCard"); + lNPCScript = llParseString2List(osGetNotecard(Note), ["\n"], []); +} + +integer SenseAvatar() +{ + //Returns a strided list of the UUID, position, and name of each avatar in the region + list avatars = llGetAgentList(AGENT_LIST_REGION ,[]); + integer numOfAvatars = llGetListLength(avatars); + if (numOfAvatars == 0) + { + DEBUG("No people"); + return 0; + } + //DEBUG("Located " + (string)numOfAvatars + " avatars and NPC's"); + + integer nAvatars; + integer i; + for( i = 0;i < numOfAvatars; i++) { + key aviKey = llList2Key(avatars,i); + if (!osIsNpc(aviKey)) { + list detail = llGetObjectDetails(aviKey,[OBJECT_POS]); + vector pos = llList2Vector(detail,0); + float dist = llVecDist(pos, llGetPos()); + if (dist < RANGE) + { + nAvatars++; + DEBUG("In range:" + llKey2Name(aviKey)); + } + } + } + //DEBUG("Located " + (string) nAvatars + " avatars"); + return nAvatars; +} + +// return TRUE if the avatar is owner when private is set, or TRUE if the avatar is in the same group and GROUP is set. +integer checkPerms() { + + integer group = (integer) KeyValueGet("pr"); + if (! group) + priPub = "Owner Only"; + else + priPub = "Group"; + + + if (llDetectedKey(0) == llGetOwner()){ + kUserKey = llDetectedKey(0); + return TRUE; + } + + if ( group && llDetectedGroup(0)) { + kUserKey = llDetectedKey(0); + return TRUE; + } + kUserKey = llDetectedKey(0); + return FALSE; +} + + + +NPCAnimate(string anim) +{ + DEBUG("Start Anim: " + anim); + if (llGetInventoryType(anim) == INVENTORY_ANIMATION ) { + + if (lastANIM != anim) { + if(llStringLength(lastANIM)) { + osNpcStopAnimation(NPCKey(), lastANIM); + } + osNpcPlayAnimation(NPCKey(), anim); + lastANIM = anim; + } + } else { + llSay(DEBUG_CHANNEL, "No animation named " + anim); + } +} + + +TimerEvent(float timesent) +{ + DEBUG("Setting timer: " + (string) timesent); + llSetTimerEvent(timesent); +} + +// Kill a NPC by Name +Kill(string param) +{ + integer count; + list avatars = osGetAvatarList(); // Returns a strided list of the UUID, position, and name of each avatar in the region except the owner.\ + integer i; + integer j = llGetListLength(avatars); + for (i=0 ; i <= j; i+=3){ + + string desired = llList2String(avatars,i+2); + desired = llStringTrim(desired,STRING_TRIM); // should not be needed but is needed + + if (desired == param){ + vector v = llList2Vector(avatars,i+1); + key target = llList2Key(avatars,i); // get the UUID of the avatar + osNpcRemove(target); + SaveKey(NULL_KEY ); + llOwnerSay("Removed " + param+ " at location " + (string) v); + count++; + } + } + if (count) + llOwnerSay("Removed " + (string) count + " NPC's"); + else + llOwnerSay("Could not locate " + param); +} + + +// return a String for the position we are at. Strings used as the caller wants strings +string Pos() +{ + vector where = llGetPos(); // find the box position + + where.z += OffsetZ; // use the ground position + an offset + + if (Editor) + where = <128,128,31 + llFrand(1)>; // center of sim for editing + + // if attached the height will be too high by 1/2 the agent size + if (llGetAttached()) { + vector size = llGetAgentSize(llGetOwner()); + float Z = size.z; + where.z -= Z/2; + } + + // DEBUG("Pos= " + (string) where); + return (string) where; +} + +// setup a menu with a timer for timeouts, called by all make*() +menu() +{ + llListenRemove(iHandle); + iChannel = llCeil(llFrand(100000) + 20000); + iHandle = llListen(iChannel,"","",""); + TimerEvent(30.0); + MENU = TRUE; +} + +// make a text box +makeText(string Param) +{ + menu(); + llTextBox(kUserKey, Param, iChannel); +} + +// top level menu +makeMainMenu() +{ + menu(); + list buttons = ["Appearance","Recording","Save","Help","-","Erase RAM", priPub,relAbs,"-","Stop NPC",mSensor,"Start NPC"]; + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Records",buttons,iChannel); +} + + +// Rev 1.4 +// top level menu for non group/ non owners +makeUserMenu() +{ + if (!allowUsers) return; + + menu(); + list buttons = ["Start NPC","Stop NPC"]; + llDialog(kUserKey,"Choose",buttons,iChannel); +} + + + +// programmable menu for @commands +makeMenu(list buttons) +{ + menu(); + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Record",buttons,iChannel); +} + + +// make one or two text boxes with prompts +Text(string cmd, string p1, string p2) +{ + sCommand = cmd; + sParam2 = ""; + if (llStringLength(p2)) + sParam2 = p2; + + makeText(p1); +} + +// Set the Avatar Present flag - if sensors are off and we are forece run, there will be one present. +ProcessSensor() +{ + integer SensorOn; + if ("on" == KeyValueGet("se")) + { + SensorOn = TRUE; // we need to scan for avatars + } else { + SensorOn = FALSE; // we need to scan for avatars + } + //DEBUG("Sensor:" + (string) SensorOn); + + integer n = SenseAvatar(); + + if (SensorOn && n) + avatarPresent = TRUE; // someone is here and we need to tell the system to run + else if (SensorOn && !n) + avatarPresent = FALSE; // someone is not here and we need to tell the system to stop + else if (!SensorOn) // Neo: maybe this fixes the weird sensor behaviour: just act as if noone is here if sensor is off + avatarPresent = TRUE; // Neo: i didnt quite understand this -> someone is effectivley always here when sensor is off and we are running + + //DEBUG("Avatar Present: " + (string) avatarPresent); +} + +vector CirclePoint(float radius) { + float x = llFrand(radius *2) - radius; // +/- radius, randomized + float y = llFrand(radius *2) - radius; // +/- radius, randomized + return ; // so this should always happen +} + +string KeyValueGet(string var) { + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k != var) jump continue; + //DEBUG("got " + var + " = " + llList2String(data, 1)); + return llList2String(data, 1); + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + return ""; +} + +KeyValueSet(string var, string val) { + + //DEBUG("set " + var + " = " + val); + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + if(llGetListLength(dVars) == 0) + { + llSetObjectDesc(var + "=" + val); + return; + } + list result = []; + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k == "") jump continue; + if(k == var && val == "") jump continue; + if(k == var) { + result += k + "=" + val; + val = ""; + jump continue; + } + string v = llList2String(data, 1); + if(v == "") jump continue; + result += k + "=" + v; + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + if(val != "") result += var + "=" + val; + llSetObjectDesc(llDumpList2String(result, "&")); +} + + +// clear RAM +Clr() { + + lCommands = []; + llOwnerSay("RAM Memory cleared. Notecards, if any, are not modified."); + makeMainMenu(); +} + +integer checkNoteCards() +{ + // Check that they have saved an Appeaance and Path notecard + integer num = llGetInventoryNumber(INVENTORY_NOTECARD); // how many notecards overall + + integer i; + integer count; + for (; i < num; i++){ + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Notecard) + count++; + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Appearance) + count++; + } + DEBUG("Checked " + (string) count + " Notecards"); + // if we have both, run the NPC + return count; +} + +Update(string SName) { + + // delete all NPC*scripts except myself + integer i; + integer j = llGetInventoryNumber(INVENTORY_SCRIPT); + for (i = 0; i < j; i++) { + string name = llGetInventoryName(INVENTORY_SCRIPT,i); + string match = llGetSubString(name,0,2); + if (match == SName && llGetScriptName() != name) + { + llRemoveInventory(name); + llOwnerSay("Upgraded"); + } + } + +} + +// Get all default saved params from the Description +GetSwitches() +{ + string rA = KeyValueGet("co"); // Get the remembered menu setting for Abs Vs Relative + if (rA == "A") + relAbs = "Absolute"; + else if (rA == "R") + relAbs = "Relative"; + else + relAbs = "Absolute"; + + + // reenable NPC if sensor is on. + if ("on" == KeyValueGet("se")) + { + mSensor = "Sense is On"; + ProcessSensor(); // fake 1 avatar to get it rezzed + } else { + mSensor = "Sense is Off"; + } + } + + +SaveKey(key akey) +{ + DEBUG("Saving Key of " + (string) akey); + KeyValueSet("key", akey); + if (akey != (key) KeyValueGet("key") ) + { + DEBUG("Fatal error, cannot save key"); + } + gNpcKey = akey; +} + + +key NPCKey() +{ + key akey = gNpcKey; // from cached copy + // gNpcKey saves a lot of CPU processing by caching the key, if blank we get it from the description + if (gNpcKey == NULL_KEY) + { + DEBUG("Get DKey"); + akey = KeyValueGet("key"); // from Description of the prim + } + DEBUG("NPC KEY:" + (string) akey); + return akey; +} + + +/////////////////// CODE BEGINS ////////////////// + + +default +{ + changed(integer change) { + if(change & CHANGED_REGION_START) { + llResetScript(); + } + } + + on_rez(integer start_param) + { + llResetScript(); + } + + state_entry() { + + llSetText("",<1,1,1>,1.0); // clr all hovertext- we may not be using it. + DoDelete(); // kill any NPC that is out running + Update("NPC"); // If dragged and ropped into a prim with any script named "NPC...", this will replace it. + GetSwitches(); // Get all default saved params from the Description + llSetTimerEvent(TIMER); + } + + + touch_start(integer n) + { // if touched, make a menu + + if (checkPerms()) { + if (RecordPath == STATE) { + makeMenu(lAtButtons); + } else { + makeMainMenu(); + } + } else { + makeUserMenu(); + } + } + + // menu listener + listen(integer iChannel, string name, key id, string message) { + + if (MENU) { + llListenRemove(iHandle); + MENU = 0; // menu is off + iHandle = 0; + } + + if (message == "Stop NPC") + { + lNPCScript = []; // force reload of notecard + if (NPCKey() != NULL_KEY){ + Kill(sNPCName); + sNPCName = ""; + } else { + bNPC_STOP = TRUE; + makeText("Enter name of an NPC to stop"); + } + } + else if (message == "Menu" ) { + makeMainMenu(); + } + else if (message == "Erase RAM"){ + Clr(); + } + else if (message == "Relative"){ + relAbs = "Absolute"; + KeyValueSet("co","A"); // remember coordinates = A + Clr(); + } + else if (message == "Absolute"){ + relAbs = "Relative"; + KeyValueSet("co","R"); // remember coordinates = R + Clr(); + } + else if (message == "Recording"){ + DoMenuForCommands(); // show them the recording menu + } + else if (message == "Owner Only") { + priPub = "Group"; + KeyValueSet("pr","1"); + + llOwnerSay("Group members have control"); + makeMainMenu(); + } + else if (message == "Group") { + priPub = "Owner Only"; + KeyValueSet("pr","0"); + llOwnerSay("Only you have control"); + makeMainMenu(); + } + else if (message == "Sense is On") { + mSensor ="Sense is Off"; + KeyValueSet("se", "off"); + llOwnerSay(mSensor); + makeMainMenu(); + } + else if (message == "Sense is Off") { + mSensor ="Sense is On"; + llOwnerSay(mSensor); + KeyValueSet("se", "on"); + + integer count = checkNoteCards(); + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + DoProcessNPCLine(); + return; + } + if (Editor) { + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording and/or appearance, so you cannot start a NPC"); + makeMainMenu(); + } + else if (message == "Appearance") { + llRemoveInventory(Appearance); // delete the notecard + osAgentSaveAppearance(kUserKey,Appearance); // make the ntecard + llOwnerSay("Your outfit has been saved"); + makeMainMenu(); + } + else if (message == "Save") { + if (llGetListLength(lCommands) == 0) { + llOwnerSay("Nothing recorded, you need to make a recording first"); + makeMainMenu(); + return; + } + DoSave(); + } + else if (message == "Help"){ + llLoadURL(kUserKey,"Click to view help","http://www.outworldz.com/opensim/posts/NPC/"); + makeMainMenu(); + } + else if (message == "Start NPC") { + integer count = checkNoteCards(); + Stopped = FALSE; // Let's run the notecard + + if (Editor) { + DoProcessNPCLine(); + return; + } + + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + Stopped = FALSE; // Let's run the notecard + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording or maybe an appearance, so we cannot start a NPC"); + + } + else if (bNPC_STOP){ + bNPC_STOP = FALSE; + Kill(message); + } + else if (message == ">>"){ + makeMenu(lMenu2); + } + else if (message == ">>>"){ + makeMenu(lMenu3); + } + else if (message == "<<") { + makeMenu(lAtButtons); + } + else if (message == "<<<") { + makeMenu(lMenu2); + } + else if (message == "@comment"){ + Text("# ","Enter a comment",""); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@run"){ + lCommands += "@run=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@fly"){ + lCommands += "@fly=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@land"){ + lCommands += "@land=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@walk") { + lCommands += "@walk=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@sound"){ + Text("@sound=","Enter a sound name or UUID to trigger",""); + } + else if (message == "@randsound"){ + lCommands += "@randsound"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@say") { + Text("@say=","Enter what the NPC will say",""); + } + else if (message == "@whisper"){ + Text("@whisper=","Enter what the NPC will whisper",""); + } + else if (message == "@shout"){ + Text("@shout=","Enter what the NPC will shout",""); + } + else if (message == "@wander") { + Text("@wander=","Enter radius to wander","Enter number of wanders"); + } + else if (message == "@pause") { + Text("@pause=","Enter time to pause",""); + } + else if (message == "@rotate") { + Text("@rotate=","Enter degrees to rotate",""); + } + else if (message == "@sit"){ + Text("@sit=","Enter name of object to sit on",""); + } + else if (message == "@touch"){ + Text("@touch=","Enter name of object to touch",""); + } + else if (message == "@cmd"){ + Text("@cmd=","Enter cjhannel to speak on","Enter text to speak"); + } + else if (message == "@stand"){ + lCommands += "@stand\n"; + llOwnerSay("Stand Recorded"); + makeMenu(lAtButtons); + } + else if (message == "@animate"){ + Text("@animate=","Enter animation name to play","Enter time to play the animation"); + } + else if (message == "@speed"){ + Text("@speed=","Enter a speed for the NPC, 1=100% normal speed, 0.5=50% speed",""); + } + else if (! llStringLength(sParam2)) { + lCommands += sCommand + message + "\n"; + llOwnerSay("Recorded"); + makeMenu(lAtButtons); + } + else if (llStringLength(sParam2)){ + sCommand = sCommand + message + "|"; + llOwnerSay("Recorded"); + makeText(sParam2); + sParam2 = ""; + } + + + // Save NPC name + else if (MakeNotecard == STATE) { + sNPCName = message; // in case we need to kill it. + + vector vDest = (vector) Pos(); + + if (relAbs == "Relative") + { + vDest -= llGetPos(); // just an offset for relative + } + sNotecard = "@spawn=" + message + "|" + (string) vDest + "\n"; + integer i; + integer j = llGetListLength(lCommands); + for (; i < j; i++){ + // get the command to save to the notecard + string line = llList2String(lCommands,i); + if (relAbs == "Absolute") { + sNotecard += line; // add the un-modified string to the notecard + } else { + // since we have to record absolute coords since we do not know where the box goes until they press Save, + // we process the absolute to relative conversion for walks here + list parts = llParseString2List(line,["="],[]); //get the @command + + if (llList2String(parts,0) == "@walk") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@walk=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@fly") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@fly=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@run") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@run=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@land") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@land=" + (string) vec + "\n"; + } + else { + sNotecard += line; // add the un-modified string to the notecard + } + } + } + llRemoveInventory(Notecard); // delete the old notecard + osMakeNotecard(Notecard,sNotecard); // Makes the notecard. + llOwnerSay("Commands notecard has been written"); + STATE = 0; + } // MakeNotecard + } + + + + timer(){ + DEBUG("tick"); + + // if llDialog is up, kill the listener for the dialog box. + if (iHandle) { + llOwnerSay("Menu timed out"); + llListenRemove(iHandle); + iHandle = 0; + return; // ^^^^^^^^^^^^^^^^^^^^^^^ + } + // if NoBodyHome, we are sensing for an avatar + else if (NobodyHome == STATE) { + if (! llGetRegionAgentCount()) { + DoNobodyHome(); + return; // ^^^^^^^^^^^^^^^^^^^^^^^ + } + } + // if we are spawning, we need time to rez the NPC, then start processing NPC Commands. + else if (Spawning == STATE) { + STATE = 0; + TimerEvent(TIMER); + } + // We end aniamtions with a timer + else if (Animate == STATE){ + NPCAnimate(STAND); + TimerEvent(TIMER); + } + + else if (Walking == STATE) { + if (--iWaitCounter) { + if (llVecDist(osNpcGetPos(NPCKey()), newDest) > MAXDIST) { + return; + } + } + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 2) { + // nothing + } else if (walkstate == 3) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 4) { + llShout(FLIGHT,"landing"); + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } + } + // Wandering timer + else if (Wander == STATE) { + if (--iWaitCounter) { // wait 60 seconds to get to a destination. + if (llVecDist(osNpcGetPos(NPCKey()), vWanderPos) > MAXDIST) + return; + } + + // see if wander counter == 0, if so, stop walking, go to stand and process next line + if(RAMwc == 0) { + NPCAnimate(STAND); + DEBUG("Wander ended, calling DoProcessNPCLine"); + STATE = 0; + DoProcessNPCLine(); + return; + } + // one less time to wander around + RAMwc--; + NPCAnimate(STAND); + TimerEvent(TIMER); + DoWanderhold(); + return; + } + // Wandering requires us to re-wander when we reach a destination + else if (WanderHold == STATE) { + DoWander(); + TimerEvent(TIMER); + return; + } + else if (DoProcess == STATE) { + TimerEvent(QUICK); + } + + STATE = 0; + + // We always process a NPC line at end of timer. + DEBUG("Tick end, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } + + // sensors are used for sitting on prims + // Neo Cortex: added different SensorFunc states to trigger sit or touch + sensor(integer num) { + if (SensorFunc == 1) { + osNpcSit(NPCKey(), llDetectedKey(0), OS_NPC_SIT_NOW); + DEBUG("Seated, calling DoProcessNPCLine"); + SensorFunc = 0; + } else if (SensorFunc == 2) { + osNpcTouch(NPCKey(), llDetectedKey(0), LINK_THIS); + DEBUG("Touched, calling DoProcessNPCLine"); + SensorFunc = 0; + } + DoProcessNPCLine(); + } + no_sensor(){ + DEBUG ("no target prim located, calling DoProcessNPCLine"); + SensorFunc = 0; + DoProcessNPCLine(); + } + + + link_message(integer sender, integer num, string str, key id){ + DEBUG("Command In:" + str); + if (str=="@go") { + Stopped = FALSE; // Let's run the notecard + DEBUG("@go approved, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } else { + if (Stopped) + { + Stack += [str]; // take anything, the controller will filter away non @ stuff + DoProcessNPCLine(); + } else { + Stack += [str]; // take anything, the controller will filter away non @ stuff + TimerEvent(TIMER); + } + } + } + +} + + + diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.4.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.4.lsl new file mode 100644 index 00000000..ff0f6892 --- /dev/null +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.4.lsl @@ -0,0 +1,1534 @@ +// :SHOW:0 +// :CATEGORY:NPC +// :NAME:All In One NPC Recorder and Player +// :AUTHOR:Ferd Frederix +// :KEYWORDS:NPC, Puppeteer +// :CREATED:2013-09-08 18:27:47 +// :EDITED:2015-09-04 19:33:58 +// :ID:27 +// :NUM:1814 +// :REV:3.4 +// :WORLD:OpenSim +// :DESCRIPTION: +// All in one NPC recorder player. +// Supports both absolute and relative paths and many new commands +// Add animations named "Fly, Walk, Stand and Run" +// Click Prim to use. +// Should be worn as a HUD to record. +// Put it on the ground and click Sensor or Start NPC when done. +// :CODE: + +FOR DEBUG PURPOSES - DO NOT USE - USE LATER VERSIONS ONLY!!! + +// This is Rev 3.3 07/19/2015 + +// Revision History +// Rev 1.1 10-2-2014 @Sit did not work. Minor tweaks to casting for lslEditor +// Rev 1.2 10-14-2014 @ sit had wrong type. +// Rev 1.3 relative movement fixed for @fly +// Rev 1.4 4-3-2014 allow anyone to use this, non owners and non group members can only start and stop. +// Rev 1.5 5-17-2014 set sensor to auto start on reboot of sim +// Rev 1.6 5-24-2014 move menu so you can get it by touching, removed many of the KeyValues to RAM for efficiency +// Rev 1.7 CHANGED_REGION_START, not CHANGED_REGION_START (Opensim difference) +// Rev 1.8 tuned up Kill NPC, added more flexible upgrader +// Rev 1.9 Better script injection by link message// Rev 2.0 Added osSetSpeed so you can speed up or slow down an NPC. +// Rev 2.1 No laggy sensor used exept to sit on stuff +// Rev 2.2 Various sensor fixes +// Rev 2.3 Sets No Sensor in menu, must be started by hand +// Rev 2.4 - reserved for patches to 2.3 if needed +// Rev 3.0 Refactor out into subs, not states to make command injection easier +// New command: @appearance=Notecardname so you can switch to a new notecard on the fly +// New command: @speed=1.0 which slows up ( < 1 ) or speeds up ( > 1) +// Rev 3.1 Commands are not interruptible by Link Message +// Rev 3.2 Sensor patches for consistency in removing the NPC +// Rev 3.3 Added Touch command by Neo.Cortex@hbase42/hopto/org:8002 +// Added Menu 3 for notecard and appearance commands +// Rev 3.4 animation timer cannot be zero or it shuts off timer tweaked +// solves the NPC starting up when no sensor is set. +//*******************************************************************// + +// Instructions on how to use this is at http://www.outworldz.com/opensim/posts/NPC/ +// This is an OpenSim-only script. +// Author: Ferd Frederix aka Fred Beckhusen - fred@mitsi.com + +//////////////////////////////////////////////////////////////////////////////////////////// +// Original code was Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // +/////////////////////////////////////////////////////////////////////////////////////////// +// Please see: http://www.gnu.org/licenses/gpl.html for legal details, // +// rights of fair usage, the disclaimer and warranty conditions. // +/////////////////////////////////////////////////////////////////////////////////////////// +// The original NPC controller was from http://was.fm/opensim:npc +// Extensive additions and bug fixes by Fred Beckhusem, aka Ferd Frederix, fred@mitsi.com +// llSensor had two params swapped +// @Wander would wander where it had rezzed, not where it was. +// There was no 'no_sensor' event in sit, so if a @sit failed, the NPC got stuck +// The animation and walks always stopped old, then started new. It should be start new, then stop old so the default stand would be suppressed. +// New code: +// Merged with new Route recorder and notecard writer +// If the NPC failed to reach a destination it never moved on. Added WAIT global to tune this +// Exposed many tunable variables and ported the code to LSLEditor. +// Added floating point to times in notecard. + +// Added @sound, @randsound, @whisper, @shout, and @cmd controls. +// +// notecards integers are not floats for better control +// +// Link Messages may be used to perform external control by injecting @commands into the stream of actions +// Example: +// To chat something, such as with a chat robot +// llMessageLinked(LINK_SET,0,"@npc_say=Hello",""); + +// This script assumes that NPCs and OSSl scripting is enabled in the OpenSim configuration. +// In order to enable them, the following changes must be made in the OpenSim.ini configuration file: +// +// ; Turn on OSSL +// AllowOSFunctions = true +// OSFunctionThreatLevel = Severe + +//[NPC] +// ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} +// Enabled = true +// +// and then the server has to be restarted. + + +// Commands: All commands begin with an @ sign. All other lines are ignored +// @commands may have optional parameters. The syntax is always: +// @cmd=parm1|parm2 +// NaN in the table below meand Not a Number. This means there is no parameter + +//Command First Parameter Second Parameter Description +//@spawn name location (vector) Rezzes an NPC with name at a location. +//@appearance NoteCardName NaN switch the NPC appearance to a new notecard +//@walk destination (vector) NaN Makes the NPC walk to destination. +//@fly destination (vector) NaN Makes the NPC fly to destination. +//@land destination (vector) NaN Makes the NPC land at destination. +//@say string NaN Makes the NPC speak a phrase. +//@whisper string NaN Makes the NPC whisper a phrase. +//@shout string NaN Makes the NPC shout a phrase. +//@pause seconds (float) NaN Makes the NPC wait for a multiple of seconds. +//@wander radius (float) cycles (integer) Makes the NPC wander in radius, for cycles seconds. +//@delete NaN NaN Removes the NPC. Requires a link message to continue +//@goto label (string) NaN Jump to the label label in the script. +//@animate animation (string) time (float) Makes the NPC trigger the animation animation for time seconds. +//@sound sound_name NaN plays a sound from inventory +//@randsound NaN NaN Plays a random sound from inventory +//@rotate degrees (float) NaN Rotate the NPC degrees around the Z axis. +//@sit primitive name NaN Sit on a primitive with a given name. +//@touch primitive name NaN Touch on a primitive with a given name. +//@stand NaN NaN If sitting on a primitive, stand up. +//@cmd channel (integer) string Says string on channel, for controlling external gadgets +//@stop NaN NaN Halts the NPC script indefinitely. Can be started with a link message +//@go NaN NaN Continues on next notecard line, for use in link messages +//@speed speed (float) NaN from 0 to N, where 1.0 ius a normal speed of an avatar. 0.2 is a turtle. +//@notecard notename (string) NaN load a new Path notecard + + +////////////////////////////////////////////////////////// +// DEBUG // +////////////////////////////////////////////////////////// +integer debug = FALSE; // set to TRUE or FALSE for debug chat on various actions +integer Editor = FALSE; // set to to TRUE to working in LSLEditor, FALSE for in-world. + // you must also include the NPC commands found in the other script since LSLEditor does not support OpenSim +integer iTitleText = TRUE; // set to TRUE to see debug info in text above the controller + +////////////////////////////////////////////////////////// +// TUNABLE CONFIGURATION // +////////////////////////////////////////////////////////// +float TIMER = 0.5; // how often the system checks the distance traveled. Fastest you can go is 0.5 seconds +float QUICK = 0.020; // when we need to move to the next state, we use a QUICK timer +string Appearance = "!Appearance"; // The name of the recorded Appearance notecard +string Notecard = "!Path"; // The name of the recorded routes +integer allowUsers = FALSE; // If true, any user can get a Start NPC and Stop NPC menu. Only groups and owners can get all commands if TRUE, or FALSE +float MAXDIST = 2.0; // how close a NPC has to get to a dest pos to continue to next state. Do not lower this too much, as it may miss the target +integer WANDERRAND = TRUE; // set to TRUE and they will pause during wanders a random number of seconds +float WANDERTIME = 3.0; // how long they stand after each @wander,if WANDERRAND is FALSE. If WANDERRAND is TRUE, this is the max time +integer WAIT = 30; // wait for this number of seconds for the NPC to reach a destination (for safety). If it fails to reach a target, it will move on after this time. +float RANGE = 50; // 1 to N meters - anyone this close to the controller will start NPCS if Sensor button is clicked +float REZTIME = 5.0; // wait this long for NPC to rez in, then start the process +string STAND = "Stand"; // the name of the default Stand animation +string WALK = "Walk"; // the name of the default Walk animation +string FLY = "Fly"; // the name of the default Fly animation +string RUN = "Run"; // the name of the default Run animation +string LAND = "Land"; // the name of the default land animation ( for birds only) +float OffsetZ = 0.5; // appear 0.5 meter above ground, this is added to all destinations to keep them from sinking in. +float SPEEDMULT =1.0; // 1.0 = regular avatar speed. Smaller numbers slow down walks. Large numbers speed them up. +integer FLIGHT = 299; // For controlling wings. A channel that is shouted at when flight starts and ends. "flying" or "landing" + +// DESCRIPTIONS FIELDS HAVE TO SURVIVE A RESET +// These vars are stored by saving them with KeyValueSet +// "pr" is a 0 if it is set for Owner Only, 1 for Group control +// "se" is "on" if Started +// "co" = "R" or "A" for relative or absolute addressing mode +// "key" = NPC key + +// These Globals used to be stored in description. Moved to RAM in V1.6 +float RAMPause; // @pause param +float RAMwd ; // @wander distance +integer RAMwc; // @wander count +float RAMrot; // @rotate +string RAMsit; // @sit primname +string RAMtouch; // @touch primname +string RAManimationName; // @animate animation (string) time (float) +float RAManimationTime; + +// other globals section +integer iChannel; // a listen channel, randomly assigned +integer iHandle; // the handle to it + +// NPC controls +vector newDest ; // tmp storage for the walks +integer iWaitCounter ; // wait for this number of seconds for the NPC to reach a desrtination +string sNPCName; // the name of the NPC that may be in world. So we can remove it. +integer bNPC_STOP = FALSE; // boolean to reuse a listener +integer Stopped = FALSE; // set to TRUE by link messages so we do not remember them +float fTimerVal ; // how long we wait when wandering (calculated) +float NPCEnabled; // true if the NPC is suppodes to be running + +// OS_NPC_CREATOR_OWNED will create an 'owned' NPC that will only respond to osNpc* commands issued from scripts that have the same owner as the one that created the NPC. +// OS_NPC_NOT_OWNED will create an 'unowned' NPC that will respond to any script that has OSSL permissions to call osNpc* commands. +integer NPCOptions = OS_NPC_CREATOR_OWNED; // only yhe owner of this box can control this NPC. + +integer walkstate = 0; // helps us reshare the walk state for run, fly and land - a bit of a hack, but it saves RAM. Has to be done this way because some bits of NPCWalkOption are asserted as 0 + +integer NPCWalkOption; // Some notes for what happens to NPCWalkOption: +// OS_NPC_FLY - Fly the avatar to the given position. The avatar will not land unless the OS_NPC_LAND_AT_TARGET option is also given. +// OS_NPC_NO_FLY - Do not fly to the target. The NPC will attempt to walk to the location. If it's up in the air then the avatar will keep bouncing hopeless until another move target is given or the move is stopped +//OS_NPC_LAND_AT_TARGET - If given and the avatar is flying, then it will land when it reaches the target. If OS_NPC_NO_FLY is given then this option has no effect. +// OS_NPC_RUNNING - if given, NPC avatar moves at running/fast flying speed, otherwise moves at walking/slow flying speed. + +// menus +string mSensor="Sense is Off"; // Sensor or "No Sensor" + +list lAtButtons = ["Menu","-", ">>", "@run", "@walk", "@fly", "@land", "@wander", "@sit", "@stand","@animate","@rotate"]; +list lMenu2 = ["<<", "@comment", ">>>", "@stop", "@say", "@whisper","@shout","@sound","@randsound","@cmd", "@pause", "@delete"]; +list lMenu3 = ["<<<","@notecard","@appearance", "@touch", "@speed", "-", "-","-", "-", "-", "-", "-" ]; + +string sCommand; // place to store a command for two-prompted ones +string sParam2; // place to store a prompt for two-prompted ones +string priPub = "Owner Only"; // Private or Group +key kUserKey; // the person who is controlling the avatar, not the Owner +// the command lists +list lCommands; // commands are stored here +list lNPCScript; // Storage for the NPC script. +string npcAction; // Storage for the next action. @cmd=0|hello, this becomes @cmd +string npcParams; // Storage for the param, @cmd=0|hello, this becomes 0|hello + +// misc vars +string sNotecard; // commands are stored here temporarily for dumping +vector vWanderPos; // a place to wander to +string lastANIM ; // last animation run +// Sensor +integer avatarPresent; // Sensor sets this flag when people are within Range. + +// Coordinate control +vector vInitialPos ; // Vector that will be filled by the script with the initial starting position in region coordinates. +vector vDestPos = ZERO_VECTOR; // Storage for destination position. +string relAbs = "Relative"; // absolute vs relative positioning + + +// STATES +integer MENU ; // processing a dialog box state, may be concurrent with STATE +integer STATE; // state storage +integer MakeNotecard = 1; // displaying a text box for NPC name +integer RecordPath = 2; // displaying a path notecard menu +integer NobodyHome = 3; // looking for an avatar +integer Spawning = 4; // spawning an avatar +integer Animate = 5; // animation timer needed +integer Walking = 6; // Hey! I am walking here! +integer Wander = 7; // Wandering around neeeds a timer, too +integer WanderHold = 8; // We reached a wander point +integer DoProcess = 9; // Set this to make it process a new command + +key gNpcKey = NULL_KEY; // global key storage for the one NPC, to save CPU cycles +list Stack ; // a command stack from link message input + +integer SensorFunc = 0; // define which function shall be triggered inside the sensor function + // 0 means none, 1 sit, 2 touch +/////////////////////////////////////////////////////////////////////////// +// FUNCTIONS // +/////////////////////////////////////////////////////////////////////////// + +// Do* functions are much like states from the old scripts. + +// Save a Path notecard +DoSave() +{ + STATE = MakeNotecard; + makeText("Stand where you want the NPC to appear, and enter the NPC Name"); +} + +// This function is used to record the path for the NPC +// Each command can take 0, 1, or 2 params +DoMenuForCommands() { + makeMenu(lAtButtons); +} + + +// No one is here when sensors were on, so we kill off the NPC +DoNobodyHome() +{ + DEBUG("Nobody Home"); + STATE = NobodyHome; + if (NPCKey() != NULL_KEY) { + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + } + TimerEvent(5); // keep ticking to sense avatars +} + +// Create a NPC +DoSpawn() { + DEBUG("state spawn"); + NPCEnabled = TRUE; // in world + // see if there is already one out there. + if (NPCKey() != NULL_KEY) { + DEBUG("Already living"); + return; + } + + STATE = Spawning; + + list name = llParseString2List(sNPCName, [" "], []); + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + vInitialPos += llGetPos(); + } + + DEBUG("Rez NPC:" + (string) vInitialPos); + key aKey = osNpcCreate(llList2String(name, 0), llList2String(name, 1), vInitialPos, Appearance, NPCOptions); + + SaveKey(aKey ); // save in desceription and global, too + + osSetSpeed(aKey,SPEEDMULT); // 1.9 speed multiplier + TimerEvent(REZTIME); + NPCAnimate(STAND); +} + +DoRotate() { + DEBUG("state rotate"); + osNpcSetRot(NPCKey(), llEuler2Rot(<0,0,RAMrot> * DEG_TO_RAD)); +} + +DoSit() { + DEBUG ("state sit - looking for " + RAMsit); + SensorFunc = 1; //triggers osNpcSit + llSensor(RAMsit, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +DoTouch() { + DEBUG ("state touch - looking for " + RAMtouch); + SensorFunc = 2; //triggers osNpcTouch + llSensor(RAMtouch, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +DoStand() { + + DEBUG("state stand"); + osNpcStand(NPCKey()); +} + + +DoAnimate() { + + DEBUG("state animate"); + STATE = Animate; + NPCAnimate(RAManimationName); + if (RAManimationTime <=0 ) // V 3.4 tweak + RAManimationTime = 1; + TimerEvent(RAManimationTime); +} + +DoWalk() { + + DEBUG("NPCWalkOption = " + (string) NPCWalkOption); + STATE = Walking; + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(WALK); + } else if (walkstate == 2) { + llShout(FLIGHT,"flying"); + NPCAnimate(FLY); + } else if (walkstate == 3) { + NPCAnimate(RUN); + } else if (walkstate == 4) { + NPCAnimate(LAND); + } + newDest = vDestPos ; + newDest.z += OffsetZ; + + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + newDest += llGetPos(); + } + + DEBUG("Moveto:" + (string) newDest); + osNpcMoveToTarget(NPCKey(), newDest, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + + +DoWander(){ + DEBUG("state wander"); + STATE = Wander; + + vector point = CirclePoint(RAMwd); + DEBUG("CirclePoint:" + (string) point); + vWanderPos = vDestPos + point; + DEBUG("vWanderPos:" + (string) vWanderPos); + + fTimerVal = WANDERTIME; // default time to pause after each wander + if (WANDERRAND) + fTimerVal = llFrand(WANDERTIME) + 1; // override, they want random times + + NPCAnimate(WALK); + + DEBUG("Wander to:" + (string) vWanderPos); + + osNpcMoveToTarget(NPCKey(), vWanderPos, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + +DoWanderhold() { + + DEBUG("Wander Hold"); + STATE = WanderHold; + + // now that we have reached a wander spot, slow the timer down to the desired value + TimerEvent(fTimerVal); +} + +// @pause=10 will do nothing for 10 seconds +DoPause() { + + DEBUG("state pause"); + if (RAMPause < 0.1) + RAMPause = 0.1; + + TimerEvent(RAMPause); +} + + +// @stop makes the NPC stop moving in whatever state it is in. You have to linkmessage to get moving again +DoStop() { + DEBUG("NPC is Stopped"); + Stopped = TRUE; // Link controlled - we mnust have a @go to continue with notecards + TimerEvent(0); +} + + +// @delete removes the NPC forever. Next command starts it up again at the beginning +DoDelete() { + DEBUG("state delete"); + + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + lNPCScript = []; // next command starts the NPC into action at the beginning + +} + +// change the appearance of the NPC +DoAppearance(string notecard) { + DEBUG("state appearance"); + if (llGetInventoryType(notecard) == INVENTORY_NOTECARD){ + DEBUG("Load appearance " + notecard); + osNpcLoadAppearance(NPCKey(),notecard); + } +} + +// Change the avatar speed +DoSpeed(string speed) { + float newspeed = (float) speed; + if (newspeed > 0.1 && newspeed < 5.0) // sanity check + osSetSpeed(NPCKey(),newspeed); +} +DoNewNote (string card) { + DEBUG("Load Notecard " + card); + NPCReadNoteCard(card); + Stopped = FALSE; +} + +// This loops over the notecard, processing each command +DoProcessNPCLine() { + DEBUG("ProcessNPCLine"); + STATE = 0; + + // auto load a notecard + if (! llGetListLength(lNPCScript)) { + DEBUG("Read Notecard"); + NPCReadNoteCard(Notecard); + Stopped = FALSE; + } + + // look for link messages on the stack + string next = llList2String(Stack,0); // lets see if there is anithing from a link message + if (llStringLength(next)) + { + Stack = llDeleteSubList(Stack,0,0); + ProcessCmd(next); //lets do this command instead. + return; + } + + // @stop issued? + if (Stopped) { + TimerEvent(0); + DEBUG("Waiting for input"); + return; + } + + // No, we have an @go for liftoff + next = llList2String(lNPCScript, 0); // get the next command + DEBUG("Execute:" + next); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); // delete it + + if (llGetListLength(lNPCScript) == 0) { + DEBUG("EOF"); + } + ProcessCmd(next); + +} + +ProcessCmd(string cmd) { + + DEBUG("ProcessCmd:" + cmd); + + if (llGetSubString(cmd, 0, 0) != "@") { + DEBUG("ignoring"); + STATE = DoProcess; + TimerEvent(QUICK); // this is so we do not recurse the stack + return; + } + + list data = llParseString2List(cmd, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data, 0), STRING_TRIM)); + + DEBUG("Action:" + npcAction); + npcParams = llStringTrim(llList2String(data, 1), STRING_TRIM); + + @commands; + + ProcessSensor(); + if (! avatarPresent){ + DoNobodyHome(); + DEBUG("No avatar nearby"); + return; + } else { + if (llStringLength(sNPCName)) { + DoSpawn(); + } + } + + if(npcAction == "@spawn") { + DEBUG("@spawn"); + list spawnData = llParseString2List(npcParams, ["|"], []); + sNPCName =llList2String(spawnData, 0); // V 1.6 name in RAM + + list spawnDest = llParseString2List(llList2String(spawnData, 1), ["<", ",", ">"], []); + vInitialPos.x = llList2Float(spawnDest, 0); + vInitialPos.y = llList2Float(spawnDest, 1); + vInitialPos.z = llList2Float(spawnDest, 2); + DoSpawn(); + + return; + } + else if(npcAction == "@stop") { + DEBUG("@stop"); + DoStop(); + return; + } + else if(npcAction == "@goto") { + DEBUG("goto"); + integer lastIdx = llGetListLength(lNPCScript)-1; + lNPCScript = llDeleteSubList(lNPCScript, lastIdx, lastIdx); + // Wind commands till goto label. + @wind; + string next1 = llList2String(lNPCScript, 0); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); + lNPCScript += next1; + if(next1 != npcParams) jump wind; + // Wind the label too. + next1 = llList2String(lNPCScript, 0); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); + lNPCScript += next1; + // Get next command. + list data1 = llParseString2List(next1, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data1, 0), STRING_TRIM)); + npcParams = llStringTrim(llList2String(data1, 1), STRING_TRIM); + // Reschedule. + jump commands; + } + else if(npcAction == "@sound") { + DEBUG("sound"); + llTriggerSound(npcParams,1.0); + } + else if(npcAction == "@randsound") { + DEBUG("@randsound"); + integer N = llGetInventoryNumber(INVENTORY_SOUND); + integer rand = llCeil(llFrand(N)) -1; // pick a random sound + string toPlay = llGetInventoryName(INVENTORY_SOUND,rand); + llTriggerSound(toPlay,1.0); + } + else if(npcAction == "@walk") { + DEBUG("@walk"); + GetDest(npcParams); + walkstate = 1;// walking + NPCWalkOption = OS_NPC_NO_FLY ; + DoWalk(); + return; + } + else if(npcAction == "@fly") { + GetDest(npcParams); + walkstate = 2;// flying + NPCWalkOption = OS_NPC_FLY ; + DoWalk(); + return; + } + else if(npcAction == "@run") { + DEBUG("@run"); + GetDest(npcParams); + walkstate = 3;// running + NPCWalkOption = OS_NPC_NO_FLY | OS_NPC_RUNNING; + DoWalk(); + return; + } + else if(npcAction == "@land") { + DEBUG("@land"); + GetDest(npcParams); + walkstate = 4;// landing + NPCWalkOption= OS_NPC_FLY | OS_NPC_LAND_AT_TARGET ; + DoWalk(); + return; + } + else if(npcAction == "@say") { + DEBUG("@say " + npcParams); + osNpcSay(NPCKey(), 0, npcParams); + } + else if(npcAction == "@shout") { + DEBUG("@shout"); + osNpcShout(NPCKey(),0, npcParams); + } + else if(npcAction == "@whisper") { + DEBUG("@whisper " + npcParams); + osNpcWhisper(NPCKey(),0, npcParams); + } + // speak a command on a channel, so you can open doors and control stuff. + else if(npcAction == "@cmd") { + DEBUG("@cmd"); + list dataToSpeak = llParseString2List(npcParams, ["|"], []); + string channel = llList2String(dataToSpeak,0); + DEBUG("Channel:"+(string) channel); + integer iChannel = (integer) channel; + string stringToSpeak = llList2String(dataToSpeak,1); + llSay(iChannel, stringToSpeak); + } + // stop everything + else if(npcAction == "@pause") { + DEBUG("@pause"); + RAMPause = (float) npcParams; + DoPause(); + return; + } + else if(npcAction == "@wander") { + DEBUG("@wander"); + list wanderData = llParseString2List(npcParams, ["|"], []); + RAMwd = (float) llList2String(wanderData, 0); + RAMwc = (integer) llList2String(wanderData, 1); + + vDestPos = osNpcGetPos(NPCKey()); // set the wander start + DEBUG("Starting at " + (string) vDestPos); + DoWander(); + return; + } + else if(npcAction == "@rotate") { + DEBUG("@rotate"); + RAMrot = (float) npcParams; + DoRotate(); + } + else if(npcAction == "@sit") { + DEBUG("@sit"); + RAMsit= npcParams; + DoSit(); + return; + } + else if(npcAction == "@touch") { + DEBUG("@touch"); + RAMtouch= npcParams; + DoTouch(); + return; + } + else if(npcAction == "@stand") { + DEBUG("@stand"); + DoStand(); + } + else if(npcAction == "@delete") { + DEBUG("@delete"); + DoDelete(); + return; + } + else if(npcAction == "@animate") { + DEBUG("@animate"); + list animateData = llParseString2List(npcParams, ["|"], []); + RAManimationName = llList2String(animateData, 0); + RAManimationTime = (float) llList2String(animateData, 1); + DoAnimate(); + return; + } + else if(npcAction == "@appearance" ) + { + DEBUG("@appearance"); + DoAppearance(npcParams); + } + else if (npcAction =="@speed") { + DEBUG("@speed"); + DoSpeed(npcParams); + } + else if (npcAction =="@notecard") { + DEBUG("@notecard"); + DoNewNote(npcParams); + Notecard = npcParams; + } + + STATE = DoProcess; + TimerEvent(QUICK); // yeah I know, not possible this fast, we just go as fast as we can go - this is so we do not recurse the stack +} + + + +/////////////////// UTILITY Functions, not state-like ////////////////// + +// DEBUG(string) will chat a string or display it as hovertext if debug == TRUE +DEBUG(string str) { + if (debug) + llOwnerSay( str); // Send the owner debug info so you can chase NPCS + if (iTitleText) { + llSetText(str,<1.0,1.0,1.0>,1.0); // show hovertext + + } +} + +GetDest(string npcParams) { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); +} + +NPCReadNoteCard(string Note) { + DEBUG("NPCReadNoteCard"); + lNPCScript = llParseString2List(osGetNotecard(Note), ["\n"], []); +} + +integer SenseAvatar() +{ + //Returns a strided list of the UUID, position, and name of each avatar in the region + list avatars = llGetAgentList(AGENT_LIST_REGION ,[]); + integer numOfAvatars = llGetListLength(avatars); + if (numOfAvatars == 0) + { + DEBUG("No people"); + return 0; + } + //DEBUG("Located " + (string)numOfAvatars + " avatars and NPC's"); + + integer nAvatars; + integer i; + for( i = 0;i < numOfAvatars; i++) { + key aviKey = llList2Key(avatars,i); + if (!osIsNpc(aviKey)) { + list detail = llGetObjectDetails(aviKey,[OBJECT_POS]); + vector pos = llList2Vector(detail,0); + float dist = llVecDist(pos, llGetPos()); + if (dist < RANGE) + { + nAvatars++; + DEBUG("In range:" + llKey2Name(aviKey)); + } + } + } + //DEBUG("Located " + (string) nAvatars + " avatars"); + return nAvatars; +} + +// return TRUE if the avatar is owner when private is set, or TRUE if the avatar is in the same group and GROUP is set. +integer checkPerms() { + + integer group = (integer) KeyValueGet("pr"); + if (! group) + priPub = "Owner Only"; + else + priPub = "Group"; + + + if (llDetectedKey(0) == llGetOwner()){ + kUserKey = llDetectedKey(0); + return TRUE; + } + + if ( group && llDetectedGroup(0)) { + kUserKey = llDetectedKey(0); + return TRUE; + } + kUserKey = llDetectedKey(0); + return FALSE; +} + + + +NPCAnimate(string anim) +{ + DEBUG("Start Anim: " + anim); + if (llGetInventoryType(anim) == INVENTORY_ANIMATION ) { + + if (lastANIM != anim) { + if(llStringLength(lastANIM)) { + osNpcStopAnimation(NPCKey(), lastANIM); + } + osNpcPlayAnimation(NPCKey(), anim); + lastANIM = anim; + } + } else { + llSay(DEBUG_CHANNEL, "No animation named " + anim); + } +} + + +TimerEvent(float timesent) +{ + DEBUG("Setting timer: " + (string) timesent); + llSetTimerEvent(timesent); +} + +// Kill a NPC by Name +Kill(string param) +{ + integer count; + list avatars = osGetAvatarList(); // Returns a strided list of the UUID, position, and name of each avatar in the region except the owner.\ + integer i; + integer j = llGetListLength(avatars); + for (i=0 ; i <= j; i+=3){ + + string desired = llList2String(avatars,i+2); + desired = llStringTrim(desired,STRING_TRIM); // should not be needed but is needed + + if (desired == param){ + vector v = llList2Vector(avatars,i+1); + key target = llList2Key(avatars,i); // get the UUID of the avatar + osNpcRemove(target); + SaveKey(NULL_KEY ); + llOwnerSay("Removed " + param+ " at location " + (string) v); + count++; + } + } + + NPCEnabled = FALSE; // not in world + + if (count) + llOwnerSay("Removed " + (string) count + " NPC's"); + else + llOwnerSay("Could not locate " + param); +} + + +// return a String for the position we are at. Strings used as the caller wants strings +string Pos() +{ + vector where = llGetPos(); // find the box position + + where.z += OffsetZ; // use the ground position + an offset + + if (Editor) + where = <128,128,31 + llFrand(1)>; // center of sim for editing + + // if attached the height will be too high by 1/2 the agent size + if (llGetAttached()) { + vector size = llGetAgentSize(llGetOwner()); + float Z = size.z; + where.z -= Z/2; + } + + // DEBUG("Pos= " + (string) where); + return (string) where; +} + +// setup a menu with a timer for timeouts, called by all make*() +menu() +{ + llListenRemove(iHandle); + iChannel = llCeil(llFrand(100000) + 20000); + iHandle = llListen(iChannel,"","",""); + TimerEvent(30.0); + MENU = TRUE; +} + +// make a text box +makeText(string Param) +{ + menu(); + llTextBox(kUserKey, Param, iChannel); +} + +// top level menu +makeMainMenu() +{ + menu(); + list buttons = ["Appearance","Recording","Save","Help","-","Erase RAM", priPub,relAbs,"-","Stop NPC",mSensor,"Start NPC"]; + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Records",buttons,iChannel); +} + + +// Rev 1.4 +// top level menu for non group/ non owners +makeUserMenu() +{ + if (!allowUsers) return; + + menu(); + list buttons = ["Start NPC","Stop NPC"]; + llDialog(kUserKey,"Choose",buttons,iChannel); +} + + + +// programmable menu for @commands +makeMenu(list buttons) +{ + menu(); + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Record",buttons,iChannel); +} + + +// make one or two text boxes with prompts +Text(string cmd, string p1, string p2) +{ + sCommand = cmd; + sParam2 = ""; + if (llStringLength(p2)) + sParam2 = p2; + + makeText(p1); +} + +// Set the Avatar Present flag - if sensors are off and we are forece run, there will be one present. +ProcessSensor() +{ + integer SensorOn; + if ("on" == KeyValueGet("se")) + { + SensorOn = TRUE; // we need to scan for avatars + } else { + SensorOn = FALSE; // we need to scan for avatars + } + DEBUG("Sensor:" + (string) SensorOn); + + integer n = SenseAvatar(); + + DEBUG("Avatars:" + (string) n); + if (SensorOn && n) + avatarPresent = TRUE; // someone is here and we need to tell the system to run + else if (SensorOn && !n) + avatarPresent = FALSE; // someone is not here and we need to tell the system to stop + else { // sensor is off, lete see if there is a NPC. If so, we are ON + DEBUG("NPCEnabled:" + (string) NPCEnabled); + if (NPCEnabled) + avatarPresent = TRUE; + else + avatarPresent = FALSE; + } + //DEBUG("Avatar Present: " + (string) avatarPresent); +} + +vector CirclePoint(float radius) { + float x = llFrand(radius *2) - radius; // +/- radius, randomized + float y = llFrand(radius *2) - radius; // +/- radius, randomized + return ; // so this should always happen +} + +string KeyValueGet(string var) { + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k != var) jump continue; + //DEBUG("got " + var + " = " + llList2String(data, 1)); + return llList2String(data, 1); + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + return ""; +} + +KeyValueSet(string var, string val) { + + //DEBUG("set " + var + " = " + val); + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + if(llGetListLength(dVars) == 0) + { + llSetObjectDesc(var + "=" + val); + return; + } + list result = []; + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k == "") jump continue; + if(k == var && val == "") jump continue; + if(k == var) { + result += k + "=" + val; + val = ""; + jump continue; + } + string v = llList2String(data, 1); + if(v == "") jump continue; + result += k + "=" + v; + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + if(val != "") result += var + "=" + val; + llSetObjectDesc(llDumpList2String(result, "&")); +} + + +// clear RAM +Clr() { + + lCommands = []; + llOwnerSay("RAM Memory cleared. Notecards, if any, are not modified."); + makeMainMenu(); +} + +integer checkNoteCards() +{ + // Check that they have saved an Appeaance and Path notecard + integer num = llGetInventoryNumber(INVENTORY_NOTECARD); // how many notecards overall + + integer i; + integer count; + for (; i < num; i++){ + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Notecard) + count++; + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Appearance) + count++; + } + DEBUG("Checked " + (string) count + " Notecards"); + // if we have both, run the NPC + return count; +} + +Update(string SName) { + + // delete all NPC*scripts except myself + integer i; + integer j = llGetInventoryNumber(INVENTORY_SCRIPT); + for (i = 0; i < j; i++) { + string name = llGetInventoryName(INVENTORY_SCRIPT,i); + string match = llGetSubString(name,0,2); + if (match == SName && llGetScriptName() != name) + { + llRemoveInventory(name); + llOwnerSay("Upgraded"); + } + } + +} + +// Get all default saved params from the Description +GetSwitches() +{ + string rA = KeyValueGet("co"); // Get the remembered menu setting for Abs Vs Relative + if (rA == "A") + relAbs = "Absolute"; + else if (rA == "R") + relAbs = "Relative"; + else + relAbs = "Absolute"; + + + // reenable NPC if sensor is on. + if ("on" == KeyValueGet("se")) + { + NPCEnabled = TRUE; + mSensor = "Sense is On"; + ProcessSensor(); // fake 1 avatar to get it rezzed + } else { + mSensor = "Sense is Off"; + } + } + + +SaveKey(key akey) +{ + DEBUG("Saving Key of " + (string) akey); + KeyValueSet("key", akey); + if (akey != (key) KeyValueGet("key") ) + { + DEBUG("Fatal error, cannot save key"); + } + gNpcKey = akey; +} + + +key NPCKey() +{ + key akey = gNpcKey; // from cached copy + // gNpcKey saves a lot of CPU processing by caching the key, if blank we get it from the description + if (gNpcKey == NULL_KEY) + { + //DEBUG("Get DKey"); + akey = KeyValueGet("key"); // from Description of the prim + } + // DEBUG("NPC KEY:" + (string) akey); + return akey; +} + + +/////////////////// CODE BEGINS ////////////////// + + +default +{ + changed(integer change) { + if(change & CHANGED_REGION_START) { + llResetScript(); + } + } + + on_rez(integer start_param) + { + llResetScript(); + } + + state_entry() { + + llSetText("",<1,1,1>,1.0); // clr all hovertext- we may not be using it. + DoDelete(); // kill any NPC that is out running + Update("NPC"); // If dragged and ropped into a prim with any script named "NPC...", this will replace it. + GetSwitches(); // Get all default saved params from the Description + llSetTimerEvent(TIMER); + } + + + touch_start(integer n) + { // if touched, make a menu + + if (checkPerms()) { + if (RecordPath == STATE) { + makeMenu(lAtButtons); + } else { + makeMainMenu(); + } + } else { + makeUserMenu(); + } + } + + // menu listener + listen(integer iChannel, string name, key id, string message) { + + if (MENU) { + llListenRemove(iHandle); + MENU = 0; // menu is off + iHandle = 0; + } + + if (message == "Stop NPC") + { + lNPCScript = []; // force reload of notecard + NPCEnabled = FALSE; + if (NPCKey() != NULL_KEY){ + Kill(sNPCName); + sNPCName = ""; + } else { + bNPC_STOP = TRUE; + makeText("Enter name of an NPC to stop"); + } + } + else if (message == "Menu" ) { + makeMainMenu(); + } + else if (message == "Erase RAM"){ + Clr(); + } + else if (message == "Relative"){ + relAbs = "Absolute"; + KeyValueSet("co","A"); // remember coordinates = A + Clr(); + } + else if (message == "Absolute"){ + relAbs = "Relative"; + KeyValueSet("co","R"); // remember coordinates = R + Clr(); + } + else if (message == "Recording"){ + DoMenuForCommands(); // show them the recording menu + } + else if (message == "Owner Only") { + priPub = "Group"; + KeyValueSet("pr","1"); + + llOwnerSay("Group members have control"); + makeMainMenu(); + } + else if (message == "Group") { + priPub = "Owner Only"; + KeyValueSet("pr","0"); + llOwnerSay("Only you have control"); + makeMainMenu(); + } + else if (message == "Sense is On") { + mSensor ="Sense is Off"; + KeyValueSet("se", "off"); + llOwnerSay(mSensor); + makeMainMenu(); + } + else if (message == "Sense is Off") { + mSensor ="Sense is On"; + llOwnerSay(mSensor); + KeyValueSet("se", "on"); + + NPCEnabled = FALSE; + + integer count = checkNoteCards(); + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + DoProcessNPCLine(); + return; + } + if (Editor) { + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording and/or appearance, so you cannot start a NPC"); + makeMainMenu(); + } + else if (message == "Appearance") { + llRemoveInventory(Appearance); // delete the notecard + osAgentSaveAppearance(kUserKey,Appearance); // make the ntecard + llOwnerSay("Your outfit has been saved"); + makeMainMenu(); + } + else if (message == "Save") { + if (llGetListLength(lCommands) == 0) { + llOwnerSay("Nothing recorded, you need to make a recording first"); + makeMainMenu(); + return; + } + DoSave(); + } + else if (message == "Help"){ + llLoadURL(kUserKey,"Click to view help","http://www.outworldz.com/opensim/posts/NPC/"); + makeMainMenu(); + } + else if (message == "Start NPC") { + integer count = checkNoteCards(); + Stopped = FALSE; // Let's run the notecard + NPCEnabled = TRUE; + + if (Editor) { + DoProcessNPCLine(); + return; + } + + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + Stopped = FALSE; // Let's run the notecard + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording or maybe an appearance, so we cannot start a NPC"); + + } + else if (bNPC_STOP){ + bNPC_STOP = FALSE; + Kill(message); + } + else if (message == ">>"){ + makeMenu(lMenu2); + } + else if (message == ">>>"){ + makeMenu(lMenu3); + } + else if (message == "<<") { + makeMenu(lAtButtons); + } + else if (message == "<<<") { + makeMenu(lMenu2); + } + else if (message == "@comment"){ + Text("# ","Enter a comment",""); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@run"){ + lCommands += "@run=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@fly"){ + lCommands += "@fly=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@land"){ + lCommands += "@land=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@walk") { + lCommands += "@walk=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@sound"){ + Text("@sound=","Enter a sound name or UUID to trigger",""); + } + else if (message == "@randsound"){ + lCommands += "@randsound"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@say") { + Text("@say=","Enter what the NPC will say",""); + } + else if (message == "@whisper"){ + Text("@whisper=","Enter what the NPC will whisper",""); + } + else if (message == "@shout"){ + Text("@shout=","Enter what the NPC will shout",""); + } + else if (message == "@wander") { + Text("@wander=","Enter radius to wander","Enter number of wanders"); + } + else if (message == "@pause") { + Text("@pause=","Enter time to pause",""); + } + else if (message == "@rotate") { + Text("@rotate=","Enter degrees to rotate",""); + } + else if (message == "@sit"){ + Text("@sit=","Enter name of object to sit on",""); + } + else if (message == "@touch"){ + Text("@touch=","Enter name of object to touch",""); + } + else if (message == "@cmd"){ + Text("@cmd=","Enter cjhannel to speak on","Enter text to speak"); + } + else if (message == "@stand"){ + lCommands += "@stand\n"; + llOwnerSay("Stand Recorded"); + makeMenu(lAtButtons); + } + else if (message == "@animate"){ + Text("@animate=","Enter animation name to play","Enter time to play the animation"); + } + else if (message == "@speed"){ + Text("@speed=","Enter a speed for the NPC, 1=100% normal speed, 0.5=50% speed",""); + } + else if (! llStringLength(sParam2)) { + lCommands += sCommand + message + "\n"; + llOwnerSay("Recorded"); + makeMenu(lAtButtons); + } + else if (llStringLength(sParam2)){ + sCommand = sCommand + message + "|"; + llOwnerSay("Recorded"); + makeText(sParam2); + sParam2 = ""; + } + + + // Save NPC name + else if (MakeNotecard == STATE) { + sNPCName = message; // in case we need to kill it. + + vector vDest = (vector) Pos(); + + if (relAbs == "Relative") + { + vDest -= llGetPos(); // just an offset for relative + } + sNotecard = "@spawn=" + message + "|" + (string) vDest + "\n"; + integer i; + integer j = llGetListLength(lCommands); + for (; i < j; i++){ + // get the command to save to the notecard + string line = llList2String(lCommands,i); + if (relAbs == "Absolute") { + sNotecard += line; // add the un-modified string to the notecard + } else { + // since we have to record absolute coords since we do not know where the box goes until they press Save, + // we process the absolute to relative conversion for walks here + list parts = llParseString2List(line,["="],[]); //get the @command + + if (llList2String(parts,0) == "@walk") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@walk=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@fly") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@fly=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@run") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@run=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@land") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@land=" + (string) vec + "\n"; + } + else { + sNotecard += line; // add the un-modified string to the notecard + } + } + } + llRemoveInventory(Notecard); // delete the old notecard + osMakeNotecard(Notecard,sNotecard); // Makes the notecard. + llOwnerSay("Commands notecard has been written"); + STATE = 0; + } // MakeNotecard + } + + + + timer(){ + DEBUG("tick"); + + // if llDialog is up, kill the listener for the dialog box. + if (iHandle) { + llOwnerSay("Menu timed out"); + llListenRemove(iHandle); + iHandle = 0; + return; // ^^^^^^^^^^^^^^^^^^^^^^^ + } + // if NoBodyHome, we are sensing for an avatar + else if (NobodyHome == STATE) { + if (! llGetRegionAgentCount()) { + DoNobodyHome(); + return; // ^^^^^^^^^^^^^^^^^^^^^^^ + } + } + // if we are spawning, we need time to rez the NPC, then start processing NPC Commands. + else if (Spawning == STATE) { + STATE = 0; + TimerEvent(TIMER); + } + // We end aniamtions with a timer + else if (Animate == STATE){ + NPCAnimate(STAND); + TimerEvent(TIMER); + } + + else if (Walking == STATE) { + if (--iWaitCounter) { + if (llVecDist(osNpcGetPos(NPCKey()), newDest) > MAXDIST) { + return; + } + } + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 2) { + // nothing + } else if (walkstate == 3) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 4) { + llShout(FLIGHT,"landing"); + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } + } + // Wandering timer + else if (Wander == STATE) { + if (--iWaitCounter) { // wait 60 seconds to get to a destination. + if (llVecDist(osNpcGetPos(NPCKey()), vWanderPos) > MAXDIST) + return; + } + + // see if wander counter == 0, if so, stop walking, go to stand and process next line + if(RAMwc == 0) { + NPCAnimate(STAND); + DEBUG("Wander ended, calling DoProcessNPCLine"); + STATE = 0; + DoProcessNPCLine(); + return; + } + // one less time to wander around + RAMwc--; + NPCAnimate(STAND); + TimerEvent(TIMER); + DoWanderhold(); + return; + } + // Wandering requires us to re-wander when we reach a destination + else if (WanderHold == STATE) { + DoWander(); + TimerEvent(TIMER); + return; + } + else if (DoProcess == STATE) { + TimerEvent(QUICK); + } + + STATE = 0; + + // We always process a NPC line at end of timer. + DEBUG("Tick end, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } + + // sensors are used for sitting on prims + // Neo Cortex: added different SensorFunc states to trigger sit or touch + sensor(integer num) { + if (SensorFunc == 1) { + osNpcSit(NPCKey(), llDetectedKey(0), OS_NPC_SIT_NOW); + DEBUG("Seated, calling DoProcessNPCLine"); + SensorFunc = 0; + } else if (SensorFunc == 2) { + osNpcTouch(NPCKey(), llDetectedKey(0), LINK_THIS); + DEBUG("Touched, calling DoProcessNPCLine"); + SensorFunc = 0; + } + DoProcessNPCLine(); + } + no_sensor(){ + DEBUG ("no target prim located, calling DoProcessNPCLine"); + SensorFunc = 0; + DoProcessNPCLine(); + } + + + link_message(integer sender, integer num, string str, key id){ + DEBUG("Command In:" + str); + if (str=="@go") { + Stopped = FALSE; // Let's run the notecard + DEBUG("@go approved, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } else { + if (Stopped) + { + Stack += [str]; // take anything, the controller will filter away non @ stuff + DoProcessNPCLine(); + } else { + Stack += [str]; // take anything, the controller will filter away non @ stuff + TimerEvent(TIMER); + } + } + } + +} + + + diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.5.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.5.lsl new file mode 100644 index 00000000..57e20dac --- /dev/null +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.5.lsl @@ -0,0 +1,1539 @@ +// :SHOW:1 +// :CATEGORY:NPC +// :NAME:All In One NPC Recorder and Player +// :AUTHOR:Ferd Frederix +// :KEYWORDS:NPC, Puppeteer +// :CREATED:2013-09-08 18:27:47 +// :EDITED:2015-08-05 08:54:13 +// :ID:27 +// :NUM:1815 +// :REV:3.5 +// :WORLD:OpenSim +// :DESCRIPTION: +// All in one NPC recorder player. +// Supports both absolute and relative paths and many new commands +// Add animations named "Fly, Walk, Stand and Run" +// Click Prim to use. +// Should be worn as a HUD to record. +// Put it on the ground and click Sensor or Start NPC when done. +// :CODE: +// This is Rev 3.3 07/19/2015 + +FOR DEBUG PURPOSES - DO NOT USE - USE LATER VERSIONS ONLY!!! + +// Revision History +// Rev 1.1 10-2-2014 @Sit did not work. Minor tweaks to casting for lslEditor +// Rev 1.2 10-14-2014 @ sit had wrong type. +// Rev 1.3 relative movement fixed for @fly +// Rev 1.4 4-3-2014 allow anyone to use this, non owners and non group members can only start and stop. +// Rev 1.5 5-17-2014 set sensor to auto start on reboot of sim +// Rev 1.6 5-24-2014 move menu so you can get it by touching, removed many of the KeyValues to RAM for efficiency +// Rev 1.7 CHANGED_REGION_START, not CHANGED_REGION_START (Opensim difference) +// Rev 1.8 tuned up Kill NPC, added more flexible upgrader +// Rev 1.9 Better script injection by link message// Rev 2.0 Added osSetSpeed so you can speed up or slow down an NPC. +// Rev 2.1 No laggy sensor used exept to sit on stuff +// Rev 2.2 Various sensor fixes +// Rev 2.3 Sets No Sensor in menu, must be started by hand +// Rev 2.4 - reserved for patches to 2.3 if needed +// Rev 3.0 Refactor out into subs, not states to make command injection easier +// New command: @appearance=Notecardname so you can switch to a new notecard on the fly +// New command: @speed=1.0 which slows up ( < 1 ) or speeds up ( > 1) +// Rev 3.1 Commands are not interruptible by Link Message +// Rev 3.2 Sensor patches for consistency in removing the NPC +// Rev 3.3 Added Touch command by Neo.Cortex@hbase42/hopto/org:8002 +// Added Menu 3 for notecard and appearance commands +// Rev 3.4 animation timer cannot be zero or it shuts off timer tweaked +// solves the NPC starting up when no sensor is set. +// Rev 3.5 fixes saving in !Path notecard +//*******************************************************************// + +// Instructions on how to use this is at http://www.outworldz.com/opensim/posts/NPC/ +// This is an OpenSim-only script. +// Author: Ferd Frederix aka Fred Beckhusen - fred@mitsi.com + +//////////////////////////////////////////////////////////////////////////////////////////// +// Original code was Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // +/////////////////////////////////////////////////////////////////////////////////////////// +// Please see: http://www.gnu.org/licenses/gpl.html for legal details, // +// rights of fair usage, the disclaimer and warranty conditions. // +/////////////////////////////////////////////////////////////////////////////////////////// +// The original NPC controller was from http://was.fm/opensim:npc +// Extensive additions and bug fixes by Fred Beckhusem, aka Ferd Frederix, fred@mitsi.com +// llSensor had two params swapped +// @Wander would wander where it had rezzed, not where it was. +// There was no 'no_sensor' event in sit, so if a @sit failed, the NPC got stuck +// The animation and walks always stopped old, then started new. It should be start new, then stop old so the default stand would be suppressed. +// New code: +// Merged with new Route recorder and notecard writer +// If the NPC failed to reach a destination it never moved on. Added WAIT global to tune this +// Exposed many tunable variables and ported the code to LSLEditor. +// Added floating point to times in notecard. + +// Added @sound, @randsound, @whisper, @shout, and @cmd controls. +// +// notecards integers are not floats for better control +// +// Link Messages may be used to perform external control by injecting @commands into the stream of actions +// Example: +// To chat something, such as with a chat robot +// llMessageLinked(LINK_SET,0,"@npc_say=Hello",""); + +// This script assumes that NPCs and OSSl scripting is enabled in the OpenSim configuration. +// In order to enable them, the following changes must be made in the OpenSim.ini configuration file: +// +// ; Turn on OSSL +// AllowOSFunctions = true +// OSFunctionThreatLevel = Severe + +//[NPC] +// ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} +// Enabled = true +// +// and then the server has to be restarted. + + +// Commands: All commands begin with an @ sign. All other lines are ignored +// @commands may have optional parameters. The syntax is always: +// @cmd=parm1|parm2 +// NaN in the table below meand Not a Number. This means there is no parameter + +//Command First Parameter Second Parameter Description +//@spawn name location (vector) Rezzes an NPC with name at a location. +//@appearance NoteCardName NaN switch the NPC appearance to a new notecard +//@walk destination (vector) NaN Makes the NPC walk to destination. +//@fly destination (vector) NaN Makes the NPC fly to destination. +//@land destination (vector) NaN Makes the NPC land at destination. +//@say string NaN Makes the NPC speak a phrase. +//@whisper string NaN Makes the NPC whisper a phrase. +//@shout string NaN Makes the NPC shout a phrase. +//@pause seconds (float) NaN Makes the NPC wait for a multiple of seconds. +//@wander radius (float) cycles (integer) Makes the NPC wander in radius, for cycles seconds. +//@delete NaN NaN Removes the NPC. Requires a link message to continue +//@goto label (string) NaN Jump to the label label in the script. +//@animate animation (string) time (float) Makes the NPC trigger the animation animation for time seconds. +//@sound sound_name NaN plays a sound from inventory +//@randsound NaN NaN Plays a random sound from inventory +//@rotate degrees (float) NaN Rotate the NPC degrees around the Z axis. +//@sit primitive name NaN Sit on a primitive with a given name. +//@touch primitive name NaN Touch on a primitive with a given name. +//@stand NaN NaN If sitting on a primitive, stand up. +//@cmd channel (integer) string Says string on channel, for controlling external gadgets +//@stop NaN NaN Halts the NPC script indefinitely. Can be started with a link message +//@go NaN NaN Continues on next notecard line, for use in link messages +//@speed speed (float) NaN from 0 to N, where 1.0 ius a normal speed of an avatar. 0.2 is a turtle. +//@notecard notename (string) NaN load a new Path notecard + + +////////////////////////////////////////////////////////// +// DEBUG // +////////////////////////////////////////////////////////// +integer debug = FALSE; // set to TRUE or FALSE for debug chat on various actions +integer Editor = FALSE; // set to to TRUE to working in LSLEditor, FALSE for in-world. + // you must also include the NPC commands found in the other script since LSLEditor does not support OpenSim +integer iTitleText = TRUE; // set to TRUE to see debug info in text above the controller + +////////////////////////////////////////////////////////// +// TUNABLE CONFIGURATION // +////////////////////////////////////////////////////////// +float TIMER = 0.5; // how often the system checks the distance traveled. Fastest you can go is 0.5 seconds +float QUICK = 0.020; // when we need to move to the next state, we use a QUICK timer +string Appearance = "!Appearance"; // The name of the recorded Appearance notecard +string Notecard = "!Path"; // The name of the recorded routes +integer allowUsers = FALSE; // If true, any user can get a Start NPC and Stop NPC menu. Only groups and owners can get all commands if TRUE, or FALSE +float MAXDIST = 2.0; // how close a NPC has to get to a dest pos to continue to next state. Do not lower this too much, as it may miss the target +integer WANDERRAND = TRUE; // set to TRUE and they will pause during wanders a random number of seconds +float WANDERTIME = 3.0; // how long they stand after each @wander,if WANDERRAND is FALSE. If WANDERRAND is TRUE, this is the max time +integer WAIT = 30; // wait for this number of seconds for the NPC to reach a destination (for safety). If it fails to reach a target, it will move on after this time. +float RANGE = 50; // 1 to N meters - anyone this close to the controller will start NPCS if Sensor button is clicked +float REZTIME = 5.0; // wait this long for NPC to rez in, then start the process +string STAND = "Stand"; // the name of the default Stand animation +string WALK = "Walk"; // the name of the default Walk animation +string FLY = "Fly"; // the name of the default Fly animation +string RUN = "Run"; // the name of the default Run animation +string LAND = "Land"; // the name of the default land animation ( for birds only) +float OffsetZ = 0.5; // appear 0.5 meter above ground, this is added to all destinations to keep them from sinking in. +float SPEEDMULT =1.0; // 1.0 = regular avatar speed. Smaller numbers slow down walks. Large numbers speed them up. +integer FLIGHT = 299; // For controlling wings. A channel that is shouted at when flight starts and ends. "flying" or "landing" + +// DESCRIPTIONS FIELDS HAVE TO SURVIVE A RESET +// These vars are stored by saving them with KeyValueSet +// "pr" is a 0 if it is set for Owner Only, 1 for Group control +// "se" is "on" if Started +// "co" = "R" or "A" for relative or absolute addressing mode +// "key" = NPC key + +// These Globals used to be stored in description. Moved to RAM in V1.6 +float RAMPause; // @pause param +float RAMwd ; // @wander distance +integer RAMwc; // @wander count +float RAMrot; // @rotate +string RAMsit; // @sit primname +string RAMtouch; // @touch primname +string RAManimationName; // @animate animation (string) time (float) +float RAManimationTime; + +// other globals section +integer iChannel; // a listen channel, randomly assigned +integer iHandle; // the handle to it + +// NPC controls +vector newDest ; // tmp storage for the walks +integer iWaitCounter ; // wait for this number of seconds for the NPC to reach a desrtination +string sNPCName; // the name of the NPC that may be in world. So we can remove it. +integer bNPC_STOP = FALSE; // boolean to reuse a listener +integer Stopped = FALSE; // set to TRUE by link messages so we do not remember them +float fTimerVal ; // how long we wait when wandering (calculated) +float NPCEnabled; // true if the NPC is suppodes to be running + +// OS_NPC_CREATOR_OWNED will create an 'owned' NPC that will only respond to osNpc* commands issued from scripts that have the same owner as the one that created the NPC. +// OS_NPC_NOT_OWNED will create an 'unowned' NPC that will respond to any script that has OSSL permissions to call osNpc* commands. +integer NPCOptions = OS_NPC_CREATOR_OWNED; // only yhe owner of this box can control this NPC. + +integer walkstate = 0; // helps us reshare the walk state for run, fly and land - a bit of a hack, but it saves RAM. Has to be done this way because some bits of NPCWalkOption are asserted as 0 + +integer NPCWalkOption; // Some notes for what happens to NPCWalkOption: +// OS_NPC_FLY - Fly the avatar to the given position. The avatar will not land unless the OS_NPC_LAND_AT_TARGET option is also given. +// OS_NPC_NO_FLY - Do not fly to the target. The NPC will attempt to walk to the location. If it's up in the air then the avatar will keep bouncing hopeless until another move target is given or the move is stopped +//OS_NPC_LAND_AT_TARGET - If given and the avatar is flying, then it will land when it reaches the target. If OS_NPC_NO_FLY is given then this option has no effect. +// OS_NPC_RUNNING - if given, NPC avatar moves at running/fast flying speed, otherwise moves at walking/slow flying speed. + +// menus +string mSensor="Sense is Off"; // Sensor or "No Sensor" + +list lAtButtons = ["Menu","-", ">>", "@run", "@walk", "@fly", "@land", "@wander", "@sit", "@stand","@animate","@rotate"]; +list lMenu2 = ["<<", "@comment", ">>>", "@stop", "@say", "@whisper","@shout","@sound","@randsound","@cmd", "@pause", "@delete"]; +list lMenu3 = ["<<<","@notecard","@appearance", "@touch", "@speed", "-", "-","-", "-", "-", "-", "-" ]; + +string sCommand; // place to store a command for two-prompted ones +string sParam2; // place to store a prompt for two-prompted ones +string priPub = "Owner Only"; // Private or Group +key kUserKey; // the person who is controlling the avatar, not the Owner +// the command lists +list lCommands; // commands are stored here +list lNPCScript; // Storage for the NPC script. +string npcAction; // Storage for the next action. @cmd=0|hello, this becomes @cmd +string npcParams; // Storage for the param, @cmd=0|hello, this becomes 0|hello + +// misc vars +string sNotecard; // commands are stored here temporarily for dumping +vector vWanderPos; // a place to wander to +string lastANIM ; // last animation run +// Sensor +integer avatarPresent; // Sensor sets this flag when people are within Range. + +// Coordinate control +vector vInitialPos ; // Vector that will be filled by the script with the initial starting position in region coordinates. +vector vDestPos = ZERO_VECTOR; // Storage for destination position. +string relAbs = "Relative"; // absolute vs relative positioning + + +// STATES +integer MENU ; // processing a dialog box state, may be concurrent with STATE +integer STATE; // state storage +integer MakeNotecard = 1; // displaying a text box for NPC name +integer RecordPath = 2; // displaying a path notecard menu +integer NobodyHome = 3; // looking for an avatar +integer Spawning = 4; // spawning an avatar +integer Animate = 5; // animation timer needed +integer Walking = 6; // Hey! I am walking here! +integer Wander = 7; // Wandering around neeeds a timer, too +integer WanderHold = 8; // We reached a wander point +integer DoProcess = 9; // Set this to make it process a new command + +key gNpcKey = NULL_KEY; // global key storage for the one NPC, to save CPU cycles +list Stack ; // a command stack from link message input + +integer SensorFunc = 0; // define which function shall be triggered inside the sensor function + // 0 means none, 1 sit, 2 touch +/////////////////////////////////////////////////////////////////////////// +// FUNCTIONS // +/////////////////////////////////////////////////////////////////////////// + +// Do* functions are much like states from the old scripts. + +// Save a Path notecard +DoSave() +{ + STATE = MakeNotecard; + makeText("Stand where you want the NPC to appear, and enter the NPC Name"); +} + +// This function is used to record the path for the NPC +// Each command can take 0, 1, or 2 params +DoMenuForCommands() { + makeMenu(lAtButtons); +} + + +// No one is here when sensors were on, so we kill off the NPC +DoNobodyHome() +{ + DEBUG("Nobody Home"); + STATE = NobodyHome; + if (NPCKey() != NULL_KEY) { + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + } + TimerEvent(5); // keep ticking to sense avatars +} + +// Create a NPC +DoSpawn() { + DEBUG("state spawn"); + NPCEnabled = TRUE; // in world + // see if there is already one out there. + if (NPCKey() != NULL_KEY) { + DEBUG("Already living"); + return; + } + + STATE = Spawning; + + list name = llParseString2List(sNPCName, [" "], []); + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + vInitialPos += llGetPos(); + } + + DEBUG("Rez NPC:" + (string) vInitialPos); + key aKey = osNpcCreate(llList2String(name, 0), llList2String(name, 1), vInitialPos, Appearance, NPCOptions); + + SaveKey(aKey ); // save in desceription and global, too + + osSetSpeed(aKey,SPEEDMULT); // 1.9 speed multiplier + TimerEvent(REZTIME); + NPCAnimate(STAND); +} + +DoRotate() { + DEBUG("state rotate"); + osNpcSetRot(NPCKey(), llEuler2Rot(<0,0,RAMrot> * DEG_TO_RAD)); +} + +DoSit() { + DEBUG ("state sit - looking for " + RAMsit); + SensorFunc = 1; //triggers osNpcSit + llSensor(RAMsit, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +DoTouch() { + DEBUG ("state touch - looking for " + RAMtouch); + SensorFunc = 2; //triggers osNpcTouch + llSensor(RAMtouch, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +DoStand() { + + DEBUG("state stand"); + osNpcStand(NPCKey()); +} + + +DoAnimate() { + + DEBUG("state animate"); + STATE = Animate; + NPCAnimate(RAManimationName); + if (RAManimationTime <=0 ) // V 3.4 tweak + RAManimationTime = 1; + TimerEvent(RAManimationTime); +} + +DoWalk() { + + DEBUG("NPCWalkOption = " + (string) NPCWalkOption); + STATE = Walking; + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(WALK); + } else if (walkstate == 2) { + llShout(FLIGHT,"flying"); + NPCAnimate(FLY); + } else if (walkstate == 3) { + NPCAnimate(RUN); + } else if (walkstate == 4) { + NPCAnimate(LAND); + } + newDest = vDestPos ; + newDest.z += OffsetZ; + + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + newDest += llGetPos(); + } + + DEBUG("Moveto:" + (string) newDest); + osNpcMoveToTarget(NPCKey(), newDest, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + + +DoWander(){ + DEBUG("state wander"); + STATE = Wander; + + vector point = CirclePoint(RAMwd); + DEBUG("CirclePoint:" + (string) point); + vWanderPos = vDestPos + point; + DEBUG("vWanderPos:" + (string) vWanderPos); + + fTimerVal = WANDERTIME; // default time to pause after each wander + if (WANDERRAND) + fTimerVal = llFrand(WANDERTIME) + 1; // override, they want random times + + NPCAnimate(WALK); + + DEBUG("Wander to:" + (string) vWanderPos); + + osNpcMoveToTarget(NPCKey(), vWanderPos, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + +DoWanderhold() { + + DEBUG("Wander Hold"); + STATE = WanderHold; + + // now that we have reached a wander spot, slow the timer down to the desired value + TimerEvent(fTimerVal); +} + +// @pause=10 will do nothing for 10 seconds +DoPause() { + + DEBUG("state pause"); + if (RAMPause < 0.1) + RAMPause = 0.1; + + TimerEvent(RAMPause); +} + + +// @stop makes the NPC stop moving in whatever state it is in. You have to linkmessage to get moving again +DoStop() { + DEBUG("NPC is Stopped"); + Stopped = TRUE; // Link controlled - we mnust have a @go to continue with notecards + TimerEvent(0); +} + + +// @delete removes the NPC forever. Next command starts it up again at the beginning +DoDelete() { + DEBUG("state delete"); + + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + lNPCScript = []; // next command starts the NPC into action at the beginning + +} + +// change the appearance of the NPC +DoAppearance(string notecard) { + DEBUG("state appearance"); + if (llGetInventoryType(notecard) == INVENTORY_NOTECARD){ + DEBUG("Load appearance " + notecard); + osNpcLoadAppearance(NPCKey(),notecard); + } +} + +// Change the avatar speed +DoSpeed(string speed) { + float newspeed = (float) speed; + if (newspeed > 0.1 && newspeed < 5.0) // sanity check + osSetSpeed(NPCKey(),newspeed); +} +DoNewNote (string card) { + DEBUG("Load Notecard " + card); + NPCReadNoteCard(card); + Stopped = FALSE; +} + +// This loops over the notecard, processing each command +DoProcessNPCLine() { + DEBUG("ProcessNPCLine"); + STATE = 0; + + // auto load a notecard + if (! llGetListLength(lNPCScript)) { + DEBUG("Read Notecard"); + NPCReadNoteCard(Notecard); + Stopped = FALSE; + } + + // look for link messages on the stack + string next = llList2String(Stack,0); // lets see if there is anithing from a link message + if (llStringLength(next)) + { + Stack = llDeleteSubList(Stack,0,0); + ProcessCmd(next); //lets do this command instead. + return; + } + + // @stop issued? + if (Stopped) { + TimerEvent(0); + DEBUG("Waiting for input"); + return; + } + + // No, we have an @go for liftoff + next = llList2String(lNPCScript, 0); // get the next command + DEBUG("Execute:" + next); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); // delete it + + if (llGetListLength(lNPCScript) == 0) { + DEBUG("EOF"); + } + ProcessCmd(next); + +} + +ProcessCmd(string cmd) { + + DEBUG("ProcessCmd:" + cmd); + + if (llGetSubString(cmd, 0, 0) != "@") { + DEBUG("ignoring"); + STATE = DoProcess; + TimerEvent(QUICK); // this is so we do not recurse the stack + return; + } + + list data = llParseString2List(cmd, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data, 0), STRING_TRIM)); + + DEBUG("Action:" + npcAction); + npcParams = llStringTrim(llList2String(data, 1), STRING_TRIM); + + @commands; + + ProcessSensor(); + if (! avatarPresent){ + DoNobodyHome(); + DEBUG("No avatar nearby"); + return; + } else { + if (llStringLength(sNPCName)) { + DoSpawn(); + } + } + + if(npcAction == "@spawn") { + DEBUG("@spawn"); + list spawnData = llParseString2List(npcParams, ["|"], []); + sNPCName =llList2String(spawnData, 0); // V 1.6 name in RAM + + list spawnDest = llParseString2List(llList2String(spawnData, 1), ["<", ",", ">"], []); + vInitialPos.x = llList2Float(spawnDest, 0); + vInitialPos.y = llList2Float(spawnDest, 1); + vInitialPos.z = llList2Float(spawnDest, 2); + DoSpawn(); + + return; + } + else if(npcAction == "@stop") { + DEBUG("@stop"); + DoStop(); + return; + } + else if(npcAction == "@goto") { + DEBUG("goto"); + integer lastIdx = llGetListLength(lNPCScript)-1; + lNPCScript = llDeleteSubList(lNPCScript, lastIdx, lastIdx); + // Wind commands till goto label. + @wind; + string next1 = llList2String(lNPCScript, 0); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); + lNPCScript += next1; + if(next1 != npcParams) jump wind; + // Wind the label too. + next1 = llList2String(lNPCScript, 0); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); + lNPCScript += next1; + // Get next command. + list data1 = llParseString2List(next1, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data1, 0), STRING_TRIM)); + npcParams = llStringTrim(llList2String(data1, 1), STRING_TRIM); + // Reschedule. + jump commands; + } + else if(npcAction == "@sound") { + DEBUG("sound"); + llTriggerSound(npcParams,1.0); + } + else if(npcAction == "@randsound") { + DEBUG("@randsound"); + integer N = llGetInventoryNumber(INVENTORY_SOUND); + integer rand = llCeil(llFrand(N)) -1; // pick a random sound + string toPlay = llGetInventoryName(INVENTORY_SOUND,rand); + llTriggerSound(toPlay,1.0); + } + else if(npcAction == "@walk") { + DEBUG("@walk"); + GetDest(npcParams); + walkstate = 1;// walking + NPCWalkOption = OS_NPC_NO_FLY ; + DoWalk(); + return; + } + else if(npcAction == "@fly") { + GetDest(npcParams); + walkstate = 2;// flying + NPCWalkOption = OS_NPC_FLY ; + DoWalk(); + return; + } + else if(npcAction == "@run") { + DEBUG("@run"); + GetDest(npcParams); + walkstate = 3;// running + NPCWalkOption = OS_NPC_NO_FLY | OS_NPC_RUNNING; + DoWalk(); + return; + } + else if(npcAction == "@land") { + DEBUG("@land"); + GetDest(npcParams); + walkstate = 4;// landing + NPCWalkOption= OS_NPC_FLY | OS_NPC_LAND_AT_TARGET ; + DoWalk(); + return; + } + else if(npcAction == "@say") { + DEBUG("@say " + npcParams); + osNpcSay(NPCKey(), 0, npcParams); + } + else if(npcAction == "@shout") { + DEBUG("@shout"); + osNpcShout(NPCKey(),0, npcParams); + } + else if(npcAction == "@whisper") { + DEBUG("@whisper " + npcParams); + osNpcWhisper(NPCKey(),0, npcParams); + } + // speak a command on a channel, so you can open doors and control stuff. + else if(npcAction == "@cmd") { + DEBUG("@cmd"); + list dataToSpeak = llParseString2List(npcParams, ["|"], []); + string channel = llList2String(dataToSpeak,0); + DEBUG("Channel:"+(string) channel); + integer iChannel = (integer) channel; + string stringToSpeak = llList2String(dataToSpeak,1); + llSay(iChannel, stringToSpeak); + } + // stop everything + else if(npcAction == "@pause") { + DEBUG("@pause"); + RAMPause = (float) npcParams; + DoPause(); + return; + } + else if(npcAction == "@wander") { + DEBUG("@wander"); + list wanderData = llParseString2List(npcParams, ["|"], []); + RAMwd = (float) llList2String(wanderData, 0); + RAMwc = (integer) llList2String(wanderData, 1); + + vDestPos = osNpcGetPos(NPCKey()); // set the wander start + DEBUG("Starting at " + (string) vDestPos); + DoWander(); + return; + } + else if(npcAction == "@rotate") { + DEBUG("@rotate"); + RAMrot = (float) npcParams; + DoRotate(); + } + else if(npcAction == "@sit") { + DEBUG("@sit"); + RAMsit= npcParams; + DoSit(); + return; + } + else if(npcAction == "@touch") { + DEBUG("@touch"); + RAMtouch= npcParams; + DoTouch(); + return; + } + else if(npcAction == "@stand") { + DEBUG("@stand"); + DoStand(); + } + else if(npcAction == "@delete") { + DEBUG("@delete"); + DoDelete(); + return; + } + else if(npcAction == "@animate") { + DEBUG("@animate"); + list animateData = llParseString2List(npcParams, ["|"], []); + RAManimationName = llList2String(animateData, 0); + RAManimationTime = (float) llList2String(animateData, 1); + DoAnimate(); + return; + } + else if(npcAction == "@appearance" ) + { + DEBUG("@appearance"); + DoAppearance(npcParams); + } + else if (npcAction =="@speed") { + DEBUG("@speed"); + DoSpeed(npcParams); + } + else if (npcAction =="@notecard") { + DEBUG("@notecard"); + DoNewNote(npcParams); + Notecard = npcParams; + } + + STATE = DoProcess; + TimerEvent(QUICK); // yeah I know, not possible this fast, we just go as fast as we can go - this is so we do not recurse the stack +} + + + +/////////////////// UTILITY Functions, not state-like ////////////////// + +// DEBUG(string) will chat a string or display it as hovertext if debug == TRUE +DEBUG(string str) { + if (debug) + llOwnerSay( str); // Send the owner debug info so you can chase NPCS + if (iTitleText) { + llSetText(str,<1.0,1.0,1.0>,1.0); // show hovertext + + } +} + +GetDest(string npcParams) { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); +} + +NPCReadNoteCard(string Note) { + DEBUG("NPCReadNoteCard"); + lNPCScript = llParseString2List(osGetNotecard(Note), ["\n"], []); +} + +integer SenseAvatar() +{ + //Returns a strided list of the UUID, position, and name of each avatar in the region + list avatars = llGetAgentList(AGENT_LIST_REGION ,[]); + integer numOfAvatars = llGetListLength(avatars); + if (numOfAvatars == 0) + { + DEBUG("No people"); + return 0; + } + //DEBUG("Located " + (string)numOfAvatars + " avatars and NPC's"); + + integer nAvatars; + integer i; + for( i = 0;i < numOfAvatars; i++) { + key aviKey = llList2Key(avatars,i); + if (!osIsNpc(aviKey)) { + list detail = llGetObjectDetails(aviKey,[OBJECT_POS]); + vector pos = llList2Vector(detail,0); + float dist = llVecDist(pos, llGetPos()); + if (dist < RANGE) + { + nAvatars++; + DEBUG("In range:" + llKey2Name(aviKey)); + } + } + } + //DEBUG("Located " + (string) nAvatars + " avatars"); + return nAvatars; +} + +// return TRUE if the avatar is owner when private is set, or TRUE if the avatar is in the same group and GROUP is set. +integer checkPerms() { + + integer group = (integer) KeyValueGet("pr"); + if (! group) + priPub = "Owner Only"; + else + priPub = "Group"; + + + if (llDetectedKey(0) == llGetOwner()){ + kUserKey = llDetectedKey(0); + return TRUE; + } + + if ( group && llDetectedGroup(0)) { + kUserKey = llDetectedKey(0); + return TRUE; + } + kUserKey = llDetectedKey(0); + return FALSE; +} + + + +NPCAnimate(string anim) +{ + DEBUG("Start Anim: " + anim); + if (llGetInventoryType(anim) == INVENTORY_ANIMATION ) { + + if (lastANIM != anim) { + if(llStringLength(lastANIM)) { + osNpcStopAnimation(NPCKey(), lastANIM); + } + osNpcPlayAnimation(NPCKey(), anim); + lastANIM = anim; + } + } else { + llSay(DEBUG_CHANNEL, "No animation named " + anim); + } +} + + +TimerEvent(float timesent) +{ + DEBUG("Setting timer: " + (string) timesent); + llSetTimerEvent(timesent); +} + +// Kill a NPC by Name +Kill(string param) +{ + integer count; + list avatars = osGetAvatarList(); // Returns a strided list of the UUID, position, and name of each avatar in the region except the owner.\ + integer i; + integer j = llGetListLength(avatars); + for (i=0 ; i <= j; i+=3){ + + string desired = llList2String(avatars,i+2); + desired = llStringTrim(desired,STRING_TRIM); // should not be needed but is needed + + if (desired == param){ + vector v = llList2Vector(avatars,i+1); + key target = llList2Key(avatars,i); // get the UUID of the avatar + osNpcRemove(target); + SaveKey(NULL_KEY ); + llOwnerSay("Removed " + param+ " at location " + (string) v); + count++; + } + } + + NPCEnabled = FALSE; // not in world + + if (count) + llOwnerSay("Removed " + (string) count + " NPC's"); + else + llOwnerSay("Could not locate " + param); +} + + +// return a String for the position we are at. Strings used as the caller wants strings +string Pos() +{ + vector where = llGetPos(); // find the box position + + where.z += OffsetZ; // use the ground position + an offset + + if (Editor) + where = <128,128,31 + llFrand(1)>; // center of sim for editing + + // if attached the height will be too high by 1/2 the agent size + if (llGetAttached()) { + vector size = llGetAgentSize(llGetOwner()); + float Z = size.z; + where.z -= Z/2; + } + + // DEBUG("Pos= " + (string) where); + return (string) where; +} + +// setup a menu with a timer for timeouts, called by all make*() +menu() +{ + llListenRemove(iHandle); + iChannel = llCeil(llFrand(100000) + 20000); + iHandle = llListen(iChannel,"","",""); + TimerEvent(30.0); + MENU = TRUE; +} + +// make a text box +makeText(string Param) +{ + menu(); + llTextBox(kUserKey, Param, iChannel); +} + +// top level menu +makeMainMenu() +{ + menu(); + list buttons = ["Appearance","Recording","Save","Help","-","Erase RAM", priPub,relAbs,"-","Stop NPC",mSensor,"Start NPC"]; + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Records",buttons,iChannel); +} + + +// Rev 1.4 +// top level menu for non group/ non owners +makeUserMenu() +{ + if (!allowUsers) return; + + menu(); + list buttons = ["Start NPC","Stop NPC"]; + llDialog(kUserKey,"Choose",buttons,iChannel); +} + + + +// programmable menu for @commands +makeMenu(list buttons) +{ + menu(); + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Record",buttons,iChannel); +} + + +// make one or two text boxes with prompts +Text(string cmd, string p1, string p2) +{ + sCommand = cmd; + sParam2 = ""; + if (llStringLength(p2)) + sParam2 = p2; + + makeText(p1); +} + +// Set the Avatar Present flag - if sensors are off and we are forece run, there will be one present. +ProcessSensor() +{ + integer SensorOn; + if ("on" == KeyValueGet("se")) + { + SensorOn = TRUE; // we need to scan for avatars + } else { + SensorOn = FALSE; // we need to scan for avatars + } + DEBUG("Sensor:" + (string) SensorOn); + + integer n = SenseAvatar(); + + DEBUG("Avatars:" + (string) n); + if (SensorOn && n) + avatarPresent = TRUE; // someone is here and we need to tell the system to run + else if (SensorOn && !n) + avatarPresent = FALSE; // someone is not here and we need to tell the system to stop + else { // sensor is off, lete see if there is a NPC. If so, we are ON + DEBUG("NPCEnabled:" + (string) NPCEnabled); + if (NPCEnabled) + avatarPresent = TRUE; + else + avatarPresent = FALSE; + } + //DEBUG("Avatar Present: " + (string) avatarPresent); +} + +vector CirclePoint(float radius) { + float x = llFrand(radius *2) - radius; // +/- radius, randomized + float y = llFrand(radius *2) - radius; // +/- radius, randomized + return ; // so this should always happen +} + +string KeyValueGet(string var) { + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k != var) jump continue; + //DEBUG("got " + var + " = " + llList2String(data, 1)); + return llList2String(data, 1); + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + return ""; +} + +KeyValueSet(string var, string val) { + + //DEBUG("set " + var + " = " + val); + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + if(llGetListLength(dVars) == 0) + { + llSetObjectDesc(var + "=" + val); + return; + } + list result = []; + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k == "") jump continue; + if(k == var && val == "") jump continue; + if(k == var) { + result += k + "=" + val; + val = ""; + jump continue; + } + string v = llList2String(data, 1); + if(v == "") jump continue; + result += k + "=" + v; + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + if(val != "") result += var + "=" + val; + llSetObjectDesc(llDumpList2String(result, "&")); +} + + +// clear RAM +Clr() { + + lCommands = []; + llOwnerSay("RAM Memory cleared. Notecards, if any, are not modified."); + makeMainMenu(); +} + +integer checkNoteCards() +{ + // Check that they have saved an Appeaance and Path notecard + integer num = llGetInventoryNumber(INVENTORY_NOTECARD); // how many notecards overall + + integer i; + integer count; + for (; i < num; i++){ + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Notecard) + count++; + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Appearance) + count++; + } + DEBUG("Checked " + (string) count + " Notecards"); + // if we have both, run the NPC + return count; +} + +Update(string SName) { + + // delete all NPC*scripts except myself + integer i; + integer j = llGetInventoryNumber(INVENTORY_SCRIPT); + for (i = 0; i < j; i++) { + string name = llGetInventoryName(INVENTORY_SCRIPT,i); + string match = llGetSubString(name,0,2); + if (match == SName && llGetScriptName() != name) + { + llRemoveInventory(name); + llOwnerSay("Upgraded"); + } + } + +} + +// Get all default saved params from the Description +GetSwitches() +{ + string rA = KeyValueGet("co"); // Get the remembered menu setting for Abs Vs Relative + if (rA == "A") + relAbs = "Absolute"; + else if (rA == "R") + relAbs = "Relative"; + else + relAbs = "Absolute"; + + + // reenable NPC if sensor is on. + if ("on" == KeyValueGet("se")) + { + NPCEnabled = TRUE; + mSensor = "Sense is On"; + ProcessSensor(); // fake 1 avatar to get it rezzed + } else { + mSensor = "Sense is Off"; + } + } + + +SaveKey(key akey) +{ + DEBUG("Saving Key of " + (string) akey); + KeyValueSet("key", akey); + if (akey != (key) KeyValueGet("key") ) + { + DEBUG("Fatal error, cannot save key"); + } + gNpcKey = akey; +} + + +key NPCKey() +{ + key akey = gNpcKey; // from cached copy + // gNpcKey saves a lot of CPU processing by caching the key, if blank we get it from the description + if (gNpcKey == NULL_KEY) + { + //DEBUG("Get DKey"); + akey = KeyValueGet("key"); // from Description of the prim + } + // DEBUG("NPC KEY:" + (string) akey); + return akey; +} + + +/////////////////// CODE BEGINS ////////////////// + + +default +{ + changed(integer change) { + if(change & CHANGED_REGION_START) { + llResetScript(); + } + } + + on_rez(integer start_param) + { + llResetScript(); + } + + state_entry() { + + llSetText("",<1,1,1>,1.0); // clr all hovertext- we may not be using it. + DoDelete(); // kill any NPC that is out running + Update("NPC"); // If dragged and ropped into a prim with any script named "NPC...", this will replace it. + GetSwitches(); // Get all default saved params from the Description + llSetTimerEvent(TIMER); + } + + + touch_start(integer n) + { // if touched, make a menu + + if (checkPerms()) { + if (RecordPath == STATE) { + makeMenu(lAtButtons); + } else { + makeMainMenu(); + } + } else { + makeUserMenu(); + } + } + + // menu listener + listen(integer iChannel, string name, key id, string message) { + + if (MENU) { + llListenRemove(iHandle); + MENU = 0; // menu is off + iHandle = 0; + } + + if (message == "Stop NPC") + { + lNPCScript = []; // force reload of notecard + NPCEnabled = FALSE; + if (NPCKey() != NULL_KEY){ + Kill(sNPCName); + sNPCName = ""; + } else { + bNPC_STOP = TRUE; + makeText("Enter name of an NPC to stop"); + } + } + else if (message == "Menu" ) { + makeMainMenu(); + } + else if (message == "Erase RAM"){ + Clr(); + } + else if (message == "Relative"){ + relAbs = "Absolute"; + KeyValueSet("co","A"); // remember coordinates = A + Clr(); + } + else if (message == "Absolute"){ + relAbs = "Relative"; + KeyValueSet("co","R"); // remember coordinates = R + Clr(); + } + else if (message == "Recording"){ + DoMenuForCommands(); // show them the recording menu + } + else if (message == "Owner Only") { + priPub = "Group"; + KeyValueSet("pr","1"); + + llOwnerSay("Group members have control"); + makeMainMenu(); + } + else if (message == "Group") { + priPub = "Owner Only"; + KeyValueSet("pr","0"); + llOwnerSay("Only you have control"); + makeMainMenu(); + } + else if (message == "Sense is On") { + mSensor ="Sense is Off"; + KeyValueSet("se", "off"); + llOwnerSay(mSensor); + makeMainMenu(); + } + else if (message == "Sense is Off") { + mSensor ="Sense is On"; + llOwnerSay(mSensor); + KeyValueSet("se", "on"); + + NPCEnabled = FALSE; + + integer count = checkNoteCards(); + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + DoProcessNPCLine(); + return; + } + if (Editor) { + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording and/or appearance, so you cannot start a NPC"); + makeMainMenu(); + } + else if (message == "Appearance") { + llRemoveInventory(Appearance); // delete the notecard + osAgentSaveAppearance(kUserKey,Appearance); // make the ntecard + llOwnerSay("Your outfit has been saved"); + makeMainMenu(); + } + else if (message == "Save") { + if (llGetListLength(lCommands) == 0) { + llOwnerSay("Nothing recorded, you need to make a recording first"); + makeMainMenu(); + return; + } + DoSave(); + } + else if (message == "Help"){ + llLoadURL(kUserKey,"Click to view help","http://www.outworldz.com/opensim/posts/NPC/"); + makeMainMenu(); + } + else if (message == "Start NPC") { + integer count = checkNoteCards(); + Stopped = FALSE; // Let's run the notecard + NPCEnabled = TRUE; + + if (Editor) { + DoProcessNPCLine(); + return; + } + + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + Stopped = FALSE; // Let's run the notecard + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording or maybe an appearance, so we cannot start a NPC"); + + } + else if (bNPC_STOP){ + bNPC_STOP = FALSE; + Kill(message); + } + else if (message == ">>"){ + makeMenu(lMenu2); + } + else if (message == ">>>"){ + makeMenu(lMenu3); + } + else if (message == "<<") { + makeMenu(lAtButtons); + } + else if (message == "<<<") { + makeMenu(lMenu2); + } + else if (message == "@comment"){ + Text("# ","Enter a comment",""); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@run"){ + lCommands += "@run=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@fly"){ + lCommands += "@fly=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@land"){ + lCommands += "@land=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@walk") { + lCommands += "@walk=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@sound"){ + Text("@sound=","Enter a sound name or UUID to trigger",""); + } + else if (message == "@randsound"){ + lCommands += "@randsound"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@say") { + Text("@say=","Enter what the NPC will say",""); + } + else if (message == "@whisper"){ + Text("@whisper=","Enter what the NPC will whisper",""); + } + else if (message == "@shout"){ + Text("@shout=","Enter what the NPC will shout",""); + } + else if (message == "@wander") { + Text("@wander=","Enter radius to wander","Enter number of wanders"); + } + else if (message == "@pause") { + Text("@pause=","Enter time to pause",""); + } + else if (message == "@rotate") { + Text("@rotate=","Enter degrees to rotate",""); + } + else if (message == "@sit"){ + Text("@sit=","Enter name of object to sit on",""); + } + else if (message == "@touch"){ + Text("@touch=","Enter name of object to touch",""); + } + else if (message == "@cmd"){ + Text("@cmd=","Enter cjhannel to speak on","Enter text to speak"); + } + else if (message == "@stand"){ + lCommands += "@stand\n"; + llOwnerSay("Stand Recorded"); + makeMenu(lAtButtons); + } + else if (message == "@animate"){ + Text("@animate=","Enter animation name to play","Enter time to play the animation"); + } + else if (message == "@speed"){ + Text("@speed=","Enter a speed for the NPC, 1=100% normal speed, 0.5=50% speed",""); + } + + + // Save NPC name + else if (MakeNotecard == STATE) { + sNPCName = message; // in case we need to kill it. + + vector vDest = (vector) Pos(); + + if (relAbs == "Relative") + { + vDest -= llGetPos(); // just an offset for relative + } + sNotecard = "@spawn=" + message + "|" + (string) vDest + "\n"; + integer i; + integer j = llGetListLength(lCommands); + for (; i < j; i++){ + // get the command to save to the notecard + string line = llList2String(lCommands,i); + if (relAbs == "Absolute") { + sNotecard += line; // add the un-modified string to the notecard + } else { + // since we have to record absolute coords since we do not know where the box goes until they press Save, + // we process the absolute to relative conversion for walks here + list parts = llParseString2List(line,["="],[]); //get the @command + + if (llList2String(parts,0) == "@walk") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@walk=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@fly") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@fly=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@run") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@run=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@land") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@land=" + (string) vec + "\n"; + } + else { + sNotecard += line; // add the un-modified string to the notecard + } + } + } + llRemoveInventory(Notecard); // delete the old notecard + osMakeNotecard(Notecard,sNotecard); // Makes the notecard. + llOwnerSay("Commands notecard has been written"); + STATE = 0; + } // MakeNotecard + + else if (! llStringLength(sParam2)) { + lCommands += sCommand + message + "\n"; + llOwnerSay("Recorded"); + makeMenu(lAtButtons); + } + else if (llStringLength(sParam2)){ + sCommand = sCommand + message + "|"; + llOwnerSay("Recorded"); + makeText(sParam2); + sParam2 = ""; + } + + } + + + + timer(){ + DEBUG("tick"); + + // if llDialog is up, kill the listener for the dialog box. + if (iHandle) { + llOwnerSay("Menu timed out"); + llListenRemove(iHandle); + iHandle = 0; + return; // ^^^^^^^^^^^^^^^^^^^^^^^ + } + // if NoBodyHome, we are sensing for an avatar + else if (NobodyHome == STATE) { + if (! llGetRegionAgentCount()) { + DoNobodyHome(); + return; // ^^^^^^^^^^^^^^^^^^^^^^^ + } + } + // if we are spawning, we need time to rez the NPC, then start processing NPC Commands. + else if (Spawning == STATE) { + STATE = 0; + TimerEvent(TIMER); + } + // We end aniamtions with a timer + else if (Animate == STATE){ + NPCAnimate(STAND); + TimerEvent(TIMER); + } + + else if (Walking == STATE) { + if (--iWaitCounter) { + if (llVecDist(osNpcGetPos(NPCKey()), newDest) > MAXDIST) { + return; + } + } + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 2) { + // nothing + } else if (walkstate == 3) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 4) { + llShout(FLIGHT,"landing"); + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } + } + // Wandering timer + else if (Wander == STATE) { + if (--iWaitCounter) { // wait 60 seconds to get to a destination. + if (llVecDist(osNpcGetPos(NPCKey()), vWanderPos) > MAXDIST) + return; + } + + // see if wander counter == 0, if so, stop walking, go to stand and process next line + if(RAMwc == 0) { + NPCAnimate(STAND); + DEBUG("Wander ended, calling DoProcessNPCLine"); + STATE = 0; + DoProcessNPCLine(); + return; + } + // one less time to wander around + RAMwc--; + NPCAnimate(STAND); + TimerEvent(TIMER); + DoWanderhold(); + return; + } + // Wandering requires us to re-wander when we reach a destination + else if (WanderHold == STATE) { + DoWander(); + TimerEvent(TIMER); + return; + } + else if (DoProcess == STATE) { + TimerEvent(QUICK); + } + + STATE = 0; + + // We always process a NPC line at end of timer. + DEBUG("Tick end, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } + + // sensors are used for sitting on prims + // Neo Cortex: added different SensorFunc states to trigger sit or touch + sensor(integer num) { + if (SensorFunc == 1) { + osNpcSit(NPCKey(), llDetectedKey(0), OS_NPC_SIT_NOW); + DEBUG("Seated, calling DoProcessNPCLine"); + SensorFunc = 0; + } else if (SensorFunc == 2) { + osNpcTouch(NPCKey(), llDetectedKey(0), LINK_THIS); + DEBUG("Touched, calling DoProcessNPCLine"); + SensorFunc = 0; + } + DoProcessNPCLine(); + } + no_sensor(){ + DEBUG ("no target prim located, calling DoProcessNPCLine"); + SensorFunc = 0; + DoProcessNPCLine(); + } + + + link_message(integer sender, integer num, string str, key id){ + DEBUG("Command In:" + str); + if (str=="@go") { + Stopped = FALSE; // Let's run the notecard + DEBUG("@go approved, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } else { + if (Stopped) + { + Stack += [str]; // take anything, the controller will filter away non @ stuff + DoProcessNPCLine(); + } else { + Stack += [str]; // take anything, the controller will filter away non @ stuff + TimerEvent(TIMER); + } + } + } + +} + + + + + + diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.6.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.6.lsl new file mode 100644 index 00000000..5afe4032 --- /dev/null +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.6.lsl @@ -0,0 +1,1557 @@ +// :SHOW:0 +// :CATEGORY:NPC +// :NAME:All In One NPC Recorder and Player +// :AUTHOR:Ferd Frederix +// :KEYWORDS:NPC, Puppeteer +// :CREATED:2013-09-08 18:27:47 +// :EDITED:2015-09-04 19:33:59 +// :ID:27 +// :NUM:1822 +// :REV:3.6 +// :WORLD:OpenSim +// :DESCRIPTION: +// All in one NPC recorder player. +// Supports both absolute and relative paths and many new commands +// Add animations named "Fly, Walk, Stand and Run" +// Click Prim to use. +// Should be worn as a HUD to record. +// Put it on the ground and click Sensor or Start NPC when done. +// :CODE: + +FOR DEBUG PURPOSES - DO NOT USE - USE LATER VERSIONS ONLY!!! + +// This is Rev 3.6 08/11/2015 + +// Revision History +// Rev 1.1 10-2-2014 @Sit did not work. Minor tweaks to casting for lslEditor +// Rev 1.2 10-14-2014 @ sit had wrong type. +// Rev 1.3 relative movement fixed for @fly +// Rev 1.4 4-3-2014 allow anyone to use this, non owners and non group members can only start and stop. +// Rev 1.5 5-17-2014 set sensor to auto start on reboot of sim +// Rev 1.6 5-24-2014 move menu so you can get it by touching, removed many of the KeyValues to RAM for efficiency +// Rev 1.7 CHANGED_REGION_START, not CHANGED_REGION_START (Opensim difference) +// Rev 1.8 tuned up Kill NPC, added more flexible upgrader +// Rev 1.9 Better script injection by link message// Rev 2.0 Added osSetSpeed so you can speed up or slow down an NPC. +// Rev 2.1 No laggy sensor used exept to sit on stuff +// Rev 2.2 Various sensor fixes +// Rev 2.3 Sets No Sensor in menu, must be started by hand +// Rev 2.4 - reserved for patches to 2.3 if needed +// Rev 3.0 Refactor out into subs, not states to make command injection easier +// New command: @appearance=Notecardname so you can switch to a new notecard on the fly +// New command: @speed=1.0 which slows up ( < 1 ) or speeds up ( > 1) +// Rev 3.1 Commands are not interruptible by Link Message +// Rev 3.2 Sensor patches for consistency in removing the NPC +// Rev 3.3 Added Touch command by Neo.Cortex@hbase42/hopto/org:8002 +// Added Menu 3 for notecard and appearance commands +// Rev 3.4 animation timer cannot be zero or it shuts off timer tweaked +// solves the NPC starting up when no sensor is set. +// Rev 3.5 fixes saving in !Path notecard +// Rev 3.6 @delete acts like @stop. TYjhe NPC now rezzes after an @go back in where it was deleted + + //*******************************************************************// + + +// Instructions on how to use this is at http://www.outworldz.com/opensim/posts/NPC/ +// This is an OpenSim-only script. +// Author: Ferd Frederix aka Fred Beckhusen - fred@mitsi.com + +//////////////////////////////////////////////////////////////////////////////////////////// +// Original code was Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // +/////////////////////////////////////////////////////////////////////////////////////////// +// Please see: http://www.gnu.org/licenses/gpl.html for legal details, // +// rights of fair usage, the disclaimer and warranty conditions. // +/////////////////////////////////////////////////////////////////////////////////////////// +// The original NPC controller was from http://was.fm/opensim:npc +// Extensive additions and bug fixes by Fred Beckhusem, aka Ferd Frederix, fred@mitsi.com +// llSensor had two params swapped +// @Wander would wander where it had rezzed, not where it was. +// There was no 'no_sensor' event in sit, so if a @sit failed, the NPC got stuck +// The animation and walks always stopped old, then started new. It should be start new, then stop old so the default stand would be suppressed. +// New code: +// Merged with new Route recorder and notecard writer +// If the NPC failed to reach a destination it never moved on. Added WAIT global to tune this +// Exposed many tunable variables and ported the code to LSLEditor. +// Added floating point to times in notecard. + +// Added @sound, @randsound, @whisper, @shout, and @cmd controls. +// +// notecards integers are not floats for better control +// +// Link Messages may be used to perform external control by injecting @commands into the stream of actions +// Example: +// To chat something, such as with a chat robot +// llMessageLinked(LINK_SET,0,"@npc_say=Hello",""); + +// This script assumes that NPCs and OSSl scripting is enabled in the OpenSim configuration. +// In order to enable them, the following changes must be made in the OpenSim.ini configuration file: +// +// ; Turn on OSSL +// AllowOSFunctions = true +// OSFunctionThreatLevel = Severe + +//[NPC] +// ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} +// Enabled = true +// +// and then the server has to be restarted. + + +// Commands: All commands begin with an @ sign. All other lines are ignored +// @commands may have optional parameters. The syntax is always: +// @cmd=parm1|parm2 +// NaN in the table below meand Not a Number. This means there is no parameter + +//Command First Parameter Second Parameter Description +//@spawn name location (vector) Rezzes an NPC with name at a location. +//@appearance NoteCardName NaN switch the NPC appearance to a new notecard +//@walk destination (vector) NaN Makes the NPC walk to destination. +//@fly destination (vector) NaN Makes the NPC fly to destination. +//@land destination (vector) NaN Makes the NPC land at destination. +//@say string NaN Makes the NPC speak a phrase. +//@whisper string NaN Makes the NPC whisper a phrase. +//@shout string NaN Makes the NPC shout a phrase. +//@pause seconds (float) NaN Makes the NPC wait for a multiple of seconds. +//@wander radius (float) cycles (integer) Makes the NPC wander in radius, for cycles seconds. +//@delete NaN NaN Removes the NPC. Requires a link message to continue +//@goto label (string) NaN Jump to the label label in the script. +//@animate animation (string) time (float) Makes the NPC trigger the animation animation for time seconds. +//@sound sound_name NaN plays a sound from inventory +//@randsound NaN NaN Plays a random sound from inventory +//@rotate degrees (float) NaN Rotate the NPC degrees around the Z axis. +//@sit primitive name NaN Sit on a primitive with a given name. +//@touch primitive name NaN Touch on a primitive with a given name. +//@stand NaN NaN If sitting on a primitive, stand up. +//@cmd channel (integer) string Says string on channel, for controlling external gadgets +//@stop NaN NaN Halts the NPC script indefinitely. Can be started with a link message +//@go NaN NaN Continues on next notecard line, for use in link messages +//@speed speed (float) NaN from 0 to N, where 1.0 ius a normal speed of an avatar. 0.2 is a turtle. +//@notecard notename (string) NaN load a new Path notecard + + +////////////////////////////////////////////////////////// +// DEBUG // +////////////////////////////////////////////////////////// +integer debug = FALSE; // set to TRUE or FALSE for debug chat on various actions +integer Editor = FALSE; // set to to TRUE to working in LSLEditor, FALSE for in-world. + // you must also include the NPC commands found in the other script since LSLEditor does not support OpenSim +integer iTitleText = TRUE; // set to TRUE to see debug info in text above the controller + +////////////////////////////////////////////////////////// +// TUNABLE CONFIGURATION // +////////////////////////////////////////////////////////// +float TIMER = 0.5; // how often the system checks the distance traveled. Fastest you can go is 0.5 seconds +float QUICK = 0.020; // when we need to move to the next state, we use a QUICK timer +string Appearance = "!Appearance"; // The name of the recorded Appearance notecard +string Notecard = "!Path"; // The name of the recorded routes +integer allowUsers = FALSE; // If true, any user can get a Start NPC and Stop NPC menu. Only groups and owners can get all commands if TRUE, or FALSE +float MAXDIST = 2.0; // how close a NPC has to get to a dest pos to continue to next state. Do not lower this too much, as it may miss the target +integer WANDERRAND = TRUE; // set to TRUE and they will pause during wanders a random number of seconds +float WANDERTIME = 3.0; // how long they stand after each @wander,if WANDERRAND is FALSE. If WANDERRAND is TRUE, this is the max time +integer WAIT = 30; // wait for this number of seconds for the NPC to reach a destination (for safety). If it fails to reach a target, it will move on after this time. +float RANGE = 50; // 1 to N meters - anyone this close to the controller will start NPCS if Sensor button is clicked +float REZTIME = 2.0; // wait this long for NPC to rez in, then start the process +string STAND = "Stand"; // the name of the default Stand animation +string WALK = "Walk"; // the name of the default Walk animation +string FLY = "Fly"; // the name of the default Fly animation +string RUN = "Run"; // the name of the default Run animation +string LAND = "Land"; // the name of the default land animation ( for birds only) +float OffsetZ = 0.5; // appear 0.5 meter above ground, this is added to all destinations to keep them from sinking in. +float SPEEDMULT =1.0; // 1.0 = regular avatar speed. Smaller numbers slow down walks. Large numbers speed them up. +integer FLIGHT = 299; // For controlling wings. A channel that is shouted at when flight starts and ends. "flying" or "landing" + +// DESCRIPTIONS FIELDS HAVE TO SURVIVE A RESET +// These vars are stored by saving them with KeyValueSet +// "pr" is a 0 if it is set for Owner Only, 1 for Group control +// "se" is "on" if Started +// "co" = "R" or "A" for relative or absolute addressing mode +// "key" = NPC key + +// These Globals used to be stored in description. Moved to RAM in V1.6 +float RAMPause; // @pause param +float RAMwd ; // @wander distance +integer RAMwc; // @wander count +float RAMrot; // @rotate +string RAMsit; // @sit primname +string RAMtouch; // @touch primname +string RAManimationName; // @animate animation (string) time (float) +float RAManimationTime; + +// other globals section +integer iChannel; // a listen channel, randomly assigned +integer iHandle; // the handle to it + +// NPC controls +vector newDest ; // tmp storage for the walks +integer iWaitCounter ; // wait for this number of seconds for the NPC to reach a desrtination +string sNPCName; // the name of the NPC that may be in world. So we can remove it. +integer bNPC_STOP = FALSE; // boolean to reuse a listener +integer Stopped = FALSE; // set to TRUE by link messages so we do not remember them +float fTimerVal ; // how long we wait when wandering (calculated) +float NPCEnabled; // true if the NPC is suppodes to be running + +// OS_NPC_CREATOR_OWNED will create an 'owned' NPC that will only respond to osNpc* commands issued from scripts that have the same owner as the one that created the NPC. +// OS_NPC_NOT_OWNED will create an 'unowned' NPC that will respond to any script that has OSSL permissions to call osNpc* commands. +integer NPCOptions = OS_NPC_CREATOR_OWNED; // only yhe owner of this box can control this NPC. + +integer walkstate = 0; // helps us reshare the walk state for run, fly and land - a bit of a hack, but it saves RAM. Has to be done this way because some bits of NPCWalkOption are asserted as 0 + +integer NPCWalkOption; // Some notes for what happens to NPCWalkOption: +// OS_NPC_FLY - Fly the avatar to the given position. The avatar will not land unless the OS_NPC_LAND_AT_TARGET option is also given. +// OS_NPC_NO_FLY - Do not fly to the target. The NPC will attempt to walk to the location. If it's up in the air then the avatar will keep bouncing hopeless until another move target is given or the move is stopped +//OS_NPC_LAND_AT_TARGET - If given and the avatar is flying, then it will land when it reaches the target. If OS_NPC_NO_FLY is given then this option has no effect. +// OS_NPC_RUNNING - if given, NPC avatar moves at running/fast flying speed, otherwise moves at walking/slow flying speed. + +// menus +string mSensor="Sense is Off"; // Sensor or "No Sensor" + +list lAtButtons = ["Menu","-", ">>", "@run", "@walk", "@fly", "@land", "@wander", "@sit", "@stand","@animate","@rotate"]; +list lMenu2 = ["<<", "@comment", ">>>", "@stop", "@say", "@whisper","@shout","@sound","@randsound","@cmd", "@pause", "@delete"]; +list lMenu3 = ["<<<","@notecard","@appearance", "@touch", "@speed", "-", "-","-", "-", "-", "-", "-" ]; + +string sCommand; // place to store a command for two-prompted ones +string sParam2; // place to store a prompt for two-prompted ones +string priPub = "Owner Only"; // Private or Group +key kUserKey; // the person who is controlling the avatar, not the Owner +// the command lists +list lCommands; // commands are stored here +list lNPCScript; // Storage for the NPC script. +string npcAction; // Storage for the next action. @cmd=0|hello, this becomes @cmd +string npcParams; // Storage for the param, @cmd=0|hello, this becomes 0|hello + +// misc vars +string sNotecard; // commands are stored here temporarily for dumping +vector vWanderPos; // a place to wander to +string lastANIM ; // last animation run +// Sensor +integer avatarPresent; // Sensor sets this flag when people are within Range. + +// Coordinate control +vector vInitialPos ; // Vector that will be filled by the script with the initial starting position in region coordinates. +vector vDestPos = ZERO_VECTOR; // Storage for destination position. +string relAbs = "Relative"; // absolute vs relative positioning +vector lastKnownPos; // last known NPC position when we deleted it + +// STATES +integer MENU ; // processing a dialog box state, may be concurrent with STATE +integer STATE; // state storage +integer MakeNotecard = 1; // displaying a text box for NPC name +integer RecordPath = 2; // displaying a path notecard menu +integer NobodyHome = 3; // looking for an avatar +integer Spawning = 4; // spawning an avatar +integer Animate = 5; // animation timer needed +integer Walking = 6; // Hey! I am walking here! +integer Wander = 7; // Wandering around neeeds a timer, too +integer WanderHold = 8; // We reached a wander point +integer DoProcess = 9; // Set this to make it process a new command + +key gNpcKey = NULL_KEY; // global key storage for the one NPC, to save CPU cycles +list Stack ; // a command stack from link message input + +integer SensorFunc = 0; // define which function shall be triggered inside the sensor function + // 0 means none, 1 sit, 2 touch +/////////////////////////////////////////////////////////////////////////// +// FUNCTIONS // +/////////////////////////////////////////////////////////////////////////// + +// Do* functions are much like states from the old scripts. + +// Save a Path notecard +DoSave() +{ + STATE = MakeNotecard; + makeText("Stand where you want the NPC to appear, and enter the NPC Name"); +} + +// This function is used to record the path for the NPC +// Each command can take 0, 1, or 2 params +DoMenuForCommands() { + makeMenu(lAtButtons); +} + + +// No one is here when sensors were on, so we kill off the NPC +DoNobodyHome() +{ + DEBUG("Nobody Home"); + STATE = NobodyHome; + if (NPCKey() != NULL_KEY) { + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + } + TimerEvent(5); // keep ticking to sense avatars +} + +// Create a NPC +DoSpawn() { + DEBUG("state spawn"); + NPCEnabled = TRUE; // in world + // see if there is already one out there. + if (NPCKey() != NULL_KEY) { + DEBUG("Already living"); + return; + } + + STATE = Spawning; + + list name = llParseString2List(sNPCName, [" "], []); + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + vector tvInitialPos = lastKnownPos; + DEBUG("lastPos:"+ (string) lastKnownPos); + + if (relAbs == "Relative"){ + tvInitialPos += llGetPos(); + } + + DEBUG("Rez NPC:" + (string) tvInitialPos); + key aKey = osNpcCreate(llList2String(name, 0), llList2String(name, 1), tvInitialPos, Appearance, NPCOptions); + + SaveKey(aKey ); // save in desceription and global, too + + osSetSpeed(aKey,SPEEDMULT); // 1.9 speed multiplier + TimerEvent(REZTIME); + NPCAnimate(STAND); +} + +DoRotate() { + DEBUG("state rotate"); + osNpcSetRot(NPCKey(), llEuler2Rot(<0,0,RAMrot> * DEG_TO_RAD)); +} + +DoSit() { + DEBUG ("state sit - looking for " + RAMsit); + SensorFunc = 1; //triggers osNpcSit + llSensor(RAMsit, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +DoTouch() { + DEBUG ("state touch - looking for " + RAMtouch); + SensorFunc = 2; //triggers osNpcTouch + llSensor(RAMtouch, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +DoStand() { + + DEBUG("state stand"); + osNpcStand(NPCKey()); +} + + +DoAnimate() { + + DEBUG("state animate"); + STATE = Animate; + NPCAnimate(RAManimationName); + if (RAManimationTime <=0 ) // V 3.4 tweak + RAManimationTime = 1; + TimerEvent(RAManimationTime); +} + +DoWalk() { + + DEBUG("NPCWalkOption = " + (string) NPCWalkOption); + STATE = Walking; + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(WALK); + } else if (walkstate == 2) { + llShout(FLIGHT,"flying"); + NPCAnimate(FLY); + } else if (walkstate == 3) { + NPCAnimate(RUN); + } else if (walkstate == 4) { + NPCAnimate(LAND); + } + newDest = vDestPos ; + newDest.z += OffsetZ; + + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + newDest += llGetPos(); + } + + DEBUG("Moveto:" + (string) newDest); + osNpcMoveToTarget(NPCKey(), newDest, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + + +DoWander(){ + DEBUG("state wander"); + STATE = Wander; + + vector point = CirclePoint(RAMwd); + DEBUG("CirclePoint:" + (string) point); + vWanderPos = vDestPos + point; + DEBUG("vWanderPos:" + (string) vWanderPos); + + fTimerVal = WANDERTIME; // default time to pause after each wander + if (WANDERRAND) + fTimerVal = llFrand(WANDERTIME) + 1; // override, they want random times + + NPCAnimate(WALK); + + DEBUG("Wander to:" + (string) vWanderPos); + + osNpcMoveToTarget(NPCKey(), vWanderPos, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + +DoWanderhold() { + + DEBUG("Wander Hold"); + STATE = WanderHold; + + // now that we have reached a wander spot, slow the timer down to the desired value + TimerEvent(fTimerVal); +} + +// @pause=10 will do nothing for 10 seconds +DoPause() { + + DEBUG("state pause"); + if (RAMPause < 0.1) + RAMPause = 0.1; + + TimerEvent(RAMPause); +} + + +// @stop makes the NPC stop moving in whatever state it is in. You have to linkmessage to get moving again +DoStop() { + DEBUG("NPC is Stopped"); + Stopped = TRUE; // Link controlled - we mnust have a @go to continue with notecards + TimerEvent(0); +} + +// @delete removes the NPC forever. Next command starts it up again at the beginning +DoDelete() { + DEBUG("state delete"); + + vector v= osNpcGetPos(NPCKey()); + if (v != ZERO_VECTOR) + lastKnownPos = v; + else + lastKnownPos = llGetPos(); + + if (relAbs == "Relative"){ + lastKnownPos -= llGetPos(); + } + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + Stopped = TRUE; // Link controlled - we mnust have a @go to continue with notecards + TimerEvent(0); +} + +// change the appearance of the NPC +DoAppearance(string notecard) { + DEBUG("state appearance"); + if (llGetInventoryType(notecard) == INVENTORY_NOTECARD){ + DEBUG("Load appearance " + notecard); + osNpcLoadAppearance(NPCKey(),notecard); + } +} + +// Change the avatar speed +DoSpeed(string speed) { + float newspeed = (float) speed; + if (newspeed > 0.1 && newspeed < 5.0) // sanity check + osSetSpeed(NPCKey(),newspeed); +} +DoNewNote (string card) { + DEBUG("Load Notecard " + card); + NPCReadNoteCard(card); + Stopped = FALSE; +} + +// This loops over the notecard, processing each command +DoProcessNPCLine() { + DEBUG("ProcessNPCLine"); + STATE = 0; + + // auto load a notecard + if (! llGetListLength(lNPCScript)) { + DEBUG("Read Notecard"); + NPCReadNoteCard(Notecard); + Stopped = FALSE; + } + + // look for link messages on the stack + string next = llList2String(Stack,0); // lets see if there is anithing from a link message + if (llStringLength(next)) + { + Stack = llDeleteSubList(Stack,0,0); + ProcessCmd(next); //lets do this command instead. + return; + } + + // @stop issued? + if (Stopped) { + TimerEvent(0); + DEBUG("Waiting for input"); + return; + } + + // No, we have an @go for liftoff + next = llList2String(lNPCScript, 0); // get the next command + DEBUG("Execute:" + next); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); // delete it + + if (llGetListLength(lNPCScript) == 0) { + DEBUG("EOF"); + } + ProcessCmd(next); + +} + + + +ProcessCmd(string cmd) { + + DEBUG("ProcessCmd:" + cmd); + + if (llGetSubString(cmd, 0, 0) != "@") { + DEBUG("ignoring"); + STATE = DoProcess; + TimerEvent(QUICK); // this is so we do not recurse the stack + return; + } + + list data = llParseString2List(cmd, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data, 0), STRING_TRIM)); + + DEBUG("Action:" + npcAction); + npcParams = llStringTrim(llList2String(data, 1), STRING_TRIM); + + @commands; + + ProcessSensor(); + if (! avatarPresent){ + DoNobodyHome(); + DEBUG("No avatar nearby"); + return; + } else { + if ( NPCKey() == NULL_KEY) { + DoSpawn(); + } + } + + if(npcAction == "@spawn") { + DEBUG("@spawn"); + list spawnData = llParseString2List(npcParams, ["|"], []); + sNPCName =llList2String(spawnData, 0); // V 1.6 name in RAM + + list spawnDest = llParseString2List(llList2String(spawnData, 1), ["<", ",", ">"], []); + vInitialPos.x = llList2Float(spawnDest, 0); + vInitialPos.y = llList2Float(spawnDest, 1); + vInitialPos.z = llList2Float(spawnDest, 2); + lastKnownPos = vInitialPos ; + DoSpawn(); + + return; + } + else if(npcAction == "@stop") { + DEBUG("@stop"); + DoStop(); + return; + } + else if(npcAction == "@goto") { + DEBUG("goto"); + integer lastIdx = llGetListLength(lNPCScript)-1; + lNPCScript = llDeleteSubList(lNPCScript, lastIdx, lastIdx); + // Wind commands till goto label. + @wind; + string next1 = llList2String(lNPCScript, 0); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); + lNPCScript += next1; + if(next1 != npcParams) jump wind; + // Wind the label too. + next1 = llList2String(lNPCScript, 0); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); + lNPCScript += next1; + // Get next command. + list data1 = llParseString2List(next1, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data1, 0), STRING_TRIM)); + npcParams = llStringTrim(llList2String(data1, 1), STRING_TRIM); + // Reschedule. + jump commands; + } + else if(npcAction == "@sound") { + DEBUG("sound"); + llTriggerSound(npcParams,1.0); + } + else if(npcAction == "@randsound") { + DEBUG("@randsound"); + integer N = llGetInventoryNumber(INVENTORY_SOUND); + integer rand = llCeil(llFrand(N)) -1; // pick a random sound + string toPlay = llGetInventoryName(INVENTORY_SOUND,rand); + llTriggerSound(toPlay,1.0); + } + else if(npcAction == "@walk") { + DEBUG("@walk"); + GetDest(npcParams); + walkstate = 1;// walking + NPCWalkOption = OS_NPC_NO_FLY ; + DoWalk(); + return; + } + else if(npcAction == "@fly") { + GetDest(npcParams); + walkstate = 2;// flying + NPCWalkOption = OS_NPC_FLY ; + DoWalk(); + return; + } + else if(npcAction == "@run") { + DEBUG("@run"); + GetDest(npcParams); + walkstate = 3;// running + NPCWalkOption = OS_NPC_NO_FLY | OS_NPC_RUNNING; + DoWalk(); + return; + } + else if(npcAction == "@land") { + DEBUG("@land"); + GetDest(npcParams); + walkstate = 4;// landing + NPCWalkOption= OS_NPC_FLY | OS_NPC_LAND_AT_TARGET ; + DoWalk(); + return; + } + else if(npcAction == "@say") { + DEBUG("@say " + npcParams); + osNpcSay(NPCKey(), 0, npcParams); + } + else if(npcAction == "@shout") { + DEBUG("@shout"); + osNpcShout(NPCKey(),0, npcParams); + } + else if(npcAction == "@whisper") { + DEBUG("@whisper " + npcParams); + osNpcWhisper(NPCKey(),0, npcParams); + } + // speak a command on a channel, so you can open doors and control stuff. + else if(npcAction == "@cmd") { + DEBUG("@cmd"); + list dataToSpeak = llParseString2List(npcParams, ["|"], []); + string channel = llList2String(dataToSpeak,0); + DEBUG("Channel:"+(string) channel); + integer iChannel = (integer) channel; + string stringToSpeak = llList2String(dataToSpeak,1); + llSay(iChannel, stringToSpeak); + } + // stop everything + else if(npcAction == "@pause") { + DEBUG("@pause"); + RAMPause = (float) npcParams; + DoPause(); + return; + } + else if(npcAction == "@wander") { + DEBUG("@wander"); + list wanderData = llParseString2List(npcParams, ["|"], []); + RAMwd = (float) llList2String(wanderData, 0); + RAMwc = (integer) llList2String(wanderData, 1); + + vDestPos = osNpcGetPos(NPCKey()); // set the wander start + DEBUG("Starting at " + (string) vDestPos); + DoWander(); + return; + } + else if(npcAction == "@rotate") { + DEBUG("@rotate"); + RAMrot = (float) npcParams; + DoRotate(); + } + else if(npcAction == "@sit") { + DEBUG("@sit"); + RAMsit= npcParams; + DoSit(); + return; + } + else if(npcAction == "@touch") { + DEBUG("@touch"); + RAMtouch= npcParams; + DoTouch(); + return; + } + else if(npcAction == "@stand") { + DEBUG("@stand"); + DoStand(); + } + else if(npcAction == "@delete") { + DEBUG("@delete"); + DoDelete(); + return; + } + else if(npcAction == "@animate") { + DEBUG("@animate"); + list animateData = llParseString2List(npcParams, ["|"], []); + RAManimationName = llList2String(animateData, 0); + RAManimationTime = (float) llList2String(animateData, 1); + DoAnimate(); + return; + } + else if(npcAction == "@appearance" ) + { + DEBUG("@appearance"); + DoAppearance(npcParams); + } + else if (npcAction =="@speed") { + DEBUG("@speed"); + DoSpeed(npcParams); + } + else if (npcAction =="@notecard") { + DEBUG("@notecard"); + DoNewNote(npcParams); + Notecard = npcParams; + } + + STATE = DoProcess; + TimerEvent(QUICK); // yeah I know, not possible this fast, we just go as fast as we can go - this is so we do not recurse the stack +} + + + +/////////////////// UTILITY Functions, not state-like ////////////////// + +// DEBUG(string) will chat a string or display it as hovertext if debug == TRUE +DEBUG(string str) { + if (debug) + llOwnerSay( str); // Send the owner debug info so you can chase NPCS + if (iTitleText) { + llSetText(str,<1.0,1.0,1.0>,1.0); // show hovertext + + } +} + +GetDest(string npcParams) { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); +} + +NPCReadNoteCard(string Note) { + DEBUG("NPCReadNoteCard"); + lNPCScript = llParseString2List(osGetNotecard(Note), ["\n"], []); +} + +integer SenseAvatar() +{ + //Returns a strided list of the UUID, position, and name of each avatar in the region + list avatars = llGetAgentList(AGENT_LIST_REGION ,[]); + integer numOfAvatars = llGetListLength(avatars); + if (numOfAvatars == 0) + { + DEBUG("No people"); + return 0; + } + //DEBUG("Located " + (string)numOfAvatars + " avatars and NPC's"); + + integer nAvatars; + integer i; + for( i = 0;i < numOfAvatars; i++) { + key aviKey = llList2Key(avatars,i); + if (!osIsNpc(aviKey)) { + list detail = llGetObjectDetails(aviKey,[OBJECT_POS]); + vector pos = llList2Vector(detail,0); + float dist = llVecDist(pos, llGetPos()); + if (dist < RANGE) + { + nAvatars++; + DEBUG("In range:" + llKey2Name(aviKey)); + } + } + } + //DEBUG("Located " + (string) nAvatars + " avatars"); + return nAvatars; +} + +// return TRUE if the avatar is owner when private is set, or TRUE if the avatar is in the same group and GROUP is set. +integer checkPerms() { + + integer group = (integer) KeyValueGet("pr"); + if (! group) + priPub = "Owner Only"; + else + priPub = "Group"; + + + if (llDetectedKey(0) == llGetOwner()){ + kUserKey = llDetectedKey(0); + return TRUE; + } + + if ( group && llDetectedGroup(0)) { + kUserKey = llDetectedKey(0); + return TRUE; + } + kUserKey = llDetectedKey(0); + return FALSE; +} + + + +NPCAnimate(string anim) +{ + DEBUG("Start Anim: " + anim); + if (llGetInventoryType(anim) == INVENTORY_ANIMATION ) { + + if (lastANIM != anim) { + if(llStringLength(lastANIM)) { + osNpcStopAnimation(NPCKey(), lastANIM); + } + osNpcPlayAnimation(NPCKey(), anim); + lastANIM = anim; + } + } else { + llSay(DEBUG_CHANNEL, "No animation named " + anim); + } +} + + +TimerEvent(float timesent) +{ + DEBUG("Setting timer: " + (string) timesent); + llSetTimerEvent(timesent); +} + +// Kill a NPC by Name +Kill(string param) +{ + integer count; + list avatars = osGetAvatarList(); // Returns a strided list of the UUID, position, and name of each avatar in the region except the owner.\ + integer i; + integer j = llGetListLength(avatars); + for (i=0 ; i <= j; i+=3){ + + string desired = llList2String(avatars,i+2); + desired = llStringTrim(desired,STRING_TRIM); // should not be needed but is needed + + if (desired == param){ + vector v = llList2Vector(avatars,i+1); + key target = llList2Key(avatars,i); // get the UUID of the avatar + osNpcRemove(target); + SaveKey(NULL_KEY ); + llOwnerSay("Removed " + param+ " at location " + (string) v); + count++; + } + } + + NPCEnabled = FALSE; // not in world + + if (count) + llOwnerSay("Removed " + (string) count + " NPC's"); + else + llOwnerSay("Could not locate " + param); +} + + +// return a String for the position we are at. Strings used as the caller wants strings +string Pos() +{ + vector where = llGetPos(); // find the box position + + where.z += OffsetZ; // use the ground position + an offset + + if (Editor) + where = <128,128,31 + llFrand(1)>; // center of sim for editing + + // if attached the height will be too high by 1/2 the agent size + if (llGetAttached()) { + vector size = llGetAgentSize(llGetOwner()); + float Z = size.z; + where.z -= Z/2; + } + + // DEBUG("Pos= " + (string) where); + return (string) where; +} + +// setup a menu with a timer for timeouts, called by all make*() +menu() +{ + llListenRemove(iHandle); + iChannel = llCeil(llFrand(100000) + 20000); + iHandle = llListen(iChannel,"","",""); + TimerEvent(30.0); + MENU = TRUE; +} + +// make a text box +makeText(string Param) +{ + menu(); + llTextBox(kUserKey, Param, iChannel); +} + +// top level menu +makeMainMenu() +{ + menu(); + list buttons = ["Appearance","Recording","Save","Help","-","Erase RAM", priPub,relAbs,"-","Stop NPC",mSensor,"Start NPC"]; + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Records",buttons,iChannel); +} + + +// Rev 1.4 +// top level menu for non group/ non owners +makeUserMenu() +{ + if (!allowUsers) return; + + menu(); + list buttons = ["Start NPC","Stop NPC"]; + llDialog(kUserKey,"Choose",buttons,iChannel); +} + + + +// programmable menu for @commands +makeMenu(list buttons) +{ + menu(); + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Record",buttons,iChannel); +} + + +// make one or two text boxes with prompts +Text(string cmd, string p1, string p2) +{ + sCommand = cmd; + sParam2 = ""; + if (llStringLength(p2)) + sParam2 = p2; + + makeText(p1); +} + +// Set the Avatar Present flag - if sensors are off and we are forece run, there will be one present. +ProcessSensor() +{ + integer SensorOn; + if ("on" == KeyValueGet("se")) + { + SensorOn = TRUE; // we need to scan for avatars + } else { + SensorOn = FALSE; // we need to scan for avatars + } + DEBUG("Sensor:" + (string) SensorOn); + + integer n = SenseAvatar(); + + DEBUG("Avatars:" + (string) n); + if (SensorOn && n) + avatarPresent = TRUE; // someone is here and we need to tell the system to run + else if (SensorOn && !n) + avatarPresent = FALSE; // someone is not here and we need to tell the system to stop + else { // sensor is off, lete see if there is a NPC. If so, we are ON + DEBUG("NPCEnabled:" + (string) NPCEnabled); + if (NPCEnabled) + avatarPresent = TRUE; + else + avatarPresent = FALSE; + } + //DEBUG("Avatar Present: " + (string) avatarPresent); +} + +vector CirclePoint(float radius) { + float x = llFrand(radius *2) - radius; // +/- radius, randomized + float y = llFrand(radius *2) - radius; // +/- radius, randomized + return ; // so this should always happen +} + +string KeyValueGet(string var) { + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k != var) jump continue; + //DEBUG("got " + var + " = " + llList2String(data, 1)); + return llList2String(data, 1); + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + return ""; +} + +KeyValueSet(string var, string val) { + + //DEBUG("set " + var + " = " + val); + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + if(llGetListLength(dVars) == 0) + { + llSetObjectDesc(var + "=" + val); + return; + } + list result = []; + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k == "") jump continue; + if(k == var && val == "") jump continue; + if(k == var) { + result += k + "=" + val; + val = ""; + jump continue; + } + string v = llList2String(data, 1); + if(v == "") jump continue; + result += k + "=" + v; + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + if(val != "") result += var + "=" + val; + llSetObjectDesc(llDumpList2String(result, "&")); +} + + +// clear RAM +Clr() { + + lCommands = []; + llOwnerSay("RAM Memory cleared. Notecards, if any, are not modified."); + makeMainMenu(); +} + +integer checkNoteCards() +{ + // Check that they have saved an Appeaance and Path notecard + integer num = llGetInventoryNumber(INVENTORY_NOTECARD); // how many notecards overall + + integer i; + integer count; + for (; i < num; i++){ + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Notecard) + count++; + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Appearance) + count++; + } + DEBUG("Checked " + (string) count + " Notecards"); + // if we have both, run the NPC + return count; +} + +Update(string SName) { + + // delete all NPC*scripts except myself + integer i; + integer j = llGetInventoryNumber(INVENTORY_SCRIPT); + for (i = 0; i < j; i++) { + string name = llGetInventoryName(INVENTORY_SCRIPT,i); + string match = llGetSubString(name,0,2); + if (match == SName && llGetScriptName() != name) + { + llRemoveInventory(name); + llOwnerSay("Upgraded"); + } + } + +} + +// Get all default saved params from the Description +GetSwitches() +{ + string rA = KeyValueGet("co"); // Get the remembered menu setting for Abs Vs Relative + if (rA == "A") + relAbs = "Absolute"; + else if (rA == "R") + relAbs = "Relative"; + else + relAbs = "Absolute"; + + + // reenable NPC if sensor is on. + if ("on" == KeyValueGet("se")) + { + NPCEnabled = TRUE; + mSensor = "Sense is On"; + ProcessSensor(); // fake 1 avatar to get it rezzed + } else { + mSensor = "Sense is Off"; + } + } + + +SaveKey(key akey) +{ + DEBUG("Saving Key of " + (string) akey); + KeyValueSet("key", akey); + if (akey != (key) KeyValueGet("key") ) + { + DEBUG("Fatal error, cannot save key"); + } + gNpcKey = akey; +} + + +key NPCKey() +{ + key akey = gNpcKey; // from cached copy + // gNpcKey saves a lot of CPU processing by caching the key, if blank we get it from the description + if (gNpcKey == NULL_KEY) + { + //DEBUG("Get DKey"); + akey = KeyValueGet("key"); // from Description of the prim + } + // DEBUG("NPC KEY:" + (string) akey); + return akey; +} + + +/////////////////// CODE BEGINS ////////////////// + + +default +{ + changed(integer change) { + if(change & CHANGED_REGION_START) { + llResetScript(); + } + } + + on_rez(integer start_param) + { + llResetScript(); + } + + state_entry() { + + llSetText("",<1,1,1>,1.0); // clr all hovertext- we may not be using it. + DoDelete(); // kill any NPC that is out running + Update("NPC"); // If dragged and ropped into a prim with any script named "NPC...", this will replace it. + GetSwitches(); // Get all default saved params from the Description + llSetTimerEvent(TIMER); + } + + + touch_start(integer n) + { // if touched, make a menu + + if (checkPerms()) { + if (RecordPath == STATE) { + makeMenu(lAtButtons); + } else { + makeMainMenu(); + } + } else { + makeUserMenu(); + } + } + + // menu listener + listen(integer iChannel, string name, key id, string message) { + + if (MENU) { + llListenRemove(iHandle); + MENU = 0; // menu is off + iHandle = 0; + } + + if (message == "Stop NPC") + { + lNPCScript = []; // force reload of notecard + NPCEnabled = FALSE; + if (NPCKey() != NULL_KEY){ + Kill(sNPCName); + sNPCName = ""; + } else { + bNPC_STOP = TRUE; + makeText("Enter name of an NPC to stop"); + } + } + else if (message == "Menu" ) { + makeMainMenu(); + } + else if (message == "Erase RAM"){ + Clr(); + } + else if (message == "Relative"){ + relAbs = "Absolute"; + KeyValueSet("co","A"); // remember coordinates = A + Clr(); + } + else if (message == "Absolute"){ + relAbs = "Relative"; + KeyValueSet("co","R"); // remember coordinates = R + Clr(); + } + else if (message == "Recording"){ + DoMenuForCommands(); // show them the recording menu + } + else if (message == "Owner Only") { + priPub = "Group"; + KeyValueSet("pr","1"); + + llOwnerSay("Group members have control"); + makeMainMenu(); + } + else if (message == "Group") { + priPub = "Owner Only"; + KeyValueSet("pr","0"); + llOwnerSay("Only you have control"); + makeMainMenu(); + } + else if (message == "Sense is On") { + mSensor ="Sense is Off"; + KeyValueSet("se", "off"); + llOwnerSay(mSensor); + makeMainMenu(); + } + else if (message == "Sense is Off") { + mSensor ="Sense is On"; + llOwnerSay(mSensor); + KeyValueSet("se", "on"); + + NPCEnabled = FALSE; + + integer count = checkNoteCards(); + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + DoProcessNPCLine(); + return; + } + if (Editor) { + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording and/or appearance, so you cannot start a NPC"); + makeMainMenu(); + } + else if (message == "Appearance") { + llRemoveInventory(Appearance); // delete the notecard + osAgentSaveAppearance(kUserKey,Appearance); // make the ntecard + llOwnerSay("Your outfit has been saved"); + makeMainMenu(); + } + else if (message == "Save") { + if (llGetListLength(lCommands) == 0) { + llOwnerSay("Nothing recorded, you need to make a recording first"); + makeMainMenu(); + return; + } + DoSave(); + } + else if (message == "Help"){ + llLoadURL(kUserKey,"Click to view help","http://www.outworldz.com/opensim/posts/NPC/"); + makeMainMenu(); + } + else if (message == "Start NPC") { + integer count = checkNoteCards(); + Stopped = FALSE; // Let's run the notecard + NPCEnabled = TRUE; + + if (Editor) { + DoProcessNPCLine(); + return; + } + + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + Stopped = FALSE; // Let's run the notecard + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording or maybe an appearance, so we cannot start a NPC"); + + } + else if (bNPC_STOP){ + bNPC_STOP = FALSE; + Kill(message); + } + else if (message == ">>"){ + makeMenu(lMenu2); + } + else if (message == ">>>"){ + makeMenu(lMenu3); + } + else if (message == "<<") { + makeMenu(lAtButtons); + } + else if (message == "<<<") { + makeMenu(lMenu2); + } + else if (message == "@comment"){ + Text("# ","Enter a comment",""); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@run"){ + lCommands += "@run=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@fly"){ + lCommands += "@fly=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@land"){ + lCommands += "@land=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@walk") { + lCommands += "@walk=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@sound"){ + Text("@sound=","Enter a sound name or UUID to trigger",""); + } + else if (message == "@randsound"){ + lCommands += "@randsound"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@say") { + Text("@say=","Enter what the NPC will say",""); + } + else if (message == "@whisper"){ + Text("@whisper=","Enter what the NPC will whisper",""); + } + else if (message == "@shout"){ + Text("@shout=","Enter what the NPC will shout",""); + } + else if (message == "@wander") { + Text("@wander=","Enter radius to wander","Enter number of wanders"); + } + else if (message == "@pause") { + Text("@pause=","Enter time to pause",""); + } + else if (message == "@rotate") { + Text("@rotate=","Enter degrees to rotate",""); + } + else if (message == "@sit"){ + Text("@sit=","Enter name of object to sit on",""); + } + else if (message == "@touch"){ + Text("@touch=","Enter name of object to touch",""); + } + else if (message == "@cmd"){ + Text("@cmd=","Enter cjhannel to speak on","Enter text to speak"); + } + else if (message == "@stand"){ + lCommands += "@stand\n"; + llOwnerSay("Stand Recorded"); + makeMenu(lAtButtons); + } + else if (message == "@animate"){ + Text("@animate=","Enter animation name to play","Enter time to play the animation"); + } + else if (message == "@speed"){ + Text("@speed=","Enter a speed for the NPC, 1=100% normal speed, 0.5=50% speed",""); + } + + + // Save NPC name + else if (MakeNotecard == STATE) { + sNPCName = message; // in case we need to kill it. + + vector vDest = (vector) Pos(); + + if (relAbs == "Relative") + { + vDest -= llGetPos(); // just an offset for relative + } + sNotecard = "@spawn=" + message + "|" + (string) vDest + "\n"; + integer i; + integer j = llGetListLength(lCommands); + for (; i < j; i++){ + // get the command to save to the notecard + string line = llList2String(lCommands,i); + if (relAbs == "Absolute") { + sNotecard += line; // add the un-modified string to the notecard + } else { + // since we have to record absolute coords since we do not know where the box goes until they press Save, + // we process the absolute to relative conversion for walks here + list parts = llParseString2List(line,["="],[]); //get the @command + + if (llList2String(parts,0) == "@walk") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@walk=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@fly") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@fly=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@run") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@run=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@land") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@land=" + (string) vec + "\n"; + } + else { + sNotecard += line; // add the un-modified string to the notecard + } + } + } + llRemoveInventory(Notecard); // delete the old notecard + osMakeNotecard(Notecard,sNotecard); // Makes the notecard. + llOwnerSay("Commands notecard has been written"); + STATE = 0; + } // MakeNotecard + + else if (! llStringLength(sParam2)) { + lCommands += sCommand + message + "\n"; + llOwnerSay("Recorded"); + makeMenu(lAtButtons); + } + else if (llStringLength(sParam2)){ + sCommand = sCommand + message + "|"; + llOwnerSay("Recorded"); + makeText(sParam2); + sParam2 = ""; + } + + } + + + + timer(){ + DEBUG("tick"); + + // if llDialog is up, kill the listener for the dialog box. + if (iHandle) { + llOwnerSay("Menu timed out"); + llListenRemove(iHandle); + iHandle = 0; + return; // ^^^^^^^^^^^^^^^^^^^^^^^ + } + // if NoBodyHome, we are sensing for an avatar + else if (NobodyHome == STATE) { + if (! llGetRegionAgentCount()) { + DoNobodyHome(); + return; // ^^^^^^^^^^^^^^^^^^^^^^^ + } + } + // if we are spawning, we need time to rez the NPC, then start processing NPC Commands. + else if (Spawning == STATE) { + STATE = 0; + TimerEvent(TIMER); + } + // We end aniamtions with a timer + else if (Animate == STATE){ + NPCAnimate(STAND); + TimerEvent(TIMER); + } + + else if (Walking == STATE) { + if (--iWaitCounter) { + if (llVecDist(osNpcGetPos(NPCKey()), newDest) > MAXDIST) { + return; + } + } + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 2) { + // nothing + } else if (walkstate == 3) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 4) { + llShout(FLIGHT,"landing"); + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } + } + // Wandering timer + else if (Wander == STATE) { + if (--iWaitCounter) { // wait 60 seconds to get to a destination. + if (llVecDist(osNpcGetPos(NPCKey()), vWanderPos) > MAXDIST) + return; + } + + // see if wander counter == 0, if so, stop walking, go to stand and process next line + if(RAMwc == 0) { + NPCAnimate(STAND); + DEBUG("Wander ended, calling DoProcessNPCLine"); + STATE = 0; + DoProcessNPCLine(); + return; + } + // one less time to wander around + RAMwc--; + NPCAnimate(STAND); + TimerEvent(TIMER); + DoWanderhold(); + return; + } + // Wandering requires us to re-wander when we reach a destination + else if (WanderHold == STATE) { + DoWander(); + TimerEvent(TIMER); + return; + } + else if (DoProcess == STATE) { + TimerEvent(QUICK); + } + + STATE = 0; + + // We always process a NPC line at end of timer. + DEBUG("Tick end, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } + + // sensors are used for sitting on prims + // Neo Cortex: added different SensorFunc states to trigger sit or touch + sensor(integer num) { + if (SensorFunc == 1) { + osNpcSit(NPCKey(), llDetectedKey(0), OS_NPC_SIT_NOW); + DEBUG("Seated, calling DoProcessNPCLine"); + SensorFunc = 0; + } else if (SensorFunc == 2) { + osNpcTouch(NPCKey(), llDetectedKey(0), LINK_THIS); + DEBUG("Touched, calling DoProcessNPCLine"); + SensorFunc = 0; + } + DoProcessNPCLine(); + } + no_sensor(){ + DEBUG ("no target prim located, calling DoProcessNPCLine"); + SensorFunc = 0; + DoProcessNPCLine(); + } + + + link_message(integer sender, integer num, string str, key id){ + DEBUG("Command In:" + str); + if (str=="@go") { + Stopped = FALSE; // Let's run the notecard + DEBUG("@go approved, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } else { + if (Stopped) + { + Stack += [str]; // take anything, the controller will filter away non @ stuff + DoProcessNPCLine(); + } else { + Stack += [str]; // take anything, the controller will filter away non @ stuff + TimerEvent(TIMER); + } + } + } + +} + + + + + + diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.8.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.8.lsl new file mode 100644 index 00000000..7565212c --- /dev/null +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.8.lsl @@ -0,0 +1,1598 @@ +// :SHOW:0 +// :CATEGORY:NPC +// :NAME:All In One NPC Recorder and Player +// :AUTHOR:Ferd Frederix +// :KEYWORDS:NPC, Puppeteer +// :CREATED:2013-09-08 18:27:47 +// :EDITED:2015-09-04 19:34:00 +// :ID:27 +// :NUM:1823 +// :REV:3.8 +// :WORLD:OpenSim +// :DESCRIPTION: +// All in one NPC recorder player. +// Supports both absolute and relative paths and many new commands +// Add animations named "Fly, Walk, Stand and Run" +// Click Prim to use. +// Should be worn as a HUD to record. +// Put it on the ground and click Sensor or Start NPC when done. +// :CODE: + +FOR DEBUG PURPOSES - DO NOT USE - USE LATER VERSIONS ONLY!!! + +// Revision History +// Rev 1.1 10-2-2014 @Sit did not work. Minor tweaks to casting for lslEditor +// Rev 1.2 10-14-2014 @ sit had wrong type. +// Rev 1.3 relative movement fixed for @fly +// Rev 1.4 4-3-2014 allow anyone to use this, non owners and non group members can only start and stop. +// Rev 1.5 5-17-2014 set sensor to auto start on reboot of sim +// Rev 1.6 5-24-2014 move menu so you can get it by touching, removed many of the KeyValues to RAM for efficiency +// Rev 1.7 CHANGED_REGION_START, not CHANGED_REGION_START (Opensim difference) +// Rev 1.8 tuned up Kill NPC, added more flexible upgrader +// Rev 1.9 Better script injection by link message// Rev 2.0 Added osSetSpeed so you can speed up or slow down an NPC. +// Rev 2.1 No laggy sensor used exept to sit on stuff +// Rev 2.2 Various sensor fixes +// Rev 2.3 Sets No Sensor in menu, must be started by hand +// Rev 2.4 - reserved for patches to 2.3 if needed +// Rev 3.0 Refactor out into subs, not states to make command injection easier +// New command: @appearance=Notecardname so you can switch to a new notecard on the fly +// New command: @speed=1.0 which slows up ( < 1 ) or speeds up ( > 1) +// Rev 3.1 Commands are not interruptible by Link Message +// Rev 3.2 Sensor patches for consistency in removing the NPC +// Rev 3.3 Added Touch command by Neo.Cortex@hbase42/hopto/org:8002 +// Added Menu 3 for notecard and appearance commands +// Rev 3.4 animation timer cannot be zero or it shuts off timer tweaked +// solves the NPC starting up when no sensor is set. +// Rev 3.5 fixes saving to !Path notecard +// Rev 3.6 08-11-2015 @delete acts like @stop. The NPC now rezzes after an @go back in where it was deleted +// Rev 3.7 08-11-2015 @attach command added to load an attachment from the inventory to the NPC +// Rev 3.8 08-17-2015 process queued commands one at a time without calling ProcessNPCLine on link message +//*******************************************************************// + +// Instructions on how to use this is at http://www.outworldz.com/opensim/posts/NPC/ +// This is an OpenSim-only script. +// Author: Ferd Frederix aka Fred Beckhusen - fred@mitsi.com + +//////////////////////////////////////////////////////////////////////////////////////////// +// Original code was Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // +/////////////////////////////////////////////////////////////////////////////////////////// +// Please see: http://www.gnu.org/licenses/gpl.html for legal details, // +// rights of fair usage, the disclaimer and warranty conditions. // +/////////////////////////////////////////////////////////////////////////////////////////// +// The original NPC controller was from http://was.fm/opensim:npc +// Extensive additions and bug fixes by Fred Beckhusem, aka Ferd Frederix, fred@mitsi.com +// llSensor had two params swapped +// @Wander would wander where it had rezzed, not where it was. +// There was no 'no_sensor' event in sit, so if a @sit failed, the NPC got stuck +// The animation and walks always stopped old, then started new. It should be start new, then stop old so the default stand would be suppressed. +// New code: +// Merged with new Route recorder and notecard writer +// If the NPC failed to reach a destination it never moved on. Added WAIT global to tune this +// Exposed many tunable variables and ported the code to LSLEditor. +// Added floating point to times in notecard. + +// Added @sound, @randsound, @whisper, @shout, and @cmd controls. +// +// notecards integers are not floats for better control +// +// Link Messages may be used to perform external control by injecting @commands into the stream of actions +// Example: +// To chat something, such as with a chat robot +// llMessageLinked(LINK_SET,0,"@npc_say=Hello",""); + +// This script assumes that NPCs and OSSl scripting is enabled in the OpenSim configuration. +// In order to enable them, the following changes must be made in the OpenSim.ini configuration file: +// +// ; Turn on OSSL +// AllowOSFunctions = true +// OSFunctionThreatLevel = Severe + +//[NPC] +// ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} +// Enabled = true +// +// and then the server has to be restarted. + + +// Commands: All commands begin with an @ sign. All other lines are ignored +// @commands may have optional parameters. The syntax is always: +// @cmd=parm1|parm2 +// NaN in the table below meand Not a Number. This means there is no parameter + +//Command First Parameter Second Parameter Description +//@spawn name location (vector) Rezzes an NPC with name at a location. +//@appearance NoteCardName NaN switch the NPC appearance to a new notecard +//@walk destination (vector) NaN Makes the NPC walk to destination. +//@fly destination (vector) NaN Makes the NPC fly to destination. +//@land destination (vector) NaN Makes the NPC land at destination. +//@say string NaN Makes the NPC speak a phrase. +//@whisper string NaN Makes the NPC whisper a phrase. +//@shout string NaN Makes the NPC shout a phrase. +//@pause seconds (float) NaN Makes the NPC wait for a multiple of seconds. +//@wander radius (float) cycles (integer) Makes the NPC wander in radius, for cycles seconds. +//@delete NaN NaN Removes the NPC. Requires a link message to continue +//@goto label (string) NaN Jump to the label label in the script. +//@animate animation (string) time (float) Makes the NPC trigger the animation animation for time seconds. +//@sound sound_name NaN plays a sound from inventory +//@randsound NaN NaN Plays a random sound from inventory +//@rotate degrees (float) NaN Rotate the NPC degrees around the Z axis. +//@sit primitive name NaN Sit on a primitive with a given name. +//@touch primitive name NaN Touch on a primitive with a given name. +//@stand NaN NaN If sitting on a primitive, stand up. +//@cmd channel (integer) string Says string on channel, for controlling external gadgets +//@stop NaN NaN Halts the NPC script indefinitely. Can be started with a link message +//@go NaN NaN Continues on next notecard line, for use in link messages +//@speed speed (float) NaN from 0 to N, where 1.0 ius a normal speed of an avatar. 0.2 is a turtle. +//@notecard notename (string) NaN load a new Path notecard +//@attach InventoryName attachmentPoint load an attachment from the inventory to the NPC onto point + +// Constant attachmentPoint Comment +// ATTACH_CHEST 1 chest/sternum +// ATTACH_HEAD 2 head +// ATTACH_LSHOULDER 3 left shoulder +// ATTACH_RSHOULDER 4 right shoulder +// ATTACH_LHAND 5 left hand +// ATTACH_RHAND 6 right hand +// ATTACH_LFOOT 7 left foot +// ATTACH_RFOOT 8 right foot +// ATTACH_BACK 9 back +// ATTACH_PELVIS 10 pelvis +// ATTACH_MOUTH 11 mouth +// ATTACH_CHIN 12 chin +// ATTACH_LEAR 13 left ear +// ATTACH_REAR 14 right ear +// ATTACH_LEYE 15 left eye +// ATTACH_REYE 16 right eye +// ATTACH_NOSE 17 nose +// ATTACH_RUARM 18 right upper arm +// ATTACH_RLARM 19 right lower arm +// ATTACH_LUARM 20 left upper arm +// ATTACH_LLARM 21 left lower arm +// ATTACH_RHIP 22 right hip +// ATTACH_RULEG 23 right upper leg +// ATTACH_RLLEG 24 right lower leg +// ATTACH_LHIP 25 left hip +// ATTACH_LULEG 26 left upper leg +// ATTACH_LLLEG 27 left lower leg +// ATTACH_BELLY 28 belly/stomach/tummy +// ATTACH_LEFT_PEC 29 left pectoral +// ATTACH_RIGHT_PEC 30 right pectoral +// ATTACH_HUD_CENTER_2 31 HUD Center 2 +// ATTACH_HUD_TOP_RIGHT 32 HUD Top Right +// ATTACH_HUD_TOP_CENTER33 HUD Top +// ATTACH_HUD_TOP_LEFT 34 HUD Top Left +// ATTACH_HUD_CENTER_1 35 HUD Center +// ATTACH_HUD_BOTTOM_LEFT 36 HUD Bottom Left +// ATTACH_HUD_BOTTOM 37 HUD Bottom +// ATTACH_HUD_BOTTOM_RIGHT 38 HUD Bottom Right +// ATTACH_NECK 39 neck +// ATTACH_AVATAR_CENTER 40 avatar center/root + + + +////////////////////////////////////////////////////////// +// DEBUG // +////////////////////////////////////////////////////////// +integer debug = FALSE; // set to TRUE or FALSE for debug chat on various actions +integer Editor = FALSE; // set to to TRUE to working in LSLEditor, FALSE for in-world. + // you must also include the NPC commands found in the other script since LSLEditor does not support OpenSim +integer iTitleText = FALSE; // set to TRUE to see debug info in text above the controller + +////////////////////////////////////////////////////////// +// TUNABLE CONFIGURATION // +////////////////////////////////////////////////////////// +float TIMER = 2; // how often the system checks the distance traveled. Fastest you can go is 0.5 seconds +float QUICK = 1; // when we need to move to the next state, we use a QUICK timer +string Appearance = "!Appearance"; // The name of the recorded Appearance notecard +string Notecard = "!Path"; // The name of the recorded routes +integer allowUsers = FALSE; // If true, any user can get a Start NPC and Stop NPC menu. Only groups and owners can get all commands if TRUE, or FALSE +float MAXDIST = 2.0; // how close a NPC has to get to a dest pos to continue to next state. Do not lower this too much, as it may miss the target +integer WANDERRAND = TRUE; // set to TRUE and they will pause during wanders a random number of seconds +float WANDERTIME = 3.0; // how long they stand after each @wander,if WANDERRAND is FALSE. If WANDERRAND is TRUE, this is the max time +integer WAIT = 30; // wait for this number of seconds for the NPC to reach a destination (for safety). If it fails to reach a target, it will move on after this time. +float RANGE = 50; // 1 to N meters - anyone this close to the controller will start NPCS if Sensor button is clicked +float REZTIME = 2.0; // wait this long for NPC to rez in, then start the process +string STAND = "Stand"; // the name of the default Stand animation +string WALK = "Walk"; // the name of the default Walk animation +string FLY = "Fly"; // the name of the default Fly animation +string RUN = "Run"; // the name of the default Run animation +string LAND = "Land"; // the name of the default land animation ( for birds only) +float OffsetZ = 0.5; // appear 0.5 meter above ground, this is added to all destinations to keep them from sinking in. +float SPEEDMULT =0.5; // 1.0 = regular avatar speed. Smaller numbers slow down walks. Large numbers speed them up. +integer FLIGHT = 299; // For controlling wings. A channel that is shouted at when flight starts and ends. "flying" or "landing" + +// DESCRIPTIONS FIELDS HAVE TO SURVIVE A RESET +// These vars are stored by saving them with KeyValueSet +// "pr" is a 0 if it is set for Owner Only, 1 for Group control +// "se" is "on" if Started +// "co" = "R" or "A" for relative or absolute addressing mode +// "key" = NPC key + +// These Globals used to be stored in description. Moved to RAM in V1.6 +float RAMPause; // @pause param +float RAMwd ; // @wander distance +integer RAMwc; // @wander count +float RAMrot; // @rotate +string RAMsit; // @sit primname +string RAMtouch; // @touch primname +string RAManimationName; // @animate animation (string) time (float) +float RAManimationTime; + +// other globals section +integer iChannel; // a listen channel, randomly assigned +integer iHandle; // the handle to it + +// NPC controls +vector newDest ; // tmp storage for the walks +integer iWaitCounter ; // wait for this number of seconds for the NPC to reach a desrtination +string sNPCName; // the name of the NPC that may be in world. So we can remove it. +integer bNPC_STOP = FALSE; // boolean to reuse a listener +integer Stopped = FALSE; // set to TRUE by link messages so we do not remember them +float fTimerVal ; // how long we wait when wandering (calculated) +float NPCEnabled; // true if the NPC is suppodes to be running + +// OS_NPC_CREATOR_OWNED will create an 'owned' NPC that will only respond to osNpc* commands issued from scripts that have the same owner as the one that created the NPC. +// OS_NPC_NOT_OWNED will create an 'unowned' NPC that will respond to any script that has OSSL permissions to call osNpc* commands. +integer NPCOptions = OS_NPC_CREATOR_OWNED; // only yhe owner of this box can control this NPC. + +integer walkstate = 0; // helps us reshare the walk state for run, fly and land - a bit of a hack, but it saves RAM. Has to be done this way because some bits of NPCWalkOption are asserted as 0 + +integer NPCWalkOption; // Some notes for what happens to NPCWalkOption: +// OS_NPC_FLY - Fly the avatar to the given position. The avatar will not land unless the OS_NPC_LAND_AT_TARGET option is also given. +// OS_NPC_NO_FLY - Do not fly to the target. The NPC will attempt to walk to the location. If it's up in the air then the avatar will keep bouncing hopeless until another move target is given or the move is stopped +//OS_NPC_LAND_AT_TARGET - If given and the avatar is flying, then it will land when it reaches the target. If OS_NPC_NO_FLY is given then this option has no effect. +// OS_NPC_RUNNING - if given, NPC avatar moves at running/fast flying speed, otherwise moves at walking/slow flying speed. + +// menus +string mSensor="Sense is Off"; // Sensor or "No Sensor" + +list lAtButtons = ["Menu","-", ">>", "@run", "@walk", "@fly", "@land", "@wander", "@sit", "@stand","@animate","@rotate"]; +list lMenu2 = ["<<", "@comment", ">>>", "@stop", "@say", "@whisper","@shout","@sound","@randsound","@cmd", "@pause", "@delete"]; +list lMenu3 = ["<<<","@notecard","@appearance", "@touch", "@speed", "@attach", "-","-", "-", "-", "-", "-" ]; + +string sCommand; // place to store a command for two-prompted ones +string sParam2; // place to store a prompt for two-prompted ones +string priPub = "Owner Only"; // Private or Group +key kUserKey; // the person who is controlling the avatar, not the Owner +// the command lists +list lCommands; // commands are stored here +list lNPCScript; // Storage for the NPC script. +string npcAction; // Storage for the next action. @cmd=0|hello, this becomes @cmd +string npcParams; // Storage for the param, @cmd=0|hello, this becomes 0|hello + +// misc vars +string sNotecard; // commands are stored here temporarily for dumping +vector vWanderPos; // a place to wander to +string lastANIM ; // last animation run +// Sensor +integer avatarPresent; // Sensor sets this flag when people are within Range. + +// Coordinate control +vector vInitialPos ; // Vector that will be filled by the script with the initial starting position in region coordinates. +vector vDestPos = ZERO_VECTOR; // Storage for destination position. +string relAbs = "Relative"; // absolute vs relative positioning +vector lastKnownPos; // last known NPC position when we deleted it + +// STATES +integer MENU ; // processing a dialog box state, may be concurrent with STATE +integer STATE; // state storage +integer MakeNotecard = 1; // displaying a text box for NPC name +integer RecordPath = 2; // displaying a path notecard menu +integer NobodyHome = 3; // looking for an avatar +integer Spawning = 4; // spawning an avatar +integer Animate = 5; // animation timer needed +integer Walking = 6; // Hey! I am walking here! +integer Wander = 7; // Wandering around neeeds a timer, too +integer WanderHold = 8; // We reached a wander point +integer DoProcess = 9; // Set this to make it process a new command + +key gNpcKey = NULL_KEY; // global key storage for the one NPC, to save CPU cycles +list Stack ; // a command stack from link message input + +integer SensorFunc = 0; // define which function shall be triggered inside the sensor function + // 0 means none, 1 sit, 2 touch +/////////////////////////////////////////////////////////////////////////// +// FUNCTIONS // +/////////////////////////////////////////////////////////////////////////// + +// Do* functions are much like states from the old V2 scripts. + +// Save a Path notecard +DoSave() +{ + STATE = MakeNotecard; + makeText("Stand where you want the NPC to appear, and enter the NPC Name"); +} + +// This function is used to record the path for the NPC +// Each command can take 0, 1, or 2 params +DoMenuForCommands() { + makeMenu(lAtButtons); +} + + +// No one is here when sensors were on, so we kill off the NPC +DoNobodyHome() +{ + DEBUG("Nobody Home"); + STATE = NobodyHome; + if (NPCKey() != NULL_KEY) { + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + } + TimerEvent(5); // keep ticking to sense avatars +} + +// Create a NPC +DoSpawn() { + DEBUG("state spawn"); + NPCEnabled = TRUE; // in world + // see if there is already one out there. + if (NPCKey() != NULL_KEY) { + DEBUG("Already living"); + return; + } + + STATE = Spawning; + + list name = llParseString2List(sNPCName, [" "], []); + + if (relAbs == "Relative"){ + vInitialPos += llGetPos(); + } + + DEBUG("Rezzing the NPC:" + (string) vInitialPos); + key aKey = osNpcCreate(llList2String(name, 0), llList2String(name, 1), vInitialPos, Appearance, NPCOptions); + + SaveKey(aKey ); // save in desceription and global, too + + osSetSpeed(aKey,SPEEDMULT); // 1.9 speed multiplier + TimerEvent(REZTIME); + NPCAnimate(STAND); +} + +DoRotate() { + DEBUG("@rotate=" + (string) RAMrot); + osNpcSetRot(NPCKey(), llEuler2Rot(<0,0,RAMrot> * DEG_TO_RAD)); +} + +DoSit() { + DEBUG ("state sit - looking for " + RAMsit); + SensorFunc = 1; //triggers osNpcSit + llSensor(RAMsit, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +DoTouch() { + DEBUG ("state touch - looking for " + RAMtouch); + SensorFunc = 2; //triggers osNpcTouch + llSensor(RAMtouch, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +DoStand() { + DEBUG("state stand"); + osNpcStand(NPCKey()); +} + + +DoAnimate() { + + DEBUG("state animate"); + STATE = Animate; + NPCAnimate(RAManimationName); + if (RAManimationTime <=0 ) // V 3.4 tweak + RAManimationTime = 1; + TimerEvent(RAManimationTime); +} + +DoWalk() { + + DEBUG("NPCWalkOption = " + (string) NPCWalkOption); + STATE = Walking; + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(WALK); + } else if (walkstate == 2) { + llShout(FLIGHT,"flying"); + NPCAnimate(FLY); + } else if (walkstate == 3) { + NPCAnimate(RUN); + } else if (walkstate == 4) { + NPCAnimate(LAND); + } + newDest = vDestPos ; + newDest.z += OffsetZ; + + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + newDest += llGetPos(); + } + + DEBUG("Moveto:" + (string) newDest); + osNpcMoveToTarget(NPCKey(), newDest, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + + +DoWander(){ + DEBUG("state wander"); + STATE = Wander; + + vector point = CirclePoint(RAMwd); + DEBUG("CirclePoint:" + (string) point); + vWanderPos = vDestPos + point; + DEBUG("vWanderPos:" + (string) vWanderPos); + + fTimerVal = WANDERTIME; // default time to pause after each wander + if (WANDERRAND) + fTimerVal = llFrand(WANDERTIME) + 1; // override, they want random times + + NPCAnimate(WALK); + + DEBUG("Wander to:" + (string) vWanderPos); + + osNpcMoveToTarget(NPCKey(), vWanderPos, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + +DoWanderhold() { + + DEBUG("Wander Hold"); + STATE = WanderHold; + + // now that we have reached a wander spot, slow the timer down to the desired value + TimerEvent(fTimerVal); +} + +// @pause=10 will do nothing for 10 seconds +DoPause() { + if (RAMPause < 0.1) + RAMPause = 0.1; + DEBUG("@pause=" + (string)RAMPause); + TimerEvent(RAMPause); +} + + +// @stop makes the NPC stop moving in whatever state it is in. You have to linkmessage to get moving again +DoStop() { + DEBUG("NPC is Stopped"); + Stopped = TRUE; // Link controlled - we mnust have a @go to continue with notecards + TimerEvent(0); + Stack = []; // v3.8 +} + +// @delete removes the NPC forever. Next command starts it up again at the beginning +DoDelete() { + DEBUG("state delete"); + + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + Stopped = TRUE; // Link controlled - we mnust have a @go to continue with notecards + TimerEvent(0); + Stack = []; // v3.8 +} + +// change the appearance of the NPC +DoAppearance(string notecard) { + DEBUG("state appearance"); + if (llGetInventoryType(notecard) == INVENTORY_NOTECARD){ + DEBUG("Load appearance " + notecard); + osNpcLoadAppearance(NPCKey(),notecard); + } +} + +// Change the avatar speed +DoSpeed(string speed) { + float newspeed = (float) speed; + if (newspeed > 0.1 && newspeed < 5.0) // sanity check + osSetSpeed(NPCKey(),newspeed); +} +DoNewNote (string card) { + DEBUG("Load Notecard " + card); + NPCReadNoteCard(card); + Stopped = FALSE; +} +DoAttach(string params) { + + list Data = llParseString2List(params, ["|"], []); + string itemName = llList2String(Data, 0); + integer attachmentPoint = (integer) llList2String(Data, 1); + if (attachmentPoint > 0 + && attachmentPoint < 40 + && llGetInventoryType(itemName) == INVENTORY_OBJECT + ) + { + osForceAttachToOtherAvatarFromInventory(NPCKey(),itemName,attachmentPoint); + } +} + +// This loops over the notecard, processing each command +DoProcessNPCLine() { + DEBUG("ProcessNPCLine"); + STATE = 0; + + // auto load a notecard + if (! llGetListLength(lNPCScript)) { + DEBUG("Read Notecard"); + NPCReadNoteCard(Notecard); + Stopped = FALSE; + } + + // look for link messages on the stack + string next = llList2String(Stack,0); // lets see if there is anithing from a link message + if (llStringLength(next)) + { + Stack = llDeleteSubList(Stack,0,0); + ProcessCmd(next); //lets do this command instead. + return; + } + + // @stop issued? + if (Stopped) { + TimerEvent(0); + DEBUG("Waiting for input"); + return; + } + + // No, we have an @go for liftoff + next = llList2String(lNPCScript, 0); // get the next command + DEBUG("Execute:" + next); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); // delete it + + if (llGetListLength(lNPCScript) == 0) { + DEBUG("EOF"); + } + ProcessCmd(next); + +} + + + +ProcessCmd(string cmd) { + + DEBUG("ProcessCmd:" + cmd); + + if (llGetSubString(cmd, 0, 0) != "@") { + DEBUG("ignoring"); + STATE = DoProcess; + TimerEvent(QUICK); // this is so we do not recurse the stack + return; + } + + list data = llParseString2List(cmd, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data, 0), STRING_TRIM)); + + DEBUG("Action:" + npcAction); + npcParams = llStringTrim(llList2String(data, 1), STRING_TRIM); + + @commands; + + ProcessSensor(); + + + if(npcAction == "@spawn") { + DEBUG("@spawn"); + list spawnData = llParseString2List(npcParams, ["|"], []); + sNPCName =llList2String(spawnData, 0); // V 1.6 name in RAM + + list spawnDest = llParseString2List(llList2String(spawnData, 1), ["<", ",", ">"], []); + vInitialPos.x = llList2Float(spawnDest, 0); + vInitialPos.y = llList2Float(spawnDest, 1); + vInitialPos.z = llList2Float(spawnDest, 2); + + DEBUG("Coords for NPC at " + (string) vInitialPos); + DoSpawn(); + return; + } + + if (! avatarPresent){ + DoNobodyHome(); + DEBUG("No avatar nearby"); + return; + } else { + if ( NPCKey() == NULL_KEY) { + DoSpawn(); + } + } + + if(npcAction == "@stop") { + DoStop(); + return; + } + else if(npcAction == "@goto") { + DEBUG("goto"); + integer lastIdx = llGetListLength(lNPCScript)-1; + lNPCScript = llDeleteSubList(lNPCScript, lastIdx, lastIdx); + // Wind commands till goto label. + @wind; + string next1 = llList2String(lNPCScript, 0); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); + lNPCScript += next1; + if(next1 != npcParams) jump wind; + // Wind the label too. + next1 = llList2String(lNPCScript, 0); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); + lNPCScript += next1; + // Get next command. + list data1 = llParseString2List(next1, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data1, 0), STRING_TRIM)); + npcParams = llStringTrim(llList2String(data1, 1), STRING_TRIM); + // Reschedule. + jump commands; + } + else if(npcAction == "@sound") { + DEBUG("sound"); + llTriggerSound(npcParams,1.0); + } + else if(npcAction == "@randsound") { + DEBUG("@randsound"); + integer N = llGetInventoryNumber(INVENTORY_SOUND); + integer rand = llCeil(llFrand(N)) -1; // pick a random sound + string toPlay = llGetInventoryName(INVENTORY_SOUND,rand); + llTriggerSound(toPlay,1.0); + } + else if(npcAction == "@walk") { + DEBUG("@walk"); + GetDest(npcParams); + walkstate = 1;// walking + NPCWalkOption = OS_NPC_NO_FLY ; + DoWalk(); + return; + } + else if(npcAction == "@fly") { + GetDest(npcParams); + walkstate = 2;// flying + NPCWalkOption = OS_NPC_FLY ; + DoWalk(); + return; + } + else if(npcAction == "@run") { + DEBUG("@run"); + GetDest(npcParams); + walkstate = 3;// running + NPCWalkOption = OS_NPC_NO_FLY | OS_NPC_RUNNING; + DoWalk(); + return; + } + else if(npcAction == "@land") { + DEBUG("@land"); + GetDest(npcParams); + walkstate = 4;// landing + NPCWalkOption= OS_NPC_FLY | OS_NPC_LAND_AT_TARGET ; + DoWalk(); + return; + } + else if(npcAction == "@say") { + DEBUG("@say " + npcParams); + osNpcSay(NPCKey(), 0, npcParams); + } + else if(npcAction == "@shout") { + DEBUG("@shout"); + osNpcShout(NPCKey(),0, npcParams); + } + else if(npcAction == "@whisper") { + DEBUG("@whisper " + npcParams); + osNpcWhisper(NPCKey(),0, npcParams); + } + // speak a command on a channel, so you can open doors and control stuff. + else if(npcAction == "@cmd") { + DEBUG("@cmd"); + list dataToSpeak = llParseString2List(npcParams, ["|"], []); + string channel = llList2String(dataToSpeak,0); + DEBUG("Channel:"+(string) channel); + integer iChannel = (integer) channel; + string stringToSpeak = llList2String(dataToSpeak,1); + llSay(iChannel, stringToSpeak); + } + // stop everything + else if(npcAction == "@pause") { + RAMPause = (float) npcParams; + DoPause(); + return; + } + else if(npcAction == "@wander") { + list wanderData = llParseString2List(npcParams, ["|"], []); + RAMwd = (float) llList2String(wanderData, 0); + RAMwc = (integer) llList2String(wanderData, 1); + vDestPos = osNpcGetPos(NPCKey()); // set the wander start + DEBUG("Starting at " + (string) vDestPos); + DoWander(); + return; + } + else if(npcAction == "@rotate") { + RAMrot = (float) npcParams; + DoRotate(); + } + else if(npcAction == "@sit") { + RAMsit= npcParams; + DoSit(); + return; + } + else if(npcAction == "@touch") { + RAMtouch= npcParams; + DoTouch(); + return; + } + else if(npcAction == "@stand") { + DoStand(); + } + else if(npcAction == "@delete") { + DoDelete(); + return; + } + else if(npcAction == "@animate") { + list animateData = llParseString2List(npcParams, ["|"], []); + RAManimationName = llList2String(animateData, 0); + RAManimationTime = (float) llList2String(animateData, 1); + DoAnimate(); + return; + } + else if(npcAction == "@appearance" ){ + DoAppearance(npcParams); + } + else if (npcAction =="@speed") { + DoSpeed(npcParams); + } + else if (npcAction =="@notecard") { + DoNewNote(npcParams); + Notecard = npcParams; + } + else if (npcAction == "@attach") + { + DoAttach(npcParams); + } + + STATE = DoProcess; + TimerEvent(QUICK); // yeah I know, not possible this fast, we just go as fast as we can go - this is so we do not recurse the stack +} + + + +/////////////////// UTILITY Functions, not state-like ////////////////// + +// DEBUG(string) will chat a string or display it as hovertext if debug == TRUE +DEBUG(string str) { + if (debug) + llOwnerSay( str); // Send the owner debug info so you can chase NPCS + if (iTitleText) { + llSetText(str,<1.0,1.0,1.0>,1.0); // show hovertext + + } +} + +GetDest(string npcParams) { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); +} + +NPCReadNoteCard(string Note) { + DEBUG("NPCReadNoteCard"); + lNPCScript = llParseString2List(osGetNotecard(Note), ["\n"], []); +} + +integer SenseAvatar() +{ + //Returns a strided list of the UUID, position, and name of each avatar in the region + list avatars = llGetAgentList(AGENT_LIST_REGION ,[]); + integer numOfAvatars = llGetListLength(avatars); + if (numOfAvatars == 0) + { + DEBUG("No people"); + return 0; + } + //DEBUG("Located " + (string)numOfAvatars + " avatars and NPC's"); + + integer nAvatars; + integer i; + for( i = 0;i < numOfAvatars; i++) { + key aviKey = llList2Key(avatars,i); + if (!osIsNpc(aviKey)) { + list detail = llGetObjectDetails(aviKey,[OBJECT_POS]); + vector pos = llList2Vector(detail,0); + float dist = llVecDist(pos, llGetPos()); + if (dist < RANGE) + { + nAvatars++; + DEBUG("In range:" + llKey2Name(aviKey)); + } + } + } + //DEBUG("Located " + (string) nAvatars + " avatars"); + return nAvatars; +} + +// return TRUE if the avatar is owner when private is set, or TRUE if the avatar is in the same group and GROUP is set. +integer checkPerms() { + + integer group = (integer) KeyValueGet("pr"); + if (! group) + priPub = "Owner Only"; + else + priPub = "Group"; + + + if (llDetectedKey(0) == llGetOwner()){ + kUserKey = llDetectedKey(0); + return TRUE; + } + + if ( group && llDetectedGroup(0)) { + kUserKey = llDetectedKey(0); + return TRUE; + } + kUserKey = llDetectedKey(0); + return FALSE; +} + + + +NPCAnimate(string anim) +{ + DEBUG("Start Anim: " + anim); + if (llGetInventoryType(anim) == INVENTORY_ANIMATION ) { + + if (lastANIM != anim) { + if(llStringLength(lastANIM)) { + osNpcStopAnimation(NPCKey(), lastANIM); + } + osNpcPlayAnimation(NPCKey(), anim); + lastANIM = anim; + } + } else { + llSay(DEBUG_CHANNEL, "No animation named " + anim); + } +} + + +TimerEvent(float timesent) +{ + DEBUG("Setting timer: " + (string) timesent); + llSetTimerEvent(timesent); +} + +// Kill a NPC by Name +Kill(string param) +{ + integer count; + list avatars = osGetAvatarList(); // Returns a strided list of the UUID, position, and name of each avatar in the region except the owner.\ + integer i; + integer j = llGetListLength(avatars); + for (i=0 ; i <= j; i+=3){ + + string desired = llList2String(avatars,i+2); + desired = llStringTrim(desired,STRING_TRIM); // should not be needed but is needed + + if (desired == param){ + vector v = llList2Vector(avatars,i+1); + key target = llList2Key(avatars,i); // get the UUID of the avatar + osNpcRemove(target); + SaveKey(NULL_KEY ); + llOwnerSay("Removed " + param+ " at location " + (string) v); + count++; + } + } + + NPCEnabled = FALSE; // not in world + + if (count) + llOwnerSay("Removed " + (string) count + " NPC's"); + else + llOwnerSay("Could not locate " + param); +} + + +// return a String for the position we are at. Strings used as the caller wants strings +string Pos() +{ + vector where = llGetPos(); // find the box position + + where.z += OffsetZ; // use the ground position + an offset + + if (Editor) + where = <128,128,31 + llFrand(1)>; // center of sim for editing + + // if attached the height will be too high by 1/2 the agent size + if (llGetAttached()) { + vector size = llGetAgentSize(llGetOwner()); + float Z = size.z; + where.z -= Z/2; + } + + // DEBUG("Pos= " + (string) where); + return (string) where; +} + +// setup a menu with a timer for timeouts, called by all make*() +menu() +{ + llListenRemove(iHandle); + iChannel = llCeil(llFrand(100000) + 20000); + iHandle = llListen(iChannel,"","",""); + TimerEvent(30.0); + MENU = TRUE; +} + +// make a text box +makeText(string Param) +{ + menu(); + llTextBox(kUserKey, Param, iChannel); +} + +// top level menu +makeMainMenu() +{ + menu(); + list buttons = ["Appearance","Recording","Save","Help","-","Erase RAM", priPub,relAbs,"-","Stop NPC",mSensor,"Start NPC"]; + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Records",buttons,iChannel); +} + + +// Rev 1.4 +// top level menu for non group/ non owners +makeUserMenu() +{ + if (!allowUsers) return; + + menu(); + list buttons = ["Start NPC","Stop NPC"]; + llDialog(kUserKey,"Choose",buttons,iChannel); +} + + + +// programmable menu for @commands +makeMenu(list buttons) +{ + menu(); + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Record",buttons,iChannel); +} + + +// make one or two text boxes with prompts +Text(string cmd, string p1, string p2) +{ + sCommand = cmd; + sParam2 = ""; + if (llStringLength(p2)) + sParam2 = p2; + + makeText(p1); +} + +// Set the Avatar Present flag - if sensors are off and we are forece run, there will be one present. +ProcessSensor() +{ + integer SensorOn; + if ("on" == KeyValueGet("se")) + { + SensorOn = TRUE; // we need to scan for avatars + } else { + SensorOn = FALSE; // we need to scan for avatars + } + DEBUG("Sensor:" + (string) SensorOn); + + integer n = SenseAvatar(); + + DEBUG("Avatars:" + (string) n); + if (SensorOn && n) + avatarPresent = TRUE; // someone is here and we need to tell the system to run + else if (SensorOn && !n) + avatarPresent = FALSE; // someone is not here and we need to tell the system to stop + else { // sensor is off, lete see if there is a NPC. If so, we are ON + DEBUG("NPCEnabled:" + (string) NPCEnabled); + if (NPCEnabled) + avatarPresent = TRUE; + else + avatarPresent = FALSE; + } + + // start up from when when no one is near + if (avatarPresent && STATE == NobodyHome) + STATE = 0; + + //DEBUG("Avatar Present: " + (string) avatarPresent); +} + +vector CirclePoint(float radius) { + float x = llFrand(radius *2) - radius; // +/- radius, randomized + float y = llFrand(radius *2) - radius; // +/- radius, randomized + return ; // so this should always happen +} + +string KeyValueGet(string var) { + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k != var) jump continue; + //DEBUG("got " + var + " = " + llList2String(data, 1)); + return llList2String(data, 1); + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + return ""; +} + +KeyValueSet(string var, string val) { + + //DEBUG("set " + var + " = " + val); + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + if(llGetListLength(dVars) == 0) + { + llSetObjectDesc(var + "=" + val); + return; + } + list result = []; + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k == "") jump continue; + if(k == var && val == "") jump continue; + if(k == var) { + result += k + "=" + val; + val = ""; + jump continue; + } + string v = llList2String(data, 1); + if(v == "") jump continue; + result += k + "=" + v; + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + if(val != "") result += var + "=" + val; + llSetObjectDesc(llDumpList2String(result, "&")); +} + + +// clear RAM +Clr() { + + lCommands = []; + llOwnerSay("RAM Memory cleared. Notecards, if any, are not modified."); + makeMainMenu(); +} + +integer checkNoteCards() +{ + // Check that they have saved an Appeaance and Path notecard + integer num = llGetInventoryNumber(INVENTORY_NOTECARD); // how many notecards overall + + integer i; + integer count; + for (; i < num; i++){ + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Notecard) + count++; + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Appearance) + count++; + } + DEBUG("Checked " + (string) count + " Notecards"); + // if we have both, run the NPC + return count; +} + +Update(string SName) { + + // delete all NPC*scripts except myself + integer i; + integer j = llGetInventoryNumber(INVENTORY_SCRIPT); + for (i = 0; i < j; i++) { + string name = llGetInventoryName(INVENTORY_SCRIPT,i); + string match = llGetSubString(name,0,2); + if (match == SName && llGetScriptName() != name) + { + llRemoveInventory(name); + llOwnerSay("Upgraded"); + } + } + +} + +// Get all default saved params from the Description +GetSwitches() +{ + string rA = KeyValueGet("co"); // Get the remembered menu setting for Abs Vs Relative + if (rA == "A") + relAbs = "Absolute"; + else if (rA == "R") + relAbs = "Relative"; + else + relAbs = "Absolute"; + + + // reenable NPC if sensor is on. + if ("on" == KeyValueGet("se")) + { + NPCEnabled = TRUE; + mSensor = "Sense is On"; + ProcessSensor(); // fake 1 avatar to get it rezzed + } else { + mSensor = "Sense is Off"; + } + } + + +SaveKey(key akey) +{ + DEBUG("Saving Key of " + (string) akey); + KeyValueSet("key", akey); + if (akey != (key) KeyValueGet("key") ) + { + DEBUG("Fatal error, cannot save key"); + } + gNpcKey = akey; +} + + +key NPCKey() +{ + key akey = gNpcKey; // from cached copy + // gNpcKey saves a lot of CPU processing by caching the key, if blank we get it from the description + if (gNpcKey == NULL_KEY) + { + //DEBUG("Get DKey"); + akey = KeyValueGet("key"); // from Description of the prim + } + // DEBUG("NPC KEY:" + (string) akey); + return akey; +} + + +/////////////////// CODE BEGINS ////////////////// + + +default +{ + changed(integer change) { + if(change & CHANGED_REGION_START) { + llResetScript(); + } + } + + on_rez(integer start_param) + { + llResetScript(); + } + + state_entry() { + + llSetText("",<1,1,1>,1.0); // clr all hovertext- we may not be using it. + DoDelete(); // kill any NPC that is out running + Update("NPC"); // If dragged and ropped into a prim with any script named "NPC...", this will replace it. + GetSwitches(); // Get all default saved params from the Description + llSetTimerEvent(TIMER); + } + + + touch_start(integer n) + { // if touched, make a menu + + if (checkPerms()) { + if (RecordPath == STATE) { + makeMenu(lAtButtons); + } else { + makeMainMenu(); + } + } else { + makeUserMenu(); + } + } + + // menu listener + listen(integer iChannel, string name, key id, string message) { + + if (MENU) { + llListenRemove(iHandle); + MENU = 0; // menu is off + iHandle = 0; + } + + if (message == "Stop NPC") + { + lNPCScript = []; // force reload of notecard + NPCEnabled = FALSE; + if (NPCKey() != NULL_KEY){ + Kill(sNPCName); + sNPCName = ""; + } else { + bNPC_STOP = TRUE; + makeText("Enter name of an NPC to stop"); + } + } + else if (message == "Menu" ) { + makeMainMenu(); + } + else if (message == "Erase RAM"){ + Clr(); + } + else if (message == "Relative"){ + relAbs = "Absolute"; + KeyValueSet("co","A"); // remember coordinates = A + Clr(); + } + else if (message == "Absolute"){ + relAbs = "Relative"; + KeyValueSet("co","R"); // remember coordinates = R + Clr(); + } + else if (message == "Recording"){ + DoMenuForCommands(); // show them the recording menu + } + else if (message == "Owner Only") { + priPub = "Group"; + KeyValueSet("pr","1"); + + llOwnerSay("Group members have control"); + makeMainMenu(); + } + else if (message == "Group") { + priPub = "Owner Only"; + KeyValueSet("pr","0"); + llOwnerSay("Only you have control"); + makeMainMenu(); + } + else if (message == "Sense is On") { + mSensor ="Sense is Off"; + KeyValueSet("se", "off"); + llOwnerSay(mSensor); + makeMainMenu(); + } + else if (message == "Sense is Off") { + mSensor ="Sense is On"; + llOwnerSay(mSensor); + KeyValueSet("se", "on"); + + NPCEnabled = FALSE; + + integer count = checkNoteCards(); + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + DoProcessNPCLine(); + return; + } + if (Editor) { + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording and/or appearance, so you cannot start a NPC"); + makeMainMenu(); + } + else if (message == "Appearance") { + llRemoveInventory(Appearance); // delete the notecard + osAgentSaveAppearance(kUserKey,Appearance); // make the ntecard + llOwnerSay("Your outfit has been saved"); + makeMainMenu(); + } + else if (message == "Save") { + if (llGetListLength(lCommands) == 0) { + llOwnerSay("Nothing recorded, you need to make a recording first"); + makeMainMenu(); + return; + } + DoSave(); + } + else if (message == "Help"){ + llLoadURL(kUserKey,"Click to view help","http://www.outworldz.com/opensim/posts/NPC/"); + makeMainMenu(); + } + else if (message == "Start NPC") { + integer count = checkNoteCards(); + Stopped = FALSE; // Let's run the notecard + NPCEnabled = TRUE; + + if (Editor) { + DoProcessNPCLine(); + return; + } + + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + Stopped = FALSE; // Let's run the notecard + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording or maybe an appearance, so we cannot start a NPC"); + + } + else if (bNPC_STOP){ + bNPC_STOP = FALSE; + Kill(message); + } + else if (message == ">>"){ + makeMenu(lMenu2); + } + else if (message == ">>>"){ + makeMenu(lMenu3); + } + else if (message == "<<") { + makeMenu(lAtButtons); + } + else if (message == "<<<") { + makeMenu(lMenu2); + } + else if (message == "@comment"){ + Text("# ","Enter a comment",""); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@run"){ + lCommands += "@run=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@fly"){ + lCommands += "@fly=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@land"){ + lCommands += "@land=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@walk") { + lCommands += "@walk=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@sound"){ + Text("@sound=","Enter a sound name or UUID to trigger",""); + } + else if (message == "@randsound"){ + lCommands += "@randsound"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@say") { + Text("@say=","Enter what the NPC will say",""); + } + else if (message == "@whisper"){ + Text("@whisper=","Enter what the NPC will whisper",""); + } + else if (message == "@shout"){ + Text("@shout=","Enter what the NPC will shout",""); + } + else if (message == "@wander") { + Text("@wander=","Enter radius to wander","Enter number of wanders"); + } + else if (message == "@pause") { + Text("@pause=","Enter time to pause",""); + } + else if (message == "@rotate") { + Text("@rotate=","Enter degrees to rotate",""); + } + else if (message == "@sit"){ + Text("@sit=","Enter name of object to sit on",""); + } + else if (message == "@touch"){ + Text("@touch=","Enter name of object to touch",""); + } + else if (message == "@cmd"){ + Text("@cmd=","Enter cjhannel to speak on","Enter text to speak"); + } + else if (message == "@stand"){ + lCommands += "@stand\n"; + llOwnerSay("Stand Recorded"); + makeMenu(lAtButtons); + } + else if (message == "@animate"){ + Text("@animate=","Enter animation name to play","Enter time to play the animation"); + } + else if (message == "@attach"){ + Text("@animate=","Enter inventory name to attach","Enter number of the attachment point (1-40)"); + } + else if (message == "@speed"){ + Text("@speed=","Enter a speed for the NPC, 1=100% normal speed, 0.5=50% speed",""); + } + + + // Save NPC name + else if (MakeNotecard == STATE) { + sNPCName = message; // in case we need to kill it. + + vector vDest = (vector) Pos(); + + if (relAbs == "Relative") + { + vDest -= llGetPos(); // just an offset for relative + } + sNotecard = "@spawn=" + message + "|" + (string) vDest + "\n"; + integer i; + integer j = llGetListLength(lCommands); + for (; i < j; i++){ + // get the command to save to the notecard + string line = llList2String(lCommands,i); + if (relAbs == "Absolute") { + sNotecard += line; // add the un-modified string to the notecard + } else { + // since we have to record absolute coords since we do not know where the box goes until they press Save, + // we process the absolute to relative conversion for walks here + list parts = llParseString2List(line,["="],[]); //get the @command + + if (llList2String(parts,0) == "@walk") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@walk=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@fly") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@fly=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@run") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@run=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@land") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@land=" + (string) vec + "\n"; + } + else { + sNotecard += line; // add the un-modified string to the notecard + } + } + } + llRemoveInventory(Notecard); // delete the old notecard + osMakeNotecard(Notecard,sNotecard); // Makes the notecard. + llSay(0,sNotecard); + llOwnerSay("Commands notecard has been written"); + STATE = 0; + } // MakeNotecard + + else if (! llStringLength(sParam2)) { + lCommands += sCommand + message + "\n"; + llOwnerSay("Recorded"); + makeMenu(lAtButtons); + } + else if (llStringLength(sParam2)){ + sCommand = sCommand + message + "|"; + llOwnerSay("Recorded"); + makeText(sParam2); + sParam2 = ""; + } + + } + + + + timer(){ + // DEBUG("tick"); + + // if llDialog is up, kill the listener for the dialog box. + if (iHandle) { + llOwnerSay("Menu timed out"); + llListenRemove(iHandle); + iHandle = 0; + return; // ^^^^^^^^^^^^^^^^^^^^^^^ + } + // if NoBodyHome, we are sensing for an avatar + else if (NobodyHome == STATE) { + ProcessSensor(); + return; + } + // if we are spawning, we need time to rez the NPC, then start processing NPC Commands. + else if (Spawning == STATE) { + STATE = 0; + TimerEvent(TIMER); + } + // We end aniamtions with a timer + else if (Animate == STATE){ + NPCAnimate(STAND); + TimerEvent(TIMER); + } + + else if (Walking == STATE) { + if (--iWaitCounter) { + if (llVecDist(osNpcGetPos(NPCKey()), newDest) > MAXDIST) { + return; + } + } + + DEBUG("At Destination: " + (string) newDest); + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 2) { + // nothing + } else if (walkstate == 3) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 4) { + llShout(FLIGHT,"landing"); + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } + } + // Wandering timer + else if (Wander == STATE) { + if (--iWaitCounter) { // wait 60 seconds to get to a destination. + if (llVecDist(osNpcGetPos(NPCKey()), vWanderPos) > MAXDIST) + return; + } + + // see if wander counter == 0, if so, stop walking, go to stand and process next line + if(RAMwc == 0) { + NPCAnimate(STAND); + DEBUG("Wander ended, calling DoProcessNPCLine"); + STATE = 0; + DoProcessNPCLine(); + return; + } + // one less time to wander around + RAMwc--; + NPCAnimate(STAND); + TimerEvent(TIMER); + DoWanderhold(); + return; + } + // Wandering requires us to re-wander when we reach a destination + else if (WanderHold == STATE) { + DoWander(); + TimerEvent(TIMER); + return; + } + else if (DoProcess == STATE) { + TimerEvent(QUICK); + } + + if (Stopped) + return; + + STATE = 0; + + // We always process a NPC line at end of timer. + DEBUG("Tick end, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } + + // sensors are used for sitting on prims + // Neo Cortex: added different SensorFunc states to trigger sit or touch + sensor(integer num) { + if (SensorFunc == 1) { + osNpcSit(NPCKey(), llDetectedKey(0), OS_NPC_SIT_NOW); + DEBUG("Seated, calling DoProcessNPCLine"); + SensorFunc = 0; + } else if (SensorFunc == 2) { + osNpcTouch(NPCKey(), llDetectedKey(0), LINK_THIS); + DEBUG("Touched, calling DoProcessNPCLine"); + SensorFunc = 0; + } + DoProcessNPCLine(); + } + no_sensor(){ + DEBUG ("no target prim located, calling DoProcessNPCLine"); + SensorFunc = 0; + DoProcessNPCLine(); + } + + + link_message(integer sender, integer num, string str, key id){ + DEBUG("Command In:" + str); + if (str=="@go") { + Stopped = FALSE; // Let's run the notecard + DEBUG("@go approved, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } else { + Stack += [str]; // take anything, the controller will filter away non @ stuff + TimerEvent(QUICK); + } + } + +} + + + + + + diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.9.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.9.lsl new file mode 100644 index 00000000..54f6ec44 --- /dev/null +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 3.9.lsl @@ -0,0 +1,1625 @@ +// :SHOW:0 +// :CATEGORY:NPC +// :NAME:All In One NPC Recorder and Player +// :AUTHOR:Ferd Frederix +// :KEYWORDS:NPC, Puppeteer +// :CREATED:2015-08-28 23:27:03 +// :EDITED:2015-09-04 19:34:01 +// :ID:27 +// :NUM:1824 +// :REV:3.9.1 +// :WORLD:OpenSim +// :DESCRIPTION: +// All in one NPC recorder player. +// Supports both absolute and relative paths and many new commands +// Add animations named "Fly, Walk, Stand and Run" +// Click Prim to use. +// Should be worn as a HUD to record. +// Put it on the ground and click Sensor or Start NPC when done. +// :CODE: + +FOR DEBUG PURPOSES - SENSORS DO NOT WORK --- DO NOT USE SENSOR MODE ALL OTHER FUNCTIONS WORK + +// This is Rev 3.9 08/27/2015 + +// Revision History +// Rev 1.1 10-2-2014 @Sit did not work. Minor tweaks to casting for lslEditor +// Rev 1.2 10-14-2014 @ sit had wrong type. +// Rev 1.3 relative movement fixed for @fly +// Rev 1.4 4-3-2014 allow anyone to use this, non owners and non group members can only start and stop. +// Rev 1.5 5-17-2014 set sensor to auto start on reboot of sim +// Rev 1.6 5-24-2014 move menu so you can get it by touching, removed many of the KeyValues to RAM for efficiency +// Rev 1.7 CHANGED_REGION_START, not CHANGED_REGION_START (Opensim difference) +// Rev 1.8 tuned up Kill NPC, added more flexible upgrader +// Rev 1.9 Better script injection by link message// Rev 2.0 Added osSetSpeed so you can speed up or slow down an NPC. +// Rev 2.1 No laggy sensor used exept to sit on stuff +// Rev 2.2 Various sensor fixes +// Rev 2.3 Sets No Sensor in menu, must be started by hand +// Rev 2.4 - reserved for patches to 2.3 if needed +// Rev 3.0 Refactor out into subs, not states to make command injection easier +// New command: @appearance=Notecardname so you can switch to a new notecard on the fly +// New command: @speed=1.0 which slows up ( < 1 ) or speeds up ( > 1) +// Rev 3.1 Commands are not interruptible by Link Message +// Rev 3.2 Sensor patches for consistency in removing the NPC +// Rev 3.3 Added Touch command by Neo.Cortex@hbase42/hopto/org:8002 +// Added Menu 3 for notecard and appearance commands +// Rev 3.4 animation timer cannot be zero or it shuts off timer tweaked +// solves the NPC starting up when no sensor is set. +// Rev 3.5 fixes saving to !Path notecard +// Rev 3.6 08-11-2015 @delete acts like @stop. TYjhe NPC now rezzes after an @go back in where it was deleted +// Rev 3.7 08-11-2015 @attach command added to load an attachment from the inventory to the NPC +// Rev 3.8 08-17-2015 process queued commands one at a time without calling ProcessNPCLine on link message +// Rev 3.9 08-23-2011 Queued command fixes including @delete which were not always working +//*******************************************************************// + +// Instructions on how to use this is at http://www.outworldz.com/opensim/posts/NPC/ +// This is an OpenSim-only script. +// Author: Ferd Frederix aka Fred Beckhusen - fred@mitsi.com + +//////////////////////////////////////////////////////////////////////////////////////////// +// Original code was Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // +/////////////////////////////////////////////////////////////////////////////////////////// +// Please see: http://www.gnu.org/licenses/gpl.html for legal details, // +// rights of fair usage, the disclaimer and warranty conditions. // +/////////////////////////////////////////////////////////////////////////////////////////// +// The original NPC controller was from http://was.fm/opensim:npc +// Extensive additions and bug fixes by Fred Beckhusem, aka Ferd Frederix, fred@mitsi.com +// llSensor had two params swapped +// @Wander would wander where it had rezzed, not where it was. +// There was no 'no_sensor' event in sit, so if a @sit failed, the NPC got stuck +// The animation and walks always stopped old, then started new. It should be start new, then stop old so the default stand would be suppressed. +// New code: +// Merged with new Route recorder and notecard writer +// If the NPC failed to reach a destination it never moved on. Added WAIT global to tune this +// Exposed many tunable variables and ported the code to LSLEditor. +// Added floating point to times in notecard. + +// Added @sound, @randsound, @whisper, @shout, and @cmd controls. +// +// notecards integers are not floats for better control +// +// Link Messages may be used to perform external control by injecting @commands into the stream of actions +// Example: +// To chat something, such as with a chat robot +// llMessageLinked(LINK_SET,0,"@npc_say=Hello",""); + +// This script assumes that NPCs and OSSl scripting is enabled in the OpenSim configuration. +// In order to enable them, the following changes must be made in the OpenSim.ini configuration file: +// +// ; Turn on OSSL +// AllowOSFunctions = true +// OSFunctionThreatLevel = Severe + +//[NPC] +// ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} +// Enabled = true +// +// and then the server has to be restarted. + + +// Commands: All commands begin with an @ sign. All other lines are ignored +// @commands may have optional parameters. The syntax is always: +// @cmd=parm1|parm2 +// NaN in the table below meand Not a Number. This means there is no parameter + +//Command First Parameter Second Parameter Description +//@spawn name location (vector) Rezzes an NPC with name at a location. +//@appearance NoteCardName NaN switch the NPC appearance to a new notecard +//@walk destination (vector) NaN Makes the NPC walk to destination. +//@fly destination (vector) NaN Makes the NPC fly to destination. +//@land destination (vector) NaN Makes the NPC land at destination. +//@say string NaN Makes the NPC speak a phrase. +//@whisper string NaN Makes the NPC whisper a phrase. +//@shout string NaN Makes the NPC shout a phrase. +//@pause seconds (float) NaN Makes the NPC wait for a multiple of seconds. +//@wander radius (float) cycles (integer) Makes the NPC wander in radius, for cycles seconds. +//@delete NaN NaN Removes the NPC. Requires a link message to continue +//@goto label (string) NaN Jump to the label label in the script. +//@animate animation (string) time (float) Makes the NPC trigger the animation animation for time seconds. +//@sound sound_name NaN plays a sound from inventory +//@randsound NaN NaN Plays a random sound from inventory +//@rotate degrees (float) NaN Rotate the NPC degrees around the Z axis. +//@sit primitive name NaN Sit on a primitive with a given name. +//@touch primitive name NaN Touch on a primitive with a given name. +//@stand NaN NaN If sitting on a primitive, stand up. +//@cmd channel (integer) string Says string on channel, for controlling external gadgets +//@stop NaN NaN Halts the NPC script indefinitely. Can be started with a link message +//@go NaN NaN Continues on next notecard line, for use in link messages +//@speed speed (float) NaN from 0 to N, where 1.0 ius a normal speed of an avatar. 0.2 is a turtle. +//@notecard notename (string) NaN load a new Path notecard +//@attach InventoryName attachmentPoint load an attachment from the inventory to the NPC onto point + +// Constant attachmentPoint Comment +// ATTACH_CHEST 1 chest/sternum +// ATTACH_HEAD 2 head +// ATTACH_LSHOULDER 3 left shoulder +// ATTACH_RSHOULDER 4 right shoulder +// ATTACH_LHAND 5 left hand +// ATTACH_RHAND 6 right hand +// ATTACH_LFOOT 7 left foot +// ATTACH_RFOOT 8 right foot +// ATTACH_BACK 9 back +// ATTACH_PELVIS 10 pelvis +// ATTACH_MOUTH 11 mouth +// ATTACH_CHIN 12 chin +// ATTACH_LEAR 13 left ear +// ATTACH_REAR 14 right ear +// ATTACH_LEYE 15 left eye +// ATTACH_REYE 16 right eye +// ATTACH_NOSE 17 nose +// ATTACH_RUARM 18 right upper arm +// ATTACH_RLARM 19 right lower arm +// ATTACH_LUARM 20 left upper arm +// ATTACH_LLARM 21 left lower arm +// ATTACH_RHIP 22 right hip +// ATTACH_RULEG 23 right upper leg +// ATTACH_RLLEG 24 right lower leg +// ATTACH_LHIP 25 left hip +// ATTACH_LULEG 26 left upper leg +// ATTACH_LLLEG 27 left lower leg +// ATTACH_BELLY 28 belly/stomach/tummy +// ATTACH_LEFT_PEC 29 left pectoral +// ATTACH_RIGHT_PEC 30 right pectoral +// ATTACH_HUD_CENTER_2 31 HUD Center 2 +// ATTACH_HUD_TOP_RIGHT 32 HUD Top Right +// ATTACH_HUD_TOP_CENTER33 HUD Top +// ATTACH_HUD_TOP_LEFT 34 HUD Top Left +// ATTACH_HUD_CENTER_1 35 HUD Center +// ATTACH_HUD_BOTTOM_LEFT 36 HUD Bottom Left +// ATTACH_HUD_BOTTOM 37 HUD Bottom +// ATTACH_HUD_BOTTOM_RIGHT 38 HUD Bottom Right +// ATTACH_NECK 39 neck +// ATTACH_AVATAR_CENTER 40 avatar center/root + + + +////////////////////////////////////////////////////////// +// DEBUG // +////////////////////////////////////////////////////////// +integer debug = TRUE; // set to TRUE or FALSE for debug chat on various actions +integer Editor = FALSE; // set to to TRUE to working in LSLEditor, FALSE for in-world. + // you must also include the NPC commands found in the other script since LSLEditor does not support OpenSim +integer iTitleText = FALSE; // set to TRUE to see debug info in text above the controller + +////////////////////////////////////////////////////////// +// TUNABLE CONFIGURATION // +////////////////////////////////////////////////////////// +float TIMER = 2; // how often the system checks the distance traveled. Fastest you can go is 0.5 seconds +float QUICK = 1; // when we need to move to the next state, we use a QUICK timer +string Appearance = "!Appearance"; // The name of the recorded Appearance notecard +string Notecard = "!Path"; // The name of the recorded routes +integer allowUsers = FALSE; // If true, any user can get a Start NPC and Stop NPC menu. Only groups and owners can get all commands if TRUE, or FALSE +float MAXDIST = 2.0; // how close a NPC has to get to a dest pos to continue to next state. Do not lower this too much, as it may miss the target +integer WANDERRAND = TRUE; // set to TRUE and they will pause during wanders a random number of seconds +float WANDERTIME = 3.0; // how long they stand after each @wander,if WANDERRAND is FALSE. If WANDERRAND is TRUE, this is the max time +integer WAIT = 30; // wait for this number of seconds for the NPC to reach a destination (for safety). If it fails to reach a target, it will move on after this time. +float RANGE = 50; // 1 to N meters - anyone this close to the controller will start NPCS if Sensor button is clicked +float REZTIME = 2.0; // wait this long for NPC to rez in, then start the process +string STAND = "Stand"; // the name of the default Stand animation +string WALK = "Walk"; // the name of the default Walk animation +string FLY = "Fly"; // the name of the default Fly animation +string RUN = "Run"; // the name of the default Run animation +string LAND = "Land"; // the name of the default land animation ( for birds only) +float OffsetZ = 0.5; // appear 0.5 meter above ground, this is added to all destinations to keep them from sinking in. +float SPEEDMULT =0.5; // 1.0 = regular avatar speed. Smaller numbers slow down walks. Large numbers speed them up. +integer FLIGHT = 299; // For controlling wings. A channel that is shouted at when flight starts and ends. "flying" or "landing" + +// DESCRIPTIONS FIELDS HAVE TO SURVIVE A RESET +// These vars are stored by saving them with KeyValueSet +// "pr" is a 0 if it is set for Owner Only, 1 for Group control +// "se" is "on" if Started +// "co" = "R" or "A" for relative or absolute addressing mode +// "key" = NPC key + +// These Globals used to be stored in description. Moved to RAM in V1.6 +float RAMPause; // @pause param +float RAMwd ; // @wander distance +integer RAMwc; // @wander count +float RAMrot; // @rotate +string RAMsit; // @sit primname +string RAMtouch; // @touch primname +string RAManimationName; // @animate animation (string) time (float) +float RAManimationTime; + +// other globals section +integer iChannel; // a listen channel, randomly assigned +integer iHandle; // the handle to it + +// NPC controls +vector newDest ; // tmp storage for the walks +integer iWaitCounter ; // wait for this number of seconds for the NPC to reach a desrtination +string sNPCName; // the name of the NPC that may be in world. So we can remove it. +integer bNPC_STOP = FALSE; // boolean to reuse a listener +integer Stopped = FALSE; // set to TRUE by link messages so we do not remember them +float fTimerVal ; // how long we wait when wandering (calculated) +float NPCEnabled; // true if the NPC is suppodes to be running + +// OS_NPC_CREATOR_OWNED will create an 'owned' NPC that will only respond to osNpc* commands issued from scripts that have the same owner as the one that created the NPC. +// OS_NPC_NOT_OWNED will create an 'unowned' NPC that will respond to any script that has OSSL permissions to call osNpc* commands. +integer NPCOptions = OS_NPC_CREATOR_OWNED; // only yhe owner of this box can control this NPC. + +integer walkstate = 0; // helps us reshare the walk state for run, fly and land - a bit of a hack, but it saves RAM. Has to be done this way because some bits of NPCWalkOption are asserted as 0 + +integer NPCWalkOption; // Some notes for what happens to NPCWalkOption: +// OS_NPC_FLY - Fly the avatar to the given position. The avatar will not land unless the OS_NPC_LAND_AT_TARGET option is also given. +// OS_NPC_NO_FLY - Do not fly to the target. The NPC will attempt to walk to the location. If it's up in the air then the avatar will keep bouncing hopeless until another move target is given or the move is stopped +//OS_NPC_LAND_AT_TARGET - If given and the avatar is flying, then it will land when it reaches the target. If OS_NPC_NO_FLY is given then this option has no effect. +// OS_NPC_RUNNING - if given, NPC avatar moves at running/fast flying speed, otherwise moves at walking/slow flying speed. + +// menus +string mSensor="Sense is Off"; // Sensor or "No Sensor" + +list lAtButtons = ["Menu","-", ">>", "@run", "@walk", "@fly", "@land", "@wander", "@sit", "@stand","@animate","@rotate"]; +list lMenu2 = ["<<", "@comment", ">>>", "@stop", "@say", "@whisper","@shout","@sound","@randsound","@cmd", "@pause", "@delete"]; +list lMenu3 = ["<<<","@notecard","@appearance", "@touch", "@speed", "@attach", "-","-", "-", "-", "-", "-" ]; + +string sCommand; // place to store a command for two-prompted ones +string sParam2; // place to store a prompt for two-prompted ones +string priPub = "Owner Only"; // Private or Group +key kUserKey; // the person who is controlling the avatar, not the Owner +// the command lists +list lCommands; // commands are stored here +list lNPCScript; // Storage for the NPC script. +string npcAction; // Storage for the next action. @cmd=0|hello, this becomes @cmd +string npcParams; // Storage for the param, @cmd=0|hello, this becomes 0|hello + +// misc vars +string sNotecard; // commands are stored here temporarily for dumping +vector vWanderPos; // a place to wander to +string lastANIM ; // last animation run +// Sensor +integer avatarPresent; // Sensor sets this flag when people are within Range. + +// Coordinate control +vector vInitialPos ; // Vector that will be filled by the script with the initial starting position in region coordinates. +vector vDestPos = ZERO_VECTOR; // Storage for destination position. +string relAbs = "Relative"; // absolute vs relative positioning +vector lastKnownPos; // last known NPC position when we deleted it + +// STATES +integer MENU ; // processing a dialog box state, may be concurrent with STATE +integer STATE; // state storage +integer MakeNotecard = 1; // displaying a text box for NPC name +integer RecordPath = 2; // displaying a path notecard menu +integer NobodyHome = 3; // looking for an avatar +integer Spawning = 4; // spawning an avatar +integer Animate = 5; // animation timer needed +integer Walking = 6; // Hey! I am walking here! +integer Wander = 7; // Wandering around neeeds a timer, too +integer WanderHold = 8; // We reached a wander point +integer DoProcess = 9; // Set this to make it process a new command +integer Touch = 10; // Timer is busy sensing something to touch +integer Sit = 11; // Timer is busy sensing something to sit on +integer Paused = 12; // Timer is busy pausing + +key gNpcKey = NULL_KEY; // global key storage for the one NPC, to save CPU cycles +list Stack ; // a command stack from link message input + +integer SensorFunc = 0; // define which function shall be triggered inside the sensor function + // 0 means none, 1 sit, 2 touch +/////////////////////////////////////////////////////////////////////////// +// FUNCTIONS // +/////////////////////////////////////////////////////////////////////////// + + +SetStop(integer what) +{ + DEBUG("Stopped set to " + (string ) what); + Stopped = what; +} +// Do* functions are much like states from the old V2 scripts. + +// Save a Path notecard +DoSave() +{ + STATE = MakeNotecard; + makeText("Stand where you want the NPC to appear, and enter the NPC Name"); +} + +// This function is used to record the path for the NPC +// Each command can take 0, 1, or 2 params +DoMenuForCommands() { + makeMenu(lAtButtons); +} + + +// No one is here when sensors were on, so we kill off the NPC +DoNobodyHome() +{ + DEBUG("Nobody Home"); + STATE = NobodyHome; + if (NPCKey() != NULL_KEY) { + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + } + TimerEvent(5); // keep ticking to sense avatars +} + +// Create a NPC +StateSpawn() { + DEBUG("state spawn"); + STATE = Spawning; + + + NPCEnabled = TRUE; // in world + // see if there is already one out there. + if (NPCKey() != NULL_KEY) { + DEBUG("Already living"); + return; + } + + + list name = llParseString2List(sNPCName, [" "], []); + + vector vRezPos = vInitialPos; + if (relAbs == "Relative"){ + vRezPos += llGetPos(); + } + + DEBUG("Rezzing the NPC:" + (string) vRezPos); + key aKey = osNpcCreate(llList2String(name, 0), llList2String(name, 1), vRezPos, Appearance, NPCOptions); + + SaveKey(aKey); // save in desceription and global, too + + osSetSpeed(aKey,SPEEDMULT); // 1.9 speed multiplier + TimerEvent(REZTIME); + NPCAnimate(STAND); +} + +DoRotate() { + DEBUG("@rotate=" + (string) RAMrot); + osNpcSetRot(NPCKey(), llEuler2Rot(<0,0,RAMrot> * DEG_TO_RAD)); +} + +StateSit() { + DEBUG ("state sit - looking for " + RAMsit); + STATE=Sit; + SensorFunc = 1; //triggers osNpcSit + llSensor(RAMsit, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +StateTouch() { + DEBUG ("state touch - looking for " + RAMtouch); + STATE = Touch; + SensorFunc = 2; //triggers osNpcTouch + llSensor(RAMtouch, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +DoStand() { + DEBUG("state stand"); + osNpcStand(NPCKey()); +} + + +StateAnimate() { + + DEBUG("state animate"); + STATE = Animate; + NPCAnimate(RAManimationName); + if (RAManimationTime <=0 ) // V 3.4 tweak + RAManimationTime = 1; + TimerEvent(RAManimationTime); +} + +StateWalk() { + + DEBUG("NPCWalkOption = " + (string) NPCWalkOption); + STATE = Walking; + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(WALK); + } else if (walkstate == 2) { + llShout(FLIGHT,"flying"); + NPCAnimate(FLY); + } else if (walkstate == 3) { + NPCAnimate(RUN); + } else if (walkstate == 4) { + NPCAnimate(LAND); + } + newDest = vDestPos ; + newDest.z += OffsetZ; + + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + newDest += llGetPos(); + } + + DEBUG("Moveto:" + (string) newDest); + osNpcMoveToTarget(NPCKey(), newDest, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + + +StateWander(){ + DEBUG("state wander"); + STATE = Wander; + + vector point = CirclePoint(RAMwd); + DEBUG("CirclePoint:" + (string) point); + vWanderPos = vDestPos + point; + DEBUG("vWanderPos:" + (string) vWanderPos); + + fTimerVal = WANDERTIME; // default time to pause after each wander + if (WANDERRAND) + fTimerVal = llFrand(WANDERTIME) + 1; // override, they want random times + + NPCAnimate(WALK); + + DEBUG("Wander to:" + (string) vWanderPos); + + osNpcMoveToTarget(NPCKey(), vWanderPos, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + +StateWanderhold() { + + DEBUG("Wander Hold"); + STATE = WanderHold; + + // now that we have reached a wander spot, slow the timer down to the desired value + TimerEvent(fTimerVal); +} + +// @pause=10 will do nothing for 10 seconds +DoPause() { + STATE =Paused; + if (RAMPause < 0.1) + RAMPause = 0.1; + DEBUG("@pause=" + (string)RAMPause); + TimerEvent(RAMPause); +} + + +// @stop makes the NPC stop moving in whatever state it is in. You have to linkmessage to get moving again +DoStop() { + DEBUG("NPC is Stopped"); + STATE = 0; // accept commands + SetStop(TRUE); // Link controlled - we mnust have a @go to continue with notecards + TimerEvent(0); + Stack = []; // v3.8 +} + +// @delete removes the NPC forever. Next command starts it up again at the beginning +DoDelete() { + DEBUG("state delete"); + STATE = 0; // accept commands + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + + TimerEvent(0); + Stack = []; // v3.8 +} + +// change the appearance of the NPC +DoAppearance(string notecard) { + DEBUG("state appearance"); + if (llGetInventoryType(notecard) == INVENTORY_NOTECARD){ + DEBUG("Load appearance " + notecard); + osNpcLoadAppearance(NPCKey(),notecard); + } +} + +// Change the avatar speed +DoSpeed(string speed) { + float newspeed = (float) speed; + if (newspeed > 0.1 && newspeed < 5.0) {// sanity check + osSetSpeed(NPCKey(),newspeed); + } +} +DoNewNote (string card) { + DEBUG("Load Notecard " + card); + NPCReadNoteCard(card); + SetStop(FALSE); +} +DoAttach(string params) { + + list Data = llParseString2List(params, ["|"], []); + string itemName = llList2String(Data, 0); + integer attachmentPoint = (integer) llList2String(Data, 1); + if (attachmentPoint > 0 + && attachmentPoint < 40 + && llGetInventoryType(itemName) == INVENTORY_OBJECT + ) + { + osForceAttachToOtherAvatarFromInventory(NPCKey(),itemName,attachmentPoint); + } +} + +// This loops over the notecard, processing each command +DoProcessNPCLine() { + DEBUG("ProcessNPCLine, stopped = " + (string) Stopped); + STATE = DoProcess; + + // auto load a notecard + if (! llGetListLength(lNPCScript)) { + DEBUG("Read Notecard"); + NPCReadNoteCard(Notecard); + } + + // look for link messages on the stack + string next = llList2String(Stack,0); // lets see if there is anithing from a link message + if (llStringLength(next)) + { + Stack = llDeleteSubList(Stack,0,0); + ProcessCmd(next); //lets do this command instead. + return; + } + + // @stop issued? + if (Stopped) { + TimerEvent(0); + DEBUG("Stopped, waiting for input"); + STATE = 0; + return; + } + + // No, we have an @go for liftoff + next = llList2String(lNPCScript, 0); // get the next command + DEBUG("Execute:" + next); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); // delete it + + if (llGetListLength(lNPCScript) == 0) { + DEBUG("EOF"); + } + ProcessCmd(next); +} + + + +ProcessCmd(string cmd) { + + DEBUG("ProcessCmd:" + cmd); + + if (llGetSubString(cmd, 0, 0) != "@") { + DEBUG("ignoring"); + STATE = DoProcess; + TimerEvent(QUICK); // this is so we do not recurse the stack + STATE = 0; + return; + } + + list data = llParseString2List(cmd, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data, 0), STRING_TRIM)); + + DEBUG("Action:" + npcAction); + npcParams = llStringTrim(llList2String(data, 1), STRING_TRIM); + + @commands; + + ProcessSensor(); + + + if(npcAction == "@spawn") { + DEBUG("@spawn"); + list spawnData = llParseString2List(npcParams, ["|"], []); + sNPCName =llList2String(spawnData, 0); // V 1.6 name in RAM + + list spawnDest = llParseString2List(llList2String(spawnData, 1), ["<", ",", ">"], []); + vInitialPos.x = llList2Float(spawnDest, 0); + vInitialPos.y = llList2Float(spawnDest, 1); + vInitialPos.z = llList2Float(spawnDest, 2); + + DEBUG("Coords for NPC at " + (string) vInitialPos); + StateSpawn(); + return; + } + + if (! avatarPresent){ + DoNobodyHome(); + DEBUG("No avatar nearby"); + STATE = 0; + return; + } else { + if ( NPCKey() == NULL_KEY) { + StateSpawn(); + } + } + + if(npcAction == "@stop") { + DoStop(); + STATE = 0; + return; + } + else if(npcAction == "@goto") { + DEBUG("goto"); + integer lastIdx = llGetListLength(lNPCScript)-1; + lNPCScript = llDeleteSubList(lNPCScript, lastIdx, lastIdx); + // Wind commands till goto label. + @wind; + string next1 = llList2String(lNPCScript, 0); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); + lNPCScript += next1; + if(next1 != npcParams) jump wind; + // Wind the label too. + next1 = llList2String(lNPCScript, 0); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); + lNPCScript += next1; + // Get next command. + list data1 = llParseString2List(next1, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data1, 0), STRING_TRIM)); + npcParams = llStringTrim(llList2String(data1, 1), STRING_TRIM); + // Reschedule. + jump commands; + } + else if(npcAction == "@sound") { + DEBUG("sound"); + llTriggerSound(npcParams,1.0); + } + else if(npcAction == "@randsound") { + DEBUG("@randsound"); + integer N = llGetInventoryNumber(INVENTORY_SOUND); + integer rand = llCeil(llFrand(N)) -1; // pick a random sound + string toPlay = llGetInventoryName(INVENTORY_SOUND,rand); + llTriggerSound(toPlay,1.0); + } + else if(npcAction == "@walk") { + DEBUG("@walk"); + GetDest(npcParams); + walkstate = 1;// walking + NPCWalkOption = OS_NPC_NO_FLY ; + StateWalk(); + return; + } + else if(npcAction == "@fly") { + GetDest(npcParams); + walkstate = 2;// flying + NPCWalkOption = OS_NPC_FLY ; + StateWalk(); + return; + } + else if(npcAction == "@run") { + DEBUG("@run"); + GetDest(npcParams); + walkstate = 3;// running + NPCWalkOption = OS_NPC_NO_FLY | OS_NPC_RUNNING; + StateWalk(); + return; + } + else if(npcAction == "@land") { + DEBUG("@land"); + GetDest(npcParams); + walkstate = 4;// landing + NPCWalkOption= OS_NPC_FLY | OS_NPC_LAND_AT_TARGET ; + StateWalk(); + return; + } + else if(npcAction == "@say") { + DEBUG("@say " + npcParams); + osNpcSay(NPCKey(), 0, npcParams); + } + else if(npcAction == "@shout") { + DEBUG("@shout"); + osNpcShout(NPCKey(),0, npcParams); + } + else if(npcAction == "@whisper") { + DEBUG("@whisper " + npcParams); + osNpcWhisper(NPCKey(),0, npcParams); + } + // speak a command on a channel, so you can open doors and control stuff. + else if(npcAction == "@cmd") { + DEBUG("@cmd"); + list dataToSpeak = llParseString2List(npcParams, ["|"], []); + string channel = llList2String(dataToSpeak,0); + DEBUG("Channel:"+(string) channel); + integer iChannel = (integer) channel; + string stringToSpeak = llList2String(dataToSpeak,1); + llSay(iChannel, stringToSpeak); + } + // stop everything + else if(npcAction == "@pause") { + RAMPause = (float) npcParams; + DoPause(); + return; + } + else if(npcAction == "@wander") { + list wanderData = llParseString2List(npcParams, ["|"], []); + RAMwd = (float) llList2String(wanderData, 0); + RAMwc = (integer) llList2String(wanderData, 1); + vDestPos = osNpcGetPos(NPCKey()); // set the wander start + DEBUG("Starting at " + (string) vDestPos); + StateWander(); + return; + } + else if(npcAction == "@rotate") { + RAMrot = (float) npcParams; + DoRotate(); + } + else if(npcAction == "@sit") { + RAMsit= npcParams; + StateSit(); + return; + } + else if(npcAction == "@touch") { + RAMtouch= npcParams; + StateTouch(); + return; + } + else if(npcAction == "@stand") { + DoStand(); + } + else if(npcAction == "@delete") { + DoDelete(); + SetStop(TRUE); // Link controlled - we mnust have a @go to continue with notecards + return; + } + else if(npcAction == "@animate") { + list animateData = llParseString2List(npcParams, ["|"], []); + RAManimationName = llList2String(animateData, 0); + RAManimationTime = (float) llList2String(animateData, 1); + StateAnimate(); + return; + } + else if(npcAction == "@appearance" ){ + DoAppearance(npcParams); + } + else if (npcAction =="@speed") { + DoSpeed(npcParams); + } + else if (npcAction =="@notecard") { + DoNewNote(npcParams); + Notecard = npcParams; + } + else if (npcAction == "@attach") + { + DoAttach(npcParams); + } + + STATE = 0; + TimerEvent(QUICK); // yeah I know, not possible this fast, we just go as fast as we can go - this is so we do not recurse the stack +} + + + +/////////////////// UTILITY Functions, not state-like ////////////////// + +// DEBUG(string) will chat a string or display it as hovertext if debug == TRUE +DEBUG(string str) { + if (debug) + llOwnerSay( str); // Send the owner debug info so you can chase NPCS + if (iTitleText) { + llSetText(str,<1.0,1.0,1.0>,1.0); // show hovertext + + } +} + +GetDest(string npcParams) { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); +} + +NPCReadNoteCard(string Note) { + DEBUG("NPCReadNoteCard"); + lNPCScript = llParseString2List(osGetNotecard(Note), ["\n"], []); +} + +integer SenseAvatar() +{ + //Returns a strided list of the UUID, position, and name of each avatar in the region + list avatars = llGetAgentList(AGENT_LIST_REGION ,[]); + integer numOfAvatars = llGetListLength(avatars); + if (numOfAvatars == 0) + { + DEBUG("No people"); + return 0; + } + //DEBUG("Located " + (string)numOfAvatars + " avatars and NPC's"); + + integer nAvatars; + integer i; + for( i = 0;i < numOfAvatars; i++) { + key aviKey = llList2Key(avatars,i); + if (!osIsNpc(aviKey)) { + list detail = llGetObjectDetails(aviKey,[OBJECT_POS]); + vector pos = llList2Vector(detail,0); + float dist = llVecDist(pos, llGetPos()); + if (dist < RANGE) + { + nAvatars++; + DEBUG("In range:" + llKey2Name(aviKey)); + } + } + } + //DEBUG("Located " + (string) nAvatars + " avatars"); + return nAvatars; +} + +// return TRUE if the avatar is owner when private is set, or TRUE if the avatar is in the same group and GROUP is set. +integer checkPerms() { + + integer group = (integer) KeyValueGet("pr"); + if (! group) + priPub = "Owner Only"; + else + priPub = "Group"; + + + if (llDetectedKey(0) == llGetOwner()){ + kUserKey = llDetectedKey(0); + return TRUE; + } + + if ( group && llDetectedGroup(0)) { + kUserKey = llDetectedKey(0); + return TRUE; + } + kUserKey = llDetectedKey(0); + return FALSE; +} + + + +NPCAnimate(string anim) +{ + DEBUG("Start Anim: " + anim); + if (llGetInventoryType(anim) == INVENTORY_ANIMATION ) { + + if (lastANIM != anim) { + if(llStringLength(lastANIM)) { + osNpcStopAnimation(NPCKey(), lastANIM); + } + osNpcPlayAnimation(NPCKey(), anim); + lastANIM = anim; + } + } else { + llSay(DEBUG_CHANNEL, "No animation named " + anim); + } +} + + +TimerEvent(float timesent) +{ + DEBUG("Setting timer: " + (string) timesent); + llSetTimerEvent(timesent); +} + +// Kill a NPC by Name +Kill(string param) +{ + integer count; + list avatars = osGetAvatarList(); // Returns a strided list of the UUID, position, and name of each avatar in the region except the owner.\ + integer i; + integer j = llGetListLength(avatars); + for (i=0 ; i <= j; i+=3){ + + string desired = llList2String(avatars,i+2); + desired = llStringTrim(desired,STRING_TRIM); // should not be needed but is needed + + if (desired == param){ + vector v = llList2Vector(avatars,i+1); + key target = llList2Key(avatars,i); // get the UUID of the avatar + osNpcRemove(target); + SaveKey(NULL_KEY ); + llOwnerSay("Removed " + param+ " at location " + (string) v); + count++; + } + } + + NPCEnabled = FALSE; // not in world + + if (count) + llOwnerSay("Removed " + (string) count + " NPC's"); + else + llOwnerSay("Could not locate " + param); +} + + +// return a String for the position we are at. Strings used as the caller wants strings +string Pos() +{ + vector where = llGetPos(); // find the box position + + where.z += OffsetZ; // use the ground position + an offset + + if (Editor) + where = <128,128,31 + llFrand(1)>; // center of sim for editing + + // if attached the height will be too high by 1/2 the agent size + if (llGetAttached()) { + vector size = llGetAgentSize(llGetOwner()); + float Z = size.z; + where.z -= Z/2; + } + + // DEBUG("Pos= " + (string) where); + return (string) where; +} + +// setup a menu with a timer for timeouts, called by all make*() +menu() +{ + llListenRemove(iHandle); + iChannel = llCeil(llFrand(100000) + 20000); + iHandle = llListen(iChannel,"","",""); + TimerEvent(30.0); + MENU = TRUE; +} + +// make a text box +makeText(string Param) +{ + menu(); + llTextBox(kUserKey, Param, iChannel); +} + +// top level menu +makeMainMenu() +{ + menu(); + list buttons = ["Appearance","Recording","Save","Help","-","Erase RAM", priPub,relAbs,"-","Stop NPC",mSensor,"Start NPC"]; + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Records",buttons,iChannel); +} + + +// Rev 1.4 +// top level menu for non group/ non owners +makeUserMenu() +{ + if (!allowUsers) return; + + menu(); + list buttons = ["Start NPC","Stop NPC"]; + llDialog(kUserKey,"Choose",buttons,iChannel); +} + + + +// programmable menu for @commands +makeMenu(list buttons) +{ + menu(); + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Record",buttons,iChannel); +} + + +// make one or two text boxes with prompts +Text(string cmd, string p1, string p2) +{ + sCommand = cmd; + sParam2 = ""; + if (llStringLength(p2)) + sParam2 = p2; + + makeText(p1); +} + +// Set the Avatar Present flag - if sensors are off and we are forece run, there will be one present. +ProcessSensor() +{ + integer SensorOn; + if ("on" == KeyValueGet("se")) + { + SensorOn = TRUE; // we need to scan for avatars + } else { + SensorOn = FALSE; // we need to scan for avatars + } + DEBUG("Sensor:" + (string) SensorOn); + + integer n = SenseAvatar(); + + DEBUG("Avatars:" + (string) n); + if (SensorOn && n) + avatarPresent = TRUE; // someone is here and we need to tell the system to run + else if (SensorOn && !n) + avatarPresent = FALSE; // someone is not here and we need to tell the system to stop + else { // sensor is off, lete see if there is a NPC. If so, we are ON + DEBUG("NPCEnabled:" + (string) NPCEnabled); + if (NPCEnabled) + avatarPresent = TRUE; + else + avatarPresent = FALSE; + } + + // start up from when when no one is near + if (avatarPresent && STATE == NobodyHome) + STATE = 0; + + //DEBUG("Avatar Present: " + (string) avatarPresent); +} + +vector CirclePoint(float radius) { + float x = llFrand(radius *2) - radius; // +/- radius, randomized + float y = llFrand(radius *2) - radius; // +/- radius, randomized + return ; // so this should always happen +} + +string KeyValueGet(string var) { + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k != var) jump continue; + //DEBUG("got " + var + " = " + llList2String(data, 1)); + return llList2String(data, 1); + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + return ""; +} + +KeyValueSet(string var, string val) { + + //DEBUG("set " + var + " = " + val); + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + if(llGetListLength(dVars) == 0) + { + llSetObjectDesc(var + "=" + val); + return; + } + list result = []; + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k == "") jump continue; + if(k == var && val == "") jump continue; + if(k == var) { + result += k + "=" + val; + val = ""; + jump continue; + } + string v = llList2String(data, 1); + if(v == "") jump continue; + result += k + "=" + v; + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + if(val != "") result += var + "=" + val; + llSetObjectDesc(llDumpList2String(result, "&")); +} + + +// clear RAM +Clr() { + + lCommands = []; + llOwnerSay("RAM Memory cleared. Notecards, if any, are not modified."); + makeMainMenu(); +} + +integer checkNoteCards() +{ + // Check that they have saved an Appeaance and Path notecard + integer num = llGetInventoryNumber(INVENTORY_NOTECARD); // how many notecards overall + + integer i; + integer count; + for (; i < num; i++){ + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Notecard) + count++; + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Appearance) + count++; + } + DEBUG("Checked " + (string) count + " Notecards"); + // if we have both, run the NPC + return count; +} + +Update(string SName) { + + // delete all NPC*scripts except myself + integer i; + integer j = llGetInventoryNumber(INVENTORY_SCRIPT); + for (i = 0; i < j; i++) { + string name = llGetInventoryName(INVENTORY_SCRIPT,i); + string match = llGetSubString(name,0,2); + if (match == SName && llGetScriptName() != name) + { + llRemoveInventory(name); + llOwnerSay("Upgraded"); + } + } + +} + +// Get all default saved params from the Description +GetSwitches() +{ + string rA = KeyValueGet("co"); // Get the remembered menu setting for Abs Vs Relative + if (rA == "A") + relAbs = "Absolute"; + else if (rA == "R") + relAbs = "Relative"; + else + relAbs = "Absolute"; + + + // reenable NPC if sensor is on. + if ("on" == KeyValueGet("se")) + { + NPCEnabled = TRUE; + mSensor = "Sense is On"; + ProcessSensor(); // fake 1 avatar to get it rezzed + } else { + mSensor = "Sense is Off"; + } + } + + +SaveKey(key akey) +{ + DEBUG("Saving Key of " + (string) akey); + KeyValueSet("key", akey); + if (akey != (key) KeyValueGet("key") ) + { + DEBUG("Fatal error, cannot save key"); + } + gNpcKey = akey; +} + + +key NPCKey() +{ + key akey = gNpcKey; // from cached copy + // gNpcKey saves a lot of CPU processing by caching the key, if blank we get it from the description + if (gNpcKey == NULL_KEY) + { + //DEBUG("Get DKey"); + akey = KeyValueGet("key"); // from Description of the prim + } + // DEBUG("NPC KEY:" + (string) akey); + return akey; +} + + +/////////////////// CODE BEGINS ////////////////// + + +default +{ + changed(integer change) { + if(change & CHANGED_REGION_START) { + llResetScript(); + } + } + + on_rez(integer start_param) + { + llResetScript(); + } + + state_entry() { + + llSetText("",<1,1,1>,1.0); // clr all hovertext- we may not be using it. + DoDelete(); // kill any NPC that is out running + Update("NPC"); // If dragged and ropped into a prim with any script named "NPC...", this will replace it. + GetSwitches(); // Get all default saved params from the Description + llSetTimerEvent(TIMER); + } + + + touch_start(integer n) + { // if touched, make a menu + + if (checkPerms()) { + if (RecordPath == STATE) { + makeMenu(lAtButtons); + } else { + makeMainMenu(); + } + } else { + makeUserMenu(); + } + } + + // menu listener + listen(integer iChannel, string name, key id, string message) { + + if (MENU) { + llListenRemove(iHandle); + MENU = 0; // menu is off + iHandle = 0; + } + + if (message == "Stop NPC") + { + lNPCScript = []; // force reload of notecard + NPCEnabled = FALSE; + if (NPCKey() != NULL_KEY){ + Kill(sNPCName); + sNPCName = ""; + } else { + bNPC_STOP = TRUE; + makeText("Enter name of an NPC to stop"); + } + } + else if (message == "Menu" ) { + makeMainMenu(); + } + else if (message == "Erase RAM"){ + Clr(); + } + else if (message == "Relative"){ + relAbs = "Absolute"; + KeyValueSet("co","A"); // remember coordinates = A + Clr(); + } + else if (message == "Absolute"){ + relAbs = "Relative"; + KeyValueSet("co","R"); // remember coordinates = R + Clr(); + } + else if (message == "Recording"){ + DoMenuForCommands(); // show them the recording menu + } + else if (message == "Owner Only") { + priPub = "Group"; + KeyValueSet("pr","1"); + + llOwnerSay("Group members have control"); + makeMainMenu(); + } + else if (message == "Group") { + priPub = "Owner Only"; + KeyValueSet("pr","0"); + llOwnerSay("Only you have control"); + makeMainMenu(); + } + else if (message == "Sense is On") { + mSensor ="Sense is Off"; + KeyValueSet("se", "off"); + llOwnerSay(mSensor); + makeMainMenu(); + } + else if (message == "Sense is Off") { + mSensor ="Sense is On"; + llOwnerSay(mSensor); + KeyValueSet("se", "on"); + + NPCEnabled = FALSE; + + integer count = checkNoteCards(); + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + DoProcessNPCLine(); + return; + } + if (Editor) { + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording and/or appearance, so you cannot start a NPC"); + makeMainMenu(); + } + else if (message == "Appearance") { + llRemoveInventory(Appearance); // delete the notecard + osAgentSaveAppearance(kUserKey,Appearance); // make the ntecard + llOwnerSay("Your outfit has been saved"); + makeMainMenu(); + } + else if (message == "Save") { + if (llGetListLength(lCommands) == 0) { + llOwnerSay("Nothing recorded, you need to make a recording first"); + makeMainMenu(); + return; + } + DoSave(); + } + else if (message == "Help"){ + llLoadURL(kUserKey,"Click to view help","http://www.outworldz.com/opensim/posts/NPC/"); + makeMainMenu(); + } + else if (message == "Start NPC") { + integer count = checkNoteCards(); + + NPCEnabled = TRUE; + + if (Editor) { + DoProcessNPCLine(); + return; + } + + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + SetStop(FALSE); // Let's run the notecard + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording or maybe an appearance, so we cannot start a NPC"); + + } + else if (bNPC_STOP){ + bNPC_STOP = FALSE; + Kill(message); + } + else if (message == ">>"){ + makeMenu(lMenu2); + } + else if (message == ">>>"){ + makeMenu(lMenu3); + } + else if (message == "<<") { + makeMenu(lAtButtons); + } + else if (message == "<<<") { + makeMenu(lMenu2); + } + else if (message == "@comment"){ + Text("# ","Enter a comment",""); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@run"){ + lCommands += "@run=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@fly"){ + lCommands += "@fly=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@land"){ + lCommands += "@land=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@walk") { + lCommands += "@walk=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@sound"){ + Text("@sound=","Enter a sound name or UUID to trigger",""); + } + else if (message == "@randsound"){ + lCommands += "@randsound"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@say") { + Text("@say=","Enter what the NPC will say",""); + } + else if (message == "@whisper"){ + Text("@whisper=","Enter what the NPC will whisper",""); + } + else if (message == "@shout"){ + Text("@shout=","Enter what the NPC will shout",""); + } + else if (message == "@wander") { + Text("@wander=","Enter radius to wander","Enter number of wanders"); + } + else if (message == "@pause") { + Text("@pause=","Enter time to pause",""); + } + else if (message == "@rotate") { + Text("@rotate=","Enter degrees to rotate",""); + } + else if (message == "@sit"){ + Text("@sit=","Enter name of object to sit on",""); + } + else if (message == "@touch"){ + Text("@touch=","Enter name of object to touch",""); + } + else if (message == "@cmd"){ + Text("@cmd=","Enter cjhannel to speak on","Enter text to speak"); + } + else if (message == "@stand"){ + lCommands += "@stand\n"; + llOwnerSay("Stand Recorded"); + makeMenu(lAtButtons); + } + else if (message == "@animate"){ + Text("@animate=","Enter animation name to play","Enter time to play the animation"); + } + else if (message == "@attach"){ + Text("@animate=","Enter inventory name to attach","Enter number of the attachment point (1-40)"); + } + else if (message == "@speed"){ + Text("@speed=","Enter a speed for the NPC, 1=100% normal speed, 0.5=50% speed",""); + } + + + // Save NPC name + else if (MakeNotecard == STATE) { + sNPCName = message; // in case we need to kill it. + + vector vDest = (vector) Pos(); + + if (relAbs == "Relative") + { + vDest -= llGetPos(); // just an offset for relative + } + sNotecard = "@spawn=" + message + "|" + (string) vDest + "\n"; + integer i; + integer j = llGetListLength(lCommands); + for (; i < j; i++){ + // get the command to save to the notecard + string line = llList2String(lCommands,i); + if (relAbs == "Absolute") { + sNotecard += line; // add the un-modified string to the notecard + } else { + // since we have to record absolute coords since we do not know where the box goes until they press Save, + // we process the absolute to relative conversion for walks here + list parts = llParseString2List(line,["="],[]); //get the @command + + if (llList2String(parts,0) == "@walk") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@walk=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@fly") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@fly=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@run") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@run=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@land") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@land=" + (string) vec + "\n"; + } + else { + sNotecard += line; // add the un-modified string to the notecard + } + } + } + llRemoveInventory(Notecard); // delete the old notecard + osMakeNotecard(Notecard,sNotecard); // Makes the notecard. + llSay(0,sNotecard); + llOwnerSay("Commands notecard has been written"); + STATE = 0; + } // MakeNotecard + + else if (! llStringLength(sParam2)) { + lCommands += sCommand + message + "\n"; + llOwnerSay("Recorded"); + makeMenu(lAtButtons); + } + else if (llStringLength(sParam2)){ + sCommand = sCommand + message + "|"; + llOwnerSay("Recorded"); + makeText(sParam2); + sParam2 = ""; + } + + } + + + + timer(){ + // DEBUG("tick"); + + // if llDialog is up, kill the listener for the dialog box. + if (iHandle) { + llOwnerSay("Menu timed out"); + llListenRemove(iHandle); + iHandle = 0; + return; // ^^^^^^^^^^^^^^^^^^^^^^^ + } + // if NoBodyHome, we are sensing for an avatar + else if (NobodyHome == STATE) { + ProcessSensor(); + return; + } + // if we are spawning, we need time to rez the NPC, then start processing NPC Commands. + else if (Spawning == STATE) { + STATE = 0; + TimerEvent(TIMER); + } + // We end aniamtions with a timer + else if (Animate == STATE){ + NPCAnimate(STAND); + TimerEvent(TIMER); + } + + else if (Walking == STATE) { + if (--iWaitCounter) { + if (llVecDist(osNpcGetPos(NPCKey()), newDest) > MAXDIST) { + return; + } + } + + DEBUG("At Destination: " + (string) newDest); + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 2) { + // nothing + } else if (walkstate == 3) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 4) { + llShout(FLIGHT,"landing"); + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } + } + // Wandering timer + else if (Wander == STATE) { + if (--iWaitCounter) { // wait 60 seconds to get to a destination. + if (llVecDist(osNpcGetPos(NPCKey()), vWanderPos) > MAXDIST) + return; + } + + // see if wander counter == 0, if so, stop walking, go to stand and process next line + if(RAMwc == 0) { + NPCAnimate(STAND); + DEBUG("Wander ended, calling DoProcessNPCLine"); + STATE = 0; + DoProcessNPCLine(); + return; + } + // one less time to wander around + RAMwc--; + NPCAnimate(STAND); + TimerEvent(TIMER); + StateWanderhold(); + return; + } + // Wandering requires us to re-wander when we reach a destination + else if (WanderHold == STATE) { + StateWander(); + TimerEvent(TIMER); + return; + } + else if (DoProcess == STATE) { + TimerEvent(QUICK); + } + + + STATE = 0; + + // We always process a NPC line at end of timer. + DEBUG("Tick end, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } + + // sensors are used for sitting on prims + // Neo Cortex: added different SensorFunc states to trigger sit or touch + sensor(integer num) { + if (SensorFunc == 1) { + osNpcSit(NPCKey(), llDetectedKey(0), OS_NPC_SIT_NOW); + DEBUG("Seated, calling DoProcessNPCLine"); + SensorFunc = 0; + } else if (SensorFunc == 2) { + osNpcTouch(NPCKey(), llDetectedKey(0), LINK_THIS); + DEBUG("Touched, calling DoProcessNPCLine"); + SensorFunc = 0; + } + DoProcessNPCLine(); + } + no_sensor(){ + DEBUG ("no target prim located, calling DoProcessNPCLine"); + SensorFunc = 0; + DoProcessNPCLine(); + } + + + link_message(integer sender, integer num, string str, key id){ + DEBUG("Command In:" + str); + if (str=="@go") { + SetStop(FALSE); // Let's run the notecard + DEBUG("@go running"); + DoProcessNPCLine(); + } else { + Stack += [str]; // take anything, the controller will filter away non @ stuff + if (STATE == 0) { + DEBUG("calling DoNPC"); + DoProcessNPCLine(); + } else{ + DEBUG("Queued"); + + } + } + } + +} + + + + + + diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 4.0.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 4.0.lsl new file mode 100644 index 00000000..98108005 --- /dev/null +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 4.0.lsl @@ -0,0 +1,1772 @@ +// :SHOW:1 +// :CATEGORY:NPC +// :NAME:All In One NPC Recorder and Player +// :AUTHOR:Ferd Frederix +// :KEYWORDS: +// :CREATED:2013-09-08 18:27:47 +// :EDITED:2015-08-02 21:09:13 +// :ID:27 +// :NUM:1603 +// :REV:1.3 +// :WORLD:OpenSim +// :DESCRIPTION: +// All in one NPC recorder player set of debug functions. Add these ONLY if you are compileing in LSLEditor. +// :CODE: +// IMPORTANT NOTE +// DELETE ALL these lines out for Opensim, leave uncommented for testing in LSLEditor + +integer OS_NPC_CREATOR_OWNED = 1; +integer OS_NPC_SIT_NOW = 1; +integer OS_NPC_SENSE_AS_AGENT = 2; +integer OS_NPC_NO_FLY = 3; +integer OS_NPC_NOT_OWNED = 4; +integer OS_NPC_RUNNING = 5; +integer OS_NPC_LAND_AT_TARGET = 6; +integer OS_NPC_FLY = 7; + + +integer osIsNpc(key id){ + return TRUE; +} + +osNpcStand(key npc) { + llOwnerSay("Standing"); +} +vector osNpcGetPos(key id) { + vector vDestPos; + vDestPos.x += llFrand(1.0); // some randomness for debugging + llOwnerSay("Reached " + (string) vDestPos); + return vDestPos; +} +osNpcMoveToTarget(key npc, vector target, integer options){ + llSay(0,"Moving to " + (string) target); +} +key osNpcCreate(string firstname, string lastname, vector position, string cloneFrom, integer options) { + llSay(0,"Creating NPC " + firstname + " " + lastname + " at " + (string) position); + return (key) "12345000-0000-0000-0000-0000000000002"; +} +osNpcLoadAppearance(key npc, string notecard) { + llSay(0,"Load notecard " + notecard); +} +osNpcPlayAnimation(key npc, string animation) { + llSay(0,"Playing animation " + animation); +} +osNpcStopAnimation(key npc, string animation) { + llSay(0,"Stopped animation " + animation); +} +osNpcSay(key npc, integer iChannel, string message) { + llSay(0,"Saying " + message); +} +osNpcWhisper(key npc, integer iChannel, string message) { + llSay(0,"Whispering " + message); +} +osNpcShout(key npc, integer iChannel, string message) { + llSay(0,"Shouting " + message); +} +osNpcSit(key npc, key target, integer options) { + llSay(0,"Sat on " +target); +} +osNpcSetRot(key npc, rotation rot) { + llSay(0,"Set rotation of NPC to " + (string) rot); +} +osOwnerSaveAppearance(string notecard) { + llSay(0,"Created Notecard " + notecard); +} +osAgentSaveAppearance(key avatar, string notecard) { + llSay(0,"Created Notecard " + notecard); +} +osNpcRemove (key target) { + llSay(0,"NPC removed"); +} +list osGetAvatarList () { + list lStuff = [(key) "12345000-0000-0000-0000-0000000000002", vDestPos, "Digit Gorilla"]; + return lStuff; +} +osMakeNotecard(string notecardName, string contents) { + llOwnerSay("Make Notecard " + notecardName + "Contents:" + (string) contents); +} +string osGetNotecard(string name) { + // sample notecard for testing + string str = "@spawn=Digit Gorilla|<645, 128, 25>\n" + + "@walk=<645, 120, 25>\n" + + "REPEAT\n" + + "@cmd=0|Hello on channel 0\n" + + "@wander=3|5\n" + + "@say=say , walking is so tiresome...\n" + + "@whisper=whisper, walking is so tiresome...\n" + + "@shout=shout, walking is so tiresome...\n" + + "@goto=REPEAT\n" + + "@goto=NEXT\n" + + "@say=i will never say this...\n" + + "NEXT\n" + + "@sound=somesound\n" + + "@randsound\n" + + "@pause=5\n" + + "@rotate=90\n" + + "@wander=3|1\n" + + "@say=Uff, I'm done...\n" + + "@delete\n"; + return str; +} + +osAvatarPlayAnimation(key npc, string animation){ + llSay(0,"playing " + animation); +} + +osAvatarStopAnimation(key npc, string animation){ + llSay(0,"Stopping " + animation); +} + +osForceOtherSit(key AvatarKey, key UUID) { + llSay(0,"Sitting"); +} + + +osSetSpeed(key NPC, float speed) { + llSay(0,"Speed set to " + (string) speed); +} + +osNpcTouch(key NPC, key thing, integer where) {;} + +osForceAttachToOtherAvatarFromInventory(key npc, string inventory, integer point) { + llSay(0,"attach " + inventory + " to " + (string) point); +} + + + + + + + + +// :SHOW:1 +// :CATEGORY:NPC +// :NAME:All In One NPC Recorder and Player +// :AUTHOR:Ferd Frederix +// :KEYWORDS:NPC, Puppeteer +// :CREATED:2015-08-28 23:27:03 +// :ID:27 +// :NUM:1824 +// :REV: 4.0 +// :WORLD:OpenSim +// :DESCRIPTION: +// All in one NPC recorder player. +// Supports both absolute and relative paths and many new commands +// Add animations named "Fly, Walk, Stand and Run" +// Click Prim to use. +// Should be worn as a HUD to record. +// Put it on the ground and click Sensor or Start NPC when done. +// :CODE: +// This is Rev 4.0 09/15/2015 + +// Revision History +// Rev 1.1 10-2-2014 @Sit did not work. Minor tweaks to casting for lslEditor +// Rev 1.2 10-14-2014 @ sit had wrong type. +// Rev 1.3 relative movement fixed for @fly +// Rev 1.4 4-3-2014 allow anyone to use this, non owners and non group members can only start and stop. +// Rev 1.5 5-17-2014 set sensor to auto start on reboot of sim +// Rev 1.6 5-24-2014 move menu so you can get it by touching, removed many of the KeyValues to RAM for efficiency +// Rev 1.7 CHANGED_REGION_START, not CHANGED_REGION_START (Opensim difference) +// Rev 1.8 tuned up Kill NPC, added more flexible upgrader +// Rev 1.9 Better script injection by link message// Rev 2.0 Added osSetSpeed so you can speed up or slow down an NPC. +// Rev 2.1 No laggy sensor used exept to sit on stuff +// Rev 2.2 Various sensor fixes +// Rev 2.3 Sets No Sensor in menu, must be started by hand +// Rev 2.4 - reserved for patches to 2.3 if needed +// Rev 3.0 Refactor out into subs, not states to make command injection easier +// New command: @appearance=Notecardname so you can switch to a new notecard on the fly +// New command: @speed=1.0 which slows up ( < 1 ) or speeds up ( > 1) +// Rev 3.1 Commands are not interruptible by Link Message +// Rev 3.2 Sensor patches for consistency in removing the NPC +// Rev 3.3 Added Touch command by Neo.Cortex@hbase42/hopto/org:8002 +// Added Menu 3 for notecard and appearance commands +// Rev 3.4 animation timer cannot be zero or it shuts off timer tweaked +// solves the NPC starting up when no sensor is set. +// Rev 3.5 fixes saving to !Path notecard +// Rev 3.6 08-11-2015 @delete acts like @stop. TYjhe NPC now rezzes after an @go back in where it was deleted +// Rev 3.7 08-11-2015 @attach command added to load an attachment from the inventory to the NPC +// Rev 3.8 08-17-2015 process queued commands one at a time without calling ProcessNPCLine on link message +// Rev 3.9 08-23-2011 Queued command fixes including @delete which were not always working +// Rev 4.0 09-15-2015 - FIxes for Sensor functions which continually rezzed a NPC when no one was around. +//*******************************************************************// + +// Instructions on how to use this are at http://www.outworldz.com/opensim/posts/NPC/ +// This is an OpenSim-only script. +// Author: Ferd Frederix aka Fred Beckhusen - fred@mitsi.com + +//////////////////////////////////////////////////////////////////////////////////////////// +// Original code was Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // +/////////////////////////////////////////////////////////////////////////////////////////// +// Please see: http://www.gnu.org/licenses/gpl.html for legal details, // +// rights of fair usage, the disclaimer and warranty conditions. // +/////////////////////////////////////////////////////////////////////////////////////////// +// The original NPC controller was from http://was.fm/opensim:npc +// Extensive additions and bug fixes by Fred Beckhusen, aka Ferd Frederix +// llSensor had two params swapped +// @Wander would wander where it had rezzed, not where it was. +// There was no 'no_sensor' event in sit, so if a @sit failed, the NPC got stuck +// The animation and walks always stopped old, then started new. It should be start new, then stop old so the default stand would be suppressed. +// New code: +// Merged with new Route recorder and notecard writer +// If the NPC failed to reach a destination it never moved on. +// Added WAIT global to tune this +// Exposed many tunable variables and ported the code +// Added floating point to times in notecard. + +// Added @sound, @randsound, @whisper, @shout, and @cmd controls. +// +// notecards integers are not floats for better control +// +// Link Messages may be used to perform external control by injecting @commands into the stream of actions +// Example: +// To chat something, such as with a chat robot +// llMessageLinked(LINK_SET,0,"@npc_say=Hello",""); + +// This script assumes that NPCs and OSSl scripting is enabled in the OpenSim configuration. +// In order to enable them, the following changes must be made in the OpenSim.ini configuration file: +// +// ; Turn on OSSL +// AllowOSFunctions = true +// OSFunctionThreatLevel = Severe + +//[NPC] +// ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} +// Enabled = true +// +// and then the server has to be restarted. + + +// Commands: All commands begin with an @ sign. All other lines are ignored +// @commands may have optional parameters. The syntax is always: +// @cmd=parm1|parm2 +// NaN in the table below meand Not a Number. This means there is no parameter + +//Command First Parameter Second Parameter Description +//@spawn name location (vector) Rezzes an NPC with name at a location. +//@appearance NoteCardName NaN switch the NPC appearance to a new notecard +//@walk destination (vector) NaN Makes the NPC walk to destination. +//@fly destination (vector) NaN Makes the NPC fly to destination. +//@land destination (vector) NaN Makes the NPC land at destination. +//@say string NaN Makes the NPC speak a phrase. +//@whisper string NaN Makes the NPC whisper a phrase. +//@shout string NaN Makes the NPC shout a phrase. +//@pause seconds (float) NaN Makes the NPC wait for a multiple of seconds. +//@wander radius (float) cycles (integer) Makes the NPC wander in radius, for cycles seconds. +//@delete NaN NaN Removes the NPC. Requires a link message to continue +//@goto label (string) NaN Jump to the label label in the script. +//@animate animation (string) time (float) Makes the NPC trigger the animation animation for time seconds. +//@sound sound_name NaN plays a sound from inventory +//@randsound NaN NaN Plays a random sound from inventory +//@rotate degrees (float) NaN Rotate the NPC degrees around the Z axis. +//@sit primitive name NaN Sit on a primitive with a given name. +//@touch primitive name NaN Touch on a primitive with a given name. +//@stand NaN NaN If sitting on a primitive, stand up. +//@cmd channel (integer) string Says string on channel, for controlling external gadgets +//@stop NaN NaN Halts the NPC script indefinitely. Can be started with a link message +//@go NaN NaN Continues on next notecard line, for use in link messages +//@speed speed (float) NaN from 0 to N, where 1.0 ius a normal speed of an avatar. 0.2 is a turtle. +//@notecard notename (string) NaN load a new Path notecard +//@attach InventoryName attachmentPoint load an attachment from the inventory to the NPC onto point + +// Constant attachmentPoint Comment +// ATTACH_CHEST 1 chest/sternum +// ATTACH_HEAD 2 head +// ATTACH_LSHOULDER 3 left shoulder +// ATTACH_RSHOULDER 4 right shoulder +// ATTACH_LHAND 5 left hand +// ATTACH_RHAND 6 right hand +// ATTACH_LFOOT 7 left foot +// ATTACH_RFOOT 8 right foot +// ATTACH_BACK 9 back +// ATTACH_PELVIS 10 pelvis +// ATTACH_MOUTH 11 mouth +// ATTACH_CHIN 12 chin +// ATTACH_LEAR 13 left ear +// ATTACH_REAR 14 right ear +// ATTACH_LEYE 15 left eye +// ATTACH_REYE 16 right eye +// ATTACH_NOSE 17 nose +// ATTACH_RUARM 18 right upper arm +// ATTACH_RLARM 19 right lower arm +// ATTACH_LUARM 20 left upper arm +// ATTACH_LLARM 21 left lower arm +// ATTACH_RHIP 22 right hip +// ATTACH_RULEG 23 right upper leg +// ATTACH_RLLEG 24 right lower leg +// ATTACH_LHIP 25 left hip +// ATTACH_LULEG 26 left upper leg +// ATTACH_LLLEG 27 left lower leg +// ATTACH_BELLY 28 belly/stomach/tummy +// ATTACH_LEFT_PEC 29 left pectoral +// ATTACH_RIGHT_PEC 30 right pectoral +// ATTACH_HUD_CENTER_2 31 HUD Center 2 +// ATTACH_HUD_TOP_RIGHT 32 HUD Top Right +// ATTACH_HUD_TOP_CENTER 33 HUD Top +// ATTACH_HUD_TOP_LEFT 34 HUD Top Left +// ATTACH_HUD_CENTER_1 35 HUD Center +// ATTACH_HUD_BOTTOM_LEFT 36 HUD Bottom Left +// ATTACH_HUD_BOTTOM 37 HUD Bottom +// ATTACH_HUD_BOTTOM_RIGHT 38 HUD Bottom Right +// ATTACH_NECK 39 neck +// ATTACH_AVATAR_CENTER 40 avatar center/root + + + +////////////////////////////////////////////////////////// +// DEBUG // +////////////////////////////////////////////////////////// +integer debug = TRUE; // set to TRUE or FALSE for debug chat on various actions +integer LSLEditor = TRUE; // set to to TRUE to working in LSLEditor, FALSE for in-world. + // you must also include the NPC commands found in the other script since LSLEditor does not support OpenSim +integer iTitleText = FALSE; // set to TRUE to see debug info in text above the controller + +////////////////////////////////////////////////////////// +// TUNABLE CONFIGURATION // +////////////////////////////////////////////////////////// +float TIMER = 2; // faster = less jerky stopping. How often the system checks the distance traveled. Fastest you can go is 0.5 seconds +float QUICK = 1; // when we need to move to the next state, we use a QUICK timer +string Appearance = "!Appearance"; // The name of the recorded Appearance notecard +string Notecard = "!Path"; // The name of the recorded routes +integer allowUsers = FALSE; // If true, any user can get a Start NPC and Stop NPC menu. Only groups and owners can get all commands if TRUE, or FALSE +float MAXDIST = 2.0; // how close a NPC has to get to a dest pos to continue to next state. Do not lower this too much, as it may miss the target +integer WANDERRAND = TRUE; // set to TRUE and they will pause during wanders a random number of seconds +float WANDERTIME = 3.0; // how long they stand after each @wander,if WANDERRAND is FALSE. If WANDERRAND is TRUE, this is the max time +integer WAIT = 30; // wait for this number of seconds for the NPC to reach a destination (for safety). If it fails to reach a target, it will move on after this time. +float RANGE = 50; // 1 to N meters - anyone this close to the controller will start NPCS if Sensor button is clicked +float REZTIME = 2.0; // wait this long for NPC to rez in, then start the process +string STAND = "Stand"; // the name of the default Stand animation +string WALK = "Walk"; // the name of the default Walk animation +string FLY = "Fly"; // the name of the default Fly animation +string RUN = "Run"; // the name of the default Run animation +string LAND = "Land"; // the name of the default land animation ( for birds only) +float OffsetZ = 0.5; // appear 0.5 meter above ground, this is added to all destinations to keep them from sinking in. +float SPEEDMULT =0.5; // 1.0 = regular avatar speed. Smaller numbers slow down walks. Large numbers speed them up. +integer FLIGHT = 299; // For controlling wings. A channel that is shouted at when flight starts and ends. "flying" or "landing" + +// DESCRIPTIONS FIELDS HAVE TO SURVIVE A RESET +// These vars are stored by saving them with KeyValueSet +// "pr" is a 0 if it is set for Owner Only, 1 for Group control +// "se" is "on" if Started +// "co" = "R" or "A" for relative or absolute addressing mode +// "key" = NPC key + +// These Globals used to be stored in description. Moved to RAM in V1.6 +float RAMPause; // @pause param +float RAMwd ; // @wander distance +integer RAMwc; // @wander count +float RAMrot; // @rotate +string RAMsit; // @sit primname +string RAMtouch; // @touch primname +string RAManimationName; // @animate animation (string) time (float) +float RAManimationTime; + +// other globals section +integer iChannel; // a listen channel, randomly assigned +integer iHandle; // the handle to it + +// NPC controls +vector newDest ; // tmp storage for the walks +integer iWaitCounter ; // wait for this number of seconds for the NPC to reach a desrtination +string sNPCName; // the name of the NPC that may be in world. So we can remove it. +integer bNPC_STOP = FALSE; // boolean to reuse a listener +integer Stopped = FALSE; // set to TRUE by link messages so we do not remember them +float fTimerVal ; // how long we wait when wandering (calculated) +float NPCEnabled; // true if the NPC is suppodes to be running + +// OS_NPC_CREATOR_OWNED will create an 'owned' NPC that will only respond to osNpc* commands issued from scripts that have the same owner as the one that created the NPC. +// OS_NPC_NOT_OWNED will create an 'unowned' NPC that will respond to any script that has OSSL permissions to call osNpc* commands. +integer NPCOptions = OS_NPC_CREATOR_OWNED; // only yhe owner of this box can control this NPC. + +integer walkstate = 0; // helps us reshare the walk state for run, fly and land - a bit of a hack, but it saves RAM. Has to be done this way because some bits of NPCWalkOption are asserted as 0 + +integer NPCWalkOption; // Some notes for what happens to NPCWalkOption: +// OS_NPC_FLY - Fly the avatar to the given position. The avatar will not land unless the OS_NPC_LAND_AT_TARGET option is also given. +// OS_NPC_NO_FLY - Do not fly to the target. The NPC will attempt to walk to the location. If it's up in the air then the avatar will keep bouncing hopeless until another move target is given or the move is stopped +//OS_NPC_LAND_AT_TARGET - If given and the avatar is flying, then it will land when it reaches the target. If OS_NPC_NO_FLY is given then this option has no effect. +// OS_NPC_RUNNING - if given, NPC avatar moves at running/fast flying speed, otherwise moves at walking/slow flying speed. + +// menus +string mSensor="Sense is Off"; // Sensor or "No Sensor" + +list lAtButtons = ["Menu","-", ">>", "@run", "@walk", "@fly", "@land", "@wander", "@sit", "@stand","@animate","@rotate"]; +list lMenu2 = ["<<", "@comment", ">>>", "@stop", "@say", "@whisper","@shout","@sound","@randsound","@cmd", "@pause", "@delete"]; +list lMenu3 = ["<<<","@notecard","@appearance", "@touch", "@speed", "@attach", "-","-", "-", "-", "-", "-" ]; + +string sCommand; // place to store a command for two-prompted ones +string sParam2; // place to store a prompt for two-prompted ones +string priPub = "Owner Only"; // Private or Group +key kUserKey; // the person who is controlling the avatar, not the Owner +// the command lists +list lCommands; // commands are stored here +list lNpcCommandList; // Storage for the NPC script. +string npcAction; // Storage for the next action. @cmd=0|hello, this becomes @cmd +string npcParams; // Storage for the param, @cmd=0|hello, this becomes 0|hello + +// misc vars +string sNotecard; // commands are stored here temporarily for dumping +vector vWanderPos; // a place to wander to +string lastANIM ; // last animation run +// Sensor +integer avatarPresent; // Sensor sets this flag when people are within Range. + +// Coordinate control +vector vInitialPos ; // Vector that will be filled by the script with the initial starting position in region coordinates. +vector vDestPos = ZERO_VECTOR; // Storage for destination position. +string relAbs = "Relative"; // absolute vs relative positioning + + +// STATES +integer MENU ; // processing a dialog box state, may be concurrent with STATE +integer STATE; // state storage +integer MakeNotecard = 1; // displaying a text box for NPC name +integer RecordPath = 2; // displaying a path notecard menu +integer NobodyHome = 3; // looking for an avatar +integer Spawning = 4; // spawning an avatar +integer Animate = 5; // animation timer needed +integer Walking = 6; // Hey! I am walking here! +integer Wander = 7; // Wandering around neeeds a timer, too +integer WanderHold = 8; // We reached a wander point +integer DoProcess = 9; // Set this to make it process a new command +integer Touch = 10; // Timer is busy sensing something to touch +integer Sit = 11; // Timer is busy sensing something to sit on +integer Paused = 12; // Timer is busy pausing + +key gNpcKey = NULL_KEY; // global key storage for the one NPC, to save CPU cycles +list Stack ; // a command stack from link message input + +integer SensorFunc = 0; // define which function shall be triggered inside the sensor function + // 0 means none, 1 sit, 2 touch +/////////////////////////////////////////////////////////////////////////// +// FUNCTIONS // +/////////////////////////////////////////////////////////////////////////// + + +TimerEvent(float timesent) +{ + if (LSLEditor) + timesent *= 5; // slow thinggs doen when the LSLEDITOR is in use + + DEBUG("Setting timer: " + (string) timesent); + llSetTimerEvent(timesent); +} + + +SetStop(integer what) +{ + DEBUG("Stopped set to " + (string ) what); + Stopped = what; +} +// Do* functions are much like states from the old V2 scripts. + +// Save a Path notecard +DoSave() +{ + STATE = MakeNotecard; + makeText("Stand where you want the NPC to appear, and enter the NPC Name"); +} + +// This function is used to record the path for the NPC +// Each command can take 0, 1, or 2 params +DoMenuForCommands() { + makeMenu(lAtButtons); +} + + +// No one is here when sensors were on, so we kill off the NPC +DoNobodyHome() +{ + DEBUG("Nobody Home"); + STATE = NobodyHome; + if (NPCKey() != NULL_KEY) { + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + } + TimerEvent(5); // keep ticking to sense avatars +} + +// Create a NPC +StateSpawn() { + DEBUG("state spawn"); + STATE = Spawning; + + + NPCEnabled = TRUE; // in world + // see if there is already one out there. + if (NPCKey() != NULL_KEY) { + DEBUG("Already living"); + return; + } + + + list name = llParseString2List(sNPCName, [" "], []); + + vector vRezPos = vInitialPos; + if (relAbs == "Relative"){ + vRezPos += llGetPos(); + } + + DEBUG("Rezzing the NPC:" + (string) vRezPos); + key aKey = osNpcCreate(llList2String(name, 0), llList2String(name, 1), vRezPos, Appearance, NPCOptions); + + SaveKey(aKey); // save in desceription and global, too + + osSetSpeed(aKey,SPEEDMULT); // 1.9 speed multiplier + TimerEvent(REZTIME); + NPCAnimate(STAND); +} + +DoRotate() { + DEBUG("@rotate=" + (string) RAMrot); + osNpcSetRot(NPCKey(), llEuler2Rot(<0,0,RAMrot> * DEG_TO_RAD)); +} + +StateSit() { + DEBUG ("state sit - looking for " + RAMsit); + STATE=Sit; + SensorFunc = 1; //triggers osNpcSit + llSensor(RAMsit, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +StateTouch() { + DEBUG ("state touch - looking for " + RAMtouch); + STATE = Touch; + SensorFunc = 2; //triggers osNpcTouch + llSensor(RAMtouch, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +DoStand() { + DEBUG("state stand"); + osNpcStand(NPCKey()); +} + + +StateAnimate() { + + DEBUG("state animate"); + STATE = Animate; + NPCAnimate(RAManimationName); + if (RAManimationTime <=0 ) // V 3.4 tweak + RAManimationTime = 1; + TimerEvent(RAManimationTime); +} + +StateWalk() { + + DEBUG("NPCWalkOption = " + (string) NPCWalkOption); + STATE = Walking; + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(WALK); + } else if (walkstate == 2) { + llShout(FLIGHT,"flying"); + NPCAnimate(FLY); + } else if (walkstate == 3) { + NPCAnimate(RUN); + } else if (walkstate == 4) { + NPCAnimate(LAND); + } + newDest = vDestPos ; + newDest.z += OffsetZ; + + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + newDest += llGetPos(); + } + + DEBUG("Moveto:" + (string) newDest); + osNpcMoveToTarget(NPCKey(), newDest, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + + +StateWander(){ + DEBUG("state wander"); + STATE = Wander; + + vector point = CirclePoint(RAMwd); + DEBUG("CirclePoint:" + (string) point); + vWanderPos = vDestPos + point; + DEBUG("vWanderPos:" + (string) vWanderPos); + + fTimerVal = WANDERTIME; // default time to pause after each wander + if (WANDERRAND) + fTimerVal = llFrand(WANDERTIME) + 1; // override, they want random times + + NPCAnimate(WALK); + + DEBUG("Wander to:" + (string) vWanderPos); + + osNpcMoveToTarget(NPCKey(), vWanderPos, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + +StateWanderhold() { + + DEBUG("Wander Hold"); + STATE = WanderHold; + + // now that we have reached a wander spot, slow the timer down to the desired value + TimerEvent(fTimerVal); +} + +// @pause=10 will do nothing for 10 seconds +DoPause() { + STATE =Paused; + if (RAMPause < 0.1) + RAMPause = 0.1; + DEBUG("@pause=" + (string)RAMPause); + TimerEvent(RAMPause); +} + + +// @stop makes the NPC stop moving in whatever state it is in. You have to linkmessage to get moving again +DoStop() { + DEBUG("NPC is Stopped"); + STATE = 0; // accept commands + SetStop(TRUE); // Link controlled - we mnust have a @go to continue with notecards + TimerEvent(0); + Stack = []; // v3.8 +} + +// @delete removes the NPC forever. Next command starts it up again at the beginning +DoDelete() { + DEBUG("state delete"); + STATE = 0; // accept commands + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + + TimerEvent(0); + Stack = []; // v3.8 +} + +// change the appearance of the NPC +DoAppearance(string notecard) { + DEBUG("state appearance"); + if (llGetInventoryType(notecard) == INVENTORY_NOTECARD){ + DEBUG("Load appearance " + notecard); + osNpcLoadAppearance(NPCKey(),notecard); + } +} + +// Change the avatar speed +DoSpeed(string speed) { + float newspeed = (float) speed; + if (newspeed > 0.1 && newspeed < 5.0) {// sanity check + osSetSpeed(NPCKey(),newspeed); + } +} +DoNewNote (string card) { + DEBUG("Load Notecard " + card); + NPCReadNoteCard(card); + SetStop(FALSE); +} +DoAttach(string params) { + + list Data = llParseString2List(params, ["|"], []); + string itemName = llList2String(Data, 0); + integer attachmentPoint = (integer) llList2String(Data, 1); + if (attachmentPoint > 0 + && attachmentPoint < 40 + && llGetInventoryType(itemName) == INVENTORY_OBJECT + ) + { + osForceAttachToOtherAvatarFromInventory(NPCKey(),itemName,attachmentPoint); + } +} + +// This loops over the notecard, processing each command +DoProcessNPCLine() { + DEBUG("ProcessNPCLine, stopped = " + (string) Stopped); + STATE = DoProcess; + + // auto load a notecard + if (! llGetListLength(lNpcCommandList)) { + DEBUG("Read Notecard"); + NPCReadNoteCard(Notecard); + SetStop(FALSE); + } + + // look for link messages on the stack + string next = llList2String(Stack,0); // lets see if there is anithing from a link message + if (llStringLength(next)) + { + Stack = llDeleteSubList(Stack,0,0); + ProcessCmd(next); //lets do this command instead. + return; + } + + // @stop issued? + if (Stopped) { + TimerEvent(0); + DEBUG("Stopped, waiting for input"); + STATE = 0; + return; + } + + // No, we have an @go for liftoff + next = llList2String(lNpcCommandList, 0); // get the next command + DEBUG("Execute:" + next); + lNpcCommandList = llDeleteSubList(lNpcCommandList, 0, 0); // delete it + + if (llGetListLength(lNpcCommandList) == 0) { + DEBUG("EOF"); + } + ProcessCmd(next); +} + + + +ProcessCmd(string cmd) { + + DEBUG("ProcessCmd:" + cmd); + + if (llGetSubString(cmd, 0, 0) != "@") { + DEBUG("ignoring"); + TimerEvent(QUICK); // this is so we do not recurse the stack + STATE = 0; + return; + } + + list data = llParseString2List(cmd, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data, 0), STRING_TRIM)); + + DEBUG("Action:" + npcAction); + npcParams = llStringTrim(llList2String(data, 1), STRING_TRIM); + DEBUG("Params:" + npcParams); + + @commands; + + ProcessSensor(); + + if(npcAction == "@spawn" && avatarPresent) { + DEBUG("@spawn"); + list spawnData = llParseString2List(npcParams, ["|"], []); + sNPCName =llList2String(spawnData, 0); // V 1.6 name in RAM + + list spawnDest = llParseString2List(llList2String(spawnData, 1), ["<", ",", ">"], []); + vInitialPos.x = llList2Float(spawnDest, 0); + vInitialPos.y = llList2Float(spawnDest, 1); + vInitialPos.z = llList2Float(spawnDest, 2); + + DEBUG("Coords for NPC at " + (string) vInitialPos); + StateSpawn(); + return; + } + + if (! avatarPresent){ + DoNobodyHome(); + DEBUG("No avatar nearby"); + STATE = 0; + return; + } else { + if ( NPCKey() == NULL_KEY) { + StateSpawn(); + } + } + + + + + if(npcAction == "@stop") { + DoStop(); + STATE = 0; + return; + } + else if(npcAction == "@goto") { + DEBUG("goto"); + integer lastIdx = llGetListLength(lNpcCommandList)-1; + lNpcCommandList = llDeleteSubList(lNpcCommandList, lastIdx, lastIdx); + // Wind commands till goto label. + @wind; + string next1 = llList2String(lNpcCommandList, 0); + lNpcCommandList = llDeleteSubList(lNpcCommandList, 0, 0); + lNpcCommandList += next1; + if(next1 != npcParams) jump wind; + // Wind the label too. + next1 = llList2String(lNpcCommandList, 0); + lNpcCommandList = llDeleteSubList(lNpcCommandList, 0, 0); + lNpcCommandList += next1; + // Get next command. + list data1 = llParseString2List(next1, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data1, 0), STRING_TRIM)); + npcParams = llStringTrim(llList2String(data1, 1), STRING_TRIM); + // Reschedule. + jump commands; + } + else if(npcAction == "@sound") { + DEBUG("sound"); + llTriggerSound(npcParams,1.0); + } + else if(npcAction == "@randsound") { + DEBUG("@randsound"); + integer N = llGetInventoryNumber(INVENTORY_SOUND); + integer rand = llCeil(llFrand(N)) -1; // pick a random sound + string toPlay = llGetInventoryName(INVENTORY_SOUND,rand); + llTriggerSound(toPlay,1.0); + } + else if(npcAction == "@walk") { + DEBUG("@walk"); + GetDest(npcParams); + walkstate = 1;// walking + NPCWalkOption = OS_NPC_NO_FLY ; + StateWalk(); + return; + } + else if(npcAction == "@fly") { + GetDest(npcParams); + walkstate = 2;// flying + NPCWalkOption = OS_NPC_FLY ; + StateWalk(); + return; + } + else if(npcAction == "@run") { + DEBUG("@run"); + GetDest(npcParams); + walkstate = 3;// running + NPCWalkOption = OS_NPC_NO_FLY | OS_NPC_RUNNING; + StateWalk(); + return; + } + else if(npcAction == "@land") { + DEBUG("@land"); + GetDest(npcParams); + walkstate = 4;// landing + NPCWalkOption= OS_NPC_FLY | OS_NPC_LAND_AT_TARGET ; + StateWalk(); + return; + } + else if(npcAction == "@say") { + DEBUG("@say " + npcParams); + osNpcSay(NPCKey(), 0, npcParams); + } + else if(npcAction == "@shout") { + DEBUG("@shout"); + osNpcShout(NPCKey(),0, npcParams); + } + else if(npcAction == "@whisper") { + DEBUG("@whisper " + npcParams); + osNpcWhisper(NPCKey(),0, npcParams); + } + // speak a command on a channel, so you can open doors and control stuff. + else if(npcAction == "@cmd") { + DEBUG("@cmd"); + list dataToSpeak = llParseString2List(npcParams, ["|"], []); + string channel = llList2String(dataToSpeak,0); + DEBUG("Channel:"+(string) channel); + integer iChannel = (integer) channel; + string stringToSpeak = llList2String(dataToSpeak,1); + llSay(iChannel, stringToSpeak); + } + // stop everything + else if(npcAction == "@pause") { + RAMPause = (float) npcParams; + DoPause(); + return; + } + else if(npcAction == "@wander") { + list wanderData = llParseString2List(npcParams, ["|"], []); + RAMwd = (float) llList2String(wanderData, 0); + RAMwc = (integer) llList2String(wanderData, 1); + vDestPos = osNpcGetPos(NPCKey()); // set the wander start + DEBUG("Starting at " + (string) vDestPos); + StateWander(); + return; + } + else if(npcAction == "@rotate") { + RAMrot = (float) npcParams; + DoRotate(); + } + else if(npcAction == "@sit") { + RAMsit= npcParams; + StateSit(); + return; + } + else if(npcAction == "@touch") { + RAMtouch= npcParams; + StateTouch(); + return; + } + else if(npcAction == "@stand") { + DoStand(); + } + else if(npcAction == "@delete") { + DoDelete(); + SetStop(TRUE); // Link controlled - we mnust have a @go to continue with notecards + return; + } + else if(npcAction == "@animate") { + list animateData = llParseString2List(npcParams, ["|"], []); + RAManimationName = llList2String(animateData, 0); + RAManimationTime = (float) llList2String(animateData, 1); + StateAnimate(); + return; + } + else if(npcAction == "@appearance" ){ + DoAppearance(npcParams); + } + else if (npcAction =="@speed") { + DoSpeed(npcParams); + } + else if (npcAction =="@notecard") { + DoNewNote(npcParams); + Notecard = npcParams; + } + else if (npcAction == "@attach") + { + DoAttach(npcParams); + } + + STATE = 0; + TimerEvent(QUICK); // yeah I know, not possible this fast, we just go as fast as we can go - this is so we do not recurse the stack +} + + + +/////////////////// UTILITY Functions, not state-like ////////////////// + +// DEBUG(string) will chat a string or display it as hovertext if debug == TRUE +DEBUG(string str) { + if (debug && ! LSLEditor) + llOwnerSay( str); // Send the owner debug info + if (debug && LSLEditor) + llSay(0, str); // Send to the Console in LSLEDitor + if (iTitleText) { + llSetText(str,<1.0,1.0,1.0>,1.0); // show hovertext + + } +} + +GetDest(string npcParams) { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); +} + +NPCReadNoteCard(string Note) { + DEBUG("NPCReadNoteCard"); + lNpcCommandList = llParseString2List(osGetNotecard(Note), ["\n"], []); +} + +integer SenseAvatar() +{ + //Returns a strided list of the UUID, position, and name of each avatar in the region + list avatars = llGetAgentList(AGENT_LIST_REGION ,[]); + integer numOfAvatars = llGetListLength(avatars); + if (numOfAvatars == 0) + { + DEBUG("No people"); + return 0; + } + //DEBUG("Located " + (string)numOfAvatars + " avatars and NPC's"); + + integer nAvatars; + integer i; + for( i = 0;i < numOfAvatars; i++) { + key aviKey = llList2Key(avatars,i); + if (!osIsNpc(aviKey)) { + list detail = llGetObjectDetails(aviKey,[OBJECT_POS]); + vector pos = llList2Vector(detail,0); + float dist = llVecDist(pos, llGetPos()); + if (dist < RANGE) + { + nAvatars++; + DEBUG("In range:" + llKey2Name(aviKey)); + } + } + } + //DEBUG("Located " + (string) nAvatars + " avatars"); + return nAvatars; +} + +// return TRUE if the avatar is owner when private is set, or TRUE if the avatar is in the same group and GROUP is set. +integer checkPerms() { + + integer group = (integer) KeyValueGet("pr"); + if (! group) + priPub = "Owner Only"; + else + priPub = "Group"; + + + if (llDetectedKey(0) == llGetOwner()){ + kUserKey = llDetectedKey(0); + return TRUE; + } + + if ( group && llDetectedGroup(0)) { + kUserKey = llDetectedKey(0); + return TRUE; + } + kUserKey = llDetectedKey(0); + return FALSE; +} + + + +NPCAnimate(string anim) +{ + DEBUG("Start Anim: " + anim); + if (llGetInventoryType(anim) == INVENTORY_ANIMATION ) { + + if (lastANIM != anim) { + if(llStringLength(lastANIM)) { + osNpcStopAnimation(NPCKey(), lastANIM); + } + osNpcPlayAnimation(NPCKey(), anim); + lastANIM = anim; + } + } else { + llSay(DEBUG_CHANNEL, "No animation named " + anim); + } +} + +// Kill a NPC by Name +Kill(string param) +{ + integer count; + list avatars = osGetAvatarList(); // Returns a strided list of the UUID, position, and name of each avatar in the region except the owner.\ + integer i; + integer j = llGetListLength(avatars); + for (i=0 ; i <= j; i+=3){ + + string desired = llList2String(avatars,i+2); + desired = llStringTrim(desired,STRING_TRIM); // should not be needed but is needed + + if (desired == param){ + vector v = llList2Vector(avatars,i+1); + key target = llList2Key(avatars,i); // get the UUID of the avatar + osNpcRemove(target); + SaveKey(NULL_KEY ); + llOwnerSay("Removed " + param+ " at location " + (string) v); + count++; + } + } + + NPCEnabled = FALSE; // not in world + + if (count) + llOwnerSay("Removed " + (string) count + " NPC's"); + else + llOwnerSay("Could not locate " + param); +} + + +// return a String for the position we are at. Strings used as the caller wants strings +string Pos() +{ + vector where = llGetPos(); // find the box position + + where.z += OffsetZ; // use the ground position + an offset + + if (LSLEditor) + where = <128,128,31 + llFrand(1)>; // force center of sim when editing + + // if attached the height will be too high by 1/2 the agent size + if (llGetAttached()) { + vector size = llGetAgentSize(llGetOwner()); + float Z = size.z; + where.z -= Z/2; + } + + // DEBUG("Pos= " + (string) where); + return (string) where; +} + +// setup a menu with a timer for timeouts, called by all make*() +menu() +{ + llListenRemove(iHandle); + iChannel = llCeil(llFrand(100000) + 20000); + iHandle = llListen(iChannel,"","",""); + TimerEvent(30.0); + MENU = TRUE; +} + +// make a text box +makeText(string Param) +{ + menu(); + llTextBox(kUserKey, Param, iChannel); +} + +// top level menu +makeMainMenu() +{ + menu(); + list buttons = ["Appearance","Recording","Save","Help","-","Erase RAM", priPub,relAbs,"-","Stop NPC",mSensor,"Start NPC"]; + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Records",buttons,iChannel); +} + + +// Rev 1.4 +// top level menu for non group/ non owners +makeUserMenu() +{ + if (!allowUsers) return; + + menu(); + list buttons = ["Start NPC","Stop NPC"]; + llDialog(kUserKey,"Choose",buttons,iChannel); +} + + + +// programmable menu for @commands +makeMenu(list buttons) +{ + menu(); + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Record",buttons,iChannel); +} + + +// make one or two text boxes with prompts +Text(string cmd, string p1, string p2) +{ + sCommand = cmd; + sParam2 = ""; + if (llStringLength(p2)) + sParam2 = p2; + + makeText(p1); +} + +// Set the Avatar Present flag - if sensors are off and we are forece run, there will be one present. +ProcessSensor() +{ + integer SensorOn; + if ("on" == KeyValueGet("se")) + { + SensorOn = TRUE; // we need to scan for avatars + } else { + SensorOn = FALSE; // we need to scan for avatars + } + DEBUG("Sensor:" + (string) SensorOn); + + integer n = SenseAvatar(); + + DEBUG("Avatars:" + (string) n); + if (SensorOn && n) + avatarPresent = TRUE; // someone is here and we need to tell the system to run + else if (SensorOn && !n) + avatarPresent = FALSE; // someone is not here and we need to tell the system to stop + else { // sensor is off, lete see if there is a NPC. If so, we are ON + DEBUG("NPCEnabled:" + (string) NPCEnabled); + if (NPCEnabled) + avatarPresent = TRUE; + else + avatarPresent = FALSE; + } + + // start up from when when no one is near + if (avatarPresent && STATE == NobodyHome) + STATE = 0; + + DEBUG("Avatar Present: " + (string) avatarPresent); +} + +vector CirclePoint(float radius) { + float x = llFrand(radius *2) - radius; // +/- radius, randomized + float y = llFrand(radius *2) - radius; // +/- radius, randomized + return ; // so this should always happen +} + +string KeyValueGet(string var) { + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k != var) jump continue; + //DEBUG("got " + var + " = " + llList2String(data, 1)); + return llList2String(data, 1); + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + return ""; +} + +KeyValueSet(string var, string val) { + + //DEBUG("set " + var + " = " + val); + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + if(llGetListLength(dVars) == 0) + { + llSetObjectDesc(var + "=" + val); + return; + } + list result = []; + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k == "") jump continue; + if(k == var && val == "") jump continue; + if(k == var) { + result += k + "=" + val; + val = ""; + jump continue; + } + string v = llList2String(data, 1); + if(v == "") jump continue; + result += k + "=" + v; + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + if(val != "") result += var + "=" + val; + llSetObjectDesc(llDumpList2String(result, "&")); +} + + +// clear RAM +Clr() { + + lCommands = []; + llOwnerSay("RAM Memory cleared. Notecards, if any, are not modified."); + makeMainMenu(); +} + +integer checkNoteCards() +{ + // Check that they have saved an Appeaance and Path notecard + integer num = llGetInventoryNumber(INVENTORY_NOTECARD); // how many notecards overall + + integer i; + integer count; + for (; i < num; i++){ + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Notecard) + count++; + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Appearance) + count++; + } + DEBUG("Checked " + (string) count + " Notecards"); + // if we have both, run the NPC + return count; +} + +Update(string SName) { + + // delete all NPC* scripts except myself + integer i; + integer j = llGetInventoryNumber(INVENTORY_SCRIPT); + for (i = 0; i < j; i++) { + string targetName = llGetInventoryName(INVENTORY_SCRIPT,i); + string match = llGetSubString(targetName,0,2); + + if (match == SName && llGetScriptName() != targetName){ + llOwnerSay("Upgrading " + targetName); + if (! LSLEditor){ // lets not kill the editor + llRemoveInventory(targetName); + } + } + } +} + +// Get all default saved params from the Description +GetSwitches() +{ + string rA = KeyValueGet("co"); // Get the remembered menu setting for Abs Vs Relative + if (rA == "A") + relAbs = "Absolute"; + else if (rA == "R") + relAbs = "Relative"; + else + relAbs = "Absolute"; + + + // reenable NPC if sensor is on. + if ("on" == KeyValueGet("se")) + { + NPCEnabled = TRUE; + mSensor = "Sense is On"; + ProcessSensor(); // fake 1 avatar to get it rezzed + } else { + mSensor = "Sense is Off"; + } + } + + +SaveKey(key akey) +{ + DEBUG("Saving Key of " + (string) akey); + KeyValueSet("key", akey); + if (akey != (key) KeyValueGet("key") ) + { + DEBUG("Fatal error, cannot save key"); + } + gNpcKey = akey; +} + + +key NPCKey() +{ + key akey = gNpcKey; // from cached copy + // gNpcKey saves a lot of CPU processing by caching the key, if blank we get it from the description + if (gNpcKey == NULL_KEY) + { + //DEBUG("Get DKey"); + akey = KeyValueGet("key"); // from Description of the prim + } + // DEBUG("NPC KEY:" + (string) akey); + return akey; +} + + +/////////////////// CODE BEGINS ////////////////// + + +default +{ + changed(integer change) { + if(change & CHANGED_REGION_START) { + llResetScript(); + } + } + + on_rez(integer start_param) + { + llResetScript(); + } + + state_entry() { + + llSetText("",<1,1,1>,1.0); // clr all hovertext- we may not be using it. + DoDelete(); // kill any NPC that is out running + Update("NPC"); // If dragged and ropped into a prim with any script named "NPC...", this will replace it. + GetSwitches(); // Get all default saved params from the Description + TimerEvent(TIMER); + } + + + touch_start(integer n) + { // if touched, make a menu + + if (checkPerms()) { + if (RecordPath == STATE) { + makeMenu(lAtButtons); + } else { + makeMainMenu(); + } + } else { + makeUserMenu(); + } + } + + // menu listener + listen(integer iChannel, string name, key id, string message) { + + if (MENU) { + llListenRemove(iHandle); + MENU = 0; // menu is off + iHandle = 0; + } + + if (message == "Stop NPC") + { + lNpcCommandList = []; // force reload of notecard + NPCEnabled = FALSE; + if (NPCKey() != NULL_KEY){ + Kill(sNPCName); + sNPCName = ""; + } else { + bNPC_STOP = TRUE; + makeText("Enter name of an NPC to stop"); + } + } + else if (message == "Menu" ) { + makeMainMenu(); + } + else if (message == "Erase RAM"){ + Clr(); + } + else if (message == "Relative"){ + relAbs = "Absolute"; + KeyValueSet("co","A"); // remember coordinates = A + Clr(); + } + else if (message == "Absolute"){ + relAbs = "Relative"; + KeyValueSet("co","R"); // remember coordinates = R + Clr(); + } + else if (message == "Recording"){ + DoMenuForCommands(); // show them the recording menu + } + else if (message == "Owner Only") { + priPub = "Group"; + KeyValueSet("pr","1"); + + llOwnerSay("Group members have control"); + makeMainMenu(); + } + else if (message == "Group") { + priPub = "Owner Only"; + KeyValueSet("pr","0"); + llOwnerSay("Only you have control"); + makeMainMenu(); + } + else if (message == "Sense is On") { + mSensor ="Sense is Off"; + KeyValueSet("se", "off"); + llOwnerSay(mSensor); + makeMainMenu(); + } + else if (message == "Sense is Off") { + mSensor ="Sense is On"; + llOwnerSay(mSensor); + KeyValueSet("se", "on"); + + NPCEnabled = FALSE; + + integer count = checkNoteCards(); + if (count >= 2) { + DEBUG("Notecards ok, DoProcessNPCLine"); + DoProcessNPCLine(); + return; + } + if (LSLEditor) { + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording and/or appearance, so you cannot start a NPC"); + makeMainMenu(); + } + else if (message == "Appearance") { + llRemoveInventory(Appearance); // delete the notecard + osAgentSaveAppearance(kUserKey,Appearance); // make the ntecard + llOwnerSay("Your outfit has been saved"); + makeMainMenu(); + } + else if (message == "Save") { + if (llGetListLength(lCommands) == 0) { + llOwnerSay("Nothing recorded, you need to make a recording first"); + makeMainMenu(); + return; + } + DoSave(); + } + else if (message == "Help"){ + llLoadURL(kUserKey,"Click to view help","http://www.outworldz.com/opensim/posts/NPC/"); + makeMainMenu(); + } + else if (message == "Start NPC") { + integer count = checkNoteCards(); + + NPCEnabled = TRUE; + + if (LSLEditor) { + DoProcessNPCLine(); + return; + } + + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + SetStop(FALSE); // Let's run the notecard + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording or maybe an appearance, so we cannot start a NPC"); + + } + else if (bNPC_STOP){ + bNPC_STOP = FALSE; + Kill(message); + } + else if (message == ">>"){ + makeMenu(lMenu2); + } + else if (message == ">>>"){ + makeMenu(lMenu3); + } + else if (message == "<<") { + makeMenu(lAtButtons); + } + else if (message == "<<<") { + makeMenu(lMenu2); + } + else if (message == "@comment"){ + Text("# ","Enter a comment",""); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@run"){ + lCommands += "@run=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@fly"){ + lCommands += "@fly=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@land"){ + lCommands += "@land=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@walk") { + lCommands += "@walk=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@sound"){ + Text("@sound=","Enter a sound name or UUID to trigger",""); + } + else if (message == "@randsound"){ + lCommands += "@randsound"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@say") { + Text("@say=","Enter what the NPC will say",""); + } + else if (message == "@whisper"){ + Text("@whisper=","Enter what the NPC will whisper",""); + } + else if (message == "@shout"){ + Text("@shout=","Enter what the NPC will shout",""); + } + else if (message == "@wander") { + Text("@wander=","Enter radius to wander","Enter number of wanders"); + } + else if (message == "@pause") { + Text("@pause=","Enter time to pause",""); + } + else if (message == "@rotate") { + Text("@rotate=","Enter degrees to rotate",""); + } + else if (message == "@sit"){ + Text("@sit=","Enter name of object to sit on",""); + } + else if (message == "@touch"){ + Text("@touch=","Enter name of object to touch",""); + } + else if (message == "@cmd"){ + Text("@cmd=","Enter cjhannel to speak on","Enter text to speak"); + } + else if (message == "@stand"){ + lCommands += "@stand\n"; + llOwnerSay("Stand Recorded"); + makeMenu(lAtButtons); + } + else if (message == "@animate"){ + Text("@animate=","Enter animation name to play","Enter time to play the animation"); + } + else if (message == "@attach"){ + Text("@animate=","Enter inventory name to attach","Enter number of the attachment point (1-40)"); + } + else if (message == "@speed"){ + Text("@speed=","Enter a speed for the NPC, 1=100% normal speed, 0.5=50% speed",""); + } + + + // Save NPC name + else if (MakeNotecard == STATE) { + sNPCName = message; // in case we need to kill it. + + vector vDest = (vector) Pos(); + + if (relAbs == "Relative") + { + vDest -= llGetPos(); // just an offset for relative + } + sNotecard = "@spawn=" + message + "|" + (string) vDest + "\n"; + integer i; + integer j = llGetListLength(lCommands); + for (; i < j; i++){ + // get the command to save to the notecard + string line = llList2String(lCommands,i); + if (relAbs == "Absolute") { + sNotecard += line; // add the un-modified string to the notecard + } else { + // since we have to record absolute coords since we do not know where the box goes until they press Save, + // we process the absolute to relative conversion for walks here + list parts = llParseString2List(line,["="],[]); //get the @command + + if (llList2String(parts,0) == "@walk") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@walk=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@fly") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@fly=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@run") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@run=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@land") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@land=" + (string) vec + "\n"; + } + else { + sNotecard += line; // add the un-modified string to the notecard + } + } + } + llRemoveInventory(Notecard); // delete the old notecard + osMakeNotecard(Notecard,sNotecard); // Makes the notecard. + llSay(0,sNotecard); + llOwnerSay("Commands notecard has been written"); + STATE = 0; + } // MakeNotecard + + else if (! llStringLength(sParam2)) { + lCommands += sCommand + message + "\n"; + llOwnerSay("Recorded"); + makeMenu(lAtButtons); + } + else if (llStringLength(sParam2)){ + sCommand = sCommand + message + "|"; + llOwnerSay("Recorded"); + makeText(sParam2); + sParam2 = ""; + } + + } + + + + timer(){ + // DEBUG("tick"); + + // if llDialog is up, kill the listener for the dialog box. + if (iHandle) { + llOwnerSay("Menu timed out"); + llListenRemove(iHandle); + iHandle = 0; + return; // ^^^^^^^^^^^^^^^^^^^^^^^ + } + // if NoBodyHome, we are sensing for an avatar + else if (NobodyHome == STATE) { + ProcessSensor(); + return; + } + // if we are spawning, we need time to rez the NPC, then start processing NPC Commands. + else if (Spawning == STATE) { + STATE = 0; + TimerEvent(TIMER); + } + // We end aniamtions with a timer + else if (Animate == STATE){ + NPCAnimate(STAND); + TimerEvent(TIMER); + } + + else if (Walking == STATE) { + if (--iWaitCounter) { + if (llVecDist(osNpcGetPos(NPCKey()), newDest) > MAXDIST) { + return; + } + } + + DEBUG("At Destination: " + (string) newDest); + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 2) { + // nothing + } else if (walkstate == 3) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 4) { + llShout(FLIGHT,"landing"); + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } + } + // Wandering timer + else if (Wander == STATE) { + if (--iWaitCounter) { // wait 60 seconds to get to a destination. + if (llVecDist(osNpcGetPos(NPCKey()), vWanderPos) > MAXDIST) + return; + } + + // see if wander counter == 0, if so, stop walking, go to stand and process next line + if(RAMwc == 0) { + NPCAnimate(STAND); + DEBUG("Wander ended, calling DoProcessNPCLine"); + STATE = 0; + DoProcessNPCLine(); + return; + } + // one less time to wander around + RAMwc--; + NPCAnimate(STAND); + TimerEvent(TIMER); + StateWanderhold(); + return; + } + // Wandering requires us to re-wander when we reach a destination + else if (WanderHold == STATE) { + StateWander(); + TimerEvent(TIMER); + return; + } + else if (DoProcess == STATE) { + TimerEvent(QUICK); + } + + + STATE = 0; + + // We always process a NPC line at end of timer. + DEBUG("Tick end, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } + + // sensors are used for sitting on prims + // Neo Cortex: added different SensorFunc states to trigger sit or touch + sensor(integer num) { + if (SensorFunc == 1) { + osNpcSit(NPCKey(), llDetectedKey(0), OS_NPC_SIT_NOW); + DEBUG("Seated, calling DoProcessNPCLine"); + SensorFunc = 0; + } else if (SensorFunc == 2) { + osNpcTouch(NPCKey(), llDetectedKey(0), LINK_THIS); + DEBUG("Touched, calling DoProcessNPCLine"); + SensorFunc = 0; + } + DoProcessNPCLine(); + } + no_sensor(){ + DEBUG ("no target prim located, calling DoProcessNPCLine"); + SensorFunc = 0; + DoProcessNPCLine(); + } + + + link_message(integer sender, integer num, string str, key id){ + DEBUG("Command In:" + str); + if (str=="@go") { + SetStop(FALSE); // Let's run the notecard + DEBUG("@go running"); + DoProcessNPCLine(); + } else { + Stack += [str]; // take anything, the controller will filter away non @ stuff + if (STATE == 0) { + DEBUG("calling DoNPC"); + DoProcessNPCLine(); + } else{ + DEBUG("Queued"); + } + } + } + +} + + + + + + diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 4.1.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 4.1.lsl new file mode 100644 index 00000000..27260abf --- /dev/null +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 4.1.lsl @@ -0,0 +1,1650 @@ +// :SHOW:1 +// :CATEGORY:NPC +// :NAME:All In One NPC Recorder and Player +// :AUTHOR:Ferd Frederix +// :KEYWORDS:NPC, Puppeteer +// :CREATED:2015-08-28 23:27:03 +// :EDITED:2015-09-23 12:06:52 +// :ID:27 +// :NUM:1826 +// :REV:4.1 +// :WORLD:OpenSim +// :DESCRIPTION: +// All in one NPC recorder player. +// Supports both absolute and relative paths and many new commands +// Add animations named "Fly, Walk, Stand and Run" +// Click Prim to use. +// Should be worn as a HUD to record. +// Put it on the ground and click Sensor or Start NPC when done. +// :CODE: +// This is Rev 4.1 09/20/2015 + +// Revision History +// Rev 1.1 10-2-2014 @Sit did not work. Minor tweaks to casting for lslEditor +// Rev 1.2 10-14-2014 @ sit had wrong type. +// Rev 1.3 relative movement fixed for @fly +// Rev 1.4 4-3-2014 allow anyone to use this, non owners and non group members can only start and stop. +// Rev 1.5 5-17-2014 set sensor to auto start on reboot of sim +// Rev 1.6 5-24-2014 move menu so you can get it by touching, removed many of the KeyValues to RAM for efficiency +// Rev 1.7 CHANGED_REGION_START, not CHANGED_REGION_START (Opensim difference) +// Rev 1.8 tuned up Kill NPC, added more flexible upgrader +// Rev 1.9 Better script injection by link message// Rev 2.0 Added osSetSpeed so you can speed up or slow down an NPC. +// Rev 2.1 No laggy sensor used exept to sit on stuff +// Rev 2.2 Various sensor fixes +// Rev 2.3 Sets No Sensor in menu, must be started by hand +// Rev 2.4 - reserved for patches to 2.3 if needed +// Rev 3.0 Refactor out into subs, not states to make command injection easier +// New command: @appearance=Notecardname so you can switch to a new notecard on the fly +// New command: @speed=1.0 which slows up ( < 1 ) or speeds up ( > 1) +// Rev 3.1 Commands are not interruptible by Link Message +// Rev 3.2 Sensor patches for consistency in removing the NPC +// Rev 3.3 Added Touch command by Neo.Cortex@hbase42/hopto/org:8002 +// Added Menu 3 for notecard and appearance commands +// Rev 3.4 animation timer cannot be zero or it shuts off timer tweaked +// solves the NPC starting up when no sensor is set. +// Rev 3.5 fixes saving to !Path notecard +// Rev 3.6 08-11-2015 @delete acts like @stop. TYjhe NPC now rezzes after an @go back in where it was deleted +// Rev 3.7 08-11-2015 @attach command added to load an attachment from the inventory to the NPC +// Rev 3.8 08-17-2015 process queued commands one at a time without calling ProcessNPCLine on link message +// Rev 3.9 08-23-2011 Queued command fixes including @delete which were not always working +// Rev 4.0 09-15-2015 Fixes for Sensor functions which continually rezzed a NPC when no one was around. +// Rev 4.1 09-20-2015 Added a Listener so link messages are not needed +//*******************************************************************// + +// Instructions on how to use this are at http://www.outworldz.com/opensim/posts/NPC/ +// This is an OpenSim-only script. +// Author: Ferd Frederix aka Fred Beckhusen - fred@mitsi.com + +//////////////////////////////////////////////////////////////////////////////////////////// +// Original code was Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // +/////////////////////////////////////////////////////////////////////////////////////////// +// Please see: http://www.gnu.org/licenses/gpl.html for legal details, // +// rights of fair usage, the disclaimer and warranty conditions. // +/////////////////////////////////////////////////////////////////////////////////////////// +// The original NPC controller was from http://was.fm/opensim:npc +// Extensive additions and bug fixes by Fred Beckhusen, aka Ferd Frederix +// llSensor had two params swapped +// @Wander would wander where it had rezzed, not where it was. +// There was no 'no_sensor' event in sit, so if a @sit failed, the NPC got stuck +// The animation and walks always stopped old, then started new. It should be start new, then stop old so the default stand would be suppressed. +// New code: +// Merged with new Route recorder and notecard writer +// If the NPC failed to reach a destination it never moved on. +// Added WAIT global to tune this +// Exposed many tunable variables and ported the code +// Added floating point to times in notecard. + +// Added @sound, @randsound, @whisper, @shout, and @cmd controls. +// +// notecards integers are not floats for better control +// +// Link Messages may be used to perform external control by injecting @commands into the stream of actions +// Example: +// To chat something, such as with a chat robot +// llMessageLinked(LINK_SET,0,"@npc_say=Hello",""); + +// This script assumes that NPCs and OSSl scripting is enabled in the OpenSim configuration. +// In order to enable them, the following changes must be made in the OpenSim.ini configuration file: +// +// ; Turn on OSSL +// AllowOSFunctions = true +// OSFunctionThreatLevel = Severe + +//[NPC] +// ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} +// Enabled = true +// +// and then the server has to be restarted. + + +// Commands: All commands begin with an @ sign. All other lines are ignored +// @commands may have optional parameters. The syntax is always: +// @cmd=parm1|parm2 +// NaN in the table below meand Not a Number. This means there is no parameter + +//Command First Parameter Second Parameter Description +//@spawn name location (vector) Rezzes an NPC with name at a location. +//@appearance NoteCardName NaN switch the NPC appearance to a new notecard +//@walk destination (vector) NaN Makes the NPC walk to destination. +//@fly destination (vector) NaN Makes the NPC fly to destination. +//@land destination (vector) NaN Makes the NPC land at destination. +//@say string NaN Makes the NPC speak a phrase. +//@whisper string NaN Makes the NPC whisper a phrase. +//@shout string NaN Makes the NPC shout a phrase. +//@pause seconds (float) NaN Makes the NPC wait for a multiple of seconds. +//@wander radius (float) cycles (integer) Makes the NPC wander in radius, for cycles seconds. +//@delete NaN NaN Removes the NPC. Requires a link message to continue +//@goto label (string) NaN Jump to the label label in the script. +//@animate animation (string) time (float) Makes the NPC trigger the animation animation for time seconds. +//@sound sound_name NaN plays a sound from inventory +//@randsound NaN NaN Plays a random sound from inventory +//@rotate degrees (float) NaN Rotate the NPC degrees around the Z axis. +//@sit primitive name NaN Sit on a primitive with a given name. +//@touch primitive name NaN Touch on a primitive with a given name. +//@stand NaN NaN If sitting on a primitive, stand up. +//@cmd channel (integer) string Says string on channel, for controlling external gadgets +//@stop NaN NaN Halts the NPC script indefinitely. Can be started with a link message +//@go NaN NaN Continues on next notecard line, for use in link messages +//@speed speed (float) NaN from 0 to N, where 1.0 ius a normal speed of an avatar. 0.2 is a turtle. +//@notecard notename (string) NaN load a new Path notecard +//@attach InventoryName attachmentPoint load an attachment from the inventory to the NPC onto point + +// Constant attachmentPoint Comment +// ATTACH_CHEST 1 chest/sternum +// ATTACH_HEAD 2 head +// ATTACH_LSHOULDER 3 left shoulder +// ATTACH_RSHOULDER 4 right shoulder +// ATTACH_LHAND 5 left hand +// ATTACH_RHAND 6 right hand +// ATTACH_LFOOT 7 left foot +// ATTACH_RFOOT 8 right foot +// ATTACH_BACK 9 back +// ATTACH_PELVIS 10 pelvis +// ATTACH_MOUTH 11 mouth +// ATTACH_CHIN 12 chin +// ATTACH_LEAR 13 left ear +// ATTACH_REAR 14 right ear +// ATTACH_LEYE 15 left eye +// ATTACH_REYE 16 right eye +// ATTACH_NOSE 17 nose +// ATTACH_RUARM 18 right upper arm +// ATTACH_RLARM 19 right lower arm +// ATTACH_LUARM 20 left upper arm +// ATTACH_LLARM 21 left lower arm +// ATTACH_RHIP 22 right hip +// ATTACH_RULEG 23 right upper leg +// ATTACH_RLLEG 24 right lower leg +// ATTACH_LHIP 25 left hip +// ATTACH_LULEG 26 left upper leg +// ATTACH_LLLEG 27 left lower leg +// ATTACH_BELLY 28 belly/stomach/tummy +// ATTACH_LEFT_PEC 29 left pectoral +// ATTACH_RIGHT_PEC 30 right pectoral +// ATTACH_HUD_CENTER_2 31 HUD Center 2 +// ATTACH_HUD_TOP_RIGHT 32 HUD Top Right +// ATTACH_HUD_TOP_CENTER 33 HUD Top +// ATTACH_HUD_TOP_LEFT 34 HUD Top Left +// ATTACH_HUD_CENTER_1 35 HUD Center +// ATTACH_HUD_BOTTOM_LEFT 36 HUD Bottom Left +// ATTACH_HUD_BOTTOM 37 HUD Bottom +// ATTACH_HUD_BOTTOM_RIGHT 38 HUD Bottom Right +// ATTACH_NECK 39 neck +// ATTACH_AVATAR_CENTER 40 avatar center/root + + + +////////////////////////////////////////////////////////// +// DEBUG // +////////////////////////////////////////////////////////// +integer debug = TRUE; // set to TRUE or FALSE for debug chat on various actions +integer LSLEditor = TRUE; // set to to TRUE to working in LSLEditor, FALSE for in-world. + // you must also include the NPC commands found in the other script since LSLEditor does not support OpenSim +integer iTitleText = FALSE; // set to TRUE to see debug info in text above the controller + +////////////////////////////////////////////////////////// +// TUNABLE CONFIGURATION // +////////////////////////////////////////////////////////// +integer allowListener = TRUE; // set to TRUE to anable a command listener. Usually, this is setto FALSE +integer link_Channel = 4223; // some random number you want to talk to this gadget on. Best if large and negative +float TIMER = 2; // faster = less jerky stopping. How often the system checks the distance traveled. Fastest you can go is 0.5 seconds +float QUICK = 1; // when we need to move to the next state, we use a QUICK timer +string Appearance = "!Appearance"; // The name of the recorded Appearance notecard +string Notecard = "!Path"; // The name of the recorded routes +integer allowUsers = FALSE; // If true, any user can get a Start NPC and Stop NPC menu. Only groups and owners can get all commands if TRUE, or FALSE +float MAXDIST = 2.0; // how close a NPC has to get to a dest pos to continue to next state. Do not lower this too much, as it may miss the target +integer WANDERRAND = TRUE; // set to TRUE and they will pause during wanders a random number of seconds +float WANDERTIME = 3.0; // how long they stand after each @wander,if WANDERRAND is FALSE. If WANDERRAND is TRUE, this is the max time +integer WAIT = 30; // wait for this number of seconds for the NPC to reach a destination (for safety). If it fails to reach a target, it will move on after this time. +float RANGE = 50; // 1 to N meters - anyone this close to the controller will start NPCS if Sensor button is clicked +float REZTIME = 2.0; // wait this long for NPC to rez in, then start the process +string STAND = "Stand"; // the name of the default Stand animation +string WALK = "Walk"; // the name of the default Walk animation +string FLY = "Fly"; // the name of the default Fly animation +string RUN = "Run"; // the name of the default Run animation +string LAND = "Land"; // the name of the default land animation ( for birds only) +float OffsetZ = 0.5; // appear 0.5 meter above ground, this is added to all destinations to keep them from sinking in. +float SPEEDMULT =0.5; // 1.0 = regular avatar speed. Smaller numbers slow down walks. Large numbers speed them up. +integer FLIGHT = 299; // For controlling wings. A channel that is shouted at when flight starts and ends. "flying" or "landing" + +// DESCRIPTIONS FIELDS HAVE TO SURVIVE A RESET +// These vars are stored by saving them with KeyValueSet +// "pr" is a 0 if it is set for Owner Only, 1 for Group control +// "se" is "on" if Started +// "co" = "R" or "A" for relative or absolute addressing mode +// "key" = NPC key + +// These Globals used to be stored in description. Moved to RAM in V1.6 +float RAMPause; // @pause param +float RAMwd ; // @wander distance +integer RAMwc; // @wander count +float RAMrot; // @rotate +string RAMsit; // @sit primname +string RAMtouch; // @touch primname +string RAManimationName; // @animate animation (string) time (float) +float RAManimationTime; + +// other globals section +integer iChannel; // a listen channel, randomly assigned +integer iHandle; // the handle to it + +// NPC controls +vector newDest ; // tmp storage for the walks +integer iWaitCounter ; // wait for this number of seconds for the NPC to reach a desrtination +string sNPCName; // the name of the NPC that may be in world. So we can remove it. +integer bNPC_STOP = FALSE; // boolean to reuse a listener +integer Stopped = FALSE; // set to TRUE by link messages so we do not remember them +float fTimerVal ; // how long we wait when wandering (calculated) +float NPCEnabled; // true if the NPC is suppodes to be running + +// OS_NPC_CREATOR_OWNED will create an 'owned' NPC that will only respond to osNpc* commands issued from scripts that have the same owner as the one that created the NPC. +// OS_NPC_NOT_OWNED will create an 'unowned' NPC that will respond to any script that has OSSL permissions to call osNpc* commands. +integer NPCOptions = OS_NPC_CREATOR_OWNED; // only yhe owner of this box can control this NPC. + +integer walkstate = 0; // helps us reshare the walk state for run, fly and land - a bit of a hack, but it saves RAM. Has to be done this way because some bits of NPCWalkOption are asserted as 0 + +integer NPCWalkOption; // Some notes for what happens to NPCWalkOption: +// OS_NPC_FLY - Fly the avatar to the given position. The avatar will not land unless the OS_NPC_LAND_AT_TARGET option is also given. +// OS_NPC_NO_FLY - Do not fly to the target. The NPC will attempt to walk to the location. If it's up in the air then the avatar will keep bouncing hopeless until another move target is given or the move is stopped +//OS_NPC_LAND_AT_TARGET - If given and the avatar is flying, then it will land when it reaches the target. If OS_NPC_NO_FLY is given then this option has no effect. +// OS_NPC_RUNNING - if given, NPC avatar moves at running/fast flying speed, otherwise moves at walking/slow flying speed. + +// menus +string mSensor="Sense is Off"; // Sensor or "No Sensor" + +list lAtButtons = ["Menu","-", ">>", "@run", "@walk", "@fly", "@land", "@wander", "@sit", "@stand","@animate","@rotate"]; +list lMenu2 = ["<<", "@comment", ">>>", "@stop", "@say", "@whisper","@shout","@sound","@randsound","@cmd", "@pause", "@delete"]; +list lMenu3 = ["<<<","@notecard","@appearance", "@touch", "@speed", "@attach", "-","-", "-", "-", "-", "-" ]; + +string sCommand; // place to store a command for two-prompted ones +string sParam2; // place to store a prompt for two-prompted ones +string priPub = "Owner Only"; // Private or Group +key kUserKey; // the person who is controlling the avatar, not the Owner +// the command lists +list lCommands; // commands are stored here +list lNpcCommandList; // Storage for the NPC script. +string npcAction; // Storage for the next action. @cmd=0|hello, this becomes @cmd +string npcParams; // Storage for the param, @cmd=0|hello, this becomes 0|hello + +// misc vars +string sNotecard; // commands are stored here temporarily for dumping +vector vWanderPos; // a place to wander to +string lastANIM ; // last animation run +// Sensor +integer avatarPresent; // Sensor sets this flag when people are within Range. + +// Coordinate control +vector vInitialPos ; // Vector that will be filled by the script with the initial starting position in region coordinates. +vector vDestPos = ZERO_VECTOR; // Storage for destination position. +string relAbs = "Relative"; // absolute vs relative positioning + + +// STATES +integer MENU ; // processing a dialog box state, may be concurrent with STATE +integer STATE; // state storage +integer MakeNotecard = 1; // displaying a text box for NPC name +integer RecordPath = 2; // displaying a path notecard menu +integer NobodyHome = 3; // looking for an avatar +integer Spawning = 4; // spawning an avatar +integer Animate = 5; // animation timer needed +integer Walking = 6; // Hey! I am walking here! +integer Wander = 7; // Wandering around neeeds a timer, too +integer WanderHold = 8; // We reached a wander point +integer DoProcess = 9; // Set this to make it process a new command +integer Touch = 10; // Timer is busy sensing something to touch +integer Sit = 11; // Timer is busy sensing something to sit on +integer Paused = 12; // Timer is busy pausing + +key gNpcKey = NULL_KEY; // global key storage for the one NPC, to save CPU cycles +list Stack ; // a command stack from link message input + +integer SensorFunc = 0; // define which function shall be triggered inside the sensor function + // 0 means none, 1 sit, 2 touch +/////////////////////////////////////////////////////////////////////////// +// FUNCTIONS // +/////////////////////////////////////////////////////////////////////////// + + +TimerEvent(float timesent) +{ + if (LSLEditor) + timesent *= 5; // slow thinggs doen when the LSLEDITOR is in use + + DEBUG("Setting timer: " + (string) timesent); + llSetTimerEvent(timesent); +} + +// for 4.1 parse a message from a Listen or a Link message +ParseMsg(string str) { + DEBUG("Command In:" + str); + if (str=="@go") { + SetStop(FALSE); // Let's run the notecard + DEBUG("@go running"); + DoProcessNPCLine(); + } else { + Stack += [str]; // take anything, the controller will filter away non @ stuff + if (STATE == 0) { + DEBUG("calling DoNPC"); + DoProcessNPCLine(); + } else{ + DEBUG("Queued"); + } + } +} + +SetStop(integer what) +{ + DEBUG("Stopped set to " + (string ) what); + Stopped = what; +} +// Do* functions are much like states from the old V2 scripts. + +// Save a Path notecard +DoSave() +{ + STATE = MakeNotecard; + makeText("Stand where you want the NPC to appear, and enter the NPC Name"); +} + +// This function is used to record the path for the NPC +// Each command can take 0, 1, or 2 params +DoMenuForCommands() { + makeMenu(lAtButtons); +} + + +// No one is here when sensors were on, so we kill off the NPC +DoNobodyHome() +{ + DEBUG("Nobody Home"); + STATE = NobodyHome; + if (NPCKey() != NULL_KEY) { + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + } + TimerEvent(5); // keep ticking to sense avatars +} + +// Create a NPC +StateSpawn() { + DEBUG("state spawn"); + STATE = Spawning; + + + NPCEnabled = TRUE; // in world + // see if there is already one out there. + if (NPCKey() != NULL_KEY) { + DEBUG("Already living"); + return; + } + + + list name = llParseString2List(sNPCName, [" "], []); + + vector vRezPos = vInitialPos; + if (relAbs == "Relative"){ + vRezPos += llGetPos(); + } + + DEBUG("Rezzing the NPC:" + (string) vRezPos); + key aKey = osNpcCreate(llList2String(name, 0), llList2String(name, 1), vRezPos, Appearance, NPCOptions); + + SaveKey(aKey); // save in desceription and global, too + + osSetSpeed(aKey,SPEEDMULT); // 1.9 speed multiplier + TimerEvent(REZTIME); + NPCAnimate(STAND); +} + +DoRotate() { + DEBUG("@rotate=" + (string) RAMrot); + osNpcSetRot(NPCKey(), llEuler2Rot(<0,0,RAMrot> * DEG_TO_RAD)); +} + +StateSit() { + DEBUG ("state sit - looking for " + RAMsit); + STATE=Sit; + SensorFunc = 1; //triggers osNpcSit + llSensor(RAMsit, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +StateTouch() { + DEBUG ("state touch - looking for " + RAMtouch); + STATE = Touch; + SensorFunc = 2; //triggers osNpcTouch + llSensor(RAMtouch, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +DoStand() { + DEBUG("state stand"); + osNpcStand(NPCKey()); +} + + +StateAnimate() { + + DEBUG("state animate"); + STATE = Animate; + NPCAnimate(RAManimationName); + if (RAManimationTime <=0 ) // V 3.4 tweak + RAManimationTime = 1; + TimerEvent(RAManimationTime); +} + +StateWalk() { + + DEBUG("NPCWalkOption = " + (string) NPCWalkOption); + STATE = Walking; + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(WALK); + } else if (walkstate == 2) { + llShout(FLIGHT,"flying"); + NPCAnimate(FLY); + } else if (walkstate == 3) { + NPCAnimate(RUN); + } else if (walkstate == 4) { + NPCAnimate(LAND); + } + newDest = vDestPos ; + newDest.z += OffsetZ; + + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + newDest += llGetPos(); + } + + DEBUG("Moveto:" + (string) newDest); + osNpcMoveToTarget(NPCKey(), newDest, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + + +StateWander(){ + DEBUG("state wander"); + STATE = Wander; + + vector point = CirclePoint(RAMwd); + DEBUG("CirclePoint:" + (string) point); + vWanderPos = vDestPos + point; + DEBUG("vWanderPos:" + (string) vWanderPos); + + fTimerVal = WANDERTIME; // default time to pause after each wander + if (WANDERRAND) + fTimerVal = llFrand(WANDERTIME) + 1; // override, they want random times + + NPCAnimate(WALK); + + DEBUG("Wander to:" + (string) vWanderPos); + + osNpcMoveToTarget(NPCKey(), vWanderPos, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + +StateWanderhold() { + + DEBUG("Wander Hold"); + STATE = WanderHold; + + // now that we have reached a wander spot, slow the timer down to the desired value + TimerEvent(fTimerVal); +} + +// @pause=10 will do nothing for 10 seconds +DoPause() { + STATE =Paused; + if (RAMPause < 0.1) + RAMPause = 0.1; + DEBUG("@pause=" + (string)RAMPause); + TimerEvent(RAMPause); +} + + +// @stop makes the NPC stop moving in whatever state it is in. You have to linkmessage to get moving again +DoStop() { + DEBUG("NPC is Stopped"); + STATE = 0; // accept commands + SetStop(TRUE); // Link controlled - we mnust have a @go to continue with notecards + TimerEvent(0); + Stack = []; // v3.8 +} + +// @delete removes the NPC forever. Next command starts it up again at the beginning +DoDelete() { + DEBUG("state delete"); + STATE = 0; // accept commands + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + + TimerEvent(0); + Stack = []; // v3.8 +} + +// change the appearance of the NPC +DoAppearance(string notecard) { + DEBUG("state appearance"); + if (llGetInventoryType(notecard) == INVENTORY_NOTECARD){ + DEBUG("Load appearance " + notecard); + osNpcLoadAppearance(NPCKey(),notecard); + } +} + +// Change the avatar speed +DoSpeed(string speed) { + float newspeed = (float) speed; + if (newspeed > 0.1 && newspeed < 5.0) {// sanity check + osSetSpeed(NPCKey(),newspeed); + } +} +DoNewNote (string card) { + DEBUG("Load Notecard " + card); + NPCReadNoteCard(card); + SetStop(FALSE); +} +DoAttach(string params) { + + list Data = llParseString2List(params, ["|"], []); + string itemName = llList2String(Data, 0); + integer attachmentPoint = (integer) llList2String(Data, 1); + if (attachmentPoint > 0 + && attachmentPoint < 40 + && llGetInventoryType(itemName) == INVENTORY_OBJECT + ) + { + osForceAttachToOtherAvatarFromInventory(NPCKey(),itemName,attachmentPoint); + } +} + +// This loops over the notecard, processing each command +DoProcessNPCLine() { + DEBUG("ProcessNPCLine, stopped = " + (string) Stopped); + STATE = DoProcess; + + // auto load a notecard + if (! llGetListLength(lNpcCommandList)) { + DEBUG("Read Notecard"); + NPCReadNoteCard(Notecard); + SetStop(FALSE); + } + + // look for link messages on the stack + string next = llList2String(Stack,0); // lets see if there is anithing from a link message + if (llStringLength(next)) + { + Stack = llDeleteSubList(Stack,0,0); + ProcessCmd(next); //lets do this command instead. + return; + } + + // @stop issued? + if (Stopped) { + TimerEvent(0); + DEBUG("Stopped, waiting for input"); + STATE = 0; + return; + } + + // No, we have an @go for liftoff + next = llList2String(lNpcCommandList, 0); // get the next command + DEBUG("Execute:" + next); + lNpcCommandList = llDeleteSubList(lNpcCommandList, 0, 0); // delete it + + if (llGetListLength(lNpcCommandList) == 0) { + DEBUG("EOF"); + } + ProcessCmd(next); +} + + + +ProcessCmd(string cmd) { + + DEBUG("ProcessCmd:" + cmd); + + if (llGetSubString(cmd, 0, 0) != "@") { + DEBUG("ignoring"); + TimerEvent(QUICK); // this is so we do not recurse the stack + STATE = 0; + return; + } + + list data = llParseString2List(cmd, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data, 0), STRING_TRIM)); + + DEBUG("Action:" + npcAction); + npcParams = llStringTrim(llList2String(data, 1), STRING_TRIM); + DEBUG("Params:" + npcParams); + + @commands; + + ProcessSensor(); + + if(npcAction == "@spawn" && avatarPresent) { + DEBUG("@spawn"); + list spawnData = llParseString2List(npcParams, ["|"], []); + sNPCName =llList2String(spawnData, 0); // V 1.6 name in RAM + + list spawnDest = llParseString2List(llList2String(spawnData, 1), ["<", ",", ">"], []); + vInitialPos.x = llList2Float(spawnDest, 0); + vInitialPos.y = llList2Float(spawnDest, 1); + vInitialPos.z = llList2Float(spawnDest, 2); + + DEBUG("Coords for NPC at " + (string) vInitialPos); + StateSpawn(); + return; + } + + if (! avatarPresent){ + DoNobodyHome(); + DEBUG("No avatar nearby"); + STATE = 0; + return; + } else { + if ( NPCKey() == NULL_KEY) { + StateSpawn(); + } + } + + + + + if(npcAction == "@stop") { + DoStop(); + STATE = 0; + return; + } + else if(npcAction == "@goto") { + DEBUG("goto"); + integer lastIdx = llGetListLength(lNpcCommandList)-1; + lNpcCommandList = llDeleteSubList(lNpcCommandList, lastIdx, lastIdx); + // Wind commands till goto label. + @wind; + string next1 = llList2String(lNpcCommandList, 0); + lNpcCommandList = llDeleteSubList(lNpcCommandList, 0, 0); + lNpcCommandList += next1; + if(next1 != npcParams) jump wind; + // Wind the label too. + next1 = llList2String(lNpcCommandList, 0); + lNpcCommandList = llDeleteSubList(lNpcCommandList, 0, 0); + lNpcCommandList += next1; + // Get next command. + list data1 = llParseString2List(next1, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data1, 0), STRING_TRIM)); + npcParams = llStringTrim(llList2String(data1, 1), STRING_TRIM); + // Reschedule. + jump commands; + } + else if(npcAction == "@sound") { + DEBUG("sound"); + llTriggerSound(npcParams,1.0); + } + else if(npcAction == "@randsound") { + DEBUG("@randsound"); + integer N = llGetInventoryNumber(INVENTORY_SOUND); + integer rand = llCeil(llFrand(N)) -1; // pick a random sound + string toPlay = llGetInventoryName(INVENTORY_SOUND,rand); + llTriggerSound(toPlay,1.0); + } + else if(npcAction == "@walk") { + DEBUG("@walk"); + GetDest(npcParams); + walkstate = 1;// walking + NPCWalkOption = OS_NPC_NO_FLY ; + StateWalk(); + return; + } + else if(npcAction == "@fly") { + GetDest(npcParams); + walkstate = 2;// flying + NPCWalkOption = OS_NPC_FLY ; + StateWalk(); + return; + } + else if(npcAction == "@run") { + DEBUG("@run"); + GetDest(npcParams); + walkstate = 3;// running + NPCWalkOption = OS_NPC_NO_FLY | OS_NPC_RUNNING; + StateWalk(); + return; + } + else if(npcAction == "@land") { + DEBUG("@land"); + GetDest(npcParams); + walkstate = 4;// landing + NPCWalkOption= OS_NPC_FLY | OS_NPC_LAND_AT_TARGET ; + StateWalk(); + return; + } + else if(npcAction == "@say") { + DEBUG("@say " + npcParams); + osNpcSay(NPCKey(), 0, npcParams); + } + else if(npcAction == "@shout") { + DEBUG("@shout"); + osNpcShout(NPCKey(),0, npcParams); + } + else if(npcAction == "@whisper") { + DEBUG("@whisper " + npcParams); + osNpcWhisper(NPCKey(),0, npcParams); + } + // speak a command on a channel, so you can open doors and control stuff. + else if(npcAction == "@cmd") { + DEBUG("@cmd"); + list dataToSpeak = llParseString2List(npcParams, ["|"], []); + string channel = llList2String(dataToSpeak,0); + DEBUG("Channel:"+(string) channel); + integer iChannel = (integer) channel; + string stringToSpeak = llList2String(dataToSpeak,1); + llSay(iChannel, stringToSpeak); + } + // stop everything + else if(npcAction == "@pause") { + RAMPause = (float) npcParams; + DoPause(); + return; + } + else if(npcAction == "@wander") { + list wanderData = llParseString2List(npcParams, ["|"], []); + RAMwd = (float) llList2String(wanderData, 0); + RAMwc = (integer) llList2String(wanderData, 1); + vDestPos = osNpcGetPos(NPCKey()); // set the wander start + DEBUG("Starting at " + (string) vDestPos); + StateWander(); + return; + } + else if(npcAction == "@rotate") { + RAMrot = (float) npcParams; + DoRotate(); + } + else if(npcAction == "@sit") { + RAMsit= npcParams; + StateSit(); + return; + } + else if(npcAction == "@touch") { + RAMtouch= npcParams; + StateTouch(); + return; + } + else if(npcAction == "@stand") { + DoStand(); + } + else if(npcAction == "@delete") { + DoDelete(); + SetStop(TRUE); // Link controlled - we mnust have a @go to continue with notecards + return; + } + else if(npcAction == "@animate") { + list animateData = llParseString2List(npcParams, ["|"], []); + RAManimationName = llList2String(animateData, 0); + RAManimationTime = (float) llList2String(animateData, 1); + StateAnimate(); + return; + } + else if(npcAction == "@appearance" ){ + DoAppearance(npcParams); + } + else if (npcAction =="@speed") { + DoSpeed(npcParams); + } + else if (npcAction =="@notecard") { + DoNewNote(npcParams); + Notecard = npcParams; + } + else if (npcAction == "@attach") + { + DoAttach(npcParams); + } + + STATE = 0; + TimerEvent(QUICK); // yeah I know, not possible this fast, we just go as fast as we can go - this is so we do not recurse the stack +} + + + +/////////////////// UTILITY Functions, not state-like ////////////////// + +// DEBUG(string) will chat a string or display it as hovertext if debug == TRUE +DEBUG(string str) { + if (debug && ! LSLEditor) + llOwnerSay( str); // Send the owner debug info + if (debug && LSLEditor) + llSay(0, str); // Send to the Console in LSLEDitor + if (iTitleText) { + llSetText(str,<1.0,1.0,1.0>,1.0); // show hovertext + + } +} + +GetDest(string npcParams) { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); +} + +NPCReadNoteCard(string Note) { + DEBUG("NPCReadNoteCard"); + lNpcCommandList = llParseString2List(osGetNotecard(Note), ["\n"], []); +} + +integer SenseAvatar() +{ + //Returns a strided list of the UUID, position, and name of each avatar in the region + list avatars = llGetAgentList(AGENT_LIST_REGION ,[]); + integer numOfAvatars = llGetListLength(avatars); + if (numOfAvatars == 0) + { + DEBUG("No people"); + return 0; + } + //DEBUG("Located " + (string)numOfAvatars + " avatars and NPC's"); + + integer nAvatars; + integer i; + for( i = 0;i < numOfAvatars; i++) { + key aviKey = llList2Key(avatars,i); + if (!osIsNpc(aviKey)) { + list detail = llGetObjectDetails(aviKey,[OBJECT_POS]); + vector pos = llList2Vector(detail,0); + float dist = llVecDist(pos, llGetPos()); + if (dist < RANGE) + { + nAvatars++; + DEBUG("In range:" + llKey2Name(aviKey)); + } + } + } + //DEBUG("Located " + (string) nAvatars + " avatars"); + return nAvatars; +} + +// return TRUE if the avatar is owner when private is set, or TRUE if the avatar is in the same group and GROUP is set. +integer checkPerms() { + + integer group = (integer) KeyValueGet("pr"); + if (! group) + priPub = "Owner Only"; + else + priPub = "Group"; + + + if (llDetectedKey(0) == llGetOwner()){ + kUserKey = llDetectedKey(0); + return TRUE; + } + + if ( group && llDetectedGroup(0)) { + kUserKey = llDetectedKey(0); + return TRUE; + } + kUserKey = llDetectedKey(0); + return FALSE; +} + + + +NPCAnimate(string anim) +{ + DEBUG("Start Anim: " + anim); + if (llGetInventoryType(anim) == INVENTORY_ANIMATION ) { + + if (lastANIM != anim) { + if(llStringLength(lastANIM)) { + osNpcStopAnimation(NPCKey(), lastANIM); + } + osNpcPlayAnimation(NPCKey(), anim); + lastANIM = anim; + } + } else { + llSay(DEBUG_CHANNEL, "No animation named " + anim); + } +} + +// Kill a NPC by Name +Kill(string param) +{ + integer count; + list avatars = osGetAvatarList(); // Returns a strided list of the UUID, position, and name of each avatar in the region except the owner.\ + integer i; + integer j = llGetListLength(avatars); + for (i=0 ; i <= j; i+=3){ + + string desired = llList2String(avatars,i+2); + desired = llStringTrim(desired,STRING_TRIM); // should not be needed but is needed + + if (desired == param){ + vector v = llList2Vector(avatars,i+1); + key target = llList2Key(avatars,i); // get the UUID of the avatar + osNpcRemove(target); + SaveKey(NULL_KEY ); + llOwnerSay("Removed " + param+ " at location " + (string) v); + count++; + } + } + + NPCEnabled = FALSE; // not in world + + if (count) + llOwnerSay("Removed " + (string) count + " NPC's"); + else + llOwnerSay("Could not locate " + param); +} + + +// return a String for the position we are at. Strings used as the caller wants strings +string Pos() +{ + vector where = llGetPos(); // find the box position + + where.z += OffsetZ; // use the ground position + an offset + + if (LSLEditor) + where = <128,128,31 + llFrand(1)>; // force center of sim when editing + + // if attached the height will be too high by 1/2 the agent size + if (llGetAttached()) { + vector size = llGetAgentSize(llGetOwner()); + float Z = size.z; + where.z -= Z/2; + } + + // DEBUG("Pos= " + (string) where); + return (string) where; +} + +// setup a menu with a timer for timeouts, called by all make*() +menu() +{ + llListenRemove(iHandle); + iChannel = llCeil(llFrand(100000) + 20000); + iHandle = llListen(iChannel,"","",""); + TimerEvent(30.0); + MENU = TRUE; +} + +// make a text box +makeText(string Param) +{ + menu(); + llTextBox(kUserKey, Param, iChannel); +} + +// top level menu +makeMainMenu() +{ + menu(); + list buttons = ["Appearance","Recording","Save","Help","-","Erase RAM", priPub,relAbs,"-","Stop NPC",mSensor,"Start NPC"]; + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Records",buttons,iChannel); +} + + +// Rev 1.4 +// top level menu for non group/ non owners +makeUserMenu() +{ + if (!allowUsers) return; + + menu(); + list buttons = ["Start NPC","Stop NPC"]; + llDialog(kUserKey,"Choose",buttons,iChannel); +} + + + +// programmable menu for @commands +makeMenu(list buttons) +{ + menu(); + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Record",buttons,iChannel); +} + + +// make one or two text boxes with prompts +Text(string cmd, string p1, string p2) +{ + sCommand = cmd; + sParam2 = ""; + if (llStringLength(p2)) + sParam2 = p2; + + makeText(p1); +} + +// Set the Avatar Present flag - if sensors are off and we are forece run, there will be one present. +ProcessSensor() +{ + integer SensorOn; + if ("on" == KeyValueGet("se")) + { + SensorOn = TRUE; // we need to scan for avatars + } else { + SensorOn = FALSE; // we need to scan for avatars + } + DEBUG("Sensor:" + (string) SensorOn); + + integer n = SenseAvatar(); + + DEBUG("Avatars:" + (string) n); + if (SensorOn && n) + avatarPresent = TRUE; // someone is here and we need to tell the system to run + else if (SensorOn && !n) + avatarPresent = FALSE; // someone is not here and we need to tell the system to stop + else { // sensor is off, lete see if there is a NPC. If so, we are ON + DEBUG("NPCEnabled:" + (string) NPCEnabled); + if (NPCEnabled) + avatarPresent = TRUE; + else + avatarPresent = FALSE; + } + + // start up from when when no one is near + if (avatarPresent && STATE == NobodyHome) + STATE = 0; + + DEBUG("Avatar Present: " + (string) avatarPresent); +} + +vector CirclePoint(float radius) { + float x = llFrand(radius *2) - radius; // +/- radius, randomized + float y = llFrand(radius *2) - radius; // +/- radius, randomized + return ; // so this should always happen +} + +string KeyValueGet(string var) { + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k != var) jump continue; + //DEBUG("got " + var + " = " + llList2String(data, 1)); + return llList2String(data, 1); + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + return ""; +} + +KeyValueSet(string var, string val) { + + //DEBUG("set " + var + " = " + val); + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + if(llGetListLength(dVars) == 0) + { + llSetObjectDesc(var + "=" + val); + return; + } + list result = []; + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k == "") jump continue; + if(k == var && val == "") jump continue; + if(k == var) { + result += k + "=" + val; + val = ""; + jump continue; + } + string v = llList2String(data, 1); + if(v == "") jump continue; + result += k + "=" + v; + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + if(val != "") result += var + "=" + val; + llSetObjectDesc(llDumpList2String(result, "&")); +} + + +// clear RAM +Clr() { + + lCommands = []; + llOwnerSay("RAM Memory cleared. Notecards, if any, are not modified."); + makeMainMenu(); +} + +integer checkNoteCards() +{ + // Check that they have saved an Appeaance and Path notecard + integer num = llGetInventoryNumber(INVENTORY_NOTECARD); // how many notecards overall + + integer i; + integer count; + for (; i < num; i++){ + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Notecard) + count++; + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Appearance) + count++; + } + DEBUG("Checked " + (string) count + " Notecards"); + // if we have both, run the NPC + return count; +} + +Update(string SName) { + + // delete all NPC* scripts except myself + integer i; + integer j = llGetInventoryNumber(INVENTORY_SCRIPT); + for (i = 0; i < j; i++) { + string targetName = llGetInventoryName(INVENTORY_SCRIPT,i); + string match = llGetSubString(targetName,0,2); + + if (match == SName && llGetScriptName() != targetName){ + llOwnerSay("Upgrading " + targetName); + if (! LSLEditor){ // lets not kill the editor + llRemoveInventory(targetName); + } + } + } +} + +// Get all default saved params from the Description +GetSwitches() +{ + string rA = KeyValueGet("co"); // Get the remembered menu setting for Abs Vs Relative + if (rA == "A") + relAbs = "Absolute"; + else if (rA == "R") + relAbs = "Relative"; + else + relAbs = "Absolute"; + + + // reenable NPC if sensor is on. + if ("on" == KeyValueGet("se")) + { + NPCEnabled = TRUE; + mSensor = "Sense is On"; + ProcessSensor(); // fake 1 avatar to get it rezzed + } else { + mSensor = "Sense is Off"; + } + } + + +SaveKey(key akey) +{ + DEBUG("Saving Key of " + (string) akey); + KeyValueSet("key", akey); + if (akey != (key) KeyValueGet("key") ) + { + DEBUG("Fatal error, cannot save key"); + } + gNpcKey = akey; +} + + +key NPCKey() +{ + key akey = gNpcKey; // from cached copy + // gNpcKey saves a lot of CPU processing by caching the key, if blank we get it from the description + if (gNpcKey == NULL_KEY) + { + //DEBUG("Get DKey"); + akey = KeyValueGet("key"); // from Description of the prim + } + // DEBUG("NPC KEY:" + (string) akey); + return akey; +} + + +/////////////////// CODE BEGINS ////////////////// + + +default +{ + changed(integer change) { + if(change & CHANGED_REGION_START) { + llResetScript(); + } + } + + on_rez(integer start_param) + { + llResetScript(); + } + + state_entry() { + + llSetText("",<1,1,1>,1.0); // clr all hovertext- we may not be using it. + DoDelete(); // kill any NPC that is out running + Update("NPC"); // If dragged and ropped into a prim with any script named "NPC...", this will replace it. + GetSwitches(); // Get all default saved params from the Description + + // 4.1 allow listeners to send us commands + if (allowListener) + llListen(link_Channel,"","",""); + TimerEvent(TIMER); + } + + + touch_start(integer n) + { // if touched, make a menu + + if (checkPerms()) { + if (RecordPath == STATE) { + makeMenu(lAtButtons); + } else { + makeMainMenu(); + } + } else { + makeUserMenu(); + } + } + + // menu listener + listen(integer iChannel, string name, key id, string message) { + + // process @commands that come in via the listener + if (iChannel == link_Channel) + { + ParseMsg(message); + return; + } + + if (MENU) { + llListenRemove(iHandle); + MENU = 0; // menu is off + iHandle = 0; + } + + if (message == "Stop NPC") + { + lNpcCommandList = []; // force reload of notecard + NPCEnabled = FALSE; + if (NPCKey() != NULL_KEY){ + Kill(sNPCName); + sNPCName = ""; + } else { + bNPC_STOP = TRUE; + makeText("Enter name of an NPC to stop"); + } + } + else if (message == "Menu" ) { + makeMainMenu(); + } + else if (message == "Erase RAM"){ + Clr(); + } + else if (message == "Relative"){ + relAbs = "Absolute"; + KeyValueSet("co","A"); // remember coordinates = A + Clr(); + } + else if (message == "Absolute"){ + relAbs = "Relative"; + KeyValueSet("co","R"); // remember coordinates = R + Clr(); + } + else if (message == "Recording"){ + DoMenuForCommands(); // show them the recording menu + } + else if (message == "Owner Only") { + priPub = "Group"; + KeyValueSet("pr","1"); + + llOwnerSay("Group members have control"); + makeMainMenu(); + } + else if (message == "Group") { + priPub = "Owner Only"; + KeyValueSet("pr","0"); + llOwnerSay("Only you have control"); + makeMainMenu(); + } + else if (message == "Sense is On") { + mSensor ="Sense is Off"; + KeyValueSet("se", "off"); + llOwnerSay(mSensor); + makeMainMenu(); + } + else if (message == "Sense is Off") { + mSensor ="Sense is On"; + llOwnerSay(mSensor); + KeyValueSet("se", "on"); + + NPCEnabled = FALSE; + + integer count = checkNoteCards(); + if (count >= 2) { + DEBUG("Notecards ok, DoProcessNPCLine"); + DoProcessNPCLine(); + return; + } + if (LSLEditor) { + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording and/or appearance, so you cannot start a NPC"); + makeMainMenu(); + } + else if (message == "Appearance") { + llRemoveInventory(Appearance); // delete the notecard + osAgentSaveAppearance(kUserKey,Appearance); // make the ntecard + llOwnerSay("Your outfit has been saved"); + makeMainMenu(); + } + else if (message == "Save") { + if (llGetListLength(lCommands) == 0) { + llOwnerSay("Nothing recorded, you need to make a recording first"); + makeMainMenu(); + return; + } + DoSave(); + } + else if (message == "Help"){ + llLoadURL(kUserKey,"Click to view help","http://www.outworldz.com/opensim/posts/NPC/"); + makeMainMenu(); + } + else if (message == "Start NPC") { + integer count = checkNoteCards(); + + NPCEnabled = TRUE; + + if (LSLEditor) { + DoProcessNPCLine(); + return; + } + + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + SetStop(FALSE); // Let's run the notecard + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording or maybe an appearance, so we cannot start a NPC"); + + } + else if (bNPC_STOP){ + bNPC_STOP = FALSE; + Kill(message); + } + else if (message == ">>"){ + makeMenu(lMenu2); + } + else if (message == ">>>"){ + makeMenu(lMenu3); + } + else if (message == "<<") { + makeMenu(lAtButtons); + } + else if (message == "<<<") { + makeMenu(lMenu2); + } + else if (message == "@comment"){ + Text("# ","Enter a comment",""); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@run"){ + lCommands += "@run=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@fly"){ + lCommands += "@fly=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@land"){ + lCommands += "@land=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@walk") { + lCommands += "@walk=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@sound"){ + Text("@sound=","Enter a sound name or UUID to trigger",""); + } + else if (message == "@randsound"){ + lCommands += "@randsound"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@say") { + Text("@say=","Enter what the NPC will say",""); + } + else if (message == "@whisper"){ + Text("@whisper=","Enter what the NPC will whisper",""); + } + else if (message == "@shout"){ + Text("@shout=","Enter what the NPC will shout",""); + } + else if (message == "@wander") { + Text("@wander=","Enter radius to wander","Enter number of wanders"); + } + else if (message == "@pause") { + Text("@pause=","Enter time to pause",""); + } + else if (message == "@rotate") { + Text("@rotate=","Enter degrees to rotate",""); + } + else if (message == "@sit"){ + Text("@sit=","Enter name of object to sit on",""); + } + else if (message == "@touch"){ + Text("@touch=","Enter name of object to touch",""); + } + else if (message == "@cmd"){ + Text("@cmd=","Enter cjhannel to speak on","Enter text to speak"); + } + else if (message == "@stand"){ + lCommands += "@stand\n"; + llOwnerSay("Stand Recorded"); + makeMenu(lAtButtons); + } + else if (message == "@animate"){ + Text("@animate=","Enter animation name to play","Enter time to play the animation"); + } + else if (message == "@attach"){ + Text("@animate=","Enter inventory name to attach","Enter number of the attachment point (1-40)"); + } + else if (message == "@speed"){ + Text("@speed=","Enter a speed for the NPC, 1=100% normal speed, 0.5=50% speed",""); + } + + + // Save NPC name + else if (MakeNotecard == STATE) { + sNPCName = message; // in case we need to kill it. + + vector vDest = (vector) Pos(); + + if (relAbs == "Relative") + { + vDest -= llGetPos(); // just an offset for relative + } + sNotecard = "@spawn=" + message + "|" + (string) vDest + "\n"; + integer i; + integer j = llGetListLength(lCommands); + for (; i < j; i++){ + // get the command to save to the notecard + string line = llList2String(lCommands,i); + if (relAbs == "Absolute") { + sNotecard += line; // add the un-modified string to the notecard + } else { + // since we have to record absolute coords since we do not know where the box goes until they press Save, + // we process the absolute to relative conversion for walks here + list parts = llParseString2List(line,["="],[]); //get the @command + + if (llList2String(parts,0) == "@walk") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@walk=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@fly") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@fly=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@run") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@run=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@land") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@land=" + (string) vec + "\n"; + } + else { + sNotecard += line; // add the un-modified string to the notecard + } + } + } + llRemoveInventory(Notecard); // delete the old notecard + osMakeNotecard(Notecard,sNotecard); // Makes the notecard. + llSay(0,sNotecard); + llOwnerSay("Commands notecard has been written"); + STATE = 0; + } // MakeNotecard + + else if (! llStringLength(sParam2)) { + lCommands += sCommand + message + "\n"; + llOwnerSay("Recorded"); + makeMenu(lAtButtons); + } + else if (llStringLength(sParam2)){ + sCommand = sCommand + message + "|"; + llOwnerSay("Recorded"); + makeText(sParam2); + sParam2 = ""; + } + + } + + + + timer(){ + // DEBUG("tick"); + + // if llDialog is up, kill the listener for the dialog box. + if (iHandle) { + llOwnerSay("Menu timed out"); + llListenRemove(iHandle); + iHandle = 0; + return; // ^^^^^^^^^^^^^^^^^^^^^^^ + } + // if NoBodyHome, we are sensing for an avatar + else if (NobodyHome == STATE) { + ProcessSensor(); + return; + } + // if we are spawning, we need time to rez the NPC, then start processing NPC Commands. + else if (Spawning == STATE) { + STATE = 0; + TimerEvent(TIMER); + } + // We end aniamtions with a timer + else if (Animate == STATE){ + NPCAnimate(STAND); + TimerEvent(TIMER); + } + + else if (Walking == STATE) { + if (--iWaitCounter) { + if (llVecDist(osNpcGetPos(NPCKey()), newDest) > MAXDIST) { + return; + } + } + + DEBUG("At Destination: " + (string) newDest); + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 2) { + // nothing + } else if (walkstate == 3) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 4) { + llShout(FLIGHT,"landing"); + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } + } + // Wandering timer + else if (Wander == STATE) { + if (--iWaitCounter) { // wait 60 seconds to get to a destination. + if (llVecDist(osNpcGetPos(NPCKey()), vWanderPos) > MAXDIST) + return; + } + + // see if wander counter == 0, if so, stop walking, go to stand and process next line + if(RAMwc == 0) { + NPCAnimate(STAND); + DEBUG("Wander ended, calling DoProcessNPCLine"); + STATE = 0; + DoProcessNPCLine(); + return; + } + // one less time to wander around + RAMwc--; + NPCAnimate(STAND); + TimerEvent(TIMER); + StateWanderhold(); + return; + } + // Wandering requires us to re-wander when we reach a destination + else if (WanderHold == STATE) { + StateWander(); + TimerEvent(TIMER); + return; + } + else if (DoProcess == STATE) { + TimerEvent(QUICK); + } + + + STATE = 0; + + // We always process a NPC line at end of timer. + DEBUG("Tick end, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } + + // sensors are used for sitting on prims + // Neo Cortex: added different SensorFunc states to trigger sit or touch + sensor(integer num) { + if (SensorFunc == 1) { + osNpcSit(NPCKey(), llDetectedKey(0), OS_NPC_SIT_NOW); + DEBUG("Seated, calling DoProcessNPCLine"); + SensorFunc = 0; + } else if (SensorFunc == 2) { + osNpcTouch(NPCKey(), llDetectedKey(0), LINK_THIS); + DEBUG("Touched, calling DoProcessNPCLine"); + SensorFunc = 0; + } + DoProcessNPCLine(); + } + no_sensor(){ + DEBUG ("no target prim located, calling DoProcessNPCLine"); + SensorFunc = 0; + DoProcessNPCLine(); + } + + + link_message(integer sender, integer num, string str, key id){ + ParseMsg(str); + } + +} + + + + + + diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 4.2.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 4.2.lsl new file mode 100644 index 00000000..170f9589 --- /dev/null +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 4.2.lsl @@ -0,0 +1,1675 @@ +// :SHOW:1 +// :CATEGORY:NPC +// :NAME:All In One NPC Recorder and Player +// :AUTHOR:Ferd Frederix +// :KEYWORDS:NPC, Puppeteer +// :CREATED:2015-08-28 23:27:03 +// :EDITED:2015-09-24 13:25:15 +// :ID:27 +// :NUM:1828 +// :REV:4.2 +// :WORLD:OpenSim +// :DESCRIPTION: +// All in one NPC recorder player. +// Supports both absolute and relative paths and many new commands +// Add animations named "Fly, Walk, Stand and Run" +// Click Prim to use. +// Should be worn as a HUD to record. +// Put it on the ground and click Sensor or Start NPC when done. +// :CODE: +// This is Rev 4.2 09/24/2015 + +// Revision History +// Rev 1.1 10-2-2014 @Sit did not work. Minor tweaks to casting for lslEditor +// Rev 1.2 10-14-2014 @ sit had wrong type. +// Rev 1.3 relative movement fixed for @fly +// Rev 1.4 4-3-2014 allow anyone to use this, non owners and non group members can only start and stop. +// Rev 1.5 5-17-2014 set sensor to auto start on reboot of sim +// Rev 1.6 5-24-2014 move menu so you can get it by touching, removed many of the KeyValues to RAM for efficiency +// Rev 1.7 CHANGED_REGION_START, not CHANGED_REGION_START (Opensim difference) +// Rev 1.8 tuned up Kill NPC, added more flexible upgrader +// Rev 1.9 Better script injection by link message// Rev 2.0 Added osSetSpeed so you can speed up or slow down an NPC. +// Rev 2.1 No laggy sensor used exept to sit on stuff +// Rev 2.2 Various sensor fixes +// Rev 2.3 Sets No Sensor in menu, must be started by hand +// Rev 2.4 - reserved for patches to 2.3 if needed +// Rev 3.0 Refactor out into subs, not states to make command injection easier +// New command: @appearance=Notecardname so you can switch to a new notecard on the fly +// New command: @speed=1.0 which slows up ( < 1 ) or speeds up ( > 1) +// Rev 3.1 Commands are not interruptible by Link Message +// Rev 3.2 Sensor patches for consistency in removing the NPC +// Rev 3.3 Added Touch command by Neo.Cortex@hbase42/hopto/org:8002 +// Added Menu 3 for notecard and appearance commands +// Rev 3.4 animation timer cannot be zero or it shuts off timer tweaked +// solves the NPC starting up when no sensor is set. +// Rev 3.5 fixes saving to !Path notecard +// Rev 3.6 08-11-2015 @delete acts like @stop. TYjhe NPC now rezzes after an @go back in where it was deleted +// Rev 3.7 08-11-2015 @attach command added to load an attachment from the inventory to the NPC +// Rev 3.8 08-17-2015 process queued commands one at a time without calling ProcessNPCLine on link message +// Rev 3.9 08-23-2011 Queued command fixes including @delete which were not always working +// Rev 4.0 09-15-2015 Fixes for Sensor functions which continually rezzed a NPC when no one was around. +// Rev 4.1 09-20-2015 Added a Listener so link messages are not needed +// Rev 4.2 09-23-2015 Added @teleport= +//*******************************************************************// + +// Instructions on how to use this are at http://www.outworldz.com/opensim/posts/NPC/ +// This is an OpenSim-only script. +// Author: Ferd Frederix aka Fred Beckhusen - fred@mitsi.com + +//////////////////////////////////////////////////////////////////////////////////////////// +// Original code was Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // +/////////////////////////////////////////////////////////////////////////////////////////// +// Please see: http://www.gnu.org/licenses/gpl.html for legal details, // +// rights of fair usage, the disclaimer and warranty conditions. // +/////////////////////////////////////////////////////////////////////////////////////////// +// The original NPC controller was from http://was.fm/opensim:npc +// Extensive additions and bug fixes by Fred Beckhusen, aka Ferd Frederix +// llSensor had two params swapped +// @Wander would wander where it had rezzed, not where it was. +// There was no 'no_sensor' event in sit, so if a @sit failed, the NPC got stuck +// The animation and walks always stopped old, then started new. It should be start new, then stop old so the default stand would be suppressed. +// New code: +// Merged with new Route recorder and notecard writer +// If the NPC failed to reach a destination it never moved on. +// Added WAIT global to tune this +// Exposed many tunable variables and ported the code +// Added floating point to times in notecard. + +// Added @sound, @randsound, @whisper, @shout, and @cmd controls. +// +// notecards integers are not floats for better control +// +// Link Messages may be used to perform external control by injecting @commands into the stream of actions +// Example: +// To chat something, such as with a chat robot +// llMessageLinked(LINK_SET,0,"@npc_say=Hello",""); + +// This script assumes that NPCs and OSSl scripting is enabled in the OpenSim configuration. +// In order to enable them, the following changes must be made in the OpenSim.ini configuration file: +// +// ; Turn on OSSL +// AllowOSFunctions = true +// OSFunctionThreatLevel = Severe + +//[NPC] +// ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} +// Enabled = true +// +// and then the server has to be restarted. + + +// Commands: All commands begin with an @ sign. All other lines are ignored +// @commands may have optional parameters. The syntax is always: +// @cmd=parm1|parm2 +// NaN in the table below meand Not a Number. This means there is no parameter + +//Command First Parameter Second Parameter Description +//@spawn name location (vector) Rezzes an NPC with name at a location. +//@appearance NoteCardName NaN switch the NPC appearance to a new notecard +//@walk destination (vector) NaN Makes the NPC walk to destination. +//@fly destination (vector) NaN Makes the NPC fly to destination. +//@land destination (vector) NaN Makes the NPC land at destination. +//@say string NaN Makes the NPC speak a phrase. +//@whisper string NaN Makes the NPC whisper a phrase. +//@shout string NaN Makes the NPC shout a phrase. +//@pause seconds (float) NaN Makes the NPC wait for a multiple of seconds. +//@wander radius (float) cycles (integer) Makes the NPC wander in radius, for cycles seconds. +//@delete NaN NaN Removes the NPC. Requires a link message to continue +//@goto label (string) NaN Jump to the label label in the script. +//@animate animation (string) time (float) Makes the NPC trigger the animation animation for time seconds. +//@sound sound_name NaN plays a sound from inventory +//@randsound NaN NaN Plays a random sound from inventory +//@rotate degrees (float) NaN Rotate the NPC degrees around the Z axis. +//@sit primitive name NaN Sit on a primitive with a given name. +//@touch primitive name NaN Touch on a primitive with a given name. +//@stand NaN NaN If sitting on a primitive, stand up. +//@cmd channel (integer) string Says string on channel, for controlling external gadgets +//@stop NaN NaN Halts the NPC script indefinitely. Can be started with a link message +//@go NaN NaN Continues on next notecard line, for use in link messages +//@speed speed (float) NaN from 0 to N, where 1.0 ius a normal speed of an avatar. 0.2 is a turtle. +//@notecard notename (string) NaN load a new Path notecard +//@attach InventoryName attachmentPoint load an attachment from the inventory to the NPC onto point +//@teleport destination (vector) NaN Makes the NPC teleport to destination in the same sim. They cannot tp to another sim or across the HG + + +// Constant attachmentPoint Comment +// ATTACH_CHEST 1 chest/sternum +// ATTACH_HEAD 2 head +// ATTACH_LSHOULDER 3 left shoulder +// ATTACH_RSHOULDER 4 right shoulder +// ATTACH_LHAND 5 left hand +// ATTACH_RHAND 6 right hand +// ATTACH_LFOOT 7 left foot +// ATTACH_RFOOT 8 right foot +// ATTACH_BACK 9 back +// ATTACH_PELVIS 10 pelvis +// ATTACH_MOUTH 11 mouth +// ATTACH_CHIN 12 chin +// ATTACH_LEAR 13 left ear +// ATTACH_REAR 14 right ear +// ATTACH_LEYE 15 left eye +// ATTACH_REYE 16 right eye +// ATTACH_NOSE 17 nose +// ATTACH_RUARM 18 right upper arm +// ATTACH_RLARM 19 right lower arm +// ATTACH_LUARM 20 left upper arm +// ATTACH_LLARM 21 left lower arm +// ATTACH_RHIP 22 right hip +// ATTACH_RULEG 23 right upper leg +// ATTACH_RLLEG 24 right lower leg +// ATTACH_LHIP 25 left hip +// ATTACH_LULEG 26 left upper leg +// ATTACH_LLLEG 27 left lower leg +// ATTACH_BELLY 28 belly/stomach/tummy +// ATTACH_LEFT_PEC 29 left pectoral +// ATTACH_RIGHT_PEC 30 right pectoral +// ATTACH_HUD_CENTER_2 31 HUD Center 2 +// ATTACH_HUD_TOP_RIGHT 32 HUD Top Right +// ATTACH_HUD_TOP_CENTER 33 HUD Top +// ATTACH_HUD_TOP_LEFT 34 HUD Top Left +// ATTACH_HUD_CENTER_1 35 HUD Center +// ATTACH_HUD_BOTTOM_LEFT 36 HUD Bottom Left +// ATTACH_HUD_BOTTOM 37 HUD Bottom +// ATTACH_HUD_BOTTOM_RIGHT 38 HUD Bottom Right +// ATTACH_NECK 39 neck +// ATTACH_AVATAR_CENTER 40 avatar center/root + + + +////////////////////////////////////////////////////////// +// DEBUG // +////////////////////////////////////////////////////////// +integer debug = TRUE; // set to TRUE or FALSE for debug chat on various actions +integer LSLEditor = TRUE; // set to to TRUE to working in LSLEditor, FALSE for in-world. + // you must also include the NPC commands found in the other script since LSLEditor does not support OpenSim +integer iTitleText = FALSE; // set to TRUE to see debug info in text above the controller + +////////////////////////////////////////////////////////// +// TUNABLE CONFIGURATION // +////////////////////////////////////////////////////////// +integer allowListener = TRUE; // set to TRUE to anable a command listener. Usually, this is setto FALSE +integer link_Channel = 4223; // some random number you want to talk to this gadget on. Best if large and negative +float TIMER = 2; // faster = less jerky stopping. How often the system checks the distance traveled. Fastest you can go is 0.5 seconds +float QUICK = 1; // when we need to move to the next state, we use a QUICK timer +string Appearance = "!Appearance"; // The name of the recorded Appearance notecard +string Notecard = "!Path"; // The name of the recorded routes +integer allowUsers = FALSE; // If true, any user can get a Start NPC and Stop NPC menu. Only groups and owners can get all commands if TRUE, or FALSE +float MAXDIST = 2.0; // how close a NPC has to get to a dest pos to continue to next state. Do not lower this too much, as it may miss the target +integer WANDERRAND = TRUE; // set to TRUE and they will pause during wanders a random number of seconds +float WANDERTIME = 3.0; // how long they stand after each @wander,if WANDERRAND is FALSE. If WANDERRAND is TRUE, this is the max time +integer WAIT = 30; // wait for this number of seconds for the NPC to reach a destination (for safety). If it fails to reach a target, it will move on after this time. +float RANGE = 50; // 1 to N meters - anyone this close to the controller will start NPCS if Sensor button is clicked +float REZTIME = 2.0; // wait this long for NPC to rez in, then start the process +string STAND = "Stand"; // the name of the default Stand animation +string WALK = "Walk"; // the name of the default Walk animation +string FLY = "Fly"; // the name of the default Fly animation +string RUN = "Run"; // the name of the default Run animation +string LAND = "Land"; // the name of the default land animation ( for birds only) +float OffsetZ = 0.5; // appear 0.5 meter above ground, this is added to all destinations to keep them from sinking in. +float SPEEDMULT =0.5; // 1.0 = regular avatar speed. Smaller numbers slow down walks. Large numbers speed them up. +integer FLIGHT = 299; // For controlling wings. A channel that is shouted at when flight starts and ends. "flying" or "landing" + +// DESCRIPTIONS FIELDS HAVE TO SURVIVE A RESET +// These vars are stored by saving them with KeyValueSet +// "pr" is a 0 if it is set for Owner Only, 1 for Group control +// "se" is "on" if Started +// "co" = "R" or "A" for relative or absolute addressing mode +// "key" = NPC key + +// These Globals used to be stored in description. Moved to RAM in V1.6 +float RAMPause; // @pause param +float RAMwd ; // @wander distance +integer RAMwc; // @wander count +float RAMrot; // @rotate +string RAMsit; // @sit primname +string RAMtouch; // @touch primname +string RAManimationName; // @animate animation (string) time (float) +float RAManimationTime; + +// other globals section +integer iChannel; // a listen channel, randomly assigned +integer iHandle; // the handle to it + +// NPC controls +vector newDest ; // tmp storage for the walks +integer iWaitCounter ; // wait for this number of seconds for the NPC to reach a desrtination +string sNPCName; // the name of the NPC that may be in world. So we can remove it. +integer bNPC_STOP = FALSE; // boolean to reuse a listener +integer Stopped = FALSE; // set to TRUE by link messages so we do not remember them +float fTimerVal ; // how long we wait when wandering (calculated) +float NPCEnabled; // true if the NPC is suppodes to be running + +// OS_NPC_CREATOR_OWNED will create an 'owned' NPC that will only respond to osNpc* commands issued from scripts that have the same owner as the one that created the NPC. +// OS_NPC_NOT_OWNED will create an 'unowned' NPC that will respond to any script that has OSSL permissions to call osNpc* commands. +integer NPCOptions = OS_NPC_CREATOR_OWNED; // only yhe owner of this box can control this NPC. + +integer walkstate = 0; // helps us reshare the walk state for run, fly and land - a bit of a hack, but it saves RAM. Has to be done this way because some bits of NPCWalkOption are asserted as 0 + +integer NPCWalkOption; // Some notes for what happens to NPCWalkOption: +// OS_NPC_FLY - Fly the avatar to the given position. The avatar will not land unless the OS_NPC_LAND_AT_TARGET option is also given. +// OS_NPC_NO_FLY - Do not fly to the target. The NPC will attempt to walk to the location. If it's up in the air then the avatar will keep bouncing hopeless until another move target is given or the move is stopped +//OS_NPC_LAND_AT_TARGET - If given and the avatar is flying, then it will land when it reaches the target. If OS_NPC_NO_FLY is given then this option has no effect. +// OS_NPC_RUNNING - if given, NPC avatar moves at running/fast flying speed, otherwise moves at walking/slow flying speed. + +// menus +string mSensor="Sense is Off"; // Sensor or "No Sensor" + +list lAtButtons = ["Menu","-", ">>", "@run", "@walk", "@fly", "@land", "@wander", "@sit", "@stand","@animate","@rotate"]; +list lMenu2 = ["<<", "@comment", ">>>", "@stop", "@say", "@whisper","@shout","@sound","@randsound","@cmd", "@pause", "@delete"]; +list lMenu3 = ["<<<","@notecard","@appearance", "@touch", "@speed", "@attach", "@teleport","-", "-", "-", "-", "-" ]; + +string sCommand; // place to store a command for two-prompted ones +string sParam2; // place to store a prompt for two-prompted ones +string priPub = "Owner Only"; // Private or Group +key kUserKey; // the person who is controlling the avatar, not the Owner +// the command lists +list lCommands; // commands are stored here +list lNpcCommandList; // Storage for the NPC script. +string npcAction; // Storage for the next action. @cmd=0|hello, this becomes @cmd +string npcParams; // Storage for the param, @cmd=0|hello, this becomes 0|hello + +// misc vars +string sNotecard; // commands are stored here temporarily for dumping +vector vWanderPos; // a place to wander to +string lastANIM ; // last animation run +// Sensor +integer avatarPresent; // Sensor sets this flag when people are within Range. + +// Coordinate control +vector vInitialPos ; // Vector that will be filled by the script with the initial starting position in region coordinates. +vector vDestPos = ZERO_VECTOR; // Storage for destination position. +string relAbs = "Relative"; // absolute vs relative positioning + + +// STATES +integer MENU ; // processing a dialog box state, may be concurrent with STATE +integer STATE; // state storage +integer MakeNotecard = 1; // displaying a text box for NPC name +integer RecordPath = 2; // displaying a path notecard menu +integer NobodyHome = 3; // looking for an avatar +integer Spawning = 4; // spawning an avatar +integer Animate = 5; // animation timer needed +integer Walking = 6; // Hey! I am walking here! +integer Wander = 7; // Wandering around neeeds a timer, too +integer WanderHold = 8; // We reached a wander point +integer DoProcess = 9; // Set this to make it process a new command +integer Touch = 10; // Timer is busy sensing something to touch +integer Sit = 11; // Timer is busy sensing something to sit on +integer Paused = 12; // Timer is busy pausing + +key gNpcKey = NULL_KEY; // global key storage for the one NPC, to save CPU cycles +list Stack ; // a command stack from link message input + +integer SensorFunc = 0; // define which function shall be triggered inside the sensor function + // 0 means none, 1 sit, 2 touch +/////////////////////////////////////////////////////////////////////////// +// FUNCTIONS // +/////////////////////////////////////////////////////////////////////////// + + +TimerEvent(float timesent) +{ + if (LSLEditor) + timesent *= 5; // slow thinggs doen when the LSLEDITOR is in use + + DEBUG("Setting timer: " + (string) timesent); + llSetTimerEvent(timesent); +} + +// for 4.1 parse a message from a Listen or a Link message +ParseMsg(string str) { + DEBUG("Command In:" + str); + if (str=="@go") { + SetStop(FALSE); // Let's run the notecard + DEBUG("@go running"); + DoProcessNPCLine(); + } else { + Stack += [str]; // take anything, the controller will filter away non @ stuff + if (STATE == 0) { + DEBUG("calling DoNPC"); + DoProcessNPCLine(); + } else{ + DEBUG("Queued"); + } + } +} + +SetStop(integer what) +{ + DEBUG("Stopped set to " + (string ) what); + Stopped = what; +} +// Do* functions are much like states from the old V2 scripts. + +// Save a Path notecard +DoSave() +{ + STATE = MakeNotecard; + makeText("Stand where you want the NPC to appear, and enter the NPC Name"); +} + +// This function is used to record the path for the NPC +// Each command can take 0, 1, or 2 params +DoMenuForCommands() { + makeMenu(lAtButtons); +} + + +// No one is here when sensors were on, so we kill off the NPC +DoNobodyHome() +{ + DEBUG("Nobody Home"); + STATE = NobodyHome; + if (NPCKey() != NULL_KEY) { + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + } + TimerEvent(5); // keep ticking to sense avatars +} + +// Create a NPC +StateSpawn() { + DEBUG("state spawn"); + STATE = Spawning; + + + NPCEnabled = TRUE; // in world + // see if there is already one out there. + if (NPCKey() != NULL_KEY) { + DEBUG("Already living"); + return; + } + + + list name = llParseString2List(sNPCName, [" "], []); + + vector vRezPos = vInitialPos; + if (relAbs == "Relative"){ + vRezPos += llGetPos(); + } + + DEBUG("Rezzing the NPC:" + (string) vRezPos); + key aKey = osNpcCreate(llList2String(name, 0), llList2String(name, 1), vRezPos, Appearance, NPCOptions); + + SaveKey(aKey); // save in desceription and global, too + + osSetSpeed(aKey,SPEEDMULT); // 1.9 speed multiplier + TimerEvent(REZTIME); + NPCAnimate(STAND); +} + +DoRotate() { + DEBUG("@rotate=" + (string) RAMrot); + osNpcSetRot(NPCKey(), llEuler2Rot(<0,0,RAMrot> * DEG_TO_RAD)); +} + +StateSit() { + DEBUG ("state sit - looking for " + RAMsit); + STATE=Sit; + SensorFunc = 1; //triggers osNpcSit + llSensor(RAMsit, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +StateTouch() { + DEBUG ("state touch - looking for " + RAMtouch); + STATE = Touch; + SensorFunc = 2; //triggers osNpcTouch + llSensor(RAMtouch, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +DoStand() { + DEBUG("state stand"); + osNpcStand(NPCKey()); +} + + +StateAnimate() { + + DEBUG("state animate"); + STATE = Animate; + NPCAnimate(RAManimationName); + if (RAManimationTime <=0 ) // V 3.4 tweak + RAManimationTime = 1; + TimerEvent(RAManimationTime); +} + +StateWalk() { + + DEBUG("NPCWalkOption = " + (string) NPCWalkOption); + STATE = Walking; + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(WALK); + } else if (walkstate == 2) { + llShout(FLIGHT,"flying"); + NPCAnimate(FLY); + } else if (walkstate == 3) { + NPCAnimate(RUN); + } else if (walkstate == 4) { + NPCAnimate(LAND); + } + newDest = vDestPos ; + newDest.z += OffsetZ; + + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + newDest += llGetPos(); + } + + DEBUG("Moveto:" + (string) newDest); + osNpcMoveToTarget(NPCKey(), newDest, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + + +StateWander(){ + DEBUG("state wander"); + STATE = Wander; + + vector point = CirclePoint(RAMwd); + DEBUG("CirclePoint:" + (string) point); + vWanderPos = vDestPos + point; + DEBUG("vWanderPos:" + (string) vWanderPos); + + fTimerVal = WANDERTIME; // default time to pause after each wander + if (WANDERRAND) + fTimerVal = llFrand(WANDERTIME) + 1; // override, they want random times + + NPCAnimate(WALK); + + DEBUG("Wander to:" + (string) vWanderPos); + + osNpcMoveToTarget(NPCKey(), vWanderPos, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + +StateWanderhold() { + + DEBUG("Wander Hold"); + STATE = WanderHold; + + // now that we have reached a wander spot, slow the timer down to the desired value + TimerEvent(fTimerVal); +} + +// @pause=10 will do nothing for 10 seconds +DoPause() { + STATE =Paused; + if (RAMPause < 0.1) + RAMPause = 0.1; + DEBUG("@pause=" + (string)RAMPause); + TimerEvent(RAMPause); +} + + +// @stop makes the NPC stop moving in whatever state it is in. You have to linkmessage to get moving again +DoStop() { + DEBUG("NPC is Stopped"); + STATE = 0; // accept commands + SetStop(TRUE); // Link controlled - we mnust have a @go to continue with notecards + TimerEvent(0); + Stack = []; // v3.8 +} + +// @delete removes the NPC forever. Next command starts it up again at the beginning +DoDelete() { + DEBUG("state delete"); + STATE = 0; // accept commands + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + + TimerEvent(0); + Stack = []; // v3.8 +} + +// change the appearance of the NPC +DoAppearance(string notecard) { + DEBUG("state appearance"); + if (llGetInventoryType(notecard) == INVENTORY_NOTECARD){ + DEBUG("Load appearance " + notecard); + osNpcLoadAppearance(NPCKey(),notecard); + } +} + +// Change the avatar speed +DoSpeed(string speed) { + float newspeed = (float) speed; + if (newspeed > 0.1 && newspeed < 5.0) {// sanity check + osSetSpeed(NPCKey(),newspeed); + } +} + +DoTeleport(string params) { + list Data = llParseString2List(params, ["|"], []); + string itemName = llList2String(Data, 0); + vector Dest = (vector) itemName; + if (Dest !=ZERO_VECTOR) { + osTeleportAgent( NPCKey(), llGetRegionName(), Dest, ZERO_VECTOR ); + } + +} + + + +DoNewNote (string card) { + DEBUG("Load Notecard " + card); + NPCReadNoteCard(card); + SetStop(FALSE); +} +DoAttach(string params) { + + list Data = llParseString2List(params, ["|"], []); + string itemName = llList2String(Data, 0); + integer attachmentPoint = (integer) llList2String(Data, 1); + if (attachmentPoint > 0 + && attachmentPoint < 40 + && llGetInventoryType(itemName) == INVENTORY_OBJECT + ) + { + osForceAttachToOtherAvatarFromInventory(NPCKey(),itemName,attachmentPoint); + } +} + +// This loops over the notecard, processing each command +DoProcessNPCLine() { + DEBUG("ProcessNPCLine, stopped = " + (string) Stopped); + STATE = DoProcess; + + // auto load a notecard + if (! llGetListLength(lNpcCommandList)) { + DEBUG("Read Notecard"); + NPCReadNoteCard(Notecard); + SetStop(FALSE); + } + + // look for link messages on the stack + string next = llList2String(Stack,0); // lets see if there is anithing from a link message + if (llStringLength(next)) + { + Stack = llDeleteSubList(Stack,0,0); + ProcessCmd(next); //lets do this command instead. + return; + } + + // @stop issued? + if (Stopped) { + TimerEvent(0); + DEBUG("Stopped, waiting for input"); + STATE = 0; + return; + } + + // No, we have an @go for liftoff + next = llList2String(lNpcCommandList, 0); // get the next command + DEBUG("Execute:" + next); + lNpcCommandList = llDeleteSubList(lNpcCommandList, 0, 0); // delete it + + if (llGetListLength(lNpcCommandList) == 0) { + DEBUG("EOF"); + } + ProcessCmd(next); +} + + + +ProcessCmd(string cmd) { + + DEBUG("ProcessCmd:" + cmd); + + if (llGetSubString(cmd, 0, 0) != "@") { + DEBUG("ignoring"); + TimerEvent(QUICK); // this is so we do not recurse the stack + STATE = 0; + return; + } + + list data = llParseString2List(cmd, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data, 0), STRING_TRIM)); + + DEBUG("Action:" + npcAction); + npcParams = llStringTrim(llList2String(data, 1), STRING_TRIM); + DEBUG("Params:" + npcParams); + + @commands; + + ProcessSensor(); + + if(npcAction == "@spawn" && avatarPresent) { + DEBUG("@spawn"); + list spawnData = llParseString2List(npcParams, ["|"], []); + sNPCName =llList2String(spawnData, 0); // V 1.6 name in RAM + + list spawnDest = llParseString2List(llList2String(spawnData, 1), ["<", ",", ">"], []); + vInitialPos.x = llList2Float(spawnDest, 0); + vInitialPos.y = llList2Float(spawnDest, 1); + vInitialPos.z = llList2Float(spawnDest, 2); + + DEBUG("Coords for NPC at " + (string) vInitialPos); + StateSpawn(); + return; + } + + if (! avatarPresent){ + DoNobodyHome(); + DEBUG("No avatar nearby"); + STATE = 0; + return; + } else { + if ( NPCKey() == NULL_KEY) { + StateSpawn(); + } + } + + + + + if(npcAction == "@stop") { + DoStop(); + STATE = 0; + return; + } + else if(npcAction == "@goto") { + DEBUG("goto"); + integer lastIdx = llGetListLength(lNpcCommandList)-1; + lNpcCommandList = llDeleteSubList(lNpcCommandList, lastIdx, lastIdx); + // Wind commands till goto label. + @wind; + string next1 = llList2String(lNpcCommandList, 0); + lNpcCommandList = llDeleteSubList(lNpcCommandList, 0, 0); + lNpcCommandList += next1; + if(next1 != npcParams) jump wind; + // Wind the label too. + next1 = llList2String(lNpcCommandList, 0); + lNpcCommandList = llDeleteSubList(lNpcCommandList, 0, 0); + lNpcCommandList += next1; + // Get next command. + list data1 = llParseString2List(next1, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data1, 0), STRING_TRIM)); + npcParams = llStringTrim(llList2String(data1, 1), STRING_TRIM); + // Reschedule. + jump commands; + } + else if(npcAction == "@sound") { + DEBUG("sound"); + llTriggerSound(npcParams,1.0); + } + else if(npcAction == "@randsound") { + DEBUG("@randsound"); + integer N = llGetInventoryNumber(INVENTORY_SOUND); + integer rand = llCeil(llFrand(N)) -1; // pick a random sound + string toPlay = llGetInventoryName(INVENTORY_SOUND,rand); + llTriggerSound(toPlay,1.0); + } + else if(npcAction == "@walk") { + DEBUG("@walk"); + GetDest(npcParams); + walkstate = 1;// walking + NPCWalkOption = OS_NPC_NO_FLY ; + StateWalk(); + return; + } + else if(npcAction == "@fly") { + GetDest(npcParams); + walkstate = 2;// flying + NPCWalkOption = OS_NPC_FLY ; + StateWalk(); + return; + } + else if(npcAction == "@run") { + DEBUG("@run"); + GetDest(npcParams); + walkstate = 3;// running + NPCWalkOption = OS_NPC_NO_FLY | OS_NPC_RUNNING; + StateWalk(); + return; + } + else if(npcAction == "@land") { + DEBUG("@land"); + GetDest(npcParams); + walkstate = 4;// landing + NPCWalkOption= OS_NPC_FLY | OS_NPC_LAND_AT_TARGET ; + StateWalk(); + return; + } + else if(npcAction == "@say") { + DEBUG("@say " + npcParams); + osNpcSay(NPCKey(), 0, npcParams); + } + else if(npcAction == "@shout") { + DEBUG("@shout"); + osNpcShout(NPCKey(),0, npcParams); + } + else if(npcAction == "@whisper") { + DEBUG("@whisper " + npcParams); + osNpcWhisper(NPCKey(),0, npcParams); + } + // speak a command on a channel, so you can open doors and control stuff. + else if(npcAction == "@cmd") { + DEBUG("@cmd"); + list dataToSpeak = llParseString2List(npcParams, ["|"], []); + string channel = llList2String(dataToSpeak,0); + DEBUG("Channel:"+(string) channel); + integer iChannel = (integer) channel; + string stringToSpeak = llList2String(dataToSpeak,1); + llSay(iChannel, stringToSpeak); + } + // stop everything + else if(npcAction == "@pause") { + RAMPause = (float) npcParams; + DoPause(); + return; + } + else if(npcAction == "@wander") { + list wanderData = llParseString2List(npcParams, ["|"], []); + RAMwd = (float) llList2String(wanderData, 0); + RAMwc = (integer) llList2String(wanderData, 1); + vDestPos = osNpcGetPos(NPCKey()); // set the wander start + DEBUG("Starting at " + (string) vDestPos); + StateWander(); + return; + } + else if(npcAction == "@rotate") { + RAMrot = (float) npcParams; + DoRotate(); + } + else if(npcAction == "@sit") { + RAMsit= npcParams; + StateSit(); + return; + } + else if(npcAction == "@touch") { + RAMtouch= npcParams; + StateTouch(); + return; + } + else if(npcAction == "@stand") { + DoStand(); + } + else if(npcAction == "@delete") { + DoDelete(); + SetStop(TRUE); // Link controlled - we mnust have a @go to continue with notecards + return; + } + else if(npcAction == "@animate") { + list animateData = llParseString2List(npcParams, ["|"], []); + RAManimationName = llList2String(animateData, 0); + RAManimationTime = (float) llList2String(animateData, 1); + StateAnimate(); + return; + } + else if(npcAction == "@appearance" ){ + DoAppearance(npcParams); + } + else if (npcAction =="@speed") { + DoSpeed(npcParams); + } + else if (npcAction =="@notecard") { + DoNewNote(npcParams); + Notecard = npcParams; + } + else if (npcAction == "@attach") + { + DoAttach(npcParams); + } + else if (npcAction == "@teleport") + { + DoTeleport(npcParams); + } + + STATE = 0; + TimerEvent(QUICK); // yeah I know, not possible this fast, we just go as fast as we can go - this is so we do not recurse the stack +} + + + +/////////////////// UTILITY Functions, not state-like ////////////////// + +// DEBUG(string) will chat a string or display it as hovertext if debug == TRUE +DEBUG(string str) { + if (debug && ! LSLEditor) + llOwnerSay( str); // Send the owner debug info + if (debug && LSLEditor) + llSay(0, str); // Send to the Console in LSLEDitor + if (iTitleText) { + llSetText(str,<1.0,1.0,1.0>,1.0); // show hovertext + + } +} + +GetDest(string npcParams) { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); +} + +NPCReadNoteCard(string Note) { + DEBUG("NPCReadNoteCard"); + lNpcCommandList = llParseString2List(osGetNotecard(Note), ["\n"], []); +} + +integer SenseAvatar() +{ + //Returns a strided list of the UUID, position, and name of each avatar in the region + list avatars = llGetAgentList(AGENT_LIST_REGION ,[]); + integer numOfAvatars = llGetListLength(avatars); + if (numOfAvatars == 0) + { + DEBUG("No people"); + return 0; + } + //DEBUG("Located " + (string)numOfAvatars + " avatars and NPC's"); + + integer nAvatars; + integer i; + for( i = 0;i < numOfAvatars; i++) { + key aviKey = llList2Key(avatars,i); + if (!osIsNpc(aviKey)) { + list detail = llGetObjectDetails(aviKey,[OBJECT_POS]); + vector pos = llList2Vector(detail,0); + float dist = llVecDist(pos, llGetPos()); + if (dist < RANGE) + { + nAvatars++; + DEBUG("In range:" + llKey2Name(aviKey)); + } + } + } + //DEBUG("Located " + (string) nAvatars + " avatars"); + return nAvatars; +} + +// return TRUE if the avatar is owner when private is set, or TRUE if the avatar is in the same group and GROUP is set. +integer checkPerms() { + + integer group = (integer) KeyValueGet("pr"); + if (! group) + priPub = "Owner Only"; + else + priPub = "Group"; + + + if (llDetectedKey(0) == llGetOwner()){ + kUserKey = llDetectedKey(0); + return TRUE; + } + + if ( group && llDetectedGroup(0)) { + kUserKey = llDetectedKey(0); + return TRUE; + } + kUserKey = llDetectedKey(0); + return FALSE; +} + + + +NPCAnimate(string anim) +{ + DEBUG("Start Anim: " + anim); + if (llGetInventoryType(anim) == INVENTORY_ANIMATION ) { + + if (lastANIM != anim) { + if(llStringLength(lastANIM)) { + osNpcStopAnimation(NPCKey(), lastANIM); + } + osNpcPlayAnimation(NPCKey(), anim); + lastANIM = anim; + } + } else { + llSay(DEBUG_CHANNEL, "No animation named " + anim); + } +} + +// Kill a NPC by Name +Kill(string param) +{ + integer count; + list avatars = osGetAvatarList(); // Returns a strided list of the UUID, position, and name of each avatar in the region except the owner.\ + integer i; + integer j = llGetListLength(avatars); + for (i=0 ; i <= j; i+=3){ + + string desired = llList2String(avatars,i+2); + desired = llStringTrim(desired,STRING_TRIM); // should not be needed but is needed + + if (desired == param){ + vector v = llList2Vector(avatars,i+1); + key target = llList2Key(avatars,i); // get the UUID of the avatar + osNpcRemove(target); + SaveKey(NULL_KEY ); + llOwnerSay("Removed " + param+ " at location " + (string) v); + count++; + } + } + + NPCEnabled = FALSE; // not in world + + if (count) + llOwnerSay("Removed " + (string) count + " NPC's"); + else + llOwnerSay("Could not locate " + param); +} + + +// return a String for the position we are at. Strings used as the caller wants strings +string Pos() +{ + vector where = llGetPos(); // find the box position + + where.z += OffsetZ; // use the ground position + an offset + + if (LSLEditor) + where = <128,128,31 + llFrand(1)>; // force center of sim when editing + + // if attached the height will be too high by 1/2 the agent size + if (llGetAttached()) { + vector size = llGetAgentSize(llGetOwner()); + float Z = size.z; + where.z -= Z/2; + } + + // DEBUG("Pos= " + (string) where); + return (string) where; +} + +// setup a menu with a timer for timeouts, called by all make*() +menu() +{ + llListenRemove(iHandle); + iChannel = llCeil(llFrand(100000) + 20000); + iHandle = llListen(iChannel,"","",""); + TimerEvent(30.0); + MENU = TRUE; +} + +// make a text box +makeText(string Param) +{ + menu(); + llTextBox(kUserKey, Param, iChannel); +} + +// top level menu +makeMainMenu() +{ + menu(); + list buttons = ["Appearance","Recording","Save","Help","-","Erase RAM", priPub,relAbs,"-","Stop NPC",mSensor,"Start NPC"]; + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Records",buttons,iChannel); +} + + +// Rev 1.4 +// top level menu for non group/ non owners +makeUserMenu() +{ + if (!allowUsers) return; + + menu(); + list buttons = ["Start NPC","Stop NPC"]; + llDialog(kUserKey,"Choose",buttons,iChannel); +} + + + +// programmable menu for @commands +makeMenu(list buttons) +{ + menu(); + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Record",buttons,iChannel); +} + + +// make one or two text boxes with prompts +Text(string cmd, string p1, string p2) +{ + sCommand = cmd; + sParam2 = ""; + if (llStringLength(p2)) + sParam2 = p2; + + makeText(p1); +} + +// Set the Avatar Present flag - if sensors are off and we are forece run, there will be one present. +ProcessSensor() +{ + integer SensorOn; + if ("on" == KeyValueGet("se")) + { + SensorOn = TRUE; // we need to scan for avatars + } else { + SensorOn = FALSE; // we need to scan for avatars + } + DEBUG("Sensor:" + (string) SensorOn); + + integer n = SenseAvatar(); + + DEBUG("Avatars:" + (string) n); + if (SensorOn && n) + avatarPresent = TRUE; // someone is here and we need to tell the system to run + else if (SensorOn && !n) + avatarPresent = FALSE; // someone is not here and we need to tell the system to stop + else { // sensor is off, lete see if there is a NPC. If so, we are ON + DEBUG("NPCEnabled:" + (string) NPCEnabled); + if (NPCEnabled) + avatarPresent = TRUE; + else + avatarPresent = FALSE; + } + + // start up from when when no one is near + if (avatarPresent && STATE == NobodyHome) + STATE = 0; + + DEBUG("Avatar Present: " + (string) avatarPresent); +} + +vector CirclePoint(float radius) { + float x = llFrand(radius *2) - radius; // +/- radius, randomized + float y = llFrand(radius *2) - radius; // +/- radius, randomized + return ; // so this should always happen +} + +string KeyValueGet(string var) { + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k != var) jump continue; + //DEBUG("got " + var + " = " + llList2String(data, 1)); + return llList2String(data, 1); + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + return ""; +} + +KeyValueSet(string var, string val) { + + //DEBUG("set " + var + " = " + val); + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + if(llGetListLength(dVars) == 0) + { + llSetObjectDesc(var + "=" + val); + return; + } + list result = []; + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k == "") jump continue; + if(k == var && val == "") jump continue; + if(k == var) { + result += k + "=" + val; + val = ""; + jump continue; + } + string v = llList2String(data, 1); + if(v == "") jump continue; + result += k + "=" + v; + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + if(val != "") result += var + "=" + val; + llSetObjectDesc(llDumpList2String(result, "&")); +} + + +// clear RAM +Clr() { + + lCommands = []; + llOwnerSay("RAM Memory cleared. Notecards, if any, are not modified."); + makeMainMenu(); +} + +integer checkNoteCards() +{ + // Check that they have saved an Appeaance and Path notecard + integer num = llGetInventoryNumber(INVENTORY_NOTECARD); // how many notecards overall + + integer i; + integer count; + for (; i < num; i++){ + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Notecard) + count++; + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Appearance) + count++; + } + DEBUG("Checked " + (string) count + " Notecards"); + // if we have both, run the NPC + return count; +} + +Update(string SName) { + + // delete all NPC* scripts except myself + integer i; + integer j = llGetInventoryNumber(INVENTORY_SCRIPT); + for (i = 0; i < j; i++) { + string targetName = llGetInventoryName(INVENTORY_SCRIPT,i); + string match = llGetSubString(targetName,0,2); + + if (match == SName && llGetScriptName() != targetName){ + llOwnerSay("Upgrading " + targetName); + if (! LSLEditor){ // lets not kill the editor + llRemoveInventory(targetName); + } + } + } +} + +// Get all default saved params from the Description +GetSwitches() +{ + string rA = KeyValueGet("co"); // Get the remembered menu setting for Abs Vs Relative + if (rA == "A") + relAbs = "Absolute"; + else if (rA == "R") + relAbs = "Relative"; + else + relAbs = "Absolute"; + + + // reenable NPC if sensor is on. + if ("on" == KeyValueGet("se")) + { + NPCEnabled = TRUE; + mSensor = "Sense is On"; + ProcessSensor(); // fake 1 avatar to get it rezzed + } else { + mSensor = "Sense is Off"; + } + } + + +SaveKey(key akey) +{ + DEBUG("Saving Key of " + (string) akey); + KeyValueSet("key", akey); + if (akey != (key) KeyValueGet("key") ) + { + DEBUG("Fatal error, cannot save key"); + } + gNpcKey = akey; +} + + +key NPCKey() +{ + key akey = gNpcKey; // from cached copy + // gNpcKey saves a lot of CPU processing by caching the key, if blank we get it from the description + if (gNpcKey == NULL_KEY) + { + //DEBUG("Get DKey"); + akey = KeyValueGet("key"); // from Description of the prim + } + // DEBUG("NPC KEY:" + (string) akey); + return akey; +} + + +/////////////////// CODE BEGINS ////////////////// + + +default +{ + changed(integer change) { + if(change & CHANGED_REGION_START) { + llResetScript(); + } + } + + on_rez(integer start_param) + { + llResetScript(); + } + + state_entry() { + + llSetText("",<1,1,1>,1.0); // clr all hovertext- we may not be using it. + DoDelete(); // kill any NPC that is out running + Update("NPC"); // If dragged and ropped into a prim with any script named "NPC...", this will replace it. + GetSwitches(); // Get all default saved params from the Description + + // 4.1 allow listeners to send us commands + if (allowListener) + llListen(link_Channel,"","",""); + TimerEvent(TIMER); + } + + + touch_start(integer n) + { // if touched, make a menu + + if (checkPerms()) { + if (RecordPath == STATE) { + makeMenu(lAtButtons); + } else { + makeMainMenu(); + } + } else { + makeUserMenu(); + } + } + + // menu listener + listen(integer iChannel, string name, key id, string message) { + + // process @commands that come in via the listener + if (iChannel == link_Channel) + { + ParseMsg(message); + return; + } + + if (MENU) { + llListenRemove(iHandle); + MENU = 0; // menu is off + iHandle = 0; + } + + if (message == "Stop NPC") + { + lNpcCommandList = []; // force reload of notecard + NPCEnabled = FALSE; + if (NPCKey() != NULL_KEY){ + Kill(sNPCName); + sNPCName = ""; + } else { + bNPC_STOP = TRUE; + makeText("Enter name of an NPC to stop"); + } + } + else if (message == "Menu" ) { + makeMainMenu(); + } + else if (message == "Erase RAM"){ + Clr(); + } + else if (message == "Relative"){ + relAbs = "Absolute"; + KeyValueSet("co","A"); // remember coordinates = A + Clr(); + } + else if (message == "Absolute"){ + relAbs = "Relative"; + KeyValueSet("co","R"); // remember coordinates = R + Clr(); + } + else if (message == "Recording"){ + DoMenuForCommands(); // show them the recording menu + } + else if (message == "Owner Only") { + priPub = "Group"; + KeyValueSet("pr","1"); + + llOwnerSay("Group members have control"); + makeMainMenu(); + } + else if (message == "Group") { + priPub = "Owner Only"; + KeyValueSet("pr","0"); + llOwnerSay("Only you have control"); + makeMainMenu(); + } + else if (message == "Sense is On") { + mSensor ="Sense is Off"; + KeyValueSet("se", "off"); + llOwnerSay(mSensor); + makeMainMenu(); + } + else if (message == "Sense is Off") { + mSensor ="Sense is On"; + llOwnerSay(mSensor); + KeyValueSet("se", "on"); + + NPCEnabled = FALSE; + + integer count = checkNoteCards(); + if (count >= 2) { + DEBUG("Notecards ok, DoProcessNPCLine"); + DoProcessNPCLine(); + return; + } + if (LSLEditor) { + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording and/or appearance, so you cannot start a NPC"); + makeMainMenu(); + } + else if (message == "Appearance") { + llRemoveInventory(Appearance); // delete the notecard + osAgentSaveAppearance(kUserKey,Appearance); // make the ntecard + llOwnerSay("Your outfit has been saved"); + makeMainMenu(); + } + else if (message == "Save") { + if (llGetListLength(lCommands) == 0) { + llOwnerSay("Nothing recorded, you need to make a recording first"); + makeMainMenu(); + return; + } + DoSave(); + } + else if (message == "Help"){ + llLoadURL(kUserKey,"Click to view help","http://www.outworldz.com/opensim/posts/NPC/"); + makeMainMenu(); + } + else if (message == "Start NPC") { + integer count = checkNoteCards(); + + NPCEnabled = TRUE; + + if (LSLEditor) { + DoProcessNPCLine(); + return; + } + + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + SetStop(FALSE); // Let's run the notecard + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording or maybe an appearance, so we cannot start a NPC"); + + } + else if (bNPC_STOP){ + bNPC_STOP = FALSE; + Kill(message); + } + else if (message == ">>"){ + makeMenu(lMenu2); + } + else if (message == ">>>"){ + makeMenu(lMenu3); + } + else if (message == "<<") { + makeMenu(lAtButtons); + } + else if (message == "<<<") { + makeMenu(lMenu2); + } + else if (message == "@comment"){ + Text("# ","Enter a comment",""); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@run"){ + lCommands += "@run=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@fly"){ + lCommands += "@fly=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@land"){ + lCommands += "@land=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@walk") { + lCommands += "@walk=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@sound"){ + Text("@sound=","Enter a sound name or UUID to trigger",""); + } + else if (message == "@randsound"){ + lCommands += "@randsound"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@say") { + Text("@say=","Enter what the NPC will say",""); + } + else if (message == "@whisper"){ + Text("@whisper=","Enter what the NPC will whisper",""); + } + else if (message == "@shout"){ + Text("@shout=","Enter what the NPC will shout",""); + } + else if (message == "@wander") { + Text("@wander=","Enter radius to wander","Enter number of wanders"); + } + else if (message == "@pause") { + Text("@pause=","Enter time to pause",""); + } + else if (message == "@rotate") { + Text("@rotate=","Enter degrees to rotate",""); + } + else if (message == "@sit"){ + Text("@sit=","Enter name of object to sit on",""); + } + else if (message == "@teleport"){ + lCommands += "@teleport=" + Pos() + "\n"; + llOwnerSay("teleport to position: " + Pos()); + makeMenu(lMenu3); + } + else if (message == "@touch"){ + Text("@touch=","Enter name of object to touch",""); + } + else if (message == "@cmd"){ + Text("@cmd=","Enter cjhannel to speak on","Enter text to speak"); + } + else if (message == "@stand"){ + lCommands += "@stand\n"; + llOwnerSay("Stand Recorded"); + makeMenu(lAtButtons); + } + else if (message == "@animate"){ + Text("@animate=","Enter animation name to play","Enter time to play the animation"); + } + else if (message == "@attach"){ + Text("@animate=","Enter inventory name to attach","Enter number of the attachment point (1-40)"); + } + else if (message == "@speed"){ + Text("@speed=","Enter a speed for the NPC, 1=100% normal speed, 0.5=50% speed",""); + } + + + // Save NPC name + else if (MakeNotecard == STATE) { + sNPCName = message; // in case we need to kill it. + + vector vDest = (vector) Pos(); + + if (relAbs == "Relative") + { + vDest -= llGetPos(); // just an offset for relative + } + sNotecard = "@spawn=" + message + "|" + (string) vDest + "\n"; + integer i; + integer j = llGetListLength(lCommands); + for (; i < j; i++){ + // get the command to save to the notecard + string line = llList2String(lCommands,i); + if (relAbs == "Absolute") { + sNotecard += line; // add the un-modified string to the notecard + } else { + // since we have to record absolute coords since we do not know where the box goes until they press Save, + // we process the absolute to relative conversion for walks here + list parts = llParseString2List(line,["="],[]); //get the @command + + if (llList2String(parts,0) == "@walk") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@walk=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@fly") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@fly=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@run") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@run=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@land") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@land=" + (string) vec + "\n"; + } + else { + sNotecard += line; // add the un-modified string to the notecard + } + } + } + llRemoveInventory(Notecard); // delete the old notecard + osMakeNotecard(Notecard,sNotecard); // Makes the notecard. + llSay(0,sNotecard); + llOwnerSay("Commands notecard has been written"); + STATE = 0; + } // MakeNotecard + + else if (! llStringLength(sParam2)) { + lCommands += sCommand + message + "\n"; + llOwnerSay("Recorded"); + makeMenu(lAtButtons); + } + else if (llStringLength(sParam2)){ + sCommand = sCommand + message + "|"; + llOwnerSay("Recorded"); + makeText(sParam2); + sParam2 = ""; + } + + } + + + + timer(){ + // DEBUG("tick"); + + // if llDialog is up, kill the listener for the dialog box. + if (iHandle) { + llOwnerSay("Menu timed out"); + llListenRemove(iHandle); + iHandle = 0; + return; // ^^^^^^^^^^^^^^^^^^^^^^^ + } + // if NoBodyHome, we are sensing for an avatar + else if (NobodyHome == STATE) { + ProcessSensor(); + return; + } + // if we are spawning, we need time to rez the NPC, then start processing NPC Commands. + else if (Spawning == STATE) { + STATE = 0; + TimerEvent(TIMER); + } + // We end aniamtions with a timer + else if (Animate == STATE){ + NPCAnimate(STAND); + TimerEvent(TIMER); + } + + else if (Walking == STATE) { + if (--iWaitCounter) { + if (llVecDist(osNpcGetPos(NPCKey()), newDest) > MAXDIST) { + return; + } + } + + DEBUG("At Destination: " + (string) newDest); + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 2) { + // nothing + } else if (walkstate == 3) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 4) { + llShout(FLIGHT,"landing"); + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } + } + // Wandering timer + else if (Wander == STATE) { + if (--iWaitCounter) { // wait 60 seconds to get to a destination. + if (llVecDist(osNpcGetPos(NPCKey()), vWanderPos) > MAXDIST) + return; + } + + // see if wander counter == 0, if so, stop walking, go to stand and process next line + if(RAMwc == 0) { + NPCAnimate(STAND); + DEBUG("Wander ended, calling DoProcessNPCLine"); + STATE = 0; + DoProcessNPCLine(); + return; + } + // one less time to wander around + RAMwc--; + NPCAnimate(STAND); + TimerEvent(TIMER); + StateWanderhold(); + return; + } + // Wandering requires us to re-wander when we reach a destination + else if (WanderHold == STATE) { + StateWander(); + TimerEvent(TIMER); + return; + } + else if (DoProcess == STATE) { + TimerEvent(QUICK); + } + + + STATE = 0; + + // We always process a NPC line at end of timer. + DEBUG("Tick end, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } + + // sensors are used for sitting on prims + // Neo Cortex: added different SensorFunc states to trigger sit or touch + sensor(integer num) { + if (SensorFunc == 1) { + osNpcSit(NPCKey(), llDetectedKey(0), OS_NPC_SIT_NOW); + DEBUG("Seated, calling DoProcessNPCLine"); + SensorFunc = 0; + } else if (SensorFunc == 2) { + osNpcTouch(NPCKey(), llDetectedKey(0), LINK_THIS); + DEBUG("Touched, calling DoProcessNPCLine"); + SensorFunc = 0; + } + DoProcessNPCLine(); + } + no_sensor(){ + DEBUG ("no target prim located, calling DoProcessNPCLine"); + SensorFunc = 0; + DoProcessNPCLine(); + } + + + link_message(integer sender, integer num, string str, key id){ + ParseMsg(str); + } + +} + + + + + + diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 4.3.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 4.3.lsl new file mode 100644 index 00000000..3a68f8ff --- /dev/null +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 4.3.lsl @@ -0,0 +1,1686 @@ +// :SHOW:1 +// :CATEGORY:NPC +// :NAME:All In One NPC Recorder and Player +// :AUTHOR:Ferd Frederix +// :KEYWORDS:NPC, Puppeteer +// :CREATED:2015-09-24 14:25:15 +// :EDITED:2015-09-24 13:25:15 +// :ID:27 +// :NUM:1829 +// :REV:4.3 +// :WORLD:OpenSim +// :DESCRIPTION: +// All in one NPC recorder player. +// Supports both absolute and relative paths and many new commands +// Add animations named "Fly, Walk, Stand and Run" +// Click Prim to use. +// Should be worn as a HUD to record. +// Put it on the ground and click Sensor or Start NPC when done. +// :CODE: +// This is Rev 4.3 09/24/2015 + +// Revision History +// Rev 1.1 10-2-2014 @Sit did not work. Minor tweaks to casting for lslEditor +// Rev 1.2 10-14-2014 @ sit had wrong type. +// Rev 1.3 relative movement fixed for @fly +// Rev 1.4 4-3-2014 allow anyone to use this, non owners and non group members can only start and stop. +// Rev 1.5 5-17-2014 set sensor to auto start on reboot of sim +// Rev 1.6 5-24-2014 move menu so you can get it by touching, removed many of the KeyValues to RAM for efficiency +// Rev 1.7 CHANGED_REGION_START, not CHANGED_REGION_START (Opensim difference) +// Rev 1.8 tuned up Kill NPC, added more flexible upgrader +// Rev 1.9 Better script injection by link message// Rev 2.0 Added osSetSpeed so you can speed up or slow down an NPC. +// Rev 2.1 No laggy sensor used exept to sit on stuff +// Rev 2.2 Various sensor fixes +// Rev 2.3 Sets No Sensor in menu, must be started by hand +// Rev 2.4 - reserved for patches to 2.3 if needed +// Rev 3.0 Refactor out into subs, not states to make command injection easier +// New command: @appearance=Notecardname so you can switch to a new notecard on the fly +// New command: @speed=1.0 which slows up ( < 1 ) or speeds up ( > 1) +// Rev 3.1 Commands are not interruptible by Link Message +// Rev 3.2 Sensor patches for consistency in removing the NPC +// Rev 3.3 Added Touch command by Neo.Cortex@hbase42/hopto/org:8002 +// Added Menu 3 for notecard and appearance commands +// Rev 3.4 animation timer cannot be zero or it shuts off timer tweaked +// solves the NPC starting up when no sensor is set. +// Rev 3.5 fixes saving to !Path notecard +// Rev 3.6 08-11-2015 @delete acts like @stop. TYjhe NPC now rezzes after an @go back in where it was deleted +// Rev 3.7 08-11-2015 @attach command added to load an attachment from the inventory to the NPC +// Rev 3.8 08-17-2015 process queued commands one at a time without calling ProcessNPCLine on link message +// Rev 3.9 08-23-2011 Queued command fixes including @delete which were not always working +// Rev 4.0 09-15-2015 Fixes for Sensor functions which continually rezzed a NPC when no one was around. +// Rev 4.1 09-20-2015 Added a Listener so link messages are not needed +// Rev 4.2 09-23-2015 Added @teleport= +// Rev 4.3 09-24-2015 Added @reset to restart the NPC at the very start of the !Path notecard +// @teleport works for relative and absolute modes + +//*******************************************************************// + +// Instructions on how to use this are at http://www.outworldz.com/opensim/posts/NPC/ +// This is an OpenSim-only script. +// Author: Ferd Frederix aka Fred Beckhusen - fred@mitsi.com + +//////////////////////////////////////////////////////////////////////////////////////////// +// Original code was Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // +/////////////////////////////////////////////////////////////////////////////////////////// +// Please see: http://www.gnu.org/licenses/gpl.html for legal details, // +// rights of fair usage, the disclaimer and warranty conditions. // +/////////////////////////////////////////////////////////////////////////////////////////// +// The original NPC controller was from http://was.fm/opensim:npc +// Extensive additions and bug fixes by Fred Beckhusen, aka Ferd Frederix +// llSensor had two params swapped +// @Wander would wander where it had rezzed, not where it was. +// There was no 'no_sensor' event in sit, so if a @sit failed, the NPC got stuck +// The animation and walks always stopped old, then started new. It should be start new, then stop old so the default stand would be suppressed. +// New code: +// Merged with new Route recorder and notecard writer +// If the NPC failed to reach a destination it never moved on. +// Added WAIT global to tune this +// Exposed many tunable variables and ported the code +// Added floating point to times in notecard. +// Added @sound, @randsound, @whisper, @shout, and @cmd controls. +// notecards integers are not floats for better control +// +// Link Messages may be used to perform external control by injecting @commands into the stream of actions +// Example: +// To chat something, such as with a chat robot +// llMessageLinked(LINK_SET,0,"@npc_say=Hello",""); + +// This script assumes that NPCs and OSSl scripting is enabled in the OpenSim configuration. +// In order to enable them, the following changes must be made in the OpenSim.ini configuration file: +// +// ; Turn on OSSL +// AllowOSFunctions = true +// OSFunctionThreatLevel = Severe + +//[NPC] +// ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} +// Enabled = true +// +// and then the server has to be restarted. +// please note that there are better ways to enable NPC in the latest Opensim. + +// Commands: All commands begin with an @ sign. All other lines are ignored +// @commands may have optional parameters. The syntax is always: +// @cmd=parm1|parm2 +// NaN in the table below meand Not a Number. This means there is no parameter + +//Command First Parameter Second Parameter Description +//@spawn name location (vector) Rezzes an NPC with name at a location. +//@appearance NoteCardName NaN switch the NPC appearance to a new notecard +//@walk destination (vector) NaN Makes the NPC walk to destination. +//@fly destination (vector) NaN Makes the NPC fly to destination. +//@land destination (vector) NaN Makes the NPC land at destination. +//@say string NaN Makes the NPC speak a phrase. +//@whisper string NaN Makes the NPC whisper a phrase. +//@shout string NaN Makes the NPC shout a phrase. +//@pause seconds (float) NaN Makes the NPC wait for a multiple of seconds. +//@wander radius (float) cycles (integer) Makes the NPC wander in radius, for cycles seconds. +//@delete NaN NaN Removes the NPC. Requires a link message to continue +//@goto label (string) NaN Jump to the label label in the script. +//@animate animation (string) time (float) Makes the NPC trigger the animation animation for time seconds. +//@sound sound_name NaN plays a sound from inventory +//@randsound NaN NaN Plays a random sound from inventory +//@rotate degrees (float) NaN Rotate the NPC degrees around the Z axis. +//@sit primitive name NaN Sit on a primitive with a given name. +//@touch primitive name NaN Touch on a primitive with a given name. +//@stand NaN NaN If sitting on a primitive, stand up. +//@cmd channel (integer) string Says string on channel, for controlling external gadgets +//@stop NaN NaN Halts the NPC script indefinitely. Can be started with a link message +//@go NaN NaN Continues on next notecard line, for use in link messages +//@speed speed (float) NaN from 0 to N, where 1.0 ius a normal speed of an avatar. 0.2 is a turtle. +//@notecard notename (string) NaN load a new Path notecard +//@attach InventoryName attachmentPoint load an attachment from the inventory to the NPC onto point +//@teleport destination (vector) NaN Makes the NPC teleport to destination in the same sim. They cannot tp to another sim or across the HG +//@reset NaN NaN Deletes the NPC, starts the !Path notecard over. + +// Constant attachmentPoint Comment +// ATTACH_CHEST 1 chest/sternum +// ATTACH_HEAD 2 head +// ATTACH_LSHOULDER 3 left shoulder +// ATTACH_RSHOULDER 4 right shoulder +// ATTACH_LHAND 5 left hand +// ATTACH_RHAND 6 right hand +// ATTACH_LFOOT 7 left foot +// ATTACH_RFOOT 8 right foot +// ATTACH_BACK 9 back +// ATTACH_PELVIS 10 pelvis +// ATTACH_MOUTH 11 mouth +// ATTACH_CHIN 12 chin +// ATTACH_LEAR 13 left ear +// ATTACH_REAR 14 right ear +// ATTACH_LEYE 15 left eye +// ATTACH_REYE 16 right eye +// ATTACH_NOSE 17 nose +// ATTACH_RUARM 18 right upper arm +// ATTACH_RLARM 19 right lower arm +// ATTACH_LUARM 20 left upper arm +// ATTACH_LLARM 21 left lower arm +// ATTACH_RHIP 22 right hip +// ATTACH_RULEG 23 right upper leg +// ATTACH_RLLEG 24 right lower leg +// ATTACH_LHIP 25 left hip +// ATTACH_LULEG 26 left upper leg +// ATTACH_LLLEG 27 left lower leg +// ATTACH_BELLY 28 belly/stomach/tummy +// ATTACH_LEFT_PEC 29 left pectoral +// ATTACH_RIGHT_PEC 30 right pectoral +// ATTACH_HUD_CENTER_2 31 HUD Center 2 +// ATTACH_HUD_TOP_RIGHT 32 HUD Top Right +// ATTACH_HUD_TOP_CENTER 33 HUD Top +// ATTACH_HUD_TOP_LEFT 34 HUD Top Left +// ATTACH_HUD_CENTER_1 35 HUD Center +// ATTACH_HUD_BOTTOM_LEFT 36 HUD Bottom Left +// ATTACH_HUD_BOTTOM 37 HUD Bottom +// ATTACH_HUD_BOTTOM_RIGHT 38 HUD Bottom Right +// ATTACH_NECK 39 neck +// ATTACH_AVATAR_CENTER 40 avatar center/root + + + +////////////////////////////////////////////////////////// +// DEBUG // +////////////////////////////////////////////////////////// +integer debug = TRUE; // set to TRUE or FALSE for debug chat on various actions +integer LSLEditor = TRUE; // set to to TRUE to working in LSLEditor, FALSE for in-world. + // you must also include the NPC commands found in the other script since LSLEditor does not support OpenSim +integer iTitleText = FALSE; // set to TRUE to see debug info in text above the controller + +////////////////////////////////////////////////////////// +// TUNABLE CONFIGURATION // +////////////////////////////////////////////////////////// +integer allowListener = TRUE; // set to TRUE to anable a command listener. Usually, this is setto FALSE +integer link_Channel = 4223; // some random number you want to talk to this gadget on. Best if large and negative +float TIMER = 2; // faster = less jerky stopping. How often the system checks the distance traveled. Fastest you can go is 0.5 seconds +float QUICK = 1; // when we need to move to the next state, we use a QUICK timer +string Appearance = "!Appearance"; // The name of the recorded Appearance notecard +string Notecard = "!Path"; // The name of the recorded routes +integer allowUsers = FALSE; // If true, any user can get a Start NPC and Stop NPC menu. Only groups and owners can get all commands if TRUE, or FALSE +float MAXDIST = 2.0; // how close a NPC has to get to a dest pos to continue to next state. Do not lower this too much, as it may miss the target +integer WANDERRAND = TRUE; // set to TRUE and they will pause during wanders a random number of seconds +float WANDERTIME = 3.0; // how long they stand after each @wander,if WANDERRAND is FALSE. If WANDERRAND is TRUE, this is the max time +integer WAIT = 30; // wait for this number of seconds for the NPC to reach a destination (for safety). If it fails to reach a target, it will move on after this time. +float RANGE = 50; // 1 to N meters - anyone this close to the controller will start NPCS if Sensor button is clicked +float REZTIME = 2.0; // wait this long for NPC to rez in, then start the process +string STAND = "Stand"; // the name of the default Stand animation +string WALK = "Walk"; // the name of the default Walk animation +string FLY = "Fly"; // the name of the default Fly animation +string RUN = "Run"; // the name of the default Run animation +string LAND = "Land"; // the name of the default land animation ( for birds only) +float OffsetZ = 0.5; // appear 0.5 meter above ground, this is added to all destinations to keep them from sinking in. +float SPEEDMULT =0.5; // 1.0 = regular avatar speed. Smaller numbers slow down walks. Large numbers speed them up. +integer FLIGHT = 299; // For controlling wings. A channel that is shouted at when flight starts and ends. "flying" or "landing" + +// DESCRIPTIONS FIELDS HAVE TO SURVIVE A RESET +// These vars are stored by saving them with KeyValueSet +// "pr" is a 0 if it is set for Owner Only, 1 for Group control +// "se" is "on" if Started +// "co" = "R" or "A" for relative or absolute addressing mode +// "key" = NPC key + +// These Globals used to be stored in description. Moved to RAM in V1.6 +float RAMPause; // @pause param +float RAMwd ; // @wander distance +integer RAMwc; // @wander count +float RAMrot; // @rotate +string RAMsit; // @sit primname +string RAMtouch; // @touch primname +string RAManimationName; // @animate animation (string) time (float) +float RAManimationTime; + +// other globals section +integer iChannel; // a listen channel, randomly assigned +integer iHandle; // the handle to it + +// NPC controls +vector newDest ; // tmp storage for the walks +integer iWaitCounter ; // wait for this number of seconds for the NPC to reach a desrtination +string sNPCName; // the name of the NPC that may be in world. So we can remove it. +integer bNPC_STOP = FALSE; // boolean to reuse a listener +integer Stopped = FALSE; // set to TRUE by link messages so we do not remember them +float fTimerVal ; // how long we wait when wandering (calculated) +float NPCEnabled; // true if the NPC is suppodes to be running + +// OS_NPC_CREATOR_OWNED will create an 'owned' NPC that will only respond to osNpc* commands issued from scripts that have the same owner as the one that created the NPC. +// OS_NPC_NOT_OWNED will create an 'unowned' NPC that will respond to any script that has OSSL permissions to call osNpc* commands. +integer NPCOptions = OS_NPC_CREATOR_OWNED; // only yhe owner of this box can control this NPC. + +integer walkstate = 0; // helps us reshare the walk state for run, fly and land - a bit of a hack, but it saves RAM. Has to be done this way because some bits of NPCWalkOption are asserted as 0 + +integer NPCWalkOption; // Some notes for what happens to NPCWalkOption: +// OS_NPC_FLY - Fly the avatar to the given position. The avatar will not land unless the OS_NPC_LAND_AT_TARGET option is also given. +// OS_NPC_NO_FLY - Do not fly to the target. The NPC will attempt to walk to the location. If it's up in the air then the avatar will keep bouncing hopeless until another move target is given or the move is stopped +//OS_NPC_LAND_AT_TARGET - If given and the avatar is flying, then it will land when it reaches the target. If OS_NPC_NO_FLY is given then this option has no effect. +// OS_NPC_RUNNING - if given, NPC avatar moves at running/fast flying speed, otherwise moves at walking/slow flying speed. + +// menus +string mSensor="Sense is Off"; // Sensor or "No Sensor" + +list lAtButtons = ["Menu","-", ">>", "@run", "@walk", "@fly", "@land", "@wander", "@sit", "@stand","@animate","@rotate"]; +list lMenu2 = ["<<", "@comment", ">>>", "@stop", "@say", "@whisper","@shout","@sound","@randsound","@cmd", "@pause", "@delete"]; +list lMenu3 = ["<<<","@notecard","@appearance", "@touch", "@speed", "@attach", "@teleport","-", "-", "-", "-", "-" ]; + +string sCommand; // place to store a command for two-prompted ones +string sParam2; // place to store a prompt for two-prompted ones +string priPub = "Owner Only"; // Private or Group +key kUserKey; // the person who is controlling the avatar, not the Owner +// the command lists +list lCommands; // commands are stored here +list lNpcCommandList; // Storage for the NPC script. +string npcAction; // Storage for the next action. @cmd=0|hello, this becomes @cmd +string npcParams; // Storage for the param, @cmd=0|hello, this becomes 0|hello + +// misc vars +string sNotecard; // commands are stored here temporarily for dumping +vector vWanderPos; // a place to wander to +string lastANIM ; // last animation run +// Sensor +integer avatarPresent; // Sensor sets this flag when people are within Range. + +// Coordinate control +vector vInitialPos ; // Vector that will be filled by the script with the initial starting position in region coordinates. +vector vDestPos = ZERO_VECTOR; // Storage for destination position. +string relAbs = "Relative"; // absolute vs relative positioning + + +// STATES +integer MENU ; // processing a dialog box state, may be concurrent with STATE +integer STATE; // state storage +integer MakeNotecard = 1; // displaying a text box for NPC name +integer RecordPath = 2; // displaying a path notecard menu +integer NobodyHome = 3; // looking for an avatar +integer Spawning = 4; // spawning an avatar +integer Animate = 5; // animation timer needed +integer Walking = 6; // Hey! I am walking here! +integer Wander = 7; // Wandering around neeeds a timer, too +integer WanderHold = 8; // We reached a wander point +integer DoProcess = 9; // Set this to make it process a new command +integer Touch = 10; // Timer is busy sensing something to touch +integer Sit = 11; // Timer is busy sensing something to sit on +integer Paused = 12; // Timer is busy pausing + +key gNpcKey = NULL_KEY; // global key storage for the one NPC, to save CPU cycles +list Stack ; // a command stack from link message input + +integer SensorFunc = 0; // define which function shall be triggered inside the sensor function + // 0 means none, 1 sit, 2 touch +/////////////////////////////////////////////////////////////////////////// +// FUNCTIONS // +/////////////////////////////////////////////////////////////////////////// + + +TimerEvent(float timesent) +{ + if (LSLEditor) + timesent *= 5; // slow thinggs doen when the LSLEDITOR is in use + + DEBUG("Setting timer: " + (string) timesent); + llSetTimerEvent(timesent); +} + +// for 4.1 parse a message from a Listen or a Link message +ParseMsg(string str) { + DEBUG("Command In:" + str); + if (str=="@go") { + SetStop(FALSE); // Let's run the notecard + DEBUG("@go running"); + DoProcessNPCLine(); + } else { + Stack += [str]; // take anything, the controller will filter away non @ stuff + if (STATE == 0) { + DEBUG("calling DoNPC"); + DoProcessNPCLine(); + } else{ + DEBUG("Queued"); + } + } +} + +SetStop(integer what) +{ + DEBUG("Stopped set to " + (string ) what); + Stopped = what; +} +// Do* functions are much like states from the old V2 scripts. + +// Save a Path notecard +DoSave() +{ + STATE = MakeNotecard; + makeText("Stand where you want the NPC to appear, and enter the NPC Name"); +} + +// This function is used to record the path for the NPC +// Each command can take 0, 1, or 2 params +DoMenuForCommands() { + makeMenu(lAtButtons); +} + + +// No one is here when sensors were on, so we kill off the NPC +DoNobodyHome() +{ + DEBUG("Nobody Home"); + STATE = NobodyHome; + if (NPCKey() != NULL_KEY) { + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + } + TimerEvent(5); // keep ticking to sense avatars +} + +// Create a NPC +StateSpawn() { + DEBUG("state spawn"); + STATE = Spawning; + + + NPCEnabled = TRUE; // in world + // see if there is already one out there. + if (NPCKey() != NULL_KEY) { + DEBUG("Already living"); + return; + } + + + list name = llParseString2List(sNPCName, [" "], []); + + vector vRezPos = vInitialPos; + if (relAbs == "Relative"){ + vRezPos += llGetPos(); + } + + DEBUG("Rezzing the NPC:" + (string) vRezPos); + key aKey = osNpcCreate(llList2String(name, 0), llList2String(name, 1), vRezPos, Appearance, NPCOptions); + + SaveKey(aKey); // save in desceription and global, too + + osSetSpeed(aKey,SPEEDMULT); // 1.9 speed multiplier + TimerEvent(REZTIME); + NPCAnimate(STAND); +} + +DoRotate() { + DEBUG("@rotate=" + (string) RAMrot); + osNpcSetRot(NPCKey(), llEuler2Rot(<0,0,RAMrot> * DEG_TO_RAD)); +} + +StateSit() { + DEBUG ("state sit - looking for " + RAMsit); + STATE=Sit; + SensorFunc = 1; //triggers osNpcSit + llSensor(RAMsit, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +StateTouch() { + DEBUG ("state touch - looking for " + RAMtouch); + STATE = Touch; + SensorFunc = 2; //triggers osNpcTouch + llSensor(RAMtouch, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +DoStand() { + DEBUG("state stand"); + osNpcStand(NPCKey()); +} + + +StateAnimate() { + + DEBUG("state animate"); + STATE = Animate; + NPCAnimate(RAManimationName); + if (RAManimationTime <=0 ) // V 3.4 tweak + RAManimationTime = 1; + TimerEvent(RAManimationTime); +} + +StateWalk() { + + DEBUG("NPCWalkOption = " + (string) NPCWalkOption); + STATE = Walking; + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(WALK); + } else if (walkstate == 2) { + llShout(FLIGHT,"flying"); + NPCAnimate(FLY); + } else if (walkstate == 3) { + NPCAnimate(RUN); + } else if (walkstate == 4) { + NPCAnimate(LAND); + } + newDest = vDestPos ; + newDest.z += OffsetZ; + + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + newDest += llGetPos(); + } + + DEBUG("Moveto:" + (string) newDest); + osNpcMoveToTarget(NPCKey(), newDest, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + + +StateWander(){ + DEBUG("state wander"); + STATE = Wander; + + vector point = CirclePoint(RAMwd); + DEBUG("CirclePoint:" + (string) point); + vWanderPos = vDestPos + point; + DEBUG("vWanderPos:" + (string) vWanderPos); + + fTimerVal = WANDERTIME; // default time to pause after each wander + if (WANDERRAND) + fTimerVal = llFrand(WANDERTIME) + 1; // override, they want random times + + NPCAnimate(WALK); + + DEBUG("Wander to:" + (string) vWanderPos); + + osNpcMoveToTarget(NPCKey(), vWanderPos, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + +StateWanderhold() { + + DEBUG("Wander Hold"); + STATE = WanderHold; + + // now that we have reached a wander spot, slow the timer down to the desired value + TimerEvent(fTimerVal); +} + +// @pause=10 will do nothing for 10 seconds +DoPause() { + STATE =Paused; + if (RAMPause < 0.1) + RAMPause = 0.1; + DEBUG("@pause=" + (string)RAMPause); + TimerEvent(RAMPause); +} + + +// @stop makes the NPC stop moving in whatever state it is in. You have to linkmessage to get moving again +DoStop() { + DEBUG("NPC is Stopped"); + STATE = 0; // accept commands + SetStop(TRUE); // Link controlled - we mnust have a @go to continue with notecards + TimerEvent(0); + Stack = []; // v3.8 +} + +// @delete removes the NPC forever. Next command starts it up again at the beginning +DoDelete() { + DEBUG("state delete"); + STATE = 0; // accept commands + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + + TimerEvent(0); + Stack = []; // v3.8 +} + +// change the appearance of the NPC +DoAppearance(string notecard) { + DEBUG("state appearance"); + if (llGetInventoryType(notecard) == INVENTORY_NOTECARD){ + DEBUG("Load appearance " + notecard); + osNpcLoadAppearance(NPCKey(),notecard); + } +} + +// Change the avatar speed +DoSpeed(string speed) { + float newspeed = (float) speed; + if (newspeed > 0.1 && newspeed < 5.0) {// sanity check + osSetSpeed(NPCKey(),newspeed); + } +} + +DoTeleport(string params) { + list Data = llParseString2List(params, ["|"], []); + string itemName = llList2String(Data, 0); + vector Dest = (vector) itemName; + if (Dest != ZERO_VECTOR) { + if (relAbs == "Relative"){ + Dest += llGetPos(); + } + osTeleportAgent( NPCKey(), llGetRegionName(), Dest, ZERO_VECTOR ); + + } else { + llSay(DEBUG_CHANNEL,"Attempt to teleport to <0,0,0> probably not what you intended: @teleport="); + } +} + + + +DoNewNote (string card) { + DEBUG("Load Notecard " + card); + NPCReadNoteCard(card); + SetStop(FALSE); +} +DoAttach(string params) { + + list Data = llParseString2List(params, ["|"], []); + string itemName = llList2String(Data, 0); + integer attachmentPoint = (integer) llList2String(Data, 1); + if (attachmentPoint > 0 + && attachmentPoint < 40 + && llGetInventoryType(itemName) == INVENTORY_OBJECT + ) + { + osForceAttachToOtherAvatarFromInventory(NPCKey(),itemName,attachmentPoint); + } +} + +// This loops over the notecard, processing each command +DoProcessNPCLine() { + DEBUG("ProcessNPCLine, stopped = " + (string) Stopped); + STATE = DoProcess; + + // auto load a notecard + if (! llGetListLength(lNpcCommandList)) { + DEBUG("Read Notecard"); + NPCReadNoteCard(Notecard); + SetStop(FALSE); + } + + // look for link messages on the stack + string next = llList2String(Stack,0); // lets see if there is anithing from a link message + if (llStringLength(next)) + { + Stack = llDeleteSubList(Stack,0,0); + ProcessCmd(next); //lets do this command instead. + return; + } + + // @stop issued? + if (Stopped) { + TimerEvent(0); + DEBUG("Stopped, waiting for input"); + STATE = 0; + return; + } + + // No, we have an @go for liftoff + next = llList2String(lNpcCommandList, 0); // get the next command + DEBUG("Execute:" + next); + lNpcCommandList = llDeleteSubList(lNpcCommandList, 0, 0); // delete it + + if (llGetListLength(lNpcCommandList) == 0) { + DEBUG("EOF"); + } + ProcessCmd(next); +} + + + +ProcessCmd(string cmd) { + + DEBUG("ProcessCmd:" + cmd); + + if (llGetSubString(cmd, 0, 0) != "@") { + DEBUG("ignoring"); + TimerEvent(QUICK); // this is so we do not recurse the stack + STATE = 0; + return; + } + + list data = llParseString2List(cmd, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data, 0), STRING_TRIM)); + + DEBUG("Action:" + npcAction); + npcParams = llStringTrim(llList2String(data, 1), STRING_TRIM); + DEBUG("Params:" + npcParams); + + @commands; + + ProcessSensor(); + + if(npcAction == "@spawn" && avatarPresent) { + DEBUG("@spawn"); + list spawnData = llParseString2List(npcParams, ["|"], []); + sNPCName =llList2String(spawnData, 0); // V 1.6 name in RAM + + list spawnDest = llParseString2List(llList2String(spawnData, 1), ["<", ",", ">"], []); + vInitialPos.x = llList2Float(spawnDest, 0); + vInitialPos.y = llList2Float(spawnDest, 1); + vInitialPos.z = llList2Float(spawnDest, 2); + + DEBUG("Coords for NPC at " + (string) vInitialPos); + StateSpawn(); + return; + } + + if (! avatarPresent){ + DoNobodyHome(); + DEBUG("No avatar nearby"); + STATE = 0; + return; + } else { + if ( NPCKey() == NULL_KEY) { + StateSpawn(); + } + } + + + + + if(npcAction == "@stop") { + DoStop(); + STATE = 0; + return; + } + else if(npcAction == "@goto") { + DEBUG("goto"); + integer lastIdx = llGetListLength(lNpcCommandList)-1; + lNpcCommandList = llDeleteSubList(lNpcCommandList, lastIdx, lastIdx); + // Wind commands till goto label. + @wind; + string next1 = llList2String(lNpcCommandList, 0); + lNpcCommandList = llDeleteSubList(lNpcCommandList, 0, 0); + lNpcCommandList += next1; + if(next1 != npcParams) jump wind; + // Wind the label too. + next1 = llList2String(lNpcCommandList, 0); + lNpcCommandList = llDeleteSubList(lNpcCommandList, 0, 0); + lNpcCommandList += next1; + // Get next command. + list data1 = llParseString2List(next1, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data1, 0), STRING_TRIM)); + npcParams = llStringTrim(llList2String(data1, 1), STRING_TRIM); + // Reschedule. + jump commands; + } + else if(npcAction == "@sound") { + DEBUG("sound"); + llTriggerSound(npcParams,1.0); + } + else if(npcAction == "@randsound") { + DEBUG("@randsound"); + integer N = llGetInventoryNumber(INVENTORY_SOUND); + integer rand = llCeil(llFrand(N)) -1; // pick a random sound + string toPlay = llGetInventoryName(INVENTORY_SOUND,rand); + llTriggerSound(toPlay,1.0); + } + else if(npcAction == "@walk") { + DEBUG("@walk"); + GetDest(npcParams); + walkstate = 1;// walking + NPCWalkOption = OS_NPC_NO_FLY ; + StateWalk(); + return; + } + else if(npcAction == "@fly") { + GetDest(npcParams); + walkstate = 2;// flying + NPCWalkOption = OS_NPC_FLY ; + StateWalk(); + return; + } + else if(npcAction == "@run") { + DEBUG("@run"); + GetDest(npcParams); + walkstate = 3;// running + NPCWalkOption = OS_NPC_NO_FLY | OS_NPC_RUNNING; + StateWalk(); + return; + } + else if(npcAction == "@land") { + DEBUG("@land"); + GetDest(npcParams); + walkstate = 4;// landing + NPCWalkOption= OS_NPC_FLY | OS_NPC_LAND_AT_TARGET ; + StateWalk(); + return; + } + else if(npcAction == "@say") { + DEBUG("@say " + npcParams); + osNpcSay(NPCKey(), 0, npcParams); + } + else if(npcAction == "@shout") { + DEBUG("@shout"); + osNpcShout(NPCKey(),0, npcParams); + } + else if(npcAction == "@whisper") { + DEBUG("@whisper " + npcParams); + osNpcWhisper(NPCKey(),0, npcParams); + } + // speak a command on a channel, so you can open doors and control stuff. + else if(npcAction == "@cmd") { + DEBUG("@cmd"); + list dataToSpeak = llParseString2List(npcParams, ["|"], []); + string channel = llList2String(dataToSpeak,0); + DEBUG("Channel:"+(string) channel); + integer iChannel = (integer) channel; + string stringToSpeak = llList2String(dataToSpeak,1); + llSay(iChannel, stringToSpeak); + } + // stop everything + else if(npcAction == "@pause") { + RAMPause = (float) npcParams; + DoPause(); + return; + } + else if(npcAction == "@wander") { + list wanderData = llParseString2List(npcParams, ["|"], []); + RAMwd = (float) llList2String(wanderData, 0); + RAMwc = (integer) llList2String(wanderData, 1); + vDestPos = osNpcGetPos(NPCKey()); // set the wander start + DEBUG("Starting at " + (string) vDestPos); + StateWander(); + return; + } + else if(npcAction == "@rotate") { + RAMrot = (float) npcParams; + DoRotate(); + } + else if(npcAction == "@sit") { + RAMsit= npcParams; + StateSit(); + return; + } + else if(npcAction == "@touch") { + RAMtouch= npcParams; + StateTouch(); + return; + } + else if(npcAction == "@stand") { + DoStand(); + } + else if(npcAction == "@delete") { + DoDelete(); + SetStop(TRUE); // Link controlled - we mnust have a @go to continue with notecards + return; + } + else if(npcAction == "@animate") { + list animateData = llParseString2List(npcParams, ["|"], []); + RAManimationName = llList2String(animateData, 0); + RAManimationTime = (float) llList2String(animateData, 1); + StateAnimate(); + return; + } + else if(npcAction == "@appearance" ){ + DoAppearance(npcParams); + } + else if (npcAction =="@speed") { + DoSpeed(npcParams); + } + else if (npcAction =="@notecard") { + DoNewNote(npcParams); + Notecard = npcParams; + } + else if (npcAction == "@attach") + { + DoAttach(npcParams); + } + else if (npcAction == "@teleport") + { + DoTeleport(npcParams); + } + else if (npcAction == "@reset") + { + DoDelete(); + SetStop(FALSE); // a @resst will restart the original !Path after deleting the notecard. + } + + STATE = 0; + TimerEvent(QUICK); // yeah I know, not possible this fast, we just go as fast as we can go - this is so we do not recurse the stack +} + + + +/////////////////// UTILITY Functions, not state-like ////////////////// + +// DEBUG(string) will chat a string or display it as hovertext if debug == TRUE +DEBUG(string str) { + if (debug && ! LSLEditor) + llOwnerSay( str); // Send the owner debug info + if (debug && LSLEditor) + llSay(0, str); // Send to the Console in LSLEDitor + if (iTitleText) { + llSetText(str,<1.0,1.0,1.0>,1.0); // show hovertext + + } +} + +GetDest(string npcParams) { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); +} + +NPCReadNoteCard(string Note) { + DEBUG("NPCReadNoteCard"); + lNpcCommandList = llParseString2List(osGetNotecard(Note), ["\n"], []); +} + +integer SenseAvatar() +{ + //Returns a strided list of the UUID, position, and name of each avatar in the region + list avatars = llGetAgentList(AGENT_LIST_REGION ,[]); + integer numOfAvatars = llGetListLength(avatars); + if (numOfAvatars == 0) + { + DEBUG("No people"); + return 0; + } + //DEBUG("Located " + (string)numOfAvatars + " avatars and NPC's"); + + integer nAvatars; + integer i; + for( i = 0;i < numOfAvatars; i++) { + key aviKey = llList2Key(avatars,i); + if (!osIsNpc(aviKey)) { + list detail = llGetObjectDetails(aviKey,[OBJECT_POS]); + vector pos = llList2Vector(detail,0); + float dist = llVecDist(pos, llGetPos()); + if (dist < RANGE) + { + nAvatars++; + DEBUG("In range:" + llKey2Name(aviKey)); + } + } + } + //DEBUG("Located " + (string) nAvatars + " avatars"); + return nAvatars; +} + +// return TRUE if the avatar is owner when private is set, or TRUE if the avatar is in the same group and GROUP is set. +integer checkPerms() { + + integer group = (integer) KeyValueGet("pr"); + if (! group) + priPub = "Owner Only"; + else + priPub = "Group"; + + + if (llDetectedKey(0) == llGetOwner()){ + kUserKey = llDetectedKey(0); + return TRUE; + } + + if ( group && llDetectedGroup(0)) { + kUserKey = llDetectedKey(0); + return TRUE; + } + kUserKey = llDetectedKey(0); + return FALSE; +} + + + +NPCAnimate(string anim) +{ + DEBUG("Start Anim: " + anim); + if (llGetInventoryType(anim) == INVENTORY_ANIMATION ) { + + if (lastANIM != anim) { + if(llStringLength(lastANIM)) { + osNpcStopAnimation(NPCKey(), lastANIM); + } + osNpcPlayAnimation(NPCKey(), anim); + lastANIM = anim; + } + } else { + llSay(DEBUG_CHANNEL, "No animation named " + anim); + } +} + +// Kill a NPC by Name +Kill(string param) +{ + integer count; + list avatars = osGetAvatarList(); // Returns a strided list of the UUID, position, and name of each avatar in the region except the owner.\ + integer i; + integer j = llGetListLength(avatars); + for (i=0 ; i <= j; i+=3){ + + string desired = llList2String(avatars,i+2); + desired = llStringTrim(desired,STRING_TRIM); // should not be needed but is needed + + if (desired == param){ + vector v = llList2Vector(avatars,i+1); + key target = llList2Key(avatars,i); // get the UUID of the avatar + osNpcRemove(target); + SaveKey(NULL_KEY ); + llOwnerSay("Removed " + param+ " at location " + (string) v); + count++; + } + } + + NPCEnabled = FALSE; // not in world + + if (count) + llOwnerSay("Removed " + (string) count + " NPC's"); + else + llOwnerSay("Could not locate " + param); +} + + +// return a String for the position we are at. Strings used as the caller wants strings +string Pos() +{ + vector where = llGetPos(); // find the box position + + where.z += OffsetZ; // use the ground position + an offset + + if (LSLEditor) + where = <128,128,31 + llFrand(1)>; // force center of sim when editing + + // if attached the height will be too high by 1/2 the agent size + if (llGetAttached()) { + vector size = llGetAgentSize(llGetOwner()); + float Z = size.z; + where.z -= Z/2; + } + + // DEBUG("Pos= " + (string) where); + return (string) where; +} + +// setup a menu with a timer for timeouts, called by all make*() +menu() +{ + llListenRemove(iHandle); + iChannel = llCeil(llFrand(100000) + 20000); + iHandle = llListen(iChannel,"","",""); + TimerEvent(30.0); + MENU = TRUE; +} + +// make a text box +makeText(string Param) +{ + menu(); + llTextBox(kUserKey, Param, iChannel); +} + +// top level menu +makeMainMenu() +{ + menu(); + list buttons = ["Appearance","Recording","Save","Help","-","Erase RAM", priPub,relAbs,"-","Stop NPC",mSensor,"Start NPC"]; + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Records",buttons,iChannel); +} + + +// Rev 1.4 +// top level menu for non group/ non owners +makeUserMenu() +{ + if (!allowUsers) return; + + menu(); + list buttons = ["Start NPC","Stop NPC"]; + llDialog(kUserKey,"Choose",buttons,iChannel); +} + + + +// programmable menu for @commands +makeMenu(list buttons) +{ + menu(); + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Record",buttons,iChannel); +} + + +// make one or two text boxes with prompts +Text(string cmd, string p1, string p2) +{ + sCommand = cmd; + sParam2 = ""; + if (llStringLength(p2)) + sParam2 = p2; + + makeText(p1); +} + +// Set the Avatar Present flag - if sensors are off and we are forece run, there will be one present. +ProcessSensor() +{ + integer SensorOn; + if ("on" == KeyValueGet("se")) + { + SensorOn = TRUE; // we need to scan for avatars + } else { + SensorOn = FALSE; // we need to scan for avatars + } + DEBUG("Sensor:" + (string) SensorOn); + + integer n = SenseAvatar(); + + DEBUG("Avatars:" + (string) n); + if (SensorOn && n) + avatarPresent = TRUE; // someone is here and we need to tell the system to run + else if (SensorOn && !n) + avatarPresent = FALSE; // someone is not here and we need to tell the system to stop + else { // sensor is off, lete see if there is a NPC. If so, we are ON + DEBUG("NPCEnabled:" + (string) NPCEnabled); + if (NPCEnabled) + avatarPresent = TRUE; + else + avatarPresent = FALSE; + } + + // start up from when when no one is near + if (avatarPresent && STATE == NobodyHome) + STATE = 0; + + DEBUG("Avatar Present: " + (string) avatarPresent); +} + +vector CirclePoint(float radius) { + float x = llFrand(radius *2) - radius; // +/- radius, randomized + float y = llFrand(radius *2) - radius; // +/- radius, randomized + return ; // so this should always happen +} + +string KeyValueGet(string var) { + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k != var) jump continue; + //DEBUG("got " + var + " = " + llList2String(data, 1)); + return llList2String(data, 1); + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + return ""; +} + +KeyValueSet(string var, string val) { + + //DEBUG("set " + var + " = " + val); + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + if(llGetListLength(dVars) == 0) + { + llSetObjectDesc(var + "=" + val); + return; + } + list result = []; + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k == "") jump continue; + if(k == var && val == "") jump continue; + if(k == var) { + result += k + "=" + val; + val = ""; + jump continue; + } + string v = llList2String(data, 1); + if(v == "") jump continue; + result += k + "=" + v; + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + if(val != "") result += var + "=" + val; + llSetObjectDesc(llDumpList2String(result, "&")); +} + + +// clear RAM +Clr() { + + lCommands = []; + llOwnerSay("RAM Memory cleared. Notecards, if any, are not modified."); + makeMainMenu(); +} + +integer checkNoteCards() +{ + // Check that they have saved an Appeaance and Path notecard + integer num = llGetInventoryNumber(INVENTORY_NOTECARD); // how many notecards overall + + integer i; + integer count; + for (; i < num; i++){ + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Notecard) + count++; + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Appearance) + count++; + } + DEBUG("Checked " + (string) count + " Notecards"); + // if we have both, run the NPC + return count; +} + +Update(string SName) { + + // delete all NPC* scripts except myself + integer i; + integer j = llGetInventoryNumber(INVENTORY_SCRIPT); + for (i = 0; i < j; i++) { + string targetName = llGetInventoryName(INVENTORY_SCRIPT,i); + string match = llGetSubString(targetName,0,2); + + if (match == SName && llGetScriptName() != targetName){ + llOwnerSay("Upgrading " + targetName); + if (! LSLEditor){ // lets not kill the editor + llRemoveInventory(targetName); + } + } + } +} + +// Get all default saved params from the Description +GetSwitches() +{ + string rA = KeyValueGet("co"); // Get the remembered menu setting for Abs Vs Relative + if (rA == "A") + relAbs = "Absolute"; + else if (rA == "R") + relAbs = "Relative"; + else + relAbs = "Absolute"; + + + // reenable NPC if sensor is on. + if ("on" == KeyValueGet("se")) + { + NPCEnabled = TRUE; + mSensor = "Sense is On"; + ProcessSensor(); // fake 1 avatar to get it rezzed + } else { + mSensor = "Sense is Off"; + } + } + + +SaveKey(key akey) +{ + DEBUG("Saving Key of " + (string) akey); + KeyValueSet("key", akey); + if (akey != (key) KeyValueGet("key") ) + { + DEBUG("Fatal error, cannot save key"); + } + gNpcKey = akey; +} + + +key NPCKey() +{ + key akey = gNpcKey; // from cached copy + // gNpcKey saves a lot of CPU processing by caching the key, if blank we get it from the description + if (gNpcKey == NULL_KEY) + { + //DEBUG("Get DKey"); + akey = KeyValueGet("key"); // from Description of the prim + } + // DEBUG("NPC KEY:" + (string) akey); + return akey; +} + + +/////////////////// CODE BEGINS ////////////////// + + +default +{ + changed(integer change) { + if(change & CHANGED_REGION_START) { + llResetScript(); + } + } + + on_rez(integer start_param) + { + llResetScript(); + } + + state_entry() { + + llSetText("",<1,1,1>,1.0); // clr all hovertext- we may not be using it. + DoDelete(); // kill any NPC that is out running + Update("NPC"); // If dragged and ropped into a prim with any script named "NPC...", this will replace it. + GetSwitches(); // Get all default saved params from the Description + + // 4.1 allow listeners to send us commands + if (allowListener) + llListen(link_Channel,"","",""); + TimerEvent(TIMER); + } + + + touch_start(integer n) + { // if touched, make a menu + + if (checkPerms()) { + if (RecordPath == STATE) { + makeMenu(lAtButtons); + } else { + makeMainMenu(); + } + } else { + makeUserMenu(); + } + } + + // menu listener + listen(integer iChannel, string name, key id, string message) { + + // process @commands that come in via the listener + if (iChannel == link_Channel) + { + ParseMsg(message); + return; + } + + if (MENU) { + llListenRemove(iHandle); + MENU = 0; // menu is off + iHandle = 0; + } + + if (message == "Stop NPC") + { + lNpcCommandList = []; // force reload of notecard + NPCEnabled = FALSE; + if (NPCKey() != NULL_KEY){ + Kill(sNPCName); + sNPCName = ""; + } else { + bNPC_STOP = TRUE; + makeText("Enter name of an NPC to stop"); + } + } + else if (message == "Menu" ) { + makeMainMenu(); + } + else if (message == "Erase RAM"){ + Clr(); + } + else if (message == "Relative"){ + relAbs = "Absolute"; + KeyValueSet("co","A"); // remember coordinates = A + Clr(); + } + else if (message == "Absolute"){ + relAbs = "Relative"; + KeyValueSet("co","R"); // remember coordinates = R + Clr(); + } + else if (message == "Recording"){ + DoMenuForCommands(); // show them the recording menu + } + else if (message == "Owner Only") { + priPub = "Group"; + KeyValueSet("pr","1"); + + llOwnerSay("Group members have control"); + makeMainMenu(); + } + else if (message == "Group") { + priPub = "Owner Only"; + KeyValueSet("pr","0"); + llOwnerSay("Only you have control"); + makeMainMenu(); + } + else if (message == "Sense is On") { + mSensor ="Sense is Off"; + KeyValueSet("se", "off"); + llOwnerSay(mSensor); + makeMainMenu(); + } + else if (message == "Sense is Off") { + mSensor ="Sense is On"; + llOwnerSay(mSensor); + KeyValueSet("se", "on"); + + NPCEnabled = FALSE; + + integer count = checkNoteCards(); + if (count >= 2) { + DEBUG("Notecards ok, DoProcessNPCLine"); + DoProcessNPCLine(); + return; + } + if (LSLEditor) { + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording and/or appearance, so you cannot start a NPC"); + makeMainMenu(); + } + else if (message == "Appearance") { + llRemoveInventory(Appearance); // delete the notecard + osAgentSaveAppearance(kUserKey,Appearance); // make the ntecard + llOwnerSay("Your outfit has been saved"); + makeMainMenu(); + } + else if (message == "Save") { + if (llGetListLength(lCommands) == 0) { + llOwnerSay("Nothing recorded, you need to make a recording first"); + makeMainMenu(); + return; + } + DoSave(); + } + else if (message == "Help"){ + llLoadURL(kUserKey,"Click to view help","http://www.outworldz.com/opensim/posts/NPC/"); + makeMainMenu(); + } + else if (message == "Start NPC") { + integer count = checkNoteCards(); + + NPCEnabled = TRUE; + + if (LSLEditor) { + DoProcessNPCLine(); + return; + } + + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + SetStop(FALSE); // Let's run the notecard + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording or maybe an appearance, so we cannot start a NPC"); + + } + else if (bNPC_STOP){ + bNPC_STOP = FALSE; + Kill(message); + } + else if (message == ">>"){ + makeMenu(lMenu2); + } + else if (message == ">>>"){ + makeMenu(lMenu3); + } + else if (message == "<<") { + makeMenu(lAtButtons); + } + else if (message == "<<<") { + makeMenu(lMenu2); + } + else if (message == "@comment"){ + Text("# ","Enter a comment",""); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@run"){ + lCommands += "@run=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@fly"){ + lCommands += "@fly=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@land"){ + lCommands += "@land=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@walk") { + lCommands += "@walk=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@sound"){ + Text("@sound=","Enter a sound name or UUID to trigger",""); + } + else if (message == "@randsound"){ + lCommands += "@randsound"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@say") { + Text("@say=","Enter what the NPC will say",""); + } + else if (message == "@whisper"){ + Text("@whisper=","Enter what the NPC will whisper",""); + } + else if (message == "@shout"){ + Text("@shout=","Enter what the NPC will shout",""); + } + else if (message == "@wander") { + Text("@wander=","Enter radius to wander","Enter number of wanders"); + } + else if (message == "@pause") { + Text("@pause=","Enter time to pause",""); + } + else if (message == "@rotate") { + Text("@rotate=","Enter degrees to rotate",""); + } + else if (message == "@sit"){ + Text("@sit=","Enter name of object to sit on",""); + } + else if (message == "@teleport"){ + lCommands += "@teleport=" + Pos() + "\n"; + llOwnerSay("teleport to position: " + Pos()); + makeMenu(lMenu3); + } + else if (message == "@touch"){ + Text("@touch=","Enter name of object to touch",""); + } + else if (message == "@cmd"){ + Text("@cmd=","Enter cjhannel to speak on","Enter text to speak"); + } + else if (message == "@stand"){ + lCommands += "@stand\n"; + llOwnerSay("Stand Recorded"); + makeMenu(lAtButtons); + } + else if (message == "@animate"){ + Text("@animate=","Enter animation name to play","Enter time to play the animation"); + } + else if (message == "@attach"){ + Text("@animate=","Enter inventory name to attach","Enter number of the attachment point (1-40)"); + } + else if (message == "@speed"){ + Text("@speed=","Enter a speed for the NPC, 1=100% normal speed, 0.5=50% speed",""); + } + + + // Save NPC name + else if (MakeNotecard == STATE) { + sNPCName = message; // in case we need to kill it. + + vector vDest = (vector) Pos(); + + if (relAbs == "Relative") + { + vDest -= llGetPos(); // just an offset for relative + } + sNotecard = "@spawn=" + message + "|" + (string) vDest + "\n"; + integer i; + integer j = llGetListLength(lCommands); + for (; i < j; i++){ + // get the command to save to the notecard + string line = llList2String(lCommands,i); + if (relAbs == "Absolute") { + sNotecard += line; // add the un-modified string to the notecard + } else { + // since we have to record absolute coords since we do not know where the box goes until they press Save, + // we process the absolute to relative conversion for walks here + list parts = llParseString2List(line,["="],[]); //get the @command + + if (llList2String(parts,0) == "@walk") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@walk=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@fly") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@fly=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@run") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@run=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@land") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@land=" + (string) vec + "\n"; + } + else { + sNotecard += line; // add the un-modified string to the notecard + } + } + } + llRemoveInventory(Notecard); // delete the old notecard + osMakeNotecard(Notecard,sNotecard); // Makes the notecard. + llSay(0,sNotecard); + llOwnerSay("Commands notecard has been written"); + STATE = 0; + } // MakeNotecard + + else if (! llStringLength(sParam2)) { + lCommands += sCommand + message + "\n"; + llOwnerSay("Recorded"); + makeMenu(lAtButtons); + } + else if (llStringLength(sParam2)){ + sCommand = sCommand + message + "|"; + llOwnerSay("Recorded"); + makeText(sParam2); + sParam2 = ""; + } + + } + + + + timer(){ + // DEBUG("tick"); + + // if llDialog is up, kill the listener for the dialog box. + if (iHandle) { + llOwnerSay("Menu timed out"); + llListenRemove(iHandle); + iHandle = 0; + return; // ^^^^^^^^^^^^^^^^^^^^^^^ + } + // if NoBodyHome, we are sensing for an avatar + else if (NobodyHome == STATE) { + ProcessSensor(); + return; + } + // if we are spawning, we need time to rez the NPC, then start processing NPC Commands. + else if (Spawning == STATE) { + STATE = 0; + TimerEvent(TIMER); + } + // We end aniamtions with a timer + else if (Animate == STATE){ + NPCAnimate(STAND); + TimerEvent(TIMER); + } + + else if (Walking == STATE) { + if (--iWaitCounter) { + if (llVecDist(osNpcGetPos(NPCKey()), newDest) > MAXDIST) { + return; + } + } + + DEBUG("At Destination: " + (string) newDest); + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 2) { + // nothing + } else if (walkstate == 3) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 4) { + llShout(FLIGHT,"landing"); + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } + } + // Wandering timer + else if (Wander == STATE) { + if (--iWaitCounter) { // wait 60 seconds to get to a destination. + if (llVecDist(osNpcGetPos(NPCKey()), vWanderPos) > MAXDIST) + return; + } + + // see if wander counter == 0, if so, stop walking, go to stand and process next line + if(RAMwc == 0) { + NPCAnimate(STAND); + DEBUG("Wander ended, calling DoProcessNPCLine"); + STATE = 0; + DoProcessNPCLine(); + return; + } + // one less time to wander around + RAMwc--; + NPCAnimate(STAND); + TimerEvent(TIMER); + StateWanderhold(); + return; + } + // Wandering requires us to re-wander when we reach a destination + else if (WanderHold == STATE) { + StateWander(); + TimerEvent(TIMER); + return; + } + else if (DoProcess == STATE) { + TimerEvent(QUICK); + } + + + STATE = 0; + + // We always process a NPC line at end of timer. + DEBUG("Tick end, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } + + // sensors are used for sitting on prims + // Neo Cortex: added different SensorFunc states to trigger sit or touch + sensor(integer num) { + if (SensorFunc == 1) { + osNpcSit(NPCKey(), llDetectedKey(0), OS_NPC_SIT_NOW); + DEBUG("Seated, calling DoProcessNPCLine"); + SensorFunc = 0; + } else if (SensorFunc == 2) { + osNpcTouch(NPCKey(), llDetectedKey(0), LINK_THIS); + DEBUG("Touched, calling DoProcessNPCLine"); + SensorFunc = 0; + } + DoProcessNPCLine(); + } + no_sensor(){ + DEBUG ("no target prim located, calling DoProcessNPCLine"); + SensorFunc = 0; + DoProcessNPCLine(); + } + + + link_message(integer sender, integer num, string str, key id){ + ParseMsg(str); + } + +} + + + + + + diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 4.4.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 4.4.lsl new file mode 100644 index 00000000..7c84c12b --- /dev/null +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 4.4.lsl @@ -0,0 +1,1688 @@ +// :SHOW:1 +// :CATEGORY:NPC +// :NAME:All In One NPC Recorder and Player +// :AUTHOR:Ferd Frederix +// :KEYWORDS:NPC, Puppeteer +// :CREATED:2015-09-29 18:04:52 +// :EDITED:2015-09-29 17:04:52 +// :ID:27 +// :NUM:1830 +// :REV:4.4 +// :WORLD:OpenSim +// :DESCRIPTION: +// All in one NPC recorder player. +// Supports both absolute and relative paths and many new commands +// Add animations named "Fly, Walk, Stand and Run" +// Click Prim to use. +// Should be worn as a HUD to record. +// Put it on the ground and click Sensor or Start NPC when done. +// :CODE: +// This is Rev 4.4 09/26/2015 + +// Revision History +// Rev 1.1 10-2-2014 @Sit did not work. Minor tweaks to casting for lslEditor +// Rev 1.2 10-14-2014 @ sit had wrong type. +// Rev 1.3 relative movement fixed for @fly +// Rev 1.4 4-3-2014 allow anyone to use this, non owners and non group members can only start and stop. +// Rev 1.5 5-17-2014 set sensor to auto start on reboot of sim +// Rev 1.6 5-24-2014 move menu so you can get it by touching, removed many of the KeyValues to RAM for efficiency +// Rev 1.7 CHANGED_REGION_START, not CHANGED_REGION_START (Opensim difference) +// Rev 1.8 tuned up Kill NPC, added more flexible upgrader +// Rev 1.9 Better script injection by link message// Rev 2.0 Added osSetSpeed so you can speed up or slow down an NPC. +// Rev 2.1 No laggy sensor used exept to sit on stuff +// Rev 2.2 Various sensor fixes +// Rev 2.3 Sets No Sensor in menu, must be started by hand +// Rev 2.4 - reserved for patches to 2.3 if needed +// Rev 3.0 Refactor out into subs, not states to make command injection easier +// New command: @appearance=Notecardname so you can switch to a new notecard on the fly +// New command: @speed=1.0 which slows up ( < 1 ) or speeds up ( > 1) +// Rev 3.1 Commands are not interruptible by Link Message +// Rev 3.2 Sensor patches for consistency in removing the NPC +// Rev 3.3 Added Touch command by Neo.Cortex@hbase42/hopto/org:8002 +// Added Menu 3 for notecard and appearance commands +// Rev 3.4 animation timer cannot be zero or it shuts off timer tweaked +// solves the NPC starting up when no sensor is set. +// Rev 3.5 fixes saving to !Path notecard +// Rev 3.6 08-11-2015 @delete acts like @stop. TYjhe NPC now rezzes after an @go back in where it was deleted +// Rev 3.7 08-11-2015 @attach command added to load an attachment from the inventory to the NPC +// Rev 3.8 08-17-2015 process queued commands one at a time without calling ProcessNPCLine on link message +// Rev 3.9 08-23-2011 Queued command fixes including @delete which were not always working +// Rev 4.0 09-15-2015 Fixes for Sensor functions which continually rezzed a NPC when no one was around. +// Rev 4.1 09-20-2015 Added a Listener so link messages are not needed +// Rev 4.2 09-23-2015 Added @teleport= +// Rev 4.3 09-24-2015 Added @reset to restart the NPC at the very start of the !Path notecard +// @teleport works for relative and absolute modes +// Rev 4.4 09-26-2015 if it could not find the (deleted) NPC, it could not restart + +//*******************************************************************// + +// Instructions on how to use this are at http://www.outworldz.com/opensim/posts/NPC/ +// This is an OpenSim-only script. +// Author: Ferd Frederix aka Fred Beckhusen - fred@mitsi.com + +//////////////////////////////////////////////////////////////////////////////////////////// +// Original code was Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // +/////////////////////////////////////////////////////////////////////////////////////////// +// Please see: http://www.gnu.org/licenses/gpl.html for legal details, // +// rights of fair usage, the disclaimer and warranty conditions. // +/////////////////////////////////////////////////////////////////////////////////////////// +// The original NPC controller was from http://was.fm/opensim:npc +// Extensive additions and bug fixes by Fred Beckhusen, aka Ferd Frederix +// llSensor had two params swapped +// @Wander would wander where it had rezzed, not where it was. +// There was no 'no_sensor' event in sit, so if a @sit failed, the NPC got stuck +// The animation and walks always stopped old, then started new. It should be start new, then stop old so the default stand would be suppressed. +// New code: +// Merged with new Route recorder and notecard writer +// If the NPC failed to reach a destination it never moved on. +// Added WAIT global to tune this +// Exposed many tunable variables and ported the code +// Added floating point to times in notecard. +// Added @sound, @randsound, @whisper, @shout, and @cmd controls. +// notecards integers are not floats for better control +// +// Link Messages may be used to perform external control by injecting @commands into the stream of actions +// Example: +// To chat something, such as with a chat robot +// llMessageLinked(LINK_SET,0,"@npc_say=Hello",""); + +// This script assumes that NPCs and OSSl scripting is enabled in the OpenSim configuration. +// In order to enable them, the following changes must be made in the OpenSim.ini configuration file: +// +// ; Turn on OSSL +// AllowOSFunctions = true +// OSFunctionThreatLevel = Severe + +//[NPC] +// ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} +// Enabled = true +// +// and then the server has to be restarted. +// please note that there are better ways to enable NPC in the latest Opensim. + +// Commands: All commands begin with an @ sign. All other lines are ignored +// @commands may have optional parameters. The syntax is always: +// @cmd=parm1|parm2 +// NaN in the table below meand Not a Number. This means there is no parameter + +//Command First Parameter Second Parameter Description +//@spawn name location (vector) Rezzes an NPC with name at a location. +//@appearance NoteCardName NaN switch the NPC appearance to a new notecard +//@walk destination (vector) NaN Makes the NPC walk to destination. +//@fly destination (vector) NaN Makes the NPC fly to destination. +//@land destination (vector) NaN Makes the NPC land at destination. +//@say string NaN Makes the NPC speak a phrase. +//@whisper string NaN Makes the NPC whisper a phrase. +//@shout string NaN Makes the NPC shout a phrase. +//@pause seconds (float) NaN Makes the NPC wait for a multiple of seconds. +//@wander radius (float) cycles (integer) Makes the NPC wander in radius, for cycles seconds. +//@delete NaN NaN Removes the NPC. Requires a link message to continue +//@goto label (string) NaN Jump to the label label in the script. +//@animate animation (string) time (float) Makes the NPC trigger the animation animation for time seconds. +//@sound sound_name NaN plays a sound from inventory +//@randsound NaN NaN Plays a random sound from inventory +//@rotate degrees (float) NaN Rotate the NPC degrees around the Z axis. +//@sit primitive name NaN Sit on a primitive with a given name. +//@touch primitive name NaN Touch on a primitive with a given name. +//@stand NaN NaN If sitting on a primitive, stand up. +//@cmd channel (integer) string Says string on channel, for controlling external gadgets +//@stop NaN NaN Halts the NPC script indefinitely. Can be started with a link message +//@go NaN NaN Continues on next notecard line, for use in link messages +//@speed speed (float) NaN from 0 to N, where 1.0 ius a normal speed of an avatar. 0.2 is a turtle. +//@notecard notename (string) NaN load a new Path notecard +//@attach InventoryName attachmentPoint load an attachment from the inventory to the NPC onto point +//@teleport destination (vector) NaN Makes the NPC teleport to destination in the same sim. They cannot tp to another sim or across the HG +//@reset NaN NaN Deletes the NPC, starts the !Path notecard over. + +// Constant attachmentPoint Comment +// ATTACH_CHEST 1 chest/sternum +// ATTACH_HEAD 2 head +// ATTACH_LSHOULDER 3 left shoulder +// ATTACH_RSHOULDER 4 right shoulder +// ATTACH_LHAND 5 left hand +// ATTACH_RHAND 6 right hand +// ATTACH_LFOOT 7 left foot +// ATTACH_RFOOT 8 right foot +// ATTACH_BACK 9 back +// ATTACH_PELVIS 10 pelvis +// ATTACH_MOUTH 11 mouth +// ATTACH_CHIN 12 chin +// ATTACH_LEAR 13 left ear +// ATTACH_REAR 14 right ear +// ATTACH_LEYE 15 left eye +// ATTACH_REYE 16 right eye +// ATTACH_NOSE 17 nose +// ATTACH_RUARM 18 right upper arm +// ATTACH_RLARM 19 right lower arm +// ATTACH_LUARM 20 left upper arm +// ATTACH_LLARM 21 left lower arm +// ATTACH_RHIP 22 right hip +// ATTACH_RULEG 23 right upper leg +// ATTACH_RLLEG 24 right lower leg +// ATTACH_LHIP 25 left hip +// ATTACH_LULEG 26 left upper leg +// ATTACH_LLLEG 27 left lower leg +// ATTACH_BELLY 28 belly/stomach/tummy +// ATTACH_LEFT_PEC 29 left pectoral +// ATTACH_RIGHT_PEC 30 right pectoral +// ATTACH_HUD_CENTER_2 31 HUD Center 2 +// ATTACH_HUD_TOP_RIGHT 32 HUD Top Right +// ATTACH_HUD_TOP_CENTER 33 HUD Top +// ATTACH_HUD_TOP_LEFT 34 HUD Top Left +// ATTACH_HUD_CENTER_1 35 HUD Center +// ATTACH_HUD_BOTTOM_LEFT 36 HUD Bottom Left +// ATTACH_HUD_BOTTOM 37 HUD Bottom +// ATTACH_HUD_BOTTOM_RIGHT 38 HUD Bottom Right +// ATTACH_NECK 39 neck +// ATTACH_AVATAR_CENTER 40 avatar center/root + + + +////////////////////////////////////////////////////////// +// DEBUG // +////////////////////////////////////////////////////////// +integer debug = TRUE; // set to TRUE or FALSE for debug chat on various actions +integer LSLEditor = TRUE; // set to to TRUE to working in LSLEditor, FALSE for in-world. + // you must also include the NPC commands found in the other script since LSLEditor does not support OpenSim +integer iTitleText = FALSE; // set to TRUE to see debug info in text above the controller + +////////////////////////////////////////////////////////// +// TUNABLE CONFIGURATION // +////////////////////////////////////////////////////////// +integer allowListener = TRUE; // set to TRUE to anable a command listener. Usually, this is setto FALSE +integer link_Channel = 4223; // some random number you want to talk to this gadget on. Best if large and negative +float TIMER = 2; // faster = less jerky stopping. How often the system checks the distance traveled. Fastest you can go is 0.5 seconds +float QUICK = 1; // when we need to move to the next state, we use a QUICK timer +string Appearance = "!Appearance"; // The name of the recorded Appearance notecard +string Notecard = "!Path"; // The name of the recorded routes +integer allowUsers = FALSE; // If true, any user can get a Start NPC and Stop NPC menu. Only groups and owners can get all commands if TRUE, or FALSE +float MAXDIST = 2.0; // how close a NPC has to get to a dest pos to continue to next state. Do not lower this too much, as it may miss the target +integer WANDERRAND = TRUE; // set to TRUE and they will pause during wanders a random number of seconds +float WANDERTIME = 3.0; // how long they stand after each @wander,if WANDERRAND is FALSE. If WANDERRAND is TRUE, this is the max time +integer WAIT = 30; // wait for this number of seconds for the NPC to reach a destination (for safety). If it fails to reach a target, it will move on after this time. +float RANGE = 50; // 1 to N meters - anyone this close to the controller will start NPCS if Sensor button is clicked +float REZTIME = 2.0; // wait this long for NPC to rez in, then start the process +string STAND = "Stand"; // the name of the default Stand animation +string WALK = "Walk"; // the name of the default Walk animation +string FLY = "Fly"; // the name of the default Fly animation +string RUN = "Run"; // the name of the default Run animation +string LAND = "Land"; // the name of the default land animation ( for birds only) +float OffsetZ = 0.5; // appear 0.5 meter above ground, this is added to all destinations to keep them from sinking in. +float SPEEDMULT =0.5; // 1.0 = regular avatar speed. Smaller numbers slow down walks. Large numbers speed them up. +integer FLIGHT = 299; // For controlling wings. A channel that is shouted at when flight starts and ends. "flying" or "landing" + +// DESCRIPTIONS FIELDS HAVE TO SURVIVE A RESET +// These vars are stored by saving them with KeyValueSet +// "pr" is a 0 if it is set for Owner Only, 1 for Group control +// "se" is "on" if Started +// "co" = "R" or "A" for relative or absolute addressing mode +// "key" = NPC key + +// These Globals used to be stored in description. Moved to RAM in V1.6 +float RAMPause; // @pause param +float RAMwd ; // @wander distance +integer RAMwc; // @wander count +float RAMrot; // @rotate +string RAMsit; // @sit primname +string RAMtouch; // @touch primname +string RAManimationName; // @animate animation (string) time (float) +float RAManimationTime; + +// other globals section +integer iChannel; // a listen channel, randomly assigned +integer iHandle; // the handle to it + +// NPC controls +vector newDest ; // tmp storage for the walks +integer iWaitCounter ; // wait for this number of seconds for the NPC to reach a desrtination +string sNPCName; // the name of the NPC that may be in world. So we can remove it. +integer bNPC_STOP = FALSE; // boolean to reuse a listener +integer Stopped = FALSE; // set to TRUE by link messages so we do not remember them +float fTimerVal ; // how long we wait when wandering (calculated) +float NPCEnabled; // true if the NPC is suppodes to be running + +// OS_NPC_CREATOR_OWNED will create an 'owned' NPC that will only respond to osNpc* commands issued from scripts that have the same owner as the one that created the NPC. +// OS_NPC_NOT_OWNED will create an 'unowned' NPC that will respond to any script that has OSSL permissions to call osNpc* commands. +integer NPCOptions = OS_NPC_CREATOR_OWNED; // only yhe owner of this box can control this NPC. + +integer walkstate = 0; // helps us reshare the walk state for run, fly and land - a bit of a hack, but it saves RAM. Has to be done this way because some bits of NPCWalkOption are asserted as 0 + +integer NPCWalkOption; // Some notes for what happens to NPCWalkOption: +// OS_NPC_FLY - Fly the avatar to the given position. The avatar will not land unless the OS_NPC_LAND_AT_TARGET option is also given. +// OS_NPC_NO_FLY - Do not fly to the target. The NPC will attempt to walk to the location. If it's up in the air then the avatar will keep bouncing hopeless until another move target is given or the move is stopped +//OS_NPC_LAND_AT_TARGET - If given and the avatar is flying, then it will land when it reaches the target. If OS_NPC_NO_FLY is given then this option has no effect. +// OS_NPC_RUNNING - if given, NPC avatar moves at running/fast flying speed, otherwise moves at walking/slow flying speed. + +// menus +string mSensor="Sense is Off"; // Sensor or "No Sensor" + +list lAtButtons = ["Menu","-", ">>", "@run", "@walk", "@fly", "@land", "@wander", "@sit", "@stand","@animate","@rotate"]; +list lMenu2 = ["<<", "@comment", ">>>", "@stop", "@say", "@whisper","@shout","@sound","@randsound","@cmd", "@pause", "@delete"]; +list lMenu3 = ["<<<","@notecard","@appearance", "@touch", "@speed", "@attach", "@teleport","-", "-", "-", "-", "-" ]; + +string sCommand; // place to store a command for two-prompted ones +string sParam2; // place to store a prompt for two-prompted ones +string priPub = "Owner Only"; // Private or Group +key kUserKey; // the person who is controlling the avatar, not the Owner +// the command lists +list lCommands; // commands are stored here +list lNpcCommandList; // Storage for the NPC script. +string npcAction; // Storage for the next action. @cmd=0|hello, this becomes @cmd +string npcParams; // Storage for the param, @cmd=0|hello, this becomes 0|hello + +// misc vars +string sNotecard; // commands are stored here temporarily for dumping +vector vWanderPos; // a place to wander to +string lastANIM ; // last animation run +// Sensor +integer avatarPresent; // Sensor sets this flag when people are within Range. + +// Coordinate control +vector vInitialPos ; // Vector that will be filled by the script with the initial starting position in region coordinates. +vector vDestPos = ZERO_VECTOR; // Storage for destination position. +string relAbs = "Relative"; // absolute vs relative positioning + + +// STATES +integer MENU ; // processing a dialog box state, may be concurrent with STATE +integer STATE; // state storage +integer MakeNotecard = 1; // displaying a text box for NPC name +integer RecordPath = 2; // displaying a path notecard menu +integer NobodyHome = 3; // looking for an avatar +integer Spawning = 4; // spawning an avatar +integer Animate = 5; // animation timer needed +integer Walking = 6; // Hey! I am walking here! +integer Wander = 7; // Wandering around neeeds a timer, too +integer WanderHold = 8; // We reached a wander point +integer DoProcess = 9; // Set this to make it process a new command +integer Touch = 10; // Timer is busy sensing something to touch +integer Sit = 11; // Timer is busy sensing something to sit on +integer Paused = 12; // Timer is busy pausing + +key gNpcKey = NULL_KEY; // global key storage for the one NPC, to save CPU cycles +list Stack ; // a command stack from link message input + +integer SensorFunc = 0; // define which function shall be triggered inside the sensor function + // 0 means none, 1 sit, 2 touch +/////////////////////////////////////////////////////////////////////////// +// FUNCTIONS // +/////////////////////////////////////////////////////////////////////////// + + +TimerEvent(float timesent) +{ + if (LSLEditor) + timesent *= 5; // slow thinggs doen when the LSLEDITOR is in use + + DEBUG("Setting timer: " + (string) timesent); + llSetTimerEvent(timesent); +} + +// for 4.1 parse a message from a Listen or a Link message +ParseMsg(string str) { + DEBUG("Command In:" + str); + if (str=="@go") { + SetStop(FALSE); // Let's run the notecard + DEBUG("@go running"); + DoProcessNPCLine(); + } else { + Stack += [str]; // take anything, the controller will filter away non @ stuff + if (STATE == 0) { + DEBUG("calling DoNPC"); + DoProcessNPCLine(); + } else{ + DEBUG("Queued"); + } + } +} + +SetStop(integer what) +{ + DEBUG("Stopped set to " + (string ) what); + Stopped = what; +} +// Do* functions are much like states from the old V2 scripts. + +// Save a Path notecard +DoSave() +{ + STATE = MakeNotecard; + makeText("Stand where you want the NPC to appear, and enter the NPC Name"); +} + +// This function is used to record the path for the NPC +// Each command can take 0, 1, or 2 params +DoMenuForCommands() { + makeMenu(lAtButtons); +} + + +// No one is here when sensors were on, so we kill off the NPC +DoNobodyHome() +{ + DEBUG("Nobody Home"); + STATE = NobodyHome; + if (NPCKey() != NULL_KEY) { + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + } + TimerEvent(5); // keep ticking to sense avatars +} + +// Create a NPC +StateSpawn() { + DEBUG("state spawn"); + STATE = Spawning; + + + NPCEnabled = TRUE; // in world + // see if there is already one out there. + if (NPCKey() != NULL_KEY) { + DEBUG("Already living"); + return; + } + + + list name = llParseString2List(sNPCName, [" "], []); + + vector vRezPos = vInitialPos; + if (relAbs == "Relative"){ + vRezPos += llGetPos(); + } + + DEBUG("Rezzing the NPC:" + (string) vRezPos); + key aKey = osNpcCreate(llList2String(name, 0), llList2String(name, 1), vRezPos, Appearance, NPCOptions); + + SaveKey(aKey); // save in desceription and global, too + + osSetSpeed(aKey,SPEEDMULT); // 1.9 speed multiplier + TimerEvent(REZTIME); + NPCAnimate(STAND); +} + +DoRotate() { + DEBUG("@rotate=" + (string) RAMrot); + osNpcSetRot(NPCKey(), llEuler2Rot(<0,0,RAMrot> * DEG_TO_RAD)); +} + +StateSit() { + DEBUG ("state sit - looking for " + RAMsit); + STATE=Sit; + SensorFunc = 1; //triggers osNpcSit + llSensor(RAMsit, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +StateTouch() { + DEBUG ("state touch - looking for " + RAMtouch); + STATE = Touch; + SensorFunc = 2; //triggers osNpcTouch + llSensor(RAMtouch, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +DoStand() { + DEBUG("state stand"); + osNpcStand(NPCKey()); +} + + +StateAnimate() { + + DEBUG("state animate"); + STATE = Animate; + NPCAnimate(RAManimationName); + if (RAManimationTime <=0 ) // V 3.4 tweak + RAManimationTime = 1; + TimerEvent(RAManimationTime); +} + +StateWalk() { + + DEBUG("NPCWalkOption = " + (string) NPCWalkOption); + STATE = Walking; + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(WALK); + } else if (walkstate == 2) { + llShout(FLIGHT,"flying"); + NPCAnimate(FLY); + } else if (walkstate == 3) { + NPCAnimate(RUN); + } else if (walkstate == 4) { + NPCAnimate(LAND); + } + newDest = vDestPos ; + newDest.z += OffsetZ; + + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + newDest += llGetPos(); + } + + DEBUG("Moveto:" + (string) newDest); + osNpcMoveToTarget(NPCKey(), newDest, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + + +StateWander(){ + DEBUG("state wander"); + STATE = Wander; + + vector point = CirclePoint(RAMwd); + DEBUG("CirclePoint:" + (string) point); + vWanderPos = vDestPos + point; + DEBUG("vWanderPos:" + (string) vWanderPos); + + fTimerVal = WANDERTIME; // default time to pause after each wander + if (WANDERRAND) + fTimerVal = llFrand(WANDERTIME) + 1; // override, they want random times + + NPCAnimate(WALK); + + DEBUG("Wander to:" + (string) vWanderPos); + + osNpcMoveToTarget(NPCKey(), vWanderPos, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + +StateWanderhold() { + + DEBUG("Wander Hold"); + STATE = WanderHold; + + // now that we have reached a wander spot, slow the timer down to the desired value + TimerEvent(fTimerVal); +} + +// @pause=10 will do nothing for 10 seconds +DoPause() { + STATE =Paused; + if (RAMPause < 0.1) + RAMPause = 0.1; + DEBUG("@pause=" + (string)RAMPause); + TimerEvent(RAMPause); +} + + +// @stop makes the NPC stop moving in whatever state it is in. You have to linkmessage to get moving again +DoStop() { + DEBUG("NPC is Stopped"); + STATE = 0; // accept commands + SetStop(TRUE); // Link controlled - we mnust have a @go to continue with notecards + TimerEvent(0); + Stack = []; // v3.8 +} + +// @delete removes the NPC forever. Next command starts it up again at the beginning +DoDelete() { + DEBUG("state delete"); + STATE = 0; // accept commands + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + + TimerEvent(0); + Stack = []; // v3.8 +} + +// change the appearance of the NPC +DoAppearance(string notecard) { + DEBUG("state appearance"); + if (llGetInventoryType(notecard) == INVENTORY_NOTECARD){ + DEBUG("Load appearance " + notecard); + osNpcLoadAppearance(NPCKey(),notecard); + } +} + +// Change the avatar speed +DoSpeed(string speed) { + float newspeed = (float) speed; + if (newspeed > 0.1 && newspeed < 5.0) {// sanity check + osSetSpeed(NPCKey(),newspeed); + } +} + +DoTeleport(string params) { + list Data = llParseString2List(params, ["|"], []); + string itemName = llList2String(Data, 0); + vector Dest = (vector) itemName; + if (Dest != ZERO_VECTOR) { + if (relAbs == "Relative"){ + Dest += llGetPos(); + } + osTeleportAgent( NPCKey(), llGetRegionName(), Dest, ZERO_VECTOR ); + + } else { + llSay(DEBUG_CHANNEL,"Attempt to teleport to <0,0,0> probably not what you intended: @teleport="); + } +} + + + +DoNewNote (string card) { + DEBUG("Load Notecard " + card); + NPCReadNoteCard(card); + SetStop(FALSE); +} +DoAttach(string params) { + + list Data = llParseString2List(params, ["|"], []); + string itemName = llList2String(Data, 0); + integer attachmentPoint = (integer) llList2String(Data, 1); + if (attachmentPoint > 0 + && attachmentPoint < 40 + && llGetInventoryType(itemName) == INVENTORY_OBJECT + ) + { + osForceAttachToOtherAvatarFromInventory(NPCKey(),itemName,attachmentPoint); + } +} + +// This loops over the notecard, processing each command +DoProcessNPCLine() { + DEBUG("ProcessNPCLine, stopped = " + (string) Stopped); + STATE = DoProcess; + + // auto load a notecard + if (! llGetListLength(lNpcCommandList)) { + DEBUG("Read Notecard"); + NPCReadNoteCard(Notecard); + SetStop(FALSE); + } + + // look for link messages on the stack + string next = llList2String(Stack,0); // lets see if there is anithing from a link message + if (llStringLength(next)) + { + Stack = llDeleteSubList(Stack,0,0); + ProcessCmd(next); //lets do this command instead. + return; + } + + // @stop issued? + if (Stopped) { + TimerEvent(0); + DEBUG("Stopped, waiting for input"); + STATE = 0; + return; + } + + // No, we have an @go for liftoff + next = llList2String(lNpcCommandList, 0); // get the next command + DEBUG("Execute:" + next); + lNpcCommandList = llDeleteSubList(lNpcCommandList, 0, 0); // delete it + + if (llGetListLength(lNpcCommandList) == 0) { + DEBUG("EOF"); + } + ProcessCmd(next); +} + + + +ProcessCmd(string cmd) { + + DEBUG("ProcessCmd:" + cmd); + + if (llGetSubString(cmd, 0, 0) != "@") { + DEBUG("ignoring"); + TimerEvent(QUICK); // this is so we do not recurse the stack + STATE = 0; + return; + } + + list data = llParseString2List(cmd, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data, 0), STRING_TRIM)); + + DEBUG("Action:" + npcAction); + npcParams = llStringTrim(llList2String(data, 1), STRING_TRIM); + DEBUG("Params:" + npcParams); + + @commands; + + ProcessSensor(); + + if(npcAction == "@spawn" && avatarPresent) { + DEBUG("@spawn"); + list spawnData = llParseString2List(npcParams, ["|"], []); + sNPCName =llList2String(spawnData, 0); // V 1.6 name in RAM + + list spawnDest = llParseString2List(llList2String(spawnData, 1), ["<", ",", ">"], []); + vInitialPos.x = llList2Float(spawnDest, 0); + vInitialPos.y = llList2Float(spawnDest, 1); + vInitialPos.z = llList2Float(spawnDest, 2); + + DEBUG("Coords for NPC at " + (string) vInitialPos); + StateSpawn(); + return; + } + + if (! avatarPresent){ + DoNobodyHome(); + DEBUG("No avatar nearby"); + STATE = 0; + return; + } else { + if ( NPCKey() == NULL_KEY) { + StateSpawn(); + } + } + + + + + if(npcAction == "@stop") { + DoStop(); + STATE = 0; + return; + } + else if(npcAction == "@goto") { + DEBUG("goto"); + integer lastIdx = llGetListLength(lNpcCommandList)-1; + lNpcCommandList = llDeleteSubList(lNpcCommandList, lastIdx, lastIdx); + // Wind commands till goto label. + @wind; + string next1 = llList2String(lNpcCommandList, 0); + lNpcCommandList = llDeleteSubList(lNpcCommandList, 0, 0); + lNpcCommandList += next1; + if(next1 != npcParams) jump wind; + // Wind the label too. + next1 = llList2String(lNpcCommandList, 0); + lNpcCommandList = llDeleteSubList(lNpcCommandList, 0, 0); + lNpcCommandList += next1; + // Get next command. + list data1 = llParseString2List(next1, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data1, 0), STRING_TRIM)); + npcParams = llStringTrim(llList2String(data1, 1), STRING_TRIM); + // Reschedule. + jump commands; + } + else if(npcAction == "@sound") { + DEBUG("sound"); + llTriggerSound(npcParams,1.0); + } + else if(npcAction == "@randsound") { + DEBUG("@randsound"); + integer N = llGetInventoryNumber(INVENTORY_SOUND); + integer rand = llCeil(llFrand(N)) -1; // pick a random sound + string toPlay = llGetInventoryName(INVENTORY_SOUND,rand); + llTriggerSound(toPlay,1.0); + } + else if(npcAction == "@walk") { + DEBUG("@walk"); + GetDest(npcParams); + walkstate = 1;// walking + NPCWalkOption = OS_NPC_NO_FLY ; + StateWalk(); + return; + } + else if(npcAction == "@fly") { + GetDest(npcParams); + walkstate = 2;// flying + NPCWalkOption = OS_NPC_FLY ; + StateWalk(); + return; + } + else if(npcAction == "@run") { + DEBUG("@run"); + GetDest(npcParams); + walkstate = 3;// running + NPCWalkOption = OS_NPC_NO_FLY | OS_NPC_RUNNING; + StateWalk(); + return; + } + else if(npcAction == "@land") { + DEBUG("@land"); + GetDest(npcParams); + walkstate = 4;// landing + NPCWalkOption= OS_NPC_FLY | OS_NPC_LAND_AT_TARGET ; + StateWalk(); + return; + } + else if(npcAction == "@say") { + DEBUG("@say " + npcParams); + osNpcSay(NPCKey(), 0, npcParams); + } + else if(npcAction == "@shout") { + DEBUG("@shout"); + osNpcShout(NPCKey(),0, npcParams); + } + else if(npcAction == "@whisper") { + DEBUG("@whisper " + npcParams); + osNpcWhisper(NPCKey(),0, npcParams); + } + // speak a command on a channel, so you can open doors and control stuff. + else if(npcAction == "@cmd") { + DEBUG("@cmd"); + list dataToSpeak = llParseString2List(npcParams, ["|"], []); + string channel = llList2String(dataToSpeak,0); + DEBUG("Channel:"+(string) channel); + integer iChannel = (integer) channel; + string stringToSpeak = llList2String(dataToSpeak,1); + llSay(iChannel, stringToSpeak); + } + // stop everything + else if(npcAction == "@pause") { + RAMPause = (float) npcParams; + DoPause(); + return; + } + else if(npcAction == "@wander") { + list wanderData = llParseString2List(npcParams, ["|"], []); + RAMwd = (float) llList2String(wanderData, 0); + RAMwc = (integer) llList2String(wanderData, 1); + vDestPos = osNpcGetPos(NPCKey()); // set the wander start + DEBUG("Starting at " + (string) vDestPos); + StateWander(); + return; + } + else if(npcAction == "@rotate") { + RAMrot = (float) npcParams; + DoRotate(); + } + else if(npcAction == "@sit") { + RAMsit= npcParams; + StateSit(); + return; + } + else if(npcAction == "@touch") { + RAMtouch= npcParams; + StateTouch(); + return; + } + else if(npcAction == "@stand") { + DoStand(); + } + else if(npcAction == "@delete") { + DoDelete(); + SetStop(TRUE); // Link controlled - we mnust have a @go to continue with notecards + return; + } + else if(npcAction == "@animate") { + list animateData = llParseString2List(npcParams, ["|"], []); + RAManimationName = llList2String(animateData, 0); + RAManimationTime = (float) llList2String(animateData, 1); + StateAnimate(); + return; + } + else if(npcAction == "@appearance" ){ + DoAppearance(npcParams); + } + else if (npcAction =="@speed") { + DoSpeed(npcParams); + } + else if (npcAction =="@notecard") { + DoNewNote(npcParams); + Notecard = npcParams; + } + else if (npcAction == "@attach") + { + DoAttach(npcParams); + } + else if (npcAction == "@teleport") + { + DoTeleport(npcParams); + } + else if (npcAction == "@reset") + { + DoDelete(); + SetStop(FALSE); // a @resst will restart the original !Path after deleting the notecard. + } + + STATE = 0; + TimerEvent(QUICK); // yeah I know, not possible this fast, we just go as fast as we can go - this is so we do not recurse the stack +} + + + +/////////////////// UTILITY Functions, not state-like ////////////////// + +// DEBUG(string) will chat a string or display it as hovertext if debug == TRUE +DEBUG(string str) { + if (debug && ! LSLEditor) + llOwnerSay( str); // Send the owner debug info + if (debug && LSLEditor) + llSay(0, str); // Send to the Console in LSLEDitor + if (iTitleText) { + llSetText(str,<1.0,1.0,1.0>,1.0); // show hovertext + + } +} + +GetDest(string npcParams) { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); +} + +NPCReadNoteCard(string Note) { + DEBUG("NPCReadNoteCard"); + lNpcCommandList = llParseString2List(osGetNotecard(Note), ["\n"], []); +} + +integer SenseAvatar() +{ + //Returns a strided list of the UUID, position, and name of each avatar in the region + list avatars = llGetAgentList(AGENT_LIST_REGION ,[]); + integer numOfAvatars = llGetListLength(avatars); + if (numOfAvatars == 0) + { + DEBUG("No people"); + return 0; + } + //DEBUG("Located " + (string)numOfAvatars + " avatars and NPC's"); + + integer nAvatars; + integer i; + for( i = 0;i < numOfAvatars; i++) { + key aviKey = llList2Key(avatars,i); + if (!osIsNpc(aviKey)) { + list detail = llGetObjectDetails(aviKey,[OBJECT_POS]); + vector pos = llList2Vector(detail,0); + float dist = llVecDist(pos, llGetPos()); + if (dist < RANGE) + { + nAvatars++; + DEBUG("In range:" + llKey2Name(aviKey)); + } + } + } + //DEBUG("Located " + (string) nAvatars + " avatars"); + return nAvatars; +} + +// return TRUE if the avatar is owner when private is set, or TRUE if the avatar is in the same group and GROUP is set. +integer checkPerms() { + + integer group = (integer) KeyValueGet("pr"); + if (! group) + priPub = "Owner Only"; + else + priPub = "Group"; + + + if (llDetectedKey(0) == llGetOwner()){ + kUserKey = llDetectedKey(0); + return TRUE; + } + + if ( group && llDetectedGroup(0)) { + kUserKey = llDetectedKey(0); + return TRUE; + } + kUserKey = llDetectedKey(0); + return FALSE; +} + + + +NPCAnimate(string anim) +{ + DEBUG("Start Anim: " + anim); + if (llGetInventoryType(anim) == INVENTORY_ANIMATION ) { + + if (lastANIM != anim) { + if(llStringLength(lastANIM)) { + osNpcStopAnimation(NPCKey(), lastANIM); + } + osNpcPlayAnimation(NPCKey(), anim); + lastANIM = anim; + } + } else { + llSay(DEBUG_CHANNEL, "No animation named " + anim); + } +} + +// Kill a NPC by Name +Kill(string param) +{ + integer count; + list avatars = osGetAvatarList(); // Returns a strided list of the UUID, position, and name of each avatar in the region except the owner.\ + integer i; + integer j = llGetListLength(avatars); + for (i=0 ; i <= j; i+=3){ + + string desired = llList2String(avatars,i+2); + desired = llStringTrim(desired,STRING_TRIM); // should not be needed but is needed + + if (desired == param){ + vector v = llList2Vector(avatars,i+1); + key target = llList2Key(avatars,i); // get the UUID of the avatar + osNpcRemove(target); + + llOwnerSay("Removed " + param+ " at location " + (string) v); + count++; + } + } + + NPCEnabled = FALSE; // not in world + SaveKey(NULL_KEY ); // Rev 4.4 + + if (count) + llOwnerSay("Removed " + (string) count + " NPC's"); + else + llOwnerSay("Could not locate " + param); +} + + +// return a String for the position we are at. Strings used as the caller wants strings +string Pos() +{ + vector where = llGetPos(); // find the box position + + where.z += OffsetZ; // use the ground position + an offset + + if (LSLEditor) + where = <128,128,31 + llFrand(1)>; // force center of sim when editing + + // if attached the height will be too high by 1/2 the agent size + if (llGetAttached()) { + vector size = llGetAgentSize(llGetOwner()); + float Z = size.z; + where.z -= Z/2; + } + + // DEBUG("Pos= " + (string) where); + return (string) where; +} + +// setup a menu with a timer for timeouts, called by all make*() +menu() +{ + llListenRemove(iHandle); + iChannel = llCeil(llFrand(100000) + 20000); + iHandle = llListen(iChannel,"","",""); + TimerEvent(30.0); + MENU = TRUE; +} + +// make a text box +makeText(string Param) +{ + menu(); + llTextBox(kUserKey, Param, iChannel); +} + +// top level menu +makeMainMenu() +{ + menu(); + list buttons = ["Appearance","Recording","Save","Help","-","Erase RAM", priPub,relAbs,"-","Stop NPC",mSensor,"Start NPC"]; + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Records",buttons,iChannel); +} + + +// Rev 1.4 +// top level menu for non group/ non owners +makeUserMenu() +{ + if (!allowUsers) return; + + menu(); + list buttons = ["Start NPC","Stop NPC"]; + llDialog(kUserKey,"Choose",buttons,iChannel); +} + + + +// programmable menu for @commands +makeMenu(list buttons) +{ + menu(); + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Record",buttons,iChannel); +} + + +// make one or two text boxes with prompts +Text(string cmd, string p1, string p2) +{ + sCommand = cmd; + sParam2 = ""; + if (llStringLength(p2)) + sParam2 = p2; + + makeText(p1); +} + +// Set the Avatar Present flag - if sensors are off and we are forece run, there will be one present. +ProcessSensor() +{ + integer SensorOn; + if ("on" == KeyValueGet("se")) + { + SensorOn = TRUE; // we need to scan for avatars + } else { + SensorOn = FALSE; // we need to scan for avatars + } + DEBUG("Sensor:" + (string) SensorOn); + + integer n = SenseAvatar(); + + DEBUG("Avatars:" + (string) n); + if (SensorOn && n) + avatarPresent = TRUE; // someone is here and we need to tell the system to run + else if (SensorOn && !n) + avatarPresent = FALSE; // someone is not here and we need to tell the system to stop + else { // sensor is off, lete see if there is a NPC. If so, we are ON + DEBUG("NPCEnabled:" + (string) NPCEnabled); + if (NPCEnabled) + avatarPresent = TRUE; + else + avatarPresent = FALSE; + } + + // start up from when when no one is near + if (avatarPresent && STATE == NobodyHome) + STATE = 0; + + DEBUG("Avatar Present: " + (string) avatarPresent); +} + +vector CirclePoint(float radius) { + float x = llFrand(radius *2) - radius; // +/- radius, randomized + float y = llFrand(radius *2) - radius; // +/- radius, randomized + return ; // so this should always happen +} + +string KeyValueGet(string var) { + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k != var) jump continue; + //DEBUG("got " + var + " = " + llList2String(data, 1)); + return llList2String(data, 1); + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + return ""; +} + +KeyValueSet(string var, string val) { + + //DEBUG("set " + var + " = " + val); + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + if(llGetListLength(dVars) == 0) + { + llSetObjectDesc(var + "=" + val); + return; + } + list result = []; + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k == "") jump continue; + if(k == var && val == "") jump continue; + if(k == var) { + result += k + "=" + val; + val = ""; + jump continue; + } + string v = llList2String(data, 1); + if(v == "") jump continue; + result += k + "=" + v; + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + if(val != "") result += var + "=" + val; + llSetObjectDesc(llDumpList2String(result, "&")); +} + + +// clear RAM +Clr() { + + lCommands = []; + llOwnerSay("RAM Memory cleared. Notecards, if any, are not modified."); + makeMainMenu(); +} + +integer checkNoteCards() +{ + // Check that they have saved an Appeaance and Path notecard + integer num = llGetInventoryNumber(INVENTORY_NOTECARD); // how many notecards overall + + integer i; + integer count; + for (; i < num; i++){ + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Notecard) + count++; + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Appearance) + count++; + } + DEBUG("Checked " + (string) count + " Notecards"); + // if we have both, run the NPC + return count; +} + +Update(string SName) { + + // delete all NPC* scripts except myself + integer i; + integer j = llGetInventoryNumber(INVENTORY_SCRIPT); + for (i = 0; i < j; i++) { + string targetName = llGetInventoryName(INVENTORY_SCRIPT,i); + string match = llGetSubString(targetName,0,2); + + if (match == SName && llGetScriptName() != targetName){ + llOwnerSay("Upgrading " + targetName); + if (! LSLEditor){ // lets not kill the editor + llRemoveInventory(targetName); + } + } + } +} + +// Get all default saved params from the Description +GetSwitches() +{ + string rA = KeyValueGet("co"); // Get the remembered menu setting for Abs Vs Relative + if (rA == "A") + relAbs = "Absolute"; + else if (rA == "R") + relAbs = "Relative"; + else + relAbs = "Absolute"; + + + // reenable NPC if sensor is on. + if ("on" == KeyValueGet("se")) + { + NPCEnabled = TRUE; + mSensor = "Sense is On"; + ProcessSensor(); // fake 1 avatar to get it rezzed + } else { + mSensor = "Sense is Off"; + } + } + + +SaveKey(key akey) +{ + DEBUG("Saving Key of " + (string) akey); + KeyValueSet("key", akey); + if (akey != (key) KeyValueGet("key") ) + { + DEBUG("Fatal error, cannot save key"); + } + gNpcKey = akey; +} + + +key NPCKey() +{ + key akey = gNpcKey; // from cached copy + // gNpcKey saves a lot of CPU processing by caching the key, if blank we get it from the description + if (gNpcKey == NULL_KEY) + { + //DEBUG("Get DKey"); + akey = KeyValueGet("key"); // from Description of the prim + } + // DEBUG("NPC KEY:" + (string) akey); + return akey; +} + + +/////////////////// CODE BEGINS ////////////////// + + +default +{ + changed(integer change) { + if(change & CHANGED_REGION_START) { + llResetScript(); + } + } + + on_rez(integer start_param) + { + llResetScript(); + } + + state_entry() { + + llSetText("",<1,1,1>,1.0); // clr all hovertext- we may not be using it. + DoDelete(); // kill any NPC that is out running + Update("NPC"); // If dragged and ropped into a prim with any script named "NPC...", this will replace it. + GetSwitches(); // Get all default saved params from the Description + + // 4.1 allow listeners to send us commands + if (allowListener) + llListen(link_Channel,"","",""); + TimerEvent(TIMER); + } + + + touch_start(integer n) + { // if touched, make a menu + + if (checkPerms()) { + if (RecordPath == STATE) { + makeMenu(lAtButtons); + } else { + makeMainMenu(); + } + } else { + makeUserMenu(); + } + } + + // menu listener + listen(integer iChannel, string name, key id, string message) { + + // process @commands that come in via the listener + if (iChannel == link_Channel) + { + ParseMsg(message); + return; + } + + if (MENU) { + llListenRemove(iHandle); + MENU = 0; // menu is off + iHandle = 0; + } + + if (message == "Stop NPC") + { + lNpcCommandList = []; // force reload of notecard + NPCEnabled = FALSE; + if (NPCKey() != NULL_KEY){ + Kill(sNPCName); + sNPCName = ""; + } else { + bNPC_STOP = TRUE; + makeText("Enter name of an NPC to stop"); + } + } + else if (message == "Menu" ) { + makeMainMenu(); + } + else if (message == "Erase RAM"){ + Clr(); + } + else if (message == "Relative"){ + relAbs = "Absolute"; + KeyValueSet("co","A"); // remember coordinates = A + Clr(); + } + else if (message == "Absolute"){ + relAbs = "Relative"; + KeyValueSet("co","R"); // remember coordinates = R + Clr(); + } + else if (message == "Recording"){ + DoMenuForCommands(); // show them the recording menu + } + else if (message == "Owner Only") { + priPub = "Group"; + KeyValueSet("pr","1"); + + llOwnerSay("Group members have control"); + makeMainMenu(); + } + else if (message == "Group") { + priPub = "Owner Only"; + KeyValueSet("pr","0"); + llOwnerSay("Only you have control"); + makeMainMenu(); + } + else if (message == "Sense is On") { + mSensor ="Sense is Off"; + KeyValueSet("se", "off"); + llOwnerSay(mSensor); + makeMainMenu(); + } + else if (message == "Sense is Off") { + mSensor ="Sense is On"; + llOwnerSay(mSensor); + KeyValueSet("se", "on"); + + NPCEnabled = FALSE; + + integer count = checkNoteCards(); + if (count >= 2) { + DEBUG("Notecards ok, DoProcessNPCLine"); + DoProcessNPCLine(); + return; + } + if (LSLEditor) { + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording and/or appearance, so you cannot start a NPC"); + makeMainMenu(); + } + else if (message == "Appearance") { + llRemoveInventory(Appearance); // delete the notecard + osAgentSaveAppearance(kUserKey,Appearance); // make the ntecard + llOwnerSay("Your outfit has been saved"); + makeMainMenu(); + } + else if (message == "Save") { + if (llGetListLength(lCommands) == 0) { + llOwnerSay("Nothing recorded, you need to make a recording first"); + makeMainMenu(); + return; + } + DoSave(); + } + else if (message == "Help"){ + llLoadURL(kUserKey,"Click to view help","http://www.outworldz.com/opensim/posts/NPC/"); + makeMainMenu(); + } + else if (message == "Start NPC") { + integer count = checkNoteCards(); + + NPCEnabled = TRUE; + + if (LSLEditor) { + DoProcessNPCLine(); + return; + } + + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + SetStop(FALSE); // Let's run the notecard + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording or maybe an appearance, so we cannot start a NPC"); + + } + else if (bNPC_STOP){ + bNPC_STOP = FALSE; + Kill(message); + } + else if (message == ">>"){ + makeMenu(lMenu2); + } + else if (message == ">>>"){ + makeMenu(lMenu3); + } + else if (message == "<<") { + makeMenu(lAtButtons); + } + else if (message == "<<<") { + makeMenu(lMenu2); + } + else if (message == "@comment"){ + Text("# ","Enter a comment",""); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@run"){ + lCommands += "@run=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@fly"){ + lCommands += "@fly=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@land"){ + lCommands += "@land=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@walk") { + lCommands += "@walk=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@sound"){ + Text("@sound=","Enter a sound name or UUID to trigger",""); + } + else if (message == "@randsound"){ + lCommands += "@randsound"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@say") { + Text("@say=","Enter what the NPC will say",""); + } + else if (message == "@whisper"){ + Text("@whisper=","Enter what the NPC will whisper",""); + } + else if (message == "@shout"){ + Text("@shout=","Enter what the NPC will shout",""); + } + else if (message == "@wander") { + Text("@wander=","Enter radius to wander","Enter number of wanders"); + } + else if (message == "@pause") { + Text("@pause=","Enter time to pause",""); + } + else if (message == "@rotate") { + Text("@rotate=","Enter degrees to rotate",""); + } + else if (message == "@sit"){ + Text("@sit=","Enter name of object to sit on",""); + } + else if (message == "@teleport"){ + lCommands += "@teleport=" + Pos() + "\n"; + llOwnerSay("teleport to position: " + Pos()); + makeMenu(lMenu3); + } + else if (message == "@touch"){ + Text("@touch=","Enter name of object to touch",""); + } + else if (message == "@cmd"){ + Text("@cmd=","Enter cjhannel to speak on","Enter text to speak"); + } + else if (message == "@stand"){ + lCommands += "@stand\n"; + llOwnerSay("Stand Recorded"); + makeMenu(lAtButtons); + } + else if (message == "@animate"){ + Text("@animate=","Enter animation name to play","Enter time to play the animation"); + } + else if (message == "@attach"){ + Text("@animate=","Enter inventory name to attach","Enter number of the attachment point (1-40)"); + } + else if (message == "@speed"){ + Text("@speed=","Enter a speed for the NPC, 1=100% normal speed, 0.5=50% speed",""); + } + + + // Save NPC name + else if (MakeNotecard == STATE) { + sNPCName = message; // in case we need to kill it. + + vector vDest = (vector) Pos(); + + if (relAbs == "Relative") + { + vDest -= llGetPos(); // just an offset for relative + } + sNotecard = "@spawn=" + message + "|" + (string) vDest + "\n"; + integer i; + integer j = llGetListLength(lCommands); + for (; i < j; i++){ + // get the command to save to the notecard + string line = llList2String(lCommands,i); + if (relAbs == "Absolute") { + sNotecard += line; // add the un-modified string to the notecard + } else { + // since we have to record absolute coords since we do not know where the box goes until they press Save, + // we process the absolute to relative conversion for walks here + list parts = llParseString2List(line,["="],[]); //get the @command + + if (llList2String(parts,0) == "@walk") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@walk=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@fly") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@fly=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@run") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@run=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@land") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@land=" + (string) vec + "\n"; + } + else { + sNotecard += line; // add the un-modified string to the notecard + } + } + } + llRemoveInventory(Notecard); // delete the old notecard + osMakeNotecard(Notecard,sNotecard); // Makes the notecard. + llSay(0,sNotecard); + llOwnerSay("Commands notecard has been written"); + STATE = 0; + } // MakeNotecard + + else if (! llStringLength(sParam2)) { + lCommands += sCommand + message + "\n"; + llOwnerSay("Recorded"); + makeMenu(lAtButtons); + } + else if (llStringLength(sParam2)){ + sCommand = sCommand + message + "|"; + llOwnerSay("Recorded"); + makeText(sParam2); + sParam2 = ""; + } + + } + + + + timer(){ + // DEBUG("tick"); + + // if llDialog is up, kill the listener for the dialog box. + if (iHandle) { + llOwnerSay("Menu timed out"); + llListenRemove(iHandle); + iHandle = 0; + return; // ^^^^^^^^^^^^^^^^^^^^^^^ + } + // if NoBodyHome, we are sensing for an avatar + else if (NobodyHome == STATE) { + ProcessSensor(); + return; + } + // if we are spawning, we need time to rez the NPC, then start processing NPC Commands. + else if (Spawning == STATE) { + STATE = 0; + TimerEvent(TIMER); + } + // We end aniamtions with a timer + else if (Animate == STATE){ + NPCAnimate(STAND); + TimerEvent(TIMER); + } + + else if (Walking == STATE) { + if (--iWaitCounter) { + if (llVecDist(osNpcGetPos(NPCKey()), newDest) > MAXDIST) { + return; + } + } + + DEBUG("At Destination: " + (string) newDest); + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 2) { + // nothing + } else if (walkstate == 3) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 4) { + llShout(FLIGHT,"landing"); + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } + } + // Wandering timer + else if (Wander == STATE) { + if (--iWaitCounter) { // wait 60 seconds to get to a destination. + if (llVecDist(osNpcGetPos(NPCKey()), vWanderPos) > MAXDIST) + return; + } + + // see if wander counter == 0, if so, stop walking, go to stand and process next line + if(RAMwc == 0) { + NPCAnimate(STAND); + DEBUG("Wander ended, calling DoProcessNPCLine"); + STATE = 0; + DoProcessNPCLine(); + return; + } + // one less time to wander around + RAMwc--; + NPCAnimate(STAND); + TimerEvent(TIMER); + StateWanderhold(); + return; + } + // Wandering requires us to re-wander when we reach a destination + else if (WanderHold == STATE) { + StateWander(); + TimerEvent(TIMER); + return; + } + else if (DoProcess == STATE) { + TimerEvent(QUICK); + } + + + STATE = 0; + + // We always process a NPC line at end of timer. + DEBUG("Tick end, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } + + // sensors are used for sitting on prims + // Neo Cortex: added different SensorFunc states to trigger sit or touch + sensor(integer num) { + if (SensorFunc == 1) { + osNpcSit(NPCKey(), llDetectedKey(0), OS_NPC_SIT_NOW); + DEBUG("Seated, calling DoProcessNPCLine"); + SensorFunc = 0; + } else if (SensorFunc == 2) { + osNpcTouch(NPCKey(), llDetectedKey(0), LINK_THIS); + DEBUG("Touched, calling DoProcessNPCLine"); + SensorFunc = 0; + } + DoProcessNPCLine(); + } + no_sensor(){ + DEBUG ("no target prim located, calling DoProcessNPCLine"); + SensorFunc = 0; + DoProcessNPCLine(); + } + + + link_message(integer sender, integer num, string str, key id){ + ParseMsg(str); + } + +} + + + + + + diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 4.5.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 4.5.lsl new file mode 100644 index 00000000..ced2d987 --- /dev/null +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC Recorder Script v 4.5.lsl @@ -0,0 +1,1689 @@ +// :SHOW:1 +// :CATEGORY:NPC +// :NAME:All In One NPC Recorder and Player +// :AUTHOR:Ferd Frederix +// :KEYWORDS:NPC, Puppeteer +// :CREATED:2015-09-29 18:04:52 +// :EDITED:2015-09-29 17:04:52 +// :ID:27 +// :NUM:1831 +// :REV:4.5 +// :WORLD:OpenSim +// :DESCRIPTION: +// All in one NPC recorder player. +// Supports both absolute and relative paths and many new commands +// Add animations named "Fly, Walk, Stand and Run" +// Click Prim to use. +// Should be worn as a HUD to record. +// Put it on the ground and click Sensor or Start NPC when done. +// :CODE: +// This is Rev 4.5 09/26/2015 + +// Revision History +// Rev 1.1 10-2-2014 @Sit did not work. Minor tweaks to casting for lslEditor +// Rev 1.2 10-14-2014 @ sit had wrong type. +// Rev 1.3 relative movement fixed for @fly +// Rev 1.4 4-3-2014 allow anyone to use this, non owners and non group members can only start and stop. +// Rev 1.5 5-17-2014 set sensor to auto start on reboot of sim +// Rev 1.6 5-24-2014 move menu so you can get it by touching, removed many of the KeyValues to RAM for efficiency +// Rev 1.7 CHANGED_REGION_START, not CHANGED_REGION_START (Opensim difference) +// Rev 1.8 tuned up Kill NPC, added more flexible upgrader +// Rev 1.9 Better script injection by link message// Rev 2.0 Added osSetSpeed so you can speed up or slow down an NPC. +// Rev 2.1 No laggy sensor used exept to sit on stuff +// Rev 2.2 Various sensor fixes +// Rev 2.3 Sets No Sensor in menu, must be started by hand +// Rev 2.4 - reserved for patches to 2.3 if needed +// Rev 3.0 Refactor out into subs, not states to make command injection easier +// New command: @appearance=Notecardname so you can switch to a new notecard on the fly +// New command: @speed=1.0 which slows up ( < 1 ) or speeds up ( > 1) +// Rev 3.1 Commands are not interruptible by Link Message +// Rev 3.2 Sensor patches for consistency in removing the NPC +// Rev 3.3 Added Touch command by Neo.Cortex@hbase42/hopto/org:8002 +// Added Menu 3 for notecard and appearance commands +// Rev 3.4 animation timer cannot be zero or it shuts off timer tweaked +// solves the NPC starting up when no sensor is set. +// Rev 3.5 fixes saving to !Path notecard +// Rev 3.6 08-11-2015 @delete acts like @stop. TYjhe NPC now rezzes after an @go back in where it was deleted +// Rev 3.7 08-11-2015 @attach command added to load an attachment from the inventory to the NPC +// Rev 3.8 08-17-2015 process queued commands one at a time without calling ProcessNPCLine on link message +// Rev 3.9 08-23-2011 Queued command fixes including @delete which were not always working +// Rev 4.0 09-15-2015 Fixes for Sensor functions which continually rezzed a NPC when no one was around. +// Rev 4.1 09-20-2015 Added a Listener so link messages are not needed +// Rev 4.2 09-23-2015 Added @teleport= +// Rev 4.3 09-24-2015 Added @reset to restart the NPC at the very start of the !Path notecard +// @teleport works for relative and absolute modes +// Rev 4.4 09-26-2015 if it could not find the (deleted) NPC, it could not restart +// Rev 4.5 09-29-2015 remove wait for STATE == 0 +//*******************************************************************// + +// Instructions on how to use this are at http://www.outworldz.com/opensim/posts/NPC/ +// This is an OpenSim-only script. +// Author: Ferd Frederix aka Fred Beckhusen - fred@mitsi.com + +//////////////////////////////////////////////////////////////////////////////////////////// +// Original code was Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // +/////////////////////////////////////////////////////////////////////////////////////////// +// Please see: http://www.gnu.org/licenses/gpl.html for legal details, // +// rights of fair usage, the disclaimer and warranty conditions. // +/////////////////////////////////////////////////////////////////////////////////////////// +// The original NPC controller was from http://was.fm/opensim:npc +// Extensive additions and bug fixes by Fred Beckhusen, aka Ferd Frederix +// llSensor had two params swapped +// @Wander would wander where it had rezzed, not where it was. +// There was no 'no_sensor' event in sit, so if a @sit failed, the NPC got stuck +// The animation and walks always stopped old, then started new. It should be start new, then stop old so the default stand would be suppressed. +// New code: +// Merged with new Route recorder and notecard writer +// If the NPC failed to reach a destination it never moved on. +// Added WAIT global to tune this +// Exposed many tunable variables and ported the code +// Added floating point to times in notecard. +// Added @sound, @randsound, @whisper, @shout, and @cmd controls. +// notecards integers are not floats for better control +// +// Link Messages may be used to perform external control by injecting @commands into the stream of actions +// Example: +// To chat something, such as with a chat robot +// llMessageLinked(LINK_SET,0,"@npc_say=Hello",""); + +// This script assumes that NPCs and OSSl scripting is enabled in the OpenSim configuration. +// In order to enable them, the following changes must be made in the OpenSim.ini configuration file: +// +// ; Turn on OSSL +// AllowOSFunctions = true +// OSFunctionThreatLevel = Severe + +//[NPC] +// ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} +// Enabled = true +// +// and then the server has to be restarted. +// please note that there are better ways to enable NPC in the latest Opensim. + +// Commands: All commands begin with an @ sign. All other lines are ignored +// @commands may have optional parameters. The syntax is always: +// @cmd=parm1|parm2 +// NaN in the table below meand Not a Number. This means there is no parameter + +//Command First Parameter Second Parameter Description +//@spawn name location (vector) Rezzes an NPC with name at a location. +//@appearance NoteCardName NaN switch the NPC appearance to a new notecard +//@walk destination (vector) NaN Makes the NPC walk to destination. +//@fly destination (vector) NaN Makes the NPC fly to destination. +//@land destination (vector) NaN Makes the NPC land at destination. +//@say string NaN Makes the NPC speak a phrase. +//@whisper string NaN Makes the NPC whisper a phrase. +//@shout string NaN Makes the NPC shout a phrase. +//@pause seconds (float) NaN Makes the NPC wait for a multiple of seconds. +//@wander radius (float) cycles (integer) Makes the NPC wander in radius, for cycles seconds. +//@delete NaN NaN Removes the NPC. Requires a link message to continue +//@goto label (string) NaN Jump to the label label in the script. +//@animate animation (string) time (float) Makes the NPC trigger the animation animation for time seconds. +//@sound sound_name NaN plays a sound from inventory +//@randsound NaN NaN Plays a random sound from inventory +//@rotate degrees (float) NaN Rotate the NPC degrees around the Z axis. +//@sit primitive name NaN Sit on a primitive with a given name. +//@touch primitive name NaN Touch on a primitive with a given name. +//@stand NaN NaN If sitting on a primitive, stand up. +//@cmd channel (integer) string Says string on channel, for controlling external gadgets +//@stop NaN NaN Halts the NPC script indefinitely. Can be started with a link message +//@go NaN NaN Continues on next notecard line, for use in link messages +//@speed speed (float) NaN from 0 to N, where 1.0 ius a normal speed of an avatar. 0.2 is a turtle. +//@notecard notename (string) NaN load a new Path notecard +//@attach InventoryName attachmentPoint load an attachment from the inventory to the NPC onto point +//@teleport destination (vector) NaN Makes the NPC teleport to destination in the same sim. They cannot tp to another sim or across the HG +//@reset NaN NaN Deletes the NPC, starts the !Path notecard over. + +// Constant attachmentPoint Comment +// ATTACH_CHEST 1 chest/sternum +// ATTACH_HEAD 2 head +// ATTACH_LSHOULDER 3 left shoulder +// ATTACH_RSHOULDER 4 right shoulder +// ATTACH_LHAND 5 left hand +// ATTACH_RHAND 6 right hand +// ATTACH_LFOOT 7 left foot +// ATTACH_RFOOT 8 right foot +// ATTACH_BACK 9 back +// ATTACH_PELVIS 10 pelvis +// ATTACH_MOUTH 11 mouth +// ATTACH_CHIN 12 chin +// ATTACH_LEAR 13 left ear +// ATTACH_REAR 14 right ear +// ATTACH_LEYE 15 left eye +// ATTACH_REYE 16 right eye +// ATTACH_NOSE 17 nose +// ATTACH_RUARM 18 right upper arm +// ATTACH_RLARM 19 right lower arm +// ATTACH_LUARM 20 left upper arm +// ATTACH_LLARM 21 left lower arm +// ATTACH_RHIP 22 right hip +// ATTACH_RULEG 23 right upper leg +// ATTACH_RLLEG 24 right lower leg +// ATTACH_LHIP 25 left hip +// ATTACH_LULEG 26 left upper leg +// ATTACH_LLLEG 27 left lower leg +// ATTACH_BELLY 28 belly/stomach/tummy +// ATTACH_LEFT_PEC 29 left pectoral +// ATTACH_RIGHT_PEC 30 right pectoral +// ATTACH_HUD_CENTER_2 31 HUD Center 2 +// ATTACH_HUD_TOP_RIGHT 32 HUD Top Right +// ATTACH_HUD_TOP_CENTER 33 HUD Top +// ATTACH_HUD_TOP_LEFT 34 HUD Top Left +// ATTACH_HUD_CENTER_1 35 HUD Center +// ATTACH_HUD_BOTTOM_LEFT 36 HUD Bottom Left +// ATTACH_HUD_BOTTOM 37 HUD Bottom +// ATTACH_HUD_BOTTOM_RIGHT 38 HUD Bottom Right +// ATTACH_NECK 39 neck +// ATTACH_AVATAR_CENTER 40 avatar center/root + + + +////////////////////////////////////////////////////////// +// DEBUG // +////////////////////////////////////////////////////////// +integer debug = FALSE; // set to TRUE or FALSE for debug chat on various actions +integer LSLEditor = FALSE; // set to to TRUE to working in LSLEditor, FALSE for in-world. + // you must also include the NPC commands found in the other script since LSLEditor does not support OpenSim +integer iTitleText = FALSE; // set to TRUE to see debug info in text above the controller + +////////////////////////////////////////////////////////// +// TUNABLE CONFIGURATION // +////////////////////////////////////////////////////////// +float RANGE = 100; // 1 to N meters - anyone this close to the controller will start NPCS if Sensor button is clicked +integer allowListener = FALSE; // set to TRUE to anable a command listener. Usually, this is setto FALSE +integer link_Channel = 4223; // some random number you want to talk to this gadget on. Best if large and negative +float TIMER = 2; // faster = less jerky stopping. How often the system checks the distance traveled. Fastest you can go is 0.5 seconds +float QUICK = 1; // when we need to move to the next state, we use a QUICK timer +string Appearance = "!Appearance"; // The name of the recorded Appearance notecard +string Notecard = "!Path"; // The name of the recorded routes +integer allowUsers = FALSE; // If true, any user can get a Start NPC and Stop NPC menu. Only groups and owners can get all commands if TRUE, or FALSE +float MAXDIST = 2.0; // how close a NPC has to get to a dest pos to continue to next state. Do not lower this too much, as it may miss the target +integer WANDERRAND = TRUE; // set to TRUE and they will pause during wanders a random number of seconds +float WANDERTIME = 3.0; // how long they stand after each @wander,if WANDERRAND is FALSE. If WANDERRAND is TRUE, this is the max time +integer WAIT = 30; // wait for this number of seconds for the NPC to reach a destination (for safety). If it fails to reach a target, it will move on after this time. + +float REZTIME = 2.0; // wait this long for NPC to rez in, then start the process +string STAND = "Stand"; // the name of the default Stand animation +string WALK = "Walk"; // the name of the default Walk animation +string FLY = "Fly"; // the name of the default Fly animation +string RUN = "Run"; // the name of the default Run animation +string LAND = "Land"; // the name of the default land animation ( for birds only) +float OffsetZ = 0.5; // appear 0.5 meter above ground, this is added to all destinations to keep them from sinking in. +float SPEEDMULT =0.8; // 1.0 = regular avatar speed. Smaller numbers slow down walks. Large numbers speed them up. +integer FLIGHT = 299; // For controlling wings. A channel that is shouted at when flight starts and ends. "flying" or "landing" + +// DESCRIPTIONS FIELDS HAVE TO SURVIVE A RESET +// These vars are stored by saving them with KeyValueSet +// "pr" is a 0 if it is set for Owner Only, 1 for Group control +// "se" is "on" if Started +// "co" = "R" or "A" for relative or absolute addressing mode +// "key" = NPC key + +// These Globals used to be stored in description. Moved to RAM in V1.6 +float RAMPause; // @pause param +float RAMwd ; // @wander distance +integer RAMwc; // @wander count +float RAMrot; // @rotate +string RAMsit; // @sit primname +string RAMtouch; // @touch primname +string RAManimationName; // @animate animation (string) time (float) +float RAManimationTime; + +// other globals section +integer iChannel; // a listen channel, randomly assigned +integer iHandle; // the handle to it + +// NPC controls +vector newDest ; // tmp storage for the walks +integer iWaitCounter ; // wait for this number of seconds for the NPC to reach a desrtination +string sNPCName; // the name of the NPC that may be in world. So we can remove it. +integer bNPC_STOP = FALSE; // boolean to reuse a listener +integer Stopped = FALSE; // set to TRUE by link messages so we do not remember them +float fTimerVal ; // how long we wait when wandering (calculated) +float NPCEnabled; // true if the NPC is suppodes to be running + +// OS_NPC_CREATOR_OWNED will create an 'owned' NPC that will only respond to osNpc* commands issued from scripts that have the same owner as the one that created the NPC. +// OS_NPC_NOT_OWNED will create an 'unowned' NPC that will respond to any script that has OSSL permissions to call osNpc* commands. +integer NPCOptions = OS_NPC_CREATOR_OWNED; // only yhe owner of this box can control this NPC. + +integer walkstate = 0; // helps us reshare the walk state for run, fly and land - a bit of a hack, but it saves RAM. Has to be done this way because some bits of NPCWalkOption are asserted as 0 + +integer NPCWalkOption; // Some notes for what happens to NPCWalkOption: +// OS_NPC_FLY - Fly the avatar to the given position. The avatar will not land unless the OS_NPC_LAND_AT_TARGET option is also given. +// OS_NPC_NO_FLY - Do not fly to the target. The NPC will attempt to walk to the location. If it's up in the air then the avatar will keep bouncing hopeless until another move target is given or the move is stopped +//OS_NPC_LAND_AT_TARGET - If given and the avatar is flying, then it will land when it reaches the target. If OS_NPC_NO_FLY is given then this option has no effect. +// OS_NPC_RUNNING - if given, NPC avatar moves at running/fast flying speed, otherwise moves at walking/slow flying speed. + +// menus +string mSensor="Sense is Off"; // Sensor or "No Sensor" + +list lAtButtons = ["Menu","-", ">>", "@run", "@walk", "@fly", "@land", "@wander", "@sit", "@stand","@animate","@rotate"]; +list lMenu2 = ["<<", "@comment", ">>>", "@stop", "@say", "@whisper","@shout","@sound","@randsound","@cmd", "@pause", "@delete"]; +list lMenu3 = ["<<<","@notecard","@appearance", "@touch", "@speed", "@attach", "@teleport","-", "-", "-", "-", "-" ]; + +string sCommand; // place to store a command for two-prompted ones +string sParam2; // place to store a prompt for two-prompted ones +string priPub = "Owner Only"; // Private or Group +key kUserKey; // the person who is controlling the avatar, not the Owner +// the command lists +list lCommands; // commands are stored here +list lNpcCommandList; // Storage for the NPC script. +string npcAction; // Storage for the next action. @cmd=0|hello, this becomes @cmd +string npcParams; // Storage for the param, @cmd=0|hello, this becomes 0|hello + +// misc vars +string sNotecard; // commands are stored here temporarily for dumping +vector vWanderPos; // a place to wander to +string lastANIM ; // last animation run +// Sensor +integer avatarPresent; // Sensor sets this flag when people are within Range. + +// Coordinate control +vector vInitialPos ; // Vector that will be filled by the script with the initial starting position in region coordinates. +vector vDestPos = ZERO_VECTOR; // Storage for destination position. +string relAbs = "Relative"; // absolute vs relative positioning + + +// STATES +integer MENU ; // processing a dialog box state, may be concurrent with STATE +integer STATE; // state storage +integer NULL = 0; // the null state +integer MakeNotecard = 1; // displaying a text box for NPC name +integer RecordPath = 2; // displaying a path notecard menu +integer NobodyHome = 3; // looking for an avatar +integer Spawning = 4; // spawning an avatar +integer Animate = 5; // animation timer needed +integer Walking = 6; // Hey! I am walking here! +integer Wander = 7; // Wandering around neeeds a timer, too +integer WanderHold = 8; // We reached a wander point +integer DoProcess = 9; // Set this to make it process a new command +integer Touch = 10; // Timer is busy sensing something to touch +integer Sit = 11; // Timer is busy sensing something to sit on +integer Paused = 12; // Timer is busy pausing + +key gNpcKey = NULL_KEY; // global key storage for the one NPC, to save CPU cycles +list Stack ; // a command stack from link message input + +/////////////////////////////////////////////////////////////////////////// +// FUNCTIONS // +/////////////////////////////////////////////////////////////////////////// + + +TimerEvent(float timesent) +{ + if (LSLEditor) + timesent *= 5; // slow thinggs doen when the LSLEDITOR is in use + + DEBUG("Setting timer: " + (string) timesent); + llSetTimerEvent(timesent); +} + +// for 4.1 parse a message from a Listen or a Link message +ParseMsg(string str) { + DEBUG("Command In:" + str); + if (str=="@go") { + SetStop(FALSE); // Let's run the notecard + DEBUG("@go running"); + DoProcessNPCLine(); + } else { + Stack += [str]; // take anything, the controller will filter away non @ stuff + if (STATE == NULL) + DoProcessNPCLine(); // v 4.5 remove wait for STATE == 0 + } +} + +SetStop(integer what) +{ + DEBUG("Stopped set to " + (string ) what); + Stopped = what; +} +// Do* functions are much like states from the old V2 scripts. + +// Save a Path notecard +DoSave() +{ + STATE = MakeNotecard; + makeText("Stand where you want the NPC to appear, and enter the NPC Name"); +} + +// This function is used to record the path for the NPC +// Each command can take 0, 1, or 2 params +DoMenuForCommands() { + makeMenu(lAtButtons); +} + + +// No one is here when sensors were on, so we kill off the NPC +DoNobodyHome() +{ + DEBUG("Nobody Home"); + STATE = NobodyHome; + if (NPCKey() != NULL_KEY) { + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + } + TimerEvent(5); // keep ticking to sense avatars +} + +/////////////////////// STATELIKE BEHAVIOUR ///////////// +// these StateXX functions need to wait on a timer to fire. +// Create a NPC +StateSpawn() { + DEBUG("state spawn"); + + + NPCEnabled = TRUE; // in world + // see if there is already one out there. + if (NPCKey() != NULL_KEY) { + DEBUG("Already living"); + return; + } + + STATE = Spawning; + list name = llParseString2List(sNPCName, [" "], []); + + vector vRezPos = vInitialPos; + if (relAbs == "Relative"){ + vRezPos += llGetPos(); + } + + // llSay(0,llDumpList2String(name,",")); + DEBUG("Rezzing the NPC:" + (string) vRezPos); + key aKey = osNpcCreate(llList2String(name, 0), llList2String(name, 1), vRezPos, Appearance, NPCOptions); + + llMessageLinked(LINK_SET,-1,"",aKey); // bboradcast the key on num = -1 + SaveKey(aKey); // save in description and global, too + + osSetSpeed(aKey,SPEEDMULT); // 1.9 speed multiplier + TimerEvent(REZTIME); + NPCAnimate(STAND); +} + +StateSit() { + DEBUG ("state sit - looking for " + RAMsit); + STATE=Sit; + llSensor(RAMsit, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +StateTouch() { + DEBUG ("state touch - looking for " + RAMtouch); + STATE = Touch; + llSensor(RAMtouch, "", PASSIVE|ACTIVE|SCRIPTED, 96, PI); +} + +DoStand() { + DEBUG("state stand"); + osNpcStand(NPCKey()); +} + + +StateAnimate() { + + DEBUG("state animate"); + STATE = Animate; + NPCAnimate(RAManimationName); + if (RAManimationTime <=0 ) // V 3.4 tweak + RAManimationTime = 1; + TimerEvent(RAManimationTime); +} + +StateWalk() { + + DEBUG("Start Walk"); + //DEBUG("NPCWalkOption = " + (string) NPCWalkOption); + STATE = Walking; + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(WALK); + } else if (walkstate == 2) { + llShout(FLIGHT,"flying"); + NPCAnimate(FLY); + } else if (walkstate == 3) { + NPCAnimate(RUN); + } else if (walkstate == 4) { + NPCAnimate(LAND); + } + newDest = vDestPos ; + newDest.z += OffsetZ; + + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + newDest += llGetPos(); + } + + DEBUG("Moveto:" + (string) newDest); + osNpcMoveToTarget(NPCKey(), newDest, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + + +StateWander(){ + DEBUG("state wander"); + STATE = Wander; + + vector point = CirclePoint(RAMwd); + DEBUG("CirclePoint:" + (string) point); + vWanderPos = vDestPos + point; + DEBUG("vWanderPos:" + (string) vWanderPos); + + fTimerVal = WANDERTIME; // default time to pause after each wander + if (WANDERRAND) + fTimerVal = llFrand(WANDERTIME) + 1; // override, they want random times + + NPCAnimate(WALK); + + DEBUG("Wander to:" + (string) vWanderPos); + + osNpcMoveToTarget(NPCKey(), vWanderPos, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + TimerEvent(TIMER); +} + +StateWanderhold() { + + DEBUG("Wander Hold"); + STATE = WanderHold; + + // now that we have reached a wander spot, slow the timer down to the desired value + TimerEvent(fTimerVal); +} + + +DoRotate() { + DEBUG("@rotate=" + (string) RAMrot); + osNpcSetRot(NPCKey(), llEuler2Rot(<0,0,RAMrot> * DEG_TO_RAD)); +} +// @pause=10 will do nothing for 10 seconds +DoPause() { + STATE = Paused; + if (RAMPause < 0.1) + RAMPause = 0.1; + DEBUG("@pause=" + (string)RAMPause); + TimerEvent(RAMPause); +} + + +// @stop makes the NPC stop moving in whatever state it is in. You have to linkmessage to get moving again +DoStop() { + DEBUG("NPC is Stopped"); + STATE = 0; // accept commands + SetStop(TRUE); // Link controlled - we mnust have a @go to continue with notecards + TimerEvent(0); + Stack = []; // v3.8 +} + +// @delete removes the NPC forever. Next command starts it up again at the beginning +DoDelete() { + DEBUG("state delete"); + osNpcRemove(NPCKey()); + SaveKey(NULL_KEY); + TimerEvent(0); + Stack = []; // v3.8 + STATE = NULL; // accept commands +} + +// change the appearance of the NPC +DoAppearance(string notecard) { + DEBUG("state appearance"); + if (llGetInventoryType(notecard) == INVENTORY_NOTECARD){ + DEBUG("Load appearance " + notecard); + osNpcLoadAppearance(NPCKey(),notecard); + } + STATE = NULL; // accept commands +} + +// Change the avatar speed +DoSpeed(string speed) { + float newspeed = (float) speed; + if (newspeed > 0.1 && newspeed < 5.0) {// sanity check + osSetSpeed(NPCKey(),newspeed); + } + STATE = NULL; // accept commands +} + +DoTeleport(string params) { + list Data = llParseString2List(params, ["|"], []); + string itemName = llList2String(Data, 0); + vector Dest = (vector) itemName; + if (Dest != ZERO_VECTOR) { + if (relAbs == "Relative"){ + Dest += llGetPos(); + } + osTeleportAgent( NPCKey(), llGetRegionName(), Dest, ZERO_VECTOR ); + + } else { + llSay(DEBUG_CHANNEL,"Attempt to teleport to <0,0,0> probably not what you intended: @teleport="); + } + STATE = NULL; // accept commands +} + + + +DoNewNote (string card) { + DEBUG("Load Notecard " + card); + NPCReadNoteCard(card); + SetStop(FALSE); + STATE = NULL; // accept commands +} +DoAttach(string params) { + + list Data = llParseString2List(params, ["|"], []); + string itemName = llList2String(Data, 0); + integer attachmentPoint = (integer) llList2String(Data, 1); + if (attachmentPoint > 0 + && attachmentPoint < 40 + && llGetInventoryType(itemName) == INVENTORY_OBJECT + ) + { + osForceAttachToOtherAvatarFromInventory(NPCKey(),itemName,attachmentPoint); + } + STATE = NULL; // accept commands +} + +// This loops over the notecard, processing each command +DoProcessNPCLine() { + DEBUG("ProcessNPCLine, stopped = " + (string) Stopped); + + STATE = DoProcess; + + // auto load a notecard + if (! llGetListLength(lNpcCommandList)) { + DEBUG("Read Notecard"); + NPCReadNoteCard(Notecard); + } + + // look for link messages on the stack + string next = llList2String(Stack,0); // lets see if there is anything from a link message + if (llStringLength(next)) + { + Stack = llDeleteSubList(Stack,0,0); + ProcessCmd(next); //lets do this command instead. + return; + } + + // @stop issued? + if (Stopped) { + TimerEvent(0); + DEBUG("Stopped, waiting for input"); + STATE = NULL; + return; + } + + // No, we have an @go for liftoff + next = llList2String(lNpcCommandList, 0); // get the next command + DEBUG("Execute:" + next); + lNpcCommandList = llDeleteSubList(lNpcCommandList, 0, 0); // delete it + + if (llGetListLength(lNpcCommandList) == 0) { + DEBUG("EOF"); + } + ProcessCmd(next); +} + + + +ProcessCmd(string cmd) { + + DEBUG("ProcessCmd:" + cmd); + + if (llGetSubString(cmd, 0, 0) != "@") { + DEBUG("ignoring"); + TimerEvent(QUICK); // this is so we do not recurse the stack + STATE = NULL; + return; + } + + list data = llParseString2List(cmd, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data, 0), STRING_TRIM)); + + DEBUG("Action:" + npcAction); + npcParams = llStringTrim(llList2String(data, 1), STRING_TRIM); + DEBUG("Params:" + npcParams); + + @commands; + + ProcessSensor(); + + if(npcAction == "@spawn" && avatarPresent) { + DEBUG("@spawn"); + list spawnData = llParseString2List(npcParams, ["|"], []); + sNPCName =llList2String(spawnData, 0); // V 1.6 name in RAM + + list spawnDest = llParseString2List(llList2String(spawnData, 1), ["<", ",", ">"], []); + vInitialPos.x = llList2Float(spawnDest, 0); + vInitialPos.y = llList2Float(spawnDest, 1); + vInitialPos.z = llList2Float(spawnDest, 2); + + DEBUG("Coords for NPC at " + (string) vInitialPos); + StateSpawn(); + return; + } + + if (! avatarPresent){ + DoNobodyHome(); + DEBUG("No avatar nearby"); + STATE = NULL; + return; + } else { + if ( NPCKey() == NULL_KEY) { + StateSpawn(); + } + } + + + + + if(npcAction == "@stop") { + DoStop(); + STATE = NULL; + return; + } + else if(npcAction == "@goto") { + DEBUG("goto"); + integer lastIdx = llGetListLength(lNpcCommandList)-1; + lNpcCommandList = llDeleteSubList(lNpcCommandList, lastIdx, lastIdx); + // Wind commands till goto label. + @wind; + string next1 = llList2String(lNpcCommandList, 0); + lNpcCommandList = llDeleteSubList(lNpcCommandList, 0, 0); + lNpcCommandList += next1; + if(next1 != npcParams) jump wind; + // Wind the label too. + next1 = llList2String(lNpcCommandList, 0); + lNpcCommandList = llDeleteSubList(lNpcCommandList, 0, 0); + lNpcCommandList += next1; + // Get next command. + list data1 = llParseString2List(next1, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data1, 0), STRING_TRIM)); + npcParams = llStringTrim(llList2String(data1, 1), STRING_TRIM); + // Reschedule. + jump commands; + } + else if(npcAction == "@sound") { + DEBUG("sound"); + llTriggerSound(npcParams,1.0); + } + else if(npcAction == "@randsound") { + DEBUG("@randsound"); + integer N = llGetInventoryNumber(INVENTORY_SOUND); + integer rand = llCeil(llFrand(N)) -1; // pick a random sound + string toPlay = llGetInventoryName(INVENTORY_SOUND,rand); + llTriggerSound(toPlay,1.0); + } + else if(npcAction == "@walk") { + DEBUG("@walk"); + GetDest(npcParams); + walkstate = 1;// walking + NPCWalkOption = OS_NPC_NO_FLY ; + StateWalk(); + return; + } + else if(npcAction == "@fly") { + GetDest(npcParams); + walkstate = 2;// flying + NPCWalkOption = OS_NPC_FLY ; + StateWalk(); + return; + } + else if(npcAction == "@run") { + DEBUG("@run"); + GetDest(npcParams); + walkstate = 3;// running + NPCWalkOption = OS_NPC_NO_FLY | OS_NPC_RUNNING; + StateWalk(); + return; + } + else if(npcAction == "@land") { + DEBUG("@land"); + GetDest(npcParams); + walkstate = 4;// landing + NPCWalkOption= OS_NPC_FLY | OS_NPC_LAND_AT_TARGET ; + StateWalk(); + return; + } + else if(npcAction == "@say") { + DEBUG("@say " + npcParams); + osNpcSay(NPCKey(), 0, npcParams); + } + else if(npcAction == "@shout") { + DEBUG("@shout"); + osNpcShout(NPCKey(),0, npcParams); + } + else if(npcAction == "@whisper") { + DEBUG("@whisper " + npcParams); + osNpcWhisper(NPCKey(),0, npcParams); + } + // speak a command on a channel, so you can open doors and control stuff. + else if(npcAction == "@cmd") { + DEBUG("@cmd"); + list dataToSpeak = llParseString2List(npcParams, ["|"], []); + string channel = llList2String(dataToSpeak,0); + DEBUG("Channel:"+(string) channel); + integer iChannel = (integer) channel; + string stringToSpeak = llList2String(dataToSpeak,1); + llSay(iChannel, stringToSpeak); + } + // stop everything + else if(npcAction == "@pause") { + RAMPause = (float) npcParams; + DoPause(); + return; + } + else if(npcAction == "@wander") { + list wanderData = llParseString2List(npcParams, ["|"], []); + RAMwd = (float) llList2String(wanderData, 0); + RAMwc = (integer) llList2String(wanderData, 1); + vDestPos = osNpcGetPos(NPCKey()); // set the wander start + DEBUG("Starting at " + (string) vDestPos); + StateWander(); + return; + } + else if(npcAction == "@rotate") { + RAMrot = (float) npcParams; + DoRotate(); + } + else if(npcAction == "@sit") { + RAMsit= npcParams; + StateSit(); + return; + } + else if(npcAction == "@touch") { + RAMtouch= npcParams; + StateTouch(); + return; + } + else if(npcAction == "@stand") { + DoStand(); + } + else if(npcAction == "@delete") { + DoDelete(); + SetStop(TRUE); // Link controlled - we mnust have a @go to continue with notecards + return; + } + else if(npcAction == "@animate") { + list animateData = llParseString2List(npcParams, ["|"], []); + RAManimationName = llList2String(animateData, 0); + RAManimationTime = (float) llList2String(animateData, 1); + StateAnimate(); + return; + } + else if(npcAction == "@appearance" ){ + DoAppearance(npcParams); + } + else if (npcAction =="@speed") { + DoSpeed(npcParams); + } + else if (npcAction =="@notecard") { + DoNewNote(npcParams); + Notecard = npcParams; + } + else if (npcAction == "@attach") + { + DoAttach(npcParams); + } + else if (npcAction == "@teleport") + { + DoTeleport(npcParams); + } + else if (npcAction == "@reset") + { + DoDelete(); + SetStop(FALSE); // a @resst will restart the original !Path after deleting the notecard. + } + + STATE = NULL; + TimerEvent(QUICK); // yeah I know, not possible this fast, we just go as fast as we can go - this is so we do not recurse the stack +} + + + +/////////////////// UTILITY Functions, not state-like ////////////////// + +// DEBUG(string) will chat a string or display it as hovertext if debug == TRUE +DEBUG(string str) { + if (debug && ! LSLEditor) + llOwnerSay( str); // Send the owner debug info + if (debug && LSLEditor) + llSay(0, str); // Send to the Console in LSLEDitor + if (iTitleText) { + llSetText(str,<1.0,1.0,1.0>,1.0); // show hovertext + + } +} + +GetDest(string npcParams) { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); +} + +NPCReadNoteCard(string Note) { + DEBUG("NPCReadNoteCard"); + lNpcCommandList = llParseString2List(osGetNotecard(Note), ["\n"], []); +} + +integer SenseAvatar() +{ + //Returns a strided list of the UUID, position, and name of each avatar in the region + list avatars = llGetAgentList(AGENT_LIST_REGION ,[]); + integer numOfAvatars = llGetListLength(avatars); + if (numOfAvatars == 0) + { + DEBUG("No people"); + return 0; + } + //DEBUG("Located " + (string)numOfAvatars + " avatars and NPC's"); + + integer nAvatars; + integer i; + for( i = 0;i < numOfAvatars; i++) { + key aviKey = llList2Key(avatars,i); + if (!osIsNpc(aviKey)) { + list detail = llGetObjectDetails(aviKey,[OBJECT_POS]); + vector pos = llList2Vector(detail,0); + float dist = llVecDist(pos, llGetPos()); + if (dist < RANGE) + { + nAvatars++; + DEBUG("In range:" + llKey2Name(aviKey)); + } + } + } + //DEBUG("Located " + (string) nAvatars + " avatars"); + return nAvatars; +} + +// return TRUE if the avatar is owner when private is set, or TRUE if the avatar is in the same group and GROUP is set. +integer checkPerms() { + + integer group = (integer) KeyValueGet("pr"); + if (! group) + priPub = "Owner Only"; + else + priPub = "Group"; + + + if (llDetectedKey(0) == llGetOwner()){ + kUserKey = llDetectedKey(0); + return TRUE; + } + + if ( group && llDetectedGroup(0)) { + kUserKey = llDetectedKey(0); + return TRUE; + } + kUserKey = llDetectedKey(0); + return FALSE; +} + + + +NPCAnimate(string anim) +{ + DEBUG("Start Anim: " + anim); + if (llGetInventoryType(anim) == INVENTORY_ANIMATION ) { + + if (lastANIM != anim) { + if(llStringLength(lastANIM)) { + osNpcStopAnimation(NPCKey(), lastANIM); + } + osNpcPlayAnimation(NPCKey(), anim); + lastANIM = anim; + } + } else { + llSay(DEBUG_CHANNEL, "No animation named " + anim); + } +} + +// Kill a NPC by Name +Kill(string param) +{ + integer count; + list avatars = osGetAvatarList(); // Returns a strided list of the UUID, position, and name of each avatar in the region except the owner.\ + integer i; + integer j = llGetListLength(avatars); + for (i=0 ; i <= j; i+=3){ + + string desired = llList2String(avatars,i+2); + desired = llStringTrim(desired,STRING_TRIM); // should not be needed but is needed + + if (desired == param){ + vector v = llList2Vector(avatars,i+1); + key target = llList2Key(avatars,i); // get the UUID of the avatar + osNpcRemove(target); + + llOwnerSay("Removed " + param+ " at location " + (string) v); + count++; + } + } + + NPCEnabled = FALSE; // not in world + SaveKey(NULL_KEY ); // Rev 4.4 + + if (count) + llOwnerSay("Removed " + (string) count + " NPC's"); + else + llOwnerSay("Could not locate " + param); +} + + +// return a String for the position we are at. Strings used as the caller wants strings +string Pos() +{ + vector where = llGetPos(); // find the box position + + where.z += OffsetZ; // use the ground position + an offset + + if (LSLEditor) + where = <128,128,31 + llFrand(1)>; // force center of sim when editing + + // if attached the height will be too high by 1/2 the agent size + if (llGetAttached()) { + vector size = llGetAgentSize(llGetOwner()); + float Z = size.z; + where.z -= Z/2; + } + + // DEBUG("Pos= " + (string) where); + return (string) where; +} + +// setup a menu with a timer for timeouts, called by all make*() +menu() +{ + llListenRemove(iHandle); + iChannel = llCeil(llFrand(100000) + 20000); + iHandle = llListen(iChannel,"","",""); + TimerEvent(30.0); + MENU = TRUE; +} + +// make a text box +makeText(string Param) +{ + menu(); + llTextBox(kUserKey, Param, iChannel); +} + +// top level menu +makeMainMenu() +{ + menu(); + list buttons = ["Appearance","Recording","Save","Help","-","Erase RAM", priPub,relAbs,"-","Stop NPC",mSensor,"Start NPC"]; + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Records",buttons,iChannel); +} + + +// Rev 1.4 +// top level menu for non group/ non owners +makeUserMenu() +{ + if (!allowUsers) return; + + menu(); + list buttons = ["Start NPC","Stop NPC"]; + llDialog(kUserKey,"Choose",buttons,iChannel); +} + + + +// programmable menu for @commands +makeMenu(list buttons) +{ + menu(); + llDialog(kUserKey,(string) llGetListLength(lCommands) + " Record",buttons,iChannel); +} + + +// make one or two text boxes with prompts +Text(string cmd, string p1, string p2) +{ + sCommand = cmd; + sParam2 = ""; + if (llStringLength(p2)) + sParam2 = p2; + + makeText(p1); +} + +// Set the Avatar Present flag - if sensors are off and we are forece run, there will be one present. +ProcessSensor() +{ + integer SensorOn; + if ("on" == KeyValueGet("se")) + { + SensorOn = TRUE; // we need to scan for avatars + } else { + SensorOn = FALSE; // we need to scan for avatars + } + //DEBUG("Sensor:" + (string) SensorOn); + + integer n = SenseAvatar(); + + DEBUG("Avatars:" + (string) n); + if (SensorOn && n) + avatarPresent = TRUE; // someone is here and we need to tell the system to run + else if (SensorOn && !n) + avatarPresent = FALSE; // someone is not here and we need to tell the system to stop + else { // sensor is off, lete see if there is a NPC. If so, we are ON + // DEBUG("NPCEnabled:" + (string) NPCEnabled); + if (NPCEnabled) + avatarPresent = TRUE; + else + avatarPresent = FALSE; + } + + // start up from when when no one is near + if (avatarPresent && STATE == NobodyHome) + NULL = 0; + + //DEBUG("Avatar Present: " + (string) avatarPresent); +} + +vector CirclePoint(float radius) { + float x = llFrand(radius *2) - radius; // +/- radius, randomized + float y = llFrand(radius *2) - radius; // +/- radius, randomized + return ; // so this should always happen +} + +string KeyValueGet(string var) { + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k != var) jump continue; + //DEBUG("got " + var + " = " + llList2String(data, 1)); + return llList2String(data, 1); + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + return ""; +} + +KeyValueSet(string var, string val) { + + //DEBUG("set " + var + " = " + val); + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + if(llGetListLength(dVars) == 0) + { + llSetObjectDesc(var + "=" + val); + return; + } + list result = []; + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k == "") jump continue; + if(k == var && val == "") jump continue; + if(k == var) { + result += k + "=" + val; + val = ""; + jump continue; + } + string v = llList2String(data, 1); + if(v == "") jump continue; + result += k + "=" + v; + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + if(val != "") result += var + "=" + val; + llSetObjectDesc(llDumpList2String(result, "&")); +} + + +// clear RAM +Clr() { + + lCommands = []; + llOwnerSay("RAM Memory cleared. Notecards, if any, are not modified."); + makeMainMenu(); +} + +integer checkNoteCards() +{ + // Check that they have saved an Appeaance and Path notecard + integer num = llGetInventoryNumber(INVENTORY_NOTECARD); // how many notecards overall + + integer i; + integer count; + for (; i < num; i++){ + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Notecard) + count++; + if (llGetInventoryName(INVENTORY_NOTECARD,i) == Appearance) + count++; + } + DEBUG("Checked " + (string) count + " Notecards"); + // if we have both, run the NPC + return count; +} + +Update(string SName) { + + // delete all NPC* scripts except myself + integer i; + integer j = llGetInventoryNumber(INVENTORY_SCRIPT); + for (i = 0; i < j; i++) { + string targetName = llGetInventoryName(INVENTORY_SCRIPT,i); + string match = llGetSubString(targetName,0,2); + + if (match == SName && llGetScriptName() != targetName){ + llOwnerSay("Upgrading " + targetName); + if (! LSLEditor){ // lets not kill the editor + llRemoveInventory(targetName); + } + } + } +} + +// Get all default saved params from the Description +GetSwitches() +{ + string rA = KeyValueGet("co"); // Get the remembered menu setting for Abs Vs Relative + if (rA == "A") + relAbs = "Absolute"; + else if (rA == "R") + relAbs = "Relative"; + else + relAbs = "Absolute"; + + + // reenable NPC if sensor is on. + if ("on" == KeyValueGet("se")) + { + NPCEnabled = TRUE; + mSensor = "Sense is On"; + ProcessSensor(); // fake 1 avatar to get it rezzed + } else { + mSensor = "Sense is Off"; + } + } + + +SaveKey(key akey) +{ + DEBUG("Saving Key of " + (string) akey); + KeyValueSet("key", akey); + if (akey != (key) KeyValueGet("key") ) + { + DEBUG("Fatal error, cannot save key"); + } + gNpcKey = akey; +} + + +key NPCKey() +{ + key akey = gNpcKey; // from cached copy + // gNpcKey saves a lot of CPU processing by caching the key, if blank we get it from the description + if (gNpcKey == NULL_KEY) + { + //DEBUG("Get DKey"); + akey = KeyValueGet("key"); // from Description of the prim + } + // DEBUG("NPC KEY:" + (string) akey); + return akey; +} + + +/////////////////// CODE BEGINS ////////////////// + + +default +{ + changed(integer change) { + if(change & CHANGED_REGION_START) { + llResetScript(); + } + } + + on_rez(integer start_param) + { + llResetScript(); + } + + state_entry() { + + llSetText("",<1,1,1>,1.0); // clr all hovertext- we may not be using it. + DoDelete(); // kill any NPC that is out running + Update("NPC"); // If dragged and ropped into a prim with any script named "NPC...", this will replace it. + GetSwitches(); // Get all default saved params from the Description + + // 4.1 allow listeners to send us commands + if (allowListener) + llListen(link_Channel,"","",""); + TimerEvent(TIMER); + } + + + touch_start(integer n) + { // if touched, make a menu + + if (checkPerms()) { + if (RecordPath == STATE) { + makeMenu(lAtButtons); + } else { + makeMainMenu(); + } + } else { + makeUserMenu(); + } + } + + // menu listener + listen(integer iChannel, string name, key id, string message) { + + // process @commands that come in via the listener + if (iChannel == link_Channel) + { + ParseMsg(message); + return; + } + + if (MENU) { + llListenRemove(iHandle); + MENU = 0; // menu is off + iHandle = 0; + } + + if (message == "Stop NPC") + { + lNpcCommandList = []; // force reload of notecard + NPCEnabled = FALSE; + if (NPCKey() != NULL_KEY){ + Kill(sNPCName); + sNPCName = ""; + } else { + bNPC_STOP = TRUE; + makeText("Enter name of an NPC to stop"); + } + } + else if (message == "Menu" ) { + makeMainMenu(); + } + else if (message == "Erase RAM"){ + Clr(); + } + else if (message == "Relative"){ + relAbs = "Absolute"; + KeyValueSet("co","A"); // remember coordinates = A + Clr(); + } + else if (message == "Absolute"){ + relAbs = "Relative"; + KeyValueSet("co","R"); // remember coordinates = R + Clr(); + } + else if (message == "Recording"){ + DoMenuForCommands(); // show them the recording menu + } + else if (message == "Owner Only") { + priPub = "Group"; + KeyValueSet("pr","1"); + + llOwnerSay("Group members have control"); + makeMainMenu(); + } + else if (message == "Group") { + priPub = "Owner Only"; + KeyValueSet("pr","0"); + llOwnerSay("Only you have control"); + makeMainMenu(); + } + else if (message == "Sense is On") { + mSensor ="Sense is Off"; + KeyValueSet("se", "off"); + llOwnerSay(mSensor); + makeMainMenu(); + } + else if (message == "Sense is Off") { + mSensor ="Sense is On"; + llOwnerSay(mSensor); + KeyValueSet("se", "on"); + + NPCEnabled = FALSE; + + integer count = checkNoteCards(); + if (count >= 2) { + DEBUG("Notecards ok, DoProcessNPCLine"); + DoProcessNPCLine(); + return; + } + if (LSLEditor) { + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording and/or appearance, so you cannot start a NPC"); + makeMainMenu(); + } + else if (message == "Appearance") { + llRemoveInventory(Appearance); // delete the notecard + osAgentSaveAppearance(kUserKey,Appearance); // make the ntecard + llOwnerSay("Your outfit has been saved"); + makeMainMenu(); + } + else if (message == "Save") { + if (llGetListLength(lCommands) == 0) { + llOwnerSay("Nothing recorded, you need to make a recording first"); + makeMainMenu(); + return; + } + DoSave(); + } + else if (message == "Help"){ + llLoadURL(kUserKey,"Click to view help","http://www.outworldz.com/opensim/posts/NPC/"); + makeMainMenu(); + } + else if (message == "Start NPC") { + integer count = checkNoteCards(); + + NPCEnabled = TRUE; + + if (LSLEditor) { + DoProcessNPCLine(); + return; + } + + if (count >= 2) { + DEBUG("Notecards approved , calling DoProcessNPCLine"); + SetStop(FALSE); // Let's run the notecard + DoProcessNPCLine(); + return; + } + + llOwnerSay("You have not saved a recording or maybe an appearance, so we cannot start a NPC"); + + } + else if (bNPC_STOP){ + bNPC_STOP = FALSE; + Kill(message); + } + else if (message == ">>"){ + makeMenu(lMenu2); + } + else if (message == ">>>"){ + makeMenu(lMenu3); + } + else if (message == "<<") { + makeMenu(lAtButtons); + } + else if (message == "<<<") { + makeMenu(lMenu2); + } + else if (message == "@comment"){ + Text("# ","Enter a comment",""); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@run"){ + lCommands += "@run=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@fly"){ + lCommands += "@fly=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@land"){ + lCommands += "@land=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@walk") { + lCommands += "@walk=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@sound"){ + Text("@sound=","Enter a sound name or UUID to trigger",""); + } + else if (message == "@randsound"){ + lCommands += "@randsound"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@say") { + Text("@say=","Enter what the NPC will say",""); + } + else if (message == "@whisper"){ + Text("@whisper=","Enter what the NPC will whisper",""); + } + else if (message == "@shout"){ + Text("@shout=","Enter what the NPC will shout",""); + } + else if (message == "@wander") { + Text("@wander=","Enter radius to wander","Enter number of wanders"); + } + else if (message == "@pause") { + Text("@pause=","Enter time to pause",""); + } + else if (message == "@rotate") { + Text("@rotate=","Enter degrees to rotate",""); + } + else if (message == "@sit"){ + Text("@sit=","Enter name of object to sit on",""); + } + else if (message == "@teleport"){ + lCommands += "@teleport=" + Pos() + "\n"; + llOwnerSay("teleport to position: " + Pos()); + makeMenu(lMenu3); + } + else if (message == "@touch"){ + Text("@touch=","Enter name of object to touch",""); + } + else if (message == "@cmd"){ + Text("@cmd=","Enter cjhannel to speak on","Enter text to speak"); + } + else if (message == "@stand"){ + lCommands += "@stand\n"; + llOwnerSay("Stand Recorded"); + makeMenu(lAtButtons); + } + else if (message == "@animate"){ + Text("@animate=","Enter animation name to play","Enter time to play the animation"); + } + else if (message == "@attach"){ + Text("@animate=","Enter inventory name to attach","Enter number of the attachment point (1-40)"); + } + else if (message == "@speed"){ + Text("@speed=","Enter a speed for the NPC, 1=100% normal speed, 0.5=50% speed",""); + } + + + // Save NPC name + else if (MakeNotecard == STATE) { + sNPCName = message; // in case we need to kill it. + + vector vDest = (vector) Pos(); + + if (relAbs == "Relative") + { + vDest -= llGetPos(); // just an offset for relative + } + sNotecard = "@spawn=" + message + "|" + (string) vDest + "\n"; + integer i; + integer j = llGetListLength(lCommands); + for (; i < j; i++){ + // get the command to save to the notecard + string line = llList2String(lCommands,i); + if (relAbs == "Absolute") { + sNotecard += line; // add the un-modified string to the notecard + } else { + // since we have to record absolute coords since we do not know where the box goes until they press Save, + // we process the absolute to relative conversion for walks here + list parts = llParseString2List(line,["="],[]); //get the @command + + if (llList2String(parts,0) == "@walk") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@walk=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@fly") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@fly=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@run") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@run=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@land") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@land=" + (string) vec + "\n"; + } + else { + sNotecard += line; // add the un-modified string to the notecard + } + } + } + llRemoveInventory(Notecard); // delete the old notecard + osMakeNotecard(Notecard,sNotecard); // Makes the notecard. + llSay(0,sNotecard); + llOwnerSay("Commands notecard has been written"); + STATE = NULL; + } // MakeNotecard + + else if (! llStringLength(sParam2)) { + lCommands += sCommand + message + "\n"; + llOwnerSay("Recorded"); + makeMenu(lAtButtons); + } + else if (llStringLength(sParam2)){ + sCommand = sCommand + message + "|"; + llOwnerSay("Recorded"); + makeText(sParam2); + sParam2 = ""; + } + + } + + + + timer(){ + // DEBUG("tick"); + + // if llDialog is up, kill the listener for the dialog box. + if (iHandle) { + llOwnerSay("Menu timed out"); + llListenRemove(iHandle); + iHandle = 0; + return; // ^^^^^^^^^^^^^^^^^^^^^^^ + } + // if NoBodyHome, we are sensing for an avatar + else if (NobodyHome == STATE) { + ProcessSensor(); + return; + } + // if we are spawning, we need time to rez the NPC, then start processing NPC Commands. + else if (Spawning == STATE) { + STATE = NULL; + TimerEvent(TIMER); + } + // We end aniamtions with a timer + else if (Animate == STATE){ + NPCAnimate(STAND); + TimerEvent(TIMER); + } + + else if (Walking == STATE) { + if (--iWaitCounter) { + DEBUG("still walking..."); + if (llVecDist(osNpcGetPos(NPCKey()), newDest) > MAXDIST) { + return; + } + } + + DEBUG("At Destination: " + (string) newDest); + + // walk, fly, run, land + if (walkstate == 1) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 2) { + // nothing + } else if (walkstate == 3) { + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } else if (walkstate == 4) { + llShout(FLIGHT,"landing"); + NPCAnimate(STAND); + NPCWalkOption = OS_NPC_NO_FLY; + } + } + // Wandering timer + else if (Wander == STATE) { + if (--iWaitCounter) { // wait 60 seconds to get to a destination. + if (llVecDist(osNpcGetPos(NPCKey()), vWanderPos) > MAXDIST) + return; + } + + // see if wander counter == 0, if so, stop walking, go to stand and process next line + if(RAMwc == 0) { + NPCAnimate(STAND); + DEBUG("Wander ended, calling DoProcessNPCLine"); + STATE = NULL; + return; + } + // one less time to wander around + RAMwc--; + NPCAnimate(STAND); + TimerEvent(TIMER); + StateWanderhold(); + return; + } + // Wandering requires us to re-wander when we reach a destination + else if (WanderHold == STATE) { + StateWander(); + } + else if (DoProcess == STATE) { + TimerEvent(QUICK); + } + + STATE = NULL; + + // We always process a NPC line at end of timer. + DEBUG("Tick end, calling DoProcessNPCLine"); + DoProcessNPCLine(); + } + + // sensors are used for sitting on prims + // Neo Cortex: added different states to trigger sit or touch + sensor(integer num) { + if (Sit == STATE ) { + osNpcSit(NPCKey(), llDetectedKey(0), OS_NPC_SIT_NOW); + DEBUG("Seated, calling DoProcessNPCLine"); + + STATE = 0; + } else if (Touch == STATE) { + osNpcTouch(NPCKey(), llDetectedKey(0), LINK_THIS); + DEBUG("Touched, calling DoProcessNPCLine"); + STATE = 0; + } + DoProcessNPCLine(); + } + no_sensor(){ + DEBUG ("no target prim located, calling DoProcessNPCLine"); + DoProcessNPCLine(); + STATE = NULL; + } + + + link_message(integer sender, integer num, string str, key id){ + if (num == 0) + ParseMsg(str); + } + +} + +// __ END__ + + + + diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC3.iar b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC3.iar new file mode 100644 index 00000000..ebfe2009 Binary files /dev/null and b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Object/NPC3.iar differ diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Chat commands.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Chat commands.lsl index 421bb5bf..f7c53ca2 100644 --- a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Chat commands.lsl +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Chat commands.lsl @@ -4,7 +4,10 @@ // :AUTHOR:Ferd Frederix // :KEYWORDS: // :CREATED:2015-07-17 13:15:19 +<<<<<<< HEAD // :EDITED:2016-07-10 09:24:25 +======= +>>>>>>> f0df6f03553fbf82e10f35590fcf71af838ab4be // :ID:27 // :NUM:1807 // :REV:1 diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Collision test.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Collision test.lsl index ae690bde..1e667a8a 100644 --- a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Collision test.lsl +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Collision test.lsl @@ -4,7 +4,10 @@ // :AUTHOR:Ferd Frederix // :KEYWORDS: // :CREATED:2015-07-17 13:15:49 +<<<<<<< HEAD // :EDITED:2016-07-10 09:24:25 +======= +>>>>>>> f0df6f03553fbf82e10f35590fcf71af838ab4be // :ID:27 // :NUM:1808 // :REV:3 diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Listener for things that appear and disappear.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Listener for things that appear and disappear.lsl new file mode 100644 index 00000000..36927967 --- /dev/null +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Listener for things that appear and disappear.lsl @@ -0,0 +1,65 @@ +// :SHOW:1 +// :CATEGORY:NPC +// :NAME:All In One NPC Recorder and Player +// :AUTHOR:Ferd Frederix +// :KEYWORDS: +// :CREATED:2015-07-17 13:15:19 +// :EDITED:2016-07-10 09:24:25 +// :ID:27 +// :NUM:1904 +// :REV:1 +// :WORLD:Opensim +// :DESCRIPTION: +// This script can be put in objects to make them appear and disappear on command +// :CODE: + +// send commands to this @cmd +// such as @cmd=99|Appear to make this prim appear +// such as @cmd=99|Disppear to make this prim disappear + +integer debug = FALSE; +integer channel = 99; // change this for each item you want to speak to +integer visible = TRUE; // set this if you want rhe item to start visible. Set it to FALSE if you want it to start invisible + +default +{ + on_rez(integer start_param) + { + // when rezzed, this needs to reset so we can establish a listener + if (debug) llSay(0,"rezzed- resetting"); + llResetScript(); + } + // when attached, this needs to resetso we can establish a listener + attach(key attached) + { + if (debug) llSay(0,"Attachment successful, resetting"); + llResetScript(); + } + state_entry() + { + // set the initial visibility. I use llSetLinkAlpha because llSetAlpha causes scripts to stop so it should be avoided in Opensim. + if (visible) { + llSetLinkAlpha(LINK_SET,1,ALL_SIDES); + } else { + llSetLinkAlpha(LINK_SET,0,ALL_SIDES); + } + + // set up a lustener on 'channel' + if (debug)llSay(0,"Listener on channel " +(string) channel + " is ready!"); + llListen(channel,"","",""); + } + listen(integer channel, string name, key id, string message) + { + if (message=="Appear") + { + if (debug)llSay(0,"Appear"); + llSetLinkAlpha(LINK_SET,1.0,ALL_SIDES); + } + if (message=="Disappear") + { + if (debug)llSay(0,"Disappear"); + llSetLinkAlpha(LINK_SET,0,ALL_SIDES); + } + } + +} diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Stop Processing.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Stop Processing.lsl index 8d9367a1..8b14f1bc 100644 --- a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Stop Processing.lsl +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Stop Processing.lsl @@ -4,7 +4,10 @@ // :AUTHOR:Ferd Frederix // :KEYWORDS: // :CREATED:2015-07-17 13:16:10 +<<<<<<< HEAD // :EDITED:2016-07-10 09:24:25 +======= +>>>>>>> f0df6f03553fbf82e10f35590fcf71af838ab4be // :ID:27 // :NUM:1809 // :REV:1 diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Touch Trigger NPC.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Touch Trigger NPC.lsl index 18de859c..927a9df1 100644 --- a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Touch Trigger NPC.lsl +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Touch Trigger NPC.lsl @@ -4,7 +4,10 @@ // :AUTHOR:Ferd Frederix // :KEYWORDS: // :CREATED:2015-07-17 13:16:51 +<<<<<<< HEAD // :EDITED:2016-07-10 09:24:25 +======= +>>>>>>> f0df6f03553fbf82e10f35590fcf71af838ab4be // :ID:27 // :NUM:1811 // :REV:1 diff --git a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Touch to Go.lsl b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Touch to Go.lsl index 4ad41161..96e70b42 100644 --- a/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Touch to Go.lsl +++ b/All In One NPC Recorder and Player/All In One NPC Recorder and Player/Test Object/Touch to Go.lsl @@ -4,7 +4,10 @@ // :AUTHOR:Ferd Frederix // :KEYWORDS: // :CREATED:2015-07-17 13:16:29 +<<<<<<< HEAD // :EDITED:2016-07-10 09:24:25 +======= +>>>>>>> f0df6f03553fbf82e10f35590fcf71af838ab4be // :ID:27 // :NUM:1810 // :REV:1 diff --git a/Flying Bee and Hive/Bee Parts/Smily Bee Body Texture.png b/Flying Bee and Hive/Bee Parts/Smily Bee Body Texture.png new file mode 100644 index 00000000..20a00632 Binary files /dev/null and b/Flying Bee and Hive/Bee Parts/Smily Bee Body Texture.png differ diff --git a/Flying Bee and Hive/Bee/Object/Opensim Bee.lsl b/Flying Bee and Hive/Bee/Object/Opensim Bee.lsl index a37a4f9a..310ae28e 100644 --- a/Flying Bee and Hive/Bee/Object/Opensim Bee.lsl +++ b/Flying Bee and Hive/Bee/Object/Opensim Bee.lsl @@ -4,7 +4,10 @@ // :AUTHOR:Ferd Frederix // :KEYWORDS: // :CREATED:2013-09-08 12:59:45 +<<<<<<< HEAD // :EDITED:2016-07-10 09:24:29 +======= +>>>>>>> f0df6f03553fbf82e10f35590fcf71af838ab4be // :ID:995 // :NUM:1725 // :REV:5 @@ -187,4 +190,8 @@ default llResetScript(); } } +<<<<<<< HEAD // end of code +======= +// end of code +>>>>>>> f0df6f03553fbf82e10f35590fcf71af838ab4be diff --git a/Multi-pose script/Multi-pose script/Object/Animation.ani b/Multi-pose script/Multi-pose script/Object/Animation.ani new file mode 100644 index 00000000..e69de29b diff --git a/Multi-pose script/Multi-pose script/Object/Animation2.ani b/Multi-pose script/Multi-pose script/Object/Animation2.ani new file mode 100644 index 00000000..e69de29b diff --git a/Multi-pose script/Multi-pose script/Object/Script.lsl b/Multi-pose script/Multi-pose script/Object/Script.lsl index b29b9629..dae78038 100644 --- a/Multi-pose script/Multi-pose script/Object/Script.lsl +++ b/Multi-pose script/Multi-pose script/Object/Script.lsl @@ -45,9 +45,9 @@ rotation sitRot=ZERO_ROTATION; // Sit Kit to determine the best position a // Uncomment one of the following five lines to choose your animation method: string animMethod="SEQUENCE_TIMED"; // each animation will be played in sequence, cycling back to the first upon reaching the end // string animMethod="RANDOM_TIMED"; // as above, except the order of animations is randomly shuffled -// string animMethod="SEQUENCE_TOUCH"; // each animation will be played in sequence, but only advances when the seated person touches the object + //string animMethod="SEQUENCE_TOUCH"; // each animation will be played in sequence, but only advances when the seated person touches the object // string animMethod="RANDOM_TOUCH"; // as above, in random order -// string animMethod="DIALOG_SELECT"; // upon sitting the avatar will be asked to pick the animation they wish to play. Once seated, touching +//string animMethod="DIALOG_SELECT"; // upon sitting the avatar will be asked to pick the animation they wish to play. Once seated, touching // the object will display the dialog again, allowing you to pick a different animation. Maximum of 12 animations. float animTimer=45.0; // if using either of the two TIMED methods, how long (in seconds) to wait before advancing to the next animation // this is ignored if you are using one of the other 3 methods @@ -108,8 +108,10 @@ nextAnim() if (llSubStringIndex(animMethod,"RANDOM")>-1) anList=llListRandomize(anList,1); } string nextAnim=llList2String(anList,curInd); + if (nextAnim!=currentAnim) { + llStartAnimation(nextAnim); llStopAnimation(currentAnim); } @@ -179,7 +181,7 @@ default { if (mySitter==NULL_KEY) return; // ignore if no sitter if (llDetectedKey(0)!=mySitter) return; // ignore if not current sitter - if (llSubStringIndex(animMethod,"TIMED")>-1) return; // ignore if using timed method + if (llSubStringIndex(animMethod,"//TIMED")>-1) return; // ignore if using timed method if (animMethod=="DIALOG_SELECT") getAnim(); else nextAnim(); } diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim.sol b/NPC Chatbot for Opensim/NPC Chatbot for Opensim.sol new file mode 100644 index 00000000..40772755 --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim.sol @@ -0,0 +1,3 @@ + + + diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/NPC Chatbot for Opensim.prj b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/NPC Chatbot for Opensim.prj new file mode 100644 index 00000000..f0cd5da6 --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/NPC Chatbot for Opensim.prj @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Appearance b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Appearance new file mode 100644 index 00000000..4a30e185 --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Appearance @@ -0,0 +1,15 @@ +// :SHOW: +// :CATEGORY:ChatBot +// :NAME:NPC Chatbot for Opensim +// :AUTHOR:Ferd Frederix +// :KEYWORDS: +// :CREATED:2016-07-27 16:13:54 +// :EDITED:2016-07-27 15:13:54 +// :ID:1108 +// :NUM:1905 +// :REV:1.0 +// :WORLD:OpenSim +// :DESCRIPTION: +// Sample Apperance notecard +// :CODE: +Appearance notecard will be made here diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Chatbot Controller.lsl b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Chatbot Controller.lsl new file mode 100644 index 00000000..50be81c6 --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Chatbot Controller.lsl @@ -0,0 +1,309 @@ +// :SHOW: +// :CATEGORY:ChatBot +// :NAME:NPC Chatbot for Opensim +// :AUTHOR:Ferd Frederix +// :KEYWORDS: +// :CREATED:2016-07-27 16:13:55 +// :EDITED:2016-07-27 15:13:55 +// :ID:1108 +// :NUM:1906 +// :REV:1.0 +// :WORLD:OpenSim +// :DESCRIPTION: +// This chatbot is for OpenSim Only. It only works on NPC's with a modified All-In-One NPC script, which is also included +// 5,000 chats are free. +// :CODE: +// Chatbot uses PersonalityForge. Get a free account at http://www.personalityforge.com. +// first, get a free account at http://www.personalityforge.com. +// Get an API ID, and add it to the apiKey : + +string apiKey = "BlahBlah"; // your supplied apiKey from your Chat Bot API subscription + + +// Add the domain or IP of your OpenSim server to the list of authorized domains at http://www.personalityforge.com/botland/myapi.php +// Add a checkmark to the "Enable Simple API" in your account. +// Click on the Simple API tab and pick a chatbot ID from the list of chatbots under the heading "Selecting A Chat Bot ID" +// for example, Countess Elvira is 99232. Put that in chatBot ID below. +// Sex Bot Ciran is 100387. +// 754 is Liddora a sexy tart + +string chatBotID = "23958"; // the ID of the chat bot you're talking to + +// The first time, you may want to test it with this set to TRUE +integer debug = FALSE; // Set this TRUE to see the gory details + +// more constants below +integer greeting = TRUE; // if TRUE, say hello when anyone comes up. +integer lookat = FALSE; + +////////// REMOVE THESE IN WORLD //////////////// +///////// LSLEDIT DEBUG ONLY//////////////////// +//osNpcSetRot(key npc, rotation rot) {llSay(0,"Roatating to " + (vector) llRot2Euler(rot));} +//osNpcStopAnimation(key npc, string animation) {llSay(0,"Stopped " + animation);} +//osNpcPlayAnimation(key npc, string animation) {llSay(0,"Playing " + animation);} +//osNpcSay(string speach) {llSay(0,speach);} +///////////////////////////////////////////////////////////////////// + +// various tuneable code bits +float range = 35; // haw far away an avatar is before we greet them/. No point in making this more than 20, that cannot hear us after that +float wpm = 85; // 33 wpm = 2.75 cps @ 5 chars per word for a typical avatar to type with. +// Larger numbers make your NPC answer quicker. +float cps; +integer emotionchannel = 199; // a secret channel that the chatbot sends emotion strings on. + // You can listen for these with other scripts worn by your chatbot, and animate something to show how your chat bot is feeling. + // this is also sent on Link Message Number 1 to all scripts in your chatbox prim + +// global variables +key npcKey ; // the NPC wearing this +string npcName; // ditto +integer starttime; // the time we started typing +key requestid; // check for out HTTP answer +integer AvatarPresent;// true is someone is here + +// first of stride is the response from the bot, the second is the built-in animation +list gAnimations = ["normal", "hello", + "happy","express_smile", + "angry","express_anger", + "averse","express_embarrased", + "sad","express_sad", + "evil","express_repulsed", + "fuming","express_worry", + "hurt","express_cry", + "surprised","express_surprise", + "insulted","express_afraid", + "confused","express_shrug", + "amused","express_laugh", + "asking","express_shrug"]; + + +list lAvatars; // a list of visitors + +DEBUG(string msg) +{ + if (debug) llSay(0,msg); +} + +string strReplace(string str, string search, string replace) { + return llDumpList2String(llParseStringKeepNulls(str, [search], []), replace); +} + +string KeyValueGet(string var) { + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k != var) jump continue; + //DEBUG("got " + var + " = " + llList2String(data, 1)); + return llList2String(data, 1); + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + return ""; +} + + +default +{ + on_rez(integer param) + { + llResetScript(); + } + + state_entry() + { + llOwnerSay("Running"); + npcKey = KeyValueGet("key"); + npcName = llGetObjectName(); + DEBUG("npc is named " + npcName); + + llListen(0,"","",""); + cps = wpm * 5 / 60; // change from words per minute to cps. + DEBUG("CPS = " + (string) cps); + + } + + link_message (integer sender, integer num, string str, key id) { + if (num == 2) { + npcKey = id; + DEBUG("Chatbot npcKey = " + (string) npcKey); + if (greeting) + llSensorRepeat("","",AGENT,range,PI,10); + } + } + + sensor(integer N) { + integer i; + for (i = 0 ; i < N; i ++) { + key avatarName = llDetectedName(i); + + if (llListFindList(lAvatars,[avatarName]) == -1) { + osNpcSay(npcKey,"Hi there, " + llDetectedName(i)+ ", the Rapunzel sim is new. Try it" ); + + lAvatars += avatarName; + + if (llGetListLength(lAvatars) > 20) { + lAvatars = llDeleteSubList(lAvatars, 0,0); + } + } + } + } + + no_sensor() + { + AvatarPresent = FALSE; } + + listen(integer channel, string name, key id, string message) + { + DEBUG("I Heard from :" + name); + // DEBUG("ID: " + (string) id); + // DEBUG("npcKey: " + (string) npcKey); + + if ( id == npcKey) { + // DEBUG("ignoring"); + return; + } + + // DEBUG("Continuing"); + // if the speaker is a prim, it will have a creator. Avatars do not have a creator + list what = llGetObjectDetails(id,[OBJECT_CREATOR, OBJECT_POS]); + key spkrKey = llList2Key(what,0); + + if (spkrKey != NULL_KEY && !debug) + { + if (! debug) + DEBUG("ignoring object "); + return; // we do not want to listen to objects + } + + list names = llParseString2List(name,[" "],[]); + string firstname = llList2String(names,0); + string lastname = llList2String(names,1); + + requestid = llHTTPRequest("http://www.personalityforge.com/api/chat" + + "?apiKey=" + llEscapeURL(apiKey) + + "&message=" + llEscapeURL(message) + + "&chatBotID=" + llEscapeURL(chatBotID) + + "&externalID=" + llEscapeURL(firstname) + + "&firstName=" + llEscapeURL(firstname) + + "&lastName=" + llEscapeURL(lastname) + ,[HTTP_METHOD,"GET"],""); + + llSleep(llFrand(3)+ 1); // think for two to five seconds before we type - for realism + + osNpcPlayAnimation(npcKey,"avatar_type"); + starttime = llGetUnixTime(); + if (lookat) { + + vector vspeaker = llList2Vector(what,1); + rotation rdelta = llRotBetween( llGetPos(), vspeaker ); + + rotation newRot = rdelta * llGetRot(); + //-- rotate the offset to be relative to npc rotation - vector now points to speaker + + osNpcSetRot(npcKey,newRot); // * = add for quats + } + + llSetTimerEvent(20); // for safety in case web site is down. + } + + timer() + { + osNpcStopAnimation(npcKey,"avatar_type"); + llSetTimerEvent(0); + } + + http_response(key request_id, integer status, list metadata, string body) + { + DEBUG(body); + // typical body: + // Checking origin: '71.252.253.290' (regex: '71\.252\.253\.290')
Matched!
{"success":1,"errorMessage":"","message":{"chatBotName":"Liddora","chatBotID":"754","message":"Look up. It's Liddora. So how have you been lately, hello?","emotion":"asking"}} + + if (request_id == requestid) + { + llSetTimerEvent(0); // shut off the error handler + + // get the name of the bot from the reponse + integer botname = llSubStringIndex(body,"chatBotName"); + string namestr = llGetSubString(body,botname,-1); + integer botnameend = llSubStringIndex(namestr,"\",\""); + + string botName = llGetSubString(namestr,14, botnameend-1); + DEBUG("Bot Name:" + (string) botName); + + integer begin = llSubStringIndex(body, "message\":\""); + string msg = llGetSubString(body, begin +10, -1); + integer msgend = llSubStringIndex(msg, "emotion"); + string reply = llGetSubString(msg, 0, msgend-4); + DEBUG("reponse:" + reply); + + // change the name in the reply to the bots real name. + DEBUG("reply:" + reply); + DEBUG("botName:" + botName); + DEBUG("npcName:" + npcName); + + reply = strReplace(reply,"
"," "); + reply = strReplace(reply,"
"," "); + reply = strReplace(reply,"Laurel",npcName); + reply = strReplace(reply,"Problem",npcName); + + DEBUG("after nameswap:" + reply); + DEBUG("Len:" + llStringLength(reply)); + // calculate how long it would take for a person to type the answer in cps or wpm + float delay = (float) llStringLength(reply) / cps; + + DEBUG("delay = " + (string) delay); + + integer t = llGetUnixTime() - starttime ; // subtract how long it has taken to look up the bots answer since we started typing. + + DEBUG("t = " + (string) t); + delay -= t; + + DEBUG("delay = " + (string) delay); + if (delay > 0) { + DEBUG("delay:" + (string) delay); + llSleep(delay) ; // fake out the delay that happens when an avatar is typing an answer + } + + + // Emotion Logic - speak on a chat channel what emotional stste the bot is in, for other scripts to use. + string emotion = llGetSubString(msg, msgend,-1); + DEBUG((string) emotion); + + msgend = llSubStringIndex(emotion, "\"}"); + emotion = llGetSubString(emotion, 10,msgend-1); + DEBUG("Emotion:" + (string) emotion); + + // sends a link animate to prim animator, attempts to play an animation + // normal, happy, angry, averse, sad, evil, fuming, + // hurt, surprised, insulted, confused, amused, asking. + + llMessageLinked(LINK_SET,1,emotion,""); + + // and also chats it on channel "emotionchannel" for external gadgetry to respond with. + llSay(emotionchannel,emotion); // for controlling external gadgets based on emotes + + osNpcStopAnimation(npcKey,"avatar_type"); + + // emotional state output + + // you can override the built-in emotion by adding an animation + // with any of the following names to the inventory + // normal, happy, angry, averse, sad, evil, fuming, + // hurt, surprised, insulted, confused, amused, asking. + + if (llGetInventoryType(emotion) == INVENTORY_ANIMATION) { + DEBUG("Playing animation from inventory named " + emotion); + osNpcPlayAnimation(npcKey,emotion); + } else { + integer index = llListFindList(gAnimations,[emotion]); + if (index != -1) { + string toPlay = llList2String(gAnimations,index + 1); + DEBUG("Playing built-in animation named " + toPlay); + osNpcPlayAnimation(npcKey,toPlay); + } + } + osNpcSay(npcKey,reply); // now speak it. + + } + } +} diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Contents.png b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Contents.png new file mode 100644 index 00000000..afafe9b0 Binary files /dev/null and b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Contents.png differ diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/NPC Control Script.lsl b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/NPC Control Script.lsl new file mode 100644 index 00000000..8e0a136b --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/NPC Control Script.lsl @@ -0,0 +1,1644 @@ +// :SHOW: +// :CATEGORY:ChatBot +// :NAME:NPC Chatbot for Opensim +// :AUTHOR:Ferd Frederix +// :KEYWORDS: +// :CREATED:2016-07-27 16:14:00 +// :EDITED:2016-07-27 15:14:00 +// :ID:1108 +// :NUM:1907 +// :REV:1.0 +// :WORLD:OpenSim +// :DESCRIPTION: +// Modified All in one NPC recorder player for NPC use +// Click Prim to use. + +// :CODE: + +//*******************************************************************// +// Instructions on how to use this is at http://www.free-lsl-scripts.com/opensim/posts/NPC/ +// This is an OpenSim-only script. +// Author: Ferd Frederix + + +//////////////////////////////////////////////////////////////////////////////////////////// +// Original code was Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // +/////////////////////////////////////////////////////////////////////////////////////////// +// Please see: http://www.gnu.org/licenses/gpl.html for legal details, // +// rights of fair usage, the disclaimer and warranty conditions. // +/////////////////////////////////////////////////////////////////////////////////////////// +// The original NPC controller was from http://was.fm/opensim:npc +// Extensive additions and bug fixes by Fred Beckhusem, aka Ferd Frederix, fred@mitsi.com +// llSensor had two params swapped +// @Wander would wander where it had rezzed, not where it was. +// There was no 'no_sensor' event in sit, so if a @sit failed, the NPC got stuck +// The animation and walks always stopped old, then started new. It should be start new, then stop old so the default stand would be suppressed. +// New code: +// Merged with new Route recorder and notecard writer +// If the NPC failed to reach a destination it never moved on. Added WAIT global to tune this +// Exposed many tunable variables and ported the code to LSLEditor. +// Added floating point to times in notecard. + +// Added @sound, @randsound, @whisper, @shout, and @cmd controls. +// +// notecards integers are not floats for better control +// +// Link Messages may be used to perform external control by injecting @commands into the stream of actions +// Example: +// To chat something, such as with a chat robot +// llMessageLinked(LINK_SET,0,"@npc_say=Hello",""); + +// This script assumes that NPCs and OSSl scripting is enabled in the OpenSim configuration. +// In order to enable them, the following changes must be made in the OpenSim.ini configuration file: +// +// ; Turn on OSSL +// AllowOSFunctions = true +// OSFunctionThreatLevel = Severe + +//[NPC] +// ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} +// Enabled = true +// +// and then the server has to be restarted. + + +// Commands: All commands begin with an @ sign. All other lines are ignored +// @commands may have optional parameters. The syntax is always: +// @cmd=parm1|parm2 +// NaN in the table below meand Not a Number. This means there is no parameter + +//Command First Parameter Second Parameter Description +//@spawn name location (vector) Rezzes an NPC with name at a location. +//@walk destination (vector) NaN Makes the NPC walk to destination. +//@fly destination (vector) NaN Makes the NPC fly to destination. +//@land destination (vector) NaN Makes the NPC land at destination. +//@say string NaN Makes the NPC speak a phrase. +//@whisper string NaN Makes the NPC whisper a phrase. +//@shout string NaN Makes the NPC shout a phrase. +//@pause seconds (float) NaN Makes the NPC wait for a multiple of seconds. +//@wander radius (float) cycles (integer) Makes the NPC wander in radius, for cycles seconds. +//@delete NaN NaN Removes the NPC. Rerquires a link message of @npc_start to continue +//@npc_start NaN NaN Starts the NPC at the beginning +//@animate animation (string) time (float) Makes the NPC trigger the animation animation for time seconds. +//@goto label (string) NaN Jump to the label label in the script. +//@rotate degrees (float) NaN Rotate the NPC degrees around the Z axis. +//@sit primitive name NaN Sit on a primitive with a given name. +//@stand NaN NaN If sitting on a primitive, stand up. +//@sound sound_name NaN plays a sound from inventory +//@randsound NaN NaN Plays a random sound from inventory +//@cmd channel (integer) string Says string on channel, for controlling external gadgets + +//@stop NaN NaN Halts the NPC script indefinitely. Can be started with a link message +//@go NaN NaN Continues on next notecard line, for use in link messages + +////////////////////////////////////////////////////////// +// DEBUG // +////////////////////////////////////////////////////////// +integer debug = FALSE; // set to TRUE or FALSE for debug chat on various actions +integer Editor = FALSE; // set to to TRUE to working in LSLEditor, FALSE for in-world. + // you must also include the NPC commands found in the other script since LSLEditor does not support OpenSim +integer iTitleText = FALSE; // set to TRUE to see debug info in text above the controller + +////////////////////////////////////////////////////////// +// TUNABLE CONFIGURATION // +////////////////////////////////////////////////////////// +integer allowUsers = TRUE; // If true, any user can get a Start NPC and Stop NPC menu. Only groups and owners canb get all commands if TRUE, or FALSE +float MAXDIST = 2.0; // how close a NPC has to get to a dest pos to continue to next state. Do not lower this too much, as it may miss the target +float TIMER = 0.5; // how often the system checks the distance traveled. Fastest you can go is 0.5 seconds +integer WANDERRAND = TRUE; // set to TRUE and they will pause during wanders a random number of seconds +float WANDERTIME = 10.0; // how long they stand after each @wander,if WANDERRAND is FALSE. If WANDERRAND is TRUE, this is the max time +integer WAIT = 10; // wait for this number of seconds for the NPC to reach a destination (for safety). If it fails to reach a target, it will move on after this time. +float RANGE = 35.0; // 1 to 96.0 meters - anyone this close to the controller will start NPCS if Sensor button is clicked +float REZTIME = 10.0; // wait this lng for NPC to rez in, then start the process +string STAND = "Stand"; // the name of the default Stand animation +string WALK = "Walk"; // the name of the default Walk animation +string FLY = "Fly"; // the name of the default Fly animation +string RUN = "Run"; // the name of the default Run animation +string LAND = "Land"; // the name of the default land animation ( for birds only) +float OffsetZ = 0.5; // appear 0.5 meter above ground, this is added to all destinations to keep them from sinking in. For fun, make this large and watch them fall out of the sky + + +// DESCRIPTIONS FIELDS HAVE TO SURVIVE A RESET +// These vars are stored by saving them with KeyValueSet +// "pr" is a 0 if it is set for Owner Only, 1 for Group control +// "se" is "on" if sensors are enabled +// "co" = "R" or "A" for relative or absolute addressing mode +// "key" = NPC key + +// These Globals used to be stored in description. Moved to RAM in V1.6 +float RAMPause; // @pause param +float RAMwd ; // @wander distance +integer RAMwc; // @wander count +float RAMrot; // @rotate +string RAMsit; // @sit primname +string RAManimationName; // @animate animation (string) time (float) +float RAManimationTime; + +// other globals section +integer iChannel; // a listen channel, randomly assigned +integer iHandle; // the handle to it + + + +// NPC controls +vector newDest ; // tmp storage for the walks +integer iWaitCounter ; // wait for this number of seconds for the NPC to reach a desrtination +string sNPCName; // the name of the NPC that may be in world. So we can remove it. +integer bNPC_STOP = FALSE; // boolean to reuse a listener +integer bForget = FALSE; // set to TRUE by link messages so we do not remember them +float fTimerVal ; // how long we wait when wandering (calculated) + +// OS_NPC_CREATOR_OWNED will create an 'owned' NPC that will only respond to osNpc* commands issued from scripts that have the same owner as the one that created the NPC. +// OS_NPC_NOT_OWNED will create an 'unowned' NPC that will respond to any script that has OSSL permissions to call osNpc* commands. +integer NPCOptions = OS_NPC_CREATOR_OWNED; // only yhe owner of this box can control this NPC. + +integer walkstate = 0; // helps us reshare the walk state for run, fly and land - a bit of a hack, but it saves RAM. Has to be done this way because some bits of NPCWalkOption are asserted as 0 + +integer NPCWalkOption; // Some notes for what happens to NPCWalkOption: +// OS_NPC_FLY - Fly the avatar to the given position. The avatar will not land unless the OS_NPC_LAND_AT_TARGET option is also given. +// OS_NPC_NO_FLY - Do not fly to the target. The NPC will attempt to walk to the location. If it's up in the air then the avatar will keep bouncing hopeless until another move target is given or the move is stopped +//OS_NPC_LAND_AT_TARGET - If given and the avatar is flying, then it will land when it reaches the target. If OS_NPC_NO_FLY is given then this option has no effect. +// OS_NPC_RUNNING - if given, NPC avatar moves at running/fast flying speed, otherwise moves at walking/slow flying speed. + +// menus +integer showMenu = FALSE; // when we switch states, we need to bring up a menu +list lAtButtons = ["Menu","-", "More", "@run","@walk","@fly", "@land","@wander","@sit", "@stand","@animate","@rotate"]; +list lMenu2 = ["<<", "@comment", "@stop", "@say","@whisper","@shout", "@sound","@randsound", "-", "@cmd", "@pause", "@delete" ]; +string sCommand; // place to store a command for two-prompted ones +string sParam2; // place to store a prompt for two-prompted ones +string priPub = "Owner Only"; // Private or Group +key kUserKey; // the person who is controlling the avatar, not the Owner + +// the command lists +list lCommands; // commands are stored here +list lNPCScript; // Storage for the NPC script. +string npcAction; // Storage for the next action. @cmd=0|hello, this becomes @cmd +string npcParams; // Storage for the param, @cmd=0|hello, this becomes 0|hello + +// misc vars +string sNotecard; // commands are stored here temporarily for dumping +vector vWanderPos; // a place to wander to +string lastANIM ; // last animation run +// Sensor +integer avatarPresent = TRUE; // Sensor sets this flag when people are within Range. +integer Sensor; // set to true if we are running a Sensor for avatars + +// Coordinate control +vector vInitialPos ; // Vector that will be filled by the script with the initial starting position in region coordinates. +vector vDestPos = ZERO_VECTOR; // Storage for destination position. +string relAbs = "Absolute"; // absolute vs relative positioning + +/////////////////////////////////////////////////////////////////////////// +// FUNCTIONS // +/////////////////////////////////////////////////////////////////////////// + + +// DEBUG(string) will chat a string or display it as hovertext if debug == TRUE +DEBUG(string str) +{ + if (debug) + llOwnerSay( str); // Send the owner debug info so you can chase NPCS + if (iTitleText) + { + llSleep(0.1); + llSetText(str,<1.0,1.0,1.0>,1.0); // show hovertext + } +} + + +// common subroutines + + + +// return TRUE if the avatar is owner when private is set, or TRUE if the avatar is in th same group and GROUP is set. +integer checkPerms() { + + integer group = (integer) KeyValueGet("pr"); + if (! group) + priPub = "Owner Only"; + else + priPub = "Group"; + + + if (llDetectedKey(0) == llGetOwner()){ + kUserKey = llDetectedKey(0); + return TRUE; + } + + if ( group && llDetectedGroup(0)) { + kUserKey = llDetectedKey(0); + return TRUE; + } + kUserKey = llDetectedKey(0); + return FALSE; +} + + + +NPCStart(string anim) +{ + DEBUG(" Start Anim: " + anim); + if (llGetInventoryType(anim) == INVENTORY_ANIMATION ) { + + if (lastANIM != anim) { + osNpcPlayAnimation(NPCKey(), anim); + + if(llStringLength(lastANIM) && llGetInventoryType(lastANIM) == INVENTORY_ANIMATION) { + osNpcStopAnimation(NPCKey(), lastANIM) ; + } + + lastANIM = anim; + } + } else { + llSay(DEBUG_CHANNEL, "No animation named " + anim); + } +} + + +TimerEvent(float timesent) +{ + //DEBUG("Setting timer: " + (string) timesent); + llSetTimerEvent(timesent); +} + + + +ProcessLink(string str) +{ + // DEBUG("Processing exern cmd : " + str); + bForget = TRUE; // tell the NPCProcess state to forget this command after processing it. + lNPCScript = llListInsertList(lNPCScript,[str],0); // add this command to the beginning of the list of commands + //NPCStart(STAND); +} + +// Kill a NPC by Name +Kill(string someNPCName) +{ + list avatars = osGetAvatarList(); // Returns a strided list of the UUID, position, and name of each avatar in the region except the owner. + + + //DEBUG(llDumpList2String(avatars,",")); + integer i; + integer count; + integer j = llGetListLength(avatars); + for (; i < j; i++){ + if (llList2String(avatars,i) == someNPCName){ + vector v = llList2Vector(avatars,i-1); + key target = llList2Key(avatars,i-2); // get the UUID of the avatar + osNpcRemove(target); + llOwnerSay("Removed " + someNPCName + " at location " + (string) v); + count++; + } + } + if (count) + llOwnerSay("Removed " + (string) count + " NPC's"); + else + llOwnerSay("Could not locate " + someNPCName); +} + + +// return a String for the position we are at. Strings used as the caller wants strings +string Pos() +{ + vector where = llGetPos(); // find the box position + + where.z += OffsetZ; // use the ground position + an offset + + if (Editor) + where = <128,128,31 + llFrand(1)>; // center of sim for editing + + // if attached the height will be too high by 1/2 the agent size + if (llGetAttached()) { + vector size = llGetAgentSize(llGetOwner()); + float Z = size.z; + where.z -= Z/2; + } + + // DEBUG("Pos= " + (string) where); + return (string) where; +} + +Expire() +{ + llOwnerSay("Menu expired"); + iHandle = 0; + TimerEvent(0.0); +} + +// setup a menu with a timer for timeouts, called by all make*() +menu() +{ + llListenRemove(iHandle); + iChannel = llCeil(llFrand(100000) + 20000); + iHandle = llListen(iChannel,"","",""); + TimerEvent(120.0); +} + + +// make a text box +makeText(string Param) +{ + menu(); + llTextBox(kUserKey, Param, iChannel); +} + +// top level menu +makeMainMenu() +{ + menu(); + list buttons = ["Appearance","Recording","Save","Help","-","Erase RAM", priPub,relAbs,"-","Stop NPC","Sensor","Start NPC"]; + llDialog(kUserKey,(string) llGetListLength(lCommands) + "Recordings",buttons,iChannel); +} + + +// Rev 1.4 +// top level menu for non group/ non owners +makeUserMenu() +{ + if (!allowUsers) + return; + menu(); + list buttons = ["Start NPC","Stop NPC"]; + llDialog(kUserKey,"Choose",buttons,iChannel); +} + + + +// programmable menu for @commands +makeMenu(list buttons) +{ + menu(); + llDialog(kUserKey,(string) llGetListLength(lCommands) + "Recordings",buttons,iChannel); +} + + + + +// make one or two text boxes with prompts +Text(string cmd, string p1, string p2) +{ + sCommand = cmd; + sParam2 = ""; + if (llStringLength(p2)) + sParam2 = p2; + + makeText(p1); +} + +ProcessSensor(integer n) +{ + DEBUG("Sensor:" + (string) n); + if (Sensor && n) + avatarPresent = TRUE; // someone is here and we need to tell the system to run + else if (Sensor && !n) + avatarPresent = FALSE; // someone is not here and we need to tell the system to stop + else + avatarPresent = TRUE; // someone is effectivly always here +} + +vector CirclePoint(float radius) { + float x = llFrand(radius *2) - radius; // +/- radius, randomized + float y = llFrand(radius *2) - radius; // +/- radius, randomized + return ; // so this should always happen +} + +string KeyValueGet(string var) { + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k != var) jump continue; + //DEBUG("got " + var + " = " + llList2String(data, 1)); + return llList2String(data, 1); + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + return ""; +} + +KeyValueSet(string var, string val) { + + //DEBUG("set " + var + " = " + val); + list dVars = llParseString2List(llGetObjectDesc(), ["&"], []); + if(llGetListLength(dVars) == 0) + { + llSetObjectDesc(var + "=" + val); + return; + } + list result = []; + do { + list data = llParseString2List(llList2String(dVars, 0), ["="], []); + string k = llList2String(data, 0); + if(k == "") jump continue; + if(k == var && val == "") jump continue; + if(k == var) { + result += k + "=" + val; + val = ""; + jump continue; + } + string v = llList2String(data, 1); + if(v == "") jump continue; + result += k + "=" + v; + @continue; + dVars = llDeleteSubList(dVars, 0, 0); + } while(llGetListLength(dVars)); + if(val != "") result += var + "=" + val; + llSetObjectDesc(llDumpList2String(result, "&")); +} + + +// clear RAM +Clr() { + + lCommands = []; + llOwnerSay("RAM Memory cleared. Notecards, if any, are not modified."); + makeMainMenu(); +} + +integer checkNoteCards() +{ + // Check that they have saved an Appeaance and Path notecard + integer num = llGetInventoryNumber(INVENTORY_NOTECARD); // how many notecards overall + + integer i; + integer count; + for (; i < num; i++){ + if (llGetInventoryName(INVENTORY_NOTECARD,i) == "Path") + count++; + if (llGetInventoryName(INVENTORY_NOTECARD,i) == "Appearance") + count++; + } + // if we have both, run the NPC + return count; +} +// saves a few bytes per call +key NPCKey() +{ + return KeyValueGet("key"); +} + +// Notes: +// No llResetScript() used so we can retain memory between rezzes and sim restarts. NPC info and stateful info is held in the Description +// + + +// This state is the first main menu +default +{ + state_entry() + { + llSetText("",<1,1,1>,1.0); // clr all hovertext- we may not be using it. + + string rA = KeyValueGet("co"); // Get the remembered menu setting for Abs Vs Relative + if (rA == "A") + relAbs = "Absolute"; + else if (rA == "R") + relAbs = "Relative"; + else + relAbs = "Absolute"; + + + if (showMenu) { + makeMainMenu(); + return; + } + + + // reenable NPC is sensor is on. + if ("on" == KeyValueGet("se")) + { + ProcessSensor(1); // fake 1 avatar to get it rezzed + Sensor = TRUE; // we need to scan for avatars + state NPCGo; + } + } + + + touch_start(integer n) { // if touched, make a menu + if (checkPerms()) + makeMainMenu(); + else + makeUserMenu(); + } + + // no changed event needed + + // menu listener + listen(integer iChannel, string name, key id, string message) { + TimerEvent(0.0); /// kill the menu expiration timer + + if (message == "Stop NPC") + { + if (llStringLength(sNPCName)){ + Kill(sNPCName); + sNPCName = ""; + } else { + bNPC_STOP = TRUE; + makeText("Enter name of an NPC to stop"); + } + } + else if (message == "Erase RAM"){ + Clr(); + } + else if (message == "Relative"){ + relAbs = "Absolute"; + KeyValueSet("co","A"); // remember coordinates = A + Clr(); + } + else if (message == "Absolute"){ + relAbs = "Relative"; + KeyValueSet("co","R"); // remember coordinates = R + Clr(); + } + else if (message == "Recording"){ + state Commands; // show them the recording menu + } + else if (message == "Owner Only") { + priPub = "Group"; + KeyValueSet("pr","1"); + + llOwnerSay("Group members have control"); + makeMainMenu(); + } + else if (message == "Group") { + priPub = "Owner Only"; + KeyValueSet("pr","0"); + llOwnerSay("Only you have control"); + makeMainMenu(); + } + else if (message == "Sensor") { + integer count = checkNoteCards(); + + if (count >= 2) { + KeyValueSet("se", "on"); + ProcessSensor(1); // fake 1 avatar to get it rezzed + Sensor = TRUE; // we need to scan for avatars + state NPCGo; + } + + // lslEditor does not handle the above, so I hack it in + if (Editor) { + Sensor = TRUE; // we need to scan for avatars + state NPCGo; + } + + llOwnerSay("You have not saved a recording and/or appearance, so you cannot start a NPC"); + makeMainMenu(); + } + else if (message == "Appearance") { + llRemoveInventory("Appearance"); // delete the notecard + osAgentSaveAppearance(kUserKey, "Appearance"); // make the ntecard + llOwnerSay("Your Appearance has been recorded in notecard 'Appearance'"); + makeMainMenu(); + } + else if (message == "Save") { + if (llGetListLength(lCommands) == 0) { + llOwnerSay("Nothing recorded, you need to make some Recodings first"); + makeMainMenu(); + return; + } + state Save; + } + else if (message == "Help"){ + llLoadURL(kUserKey,"Click to view help","http://www.outworldz.com/opensim/posts/NPC/"); + makeMainMenu(); + } + else if (message == "Start NPC") { + integer count = checkNoteCards(); + if (Editor) state NPCGo; + if (count == 2) + state NPCGo; + + llOwnerSay("You have not saved a either recording or and appearance, so we cannot start a NPC"); + + } + else if (bNPC_STOP){ + bNPC_STOP = FALSE; + Kill(message); + } + } + timer(){ + Expire(); + } +} + + +// This state is used to save a Path notecard +state Save +{ + state_entry(){ + makeText("Stand where you want the NPC to appear, and enter the NPC Name"); + } + listen(integer iChannel, string name, key id, string message) { + TimerEvent(0.0); /// kill the menu expiration timer + + sNPCName = message; // in case we need to kill it. + vector vDest = (vector) Pos(); + + if (relAbs == "Relative") + { + vDest -= llGetPos(); // just an offset for relative + } + sNotecard = "@spawn=" + message + "|" + (string) vDest + "\n"; + integer i; + integer j = llGetListLength(lCommands); + for (; i < j; i++){ + // get the command to save to the notecard + string line = llList2String(lCommands,i); + if (relAbs == "Absolute") { + sNotecard += line; // add the un-modified string to the notecard + } else { + // since we have to record absolute coords since we do not know where the box goes until they press Save, + // we process the absolute to relative conversion for walks here + list parts = llParseString2List(line,["="],[]); //get the @command + + if (llList2String(parts,0) == "@walk") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@walk=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@fly") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@fly=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@run") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@run=" + (string) vec + "\n"; + } + else if (llList2String(parts,0) == "@land") { + vector vec = (vector) llList2String(parts,1) - llGetPos(); + sNotecard += "@land=" + (string) vec + "\n"; + } + else { + sNotecard += line; // add the un-modified string to the notecard + } + } + } + llRemoveInventory("Path"); // delete the old notecard + osMakeNotecard("Path",sNotecard); // Makes the notecard. + llOwnerSay("'Path' notecard has been written"); + state default; + } + timer(){ + Expire(); + } + +} + +// This state is used to record the path for the NPC +// Each command can take 0, 1, or 2 params +state Commands +{ + state_entry() { + makeMenu(lAtButtons); + } + + on_rez(integer p) { + showMenu= TRUE; + state default; + } + touch_start(integer n){ + if (checkPerms()) + makeMenu(lAtButtons); + else + makeUserMenu(); + + } + + listen(integer iChannel, string name, key id, string message) + { + TimerEvent(0.0); /// kill the menu expiration timer + + if (message == "Menu"){ + showMenu= TRUE; + state default; + } + else if (message == "More"){ + makeMenu(lMenu2); + } + else if (message == "<<") { + makeMenu(lAtButtons); + } + else if (message == "@comment"){ + Text("# ","Enter a comment",""); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@run"){ + lCommands += "@run=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@fly"){ + lCommands += "@fly=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@land"){ + lCommands += "@land=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@walk") { + lCommands += "@walk=" + Pos() + "\n"; + llOwnerSay("Recorded position: " + Pos()); + makeMenu(lAtButtons); + } + else if (message == "@stop"){ + lCommands += "@stop"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@sound"){ + Text("@sound=","Enter a sound name or UUID to trigger",""); + } + else if (message == "@randsound"){ + lCommands += "@randsound"+ "\n"; + makeMenu(lAtButtons); + } + else if (message == "@say") { + Text("@say=","Enter what the NPC will say",""); + } + else if (message == "@whisper"){ + Text("@whisper=","Enter what the NPC will whisper",""); + } + else if (message == "@shout"){ + Text("@shout=","Enter what the NPC will shout",""); + } + else if (message == "@wander") { + Text("@wander=","Enter radius to wander","Enter number of wanders"); + } + else if (message == "@pause") { + Text("@pause=","Enter time to pause",""); + } + else if (message == "@rotate") { + Text("@rotate=","Enter degrees to rotate",""); + } + else if (message == "@sit"){ + Text("@sit=","Enter name of object to sit on",""); + } + else if (message == "@cmd"){ + Text("@cmd=","Enter cjhannel to speak on","Enter text to speak"); + } + else if (message == "@stand"){ + lCommands += "@stand\n"; + llOwnerSay("Stand Recorded"); + makeMenu(lAtButtons); + } + else if (message == "@animate"){ + Text("@animate=","Enter animation name to play","Enter time to play the animation"); + } + else if (! llStringLength(sParam2)) { + lCommands += sCommand + message + "\n"; + llOwnerSay("Recorded"); + makeMenu(lAtButtons); + } + else if (llStringLength(sParam2)){ + sCommand = sCommand + message + "|"; + llOwnerSay("Recorded"); + makeText(sParam2); + sParam2 = ""; + } + } + timer() { + Expire(); +} + + + +} + + +// This state will create an NPC in world +state NPCGo { + state_entry() { + // DEBUG("NPCGo"); + ProcessSensor(1); // assert that someone is home so we can get rezzed. + osNpcRemove(NPCKey()); + TimerEvent(5); + } + timer() { + lNPCScript = llParseString2List(osGetNotecard("Path"), ["\n"], []); + if(llGetListLength(lNPCScript) == 0) { + llSay(DEBUG_CHANNEL, "No Path notecard found."); + TimerEvent(0.0); + return; + } + state ProcessNPCLine; + } + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state ProcessNPCLine; + } + on_rez(integer num) { + llResetScript(); + } + state_exit() { + TimerEvent(0.0); + } +} + + +// This state loops over the notecard, processing each command +state ProcessNPCLine +{ + state_entry() + { + // DEBUG("ProcessNPCLine"); + @ignore; + + string next = llList2String(lNPCScript, 0); // get the next command + // DEBUG("Cmd:" + next); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); // delete it + if (! bForget) { + lNPCScript += next; // put it on the end unless we are told to forget it from a Link Message + bForget = FALSE; + } + if(llGetSubString(next, 0, 0) != "@") jump ignore; // ignore non-@ commands + list data = llParseString2List(next, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data, 0), STRING_TRIM)); + npcParams = llStringTrim(llList2String(data, 1), STRING_TRIM); + + @commands; + + if (! avatarPresent){ + state nobodyHome; + } + if(npcAction == "@spawn") { + // DEBUG("Spawning"); + integer lastIdx = llGetListLength(lNPCScript)-1; + lNPCScript = llDeleteSubList(lNPCScript, lastIdx, lastIdx); // remove spawn commands, we do them only once + list spawnData = llParseString2List(npcParams, ["|"], []); + sNPCName =llList2String(spawnData, 0); // V 1.6 name in RAM + + list spawnDest = llParseString2List(llList2String(spawnData, 1), ["<", ",", ">"], []); + vInitialPos.x = llList2Float(spawnDest, 0); + vInitialPos.y = llList2Float(spawnDest, 1); + vInitialPos.z = llList2Float(spawnDest, 2); + state spawn; + } + if(npcAction == "@stop") { + state stop; + } + if(npcAction == "@goto") { + // DEBUG("goto"); + integer lastIdx = llGetListLength(lNPCScript)-1; + lNPCScript = llDeleteSubList(lNPCScript, lastIdx, lastIdx); + // Wind commands till goto label. + @wind; + string next1 = llList2String(lNPCScript, 0); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); + lNPCScript += next1; + if(next1 != npcParams) jump wind; + // Wind the label too. + next1 = llList2String(lNPCScript, 0); + lNPCScript = llDeleteSubList(lNPCScript, 0, 0); + lNPCScript += next1; + // Get next command. + list data1 = llParseString2List(next1, ["="], []); + npcAction = llToLower(llStringTrim(llList2String(data1, 0), STRING_TRIM)); + npcParams = llStringTrim(llList2String(data1, 1), STRING_TRIM); + // Reschedule. + jump commands; + } + + if(npcAction == "@sound") { + // DEBUG("sound"); + llTriggerSound(npcParams,1.0); + jump ignore; // process next line + } + if(npcAction == "@randsound") { + // DEBUG("random sound"); + integer N = llGetInventoryNumber(INVENTORY_SOUND); + integer rand = llCeil(llFrand(N)) -1; // pick a random sound + string toPlay = llGetInventoryName(INVENTORY_SOUND,rand); + llTriggerSound(toPlay,1.0); + jump ignore; // process next line + } + + if(npcAction == "@walk") { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); + + if (vDestPos == ZERO_VECTOR) { + llSay(DEBUG_CHANNEL,"Bad (zeros) position for @walk"); + state ProcessNPCLine; + } + walkstate = 1;// walking + NPCWalkOption = OS_NPC_NO_FLY ; + state walk; + } + + if(npcAction == "@fly") { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); + + if (vDestPos == ZERO_VECTOR) { + llSay(DEBUG_CHANNEL,"Bad (zeros) position for @fly"); + state ProcessNPCLine; + } + + walkstate = 2;// flying + NPCWalkOption = OS_NPC_FLY ; + state walk; + } + + if(npcAction == "@run") { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); + + if (vDestPos == ZERO_VECTOR) { + llSay(DEBUG_CHANNEL,"Bad (zeros) position for @walk"); + state ProcessNPCLine; + } + walkstate = 3;// running + NPCWalkOption = OS_NPC_NO_FLY | OS_NPC_RUNNING; + state walk; + } + + if(npcAction == "@land") { + list dest = llParseString2List(npcParams, ["<", ",", ">"], []); + vDestPos.x = llList2Float(dest, 0); + vDestPos.y = llList2Float(dest, 1); + vDestPos.z = llList2Float(dest, 2); + + if (vDestPos == ZERO_VECTOR) { + llSay(DEBUG_CHANNEL,"Bad (zeros) position for @walk"); + state ProcessNPCLine; + } + + walkstate = 4;// landing + + + NPCWalkOption= OS_NPC_FLY | OS_NPC_LAND_AT_TARGET ; + state walk; + } + + + + // chat commands + // speak in white text + + if(npcAction == "@say") { + // DEBUG("say"); + osNpcSay(NPCKey(),0, npcParams); + jump ignore; // process next line + } + if(npcAction == "@shout") { + // DEBUG("shout"); + osNpcShout(NPCKey(),0, npcParams); + jump ignore; // process next line + } + if(npcAction == "@whisper") { + // DEBUG("whisper"); + osNpcWhisper(NPCKey(),0, npcParams); + jump ignore; // process next line + } + // speak a command on a channel, so you can open doors and control stuff. + if(npcAction == "@cmd") { + // DEBUG("cmd"); + list dataToSpeak = llParseString2List(npcParams, ["|"], []); + integer iChannel = (integer) llList2String(dataToSpeak,0); + string stringToSpeak = llList2String(dataToSpeak,1); + llRegionSay(iChannel, stringToSpeak); // V 1.2 + + jump ignore; // process next line + } + // stop everything + if(npcAction == "@pause") { + // DEBUG("pause"); + RAMPause = (float) npcParams; + state pause; + } + if(npcAction == "@wander") { + // DEBUG("wander"); + list wanderData = llParseString2List(npcParams, ["|"], []); + RAMwd = (float) llList2String(wanderData, 0); + RAMwc = (integer) llList2String(wanderData, 1); + + vDestPos = osNpcGetPos(NPCKey()); // set the wander start + DEBUG("Starting at " + (string) vDestPos); + state wander; + } + if(npcAction == "@rotate") { + // DEBUG("rotate"); + RAMrot = (float) npcParams; + state rotate; + } + if(npcAction == "@sit") { + // DEBUG("sit"); + RAMsit= npcParams; + state sit; + } + if(npcAction == "@stand") { + // DEBUG("stand"); + state stand; + } + if(npcAction == "@delete") { + state delete; + } + if(npcAction == "@animate") { + // DEBUG("animate"); + list animateData = llParseString2List(npcParams, ["|"], []); + RAManimationName = llList2String(animateData, 0); + RAManimationTime = (float) llList2String(animateData, 1); + state animate; + } + llSay(DEBUG_CHANNEL, "ERROR: Unrecognized script line: " + npcAction + "=" + npcParams); + jump ignore; + + } + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + on_rez(integer num) { + llResetScript(); + } + link_message(integer sender, integer num, string str, key id) { + ProcessLink(str); + state ProcessNPCLine; + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else { + makeUserMenu(); + } + + } +} + + +state nobodyHome +{ + state_entry() { + // DEBUG("Removing NPC"); + osNpcRemove(NPCKey()); + llSensorRepeat("","",AGENT,RANGE,TWO_PI, 5); + } + sensor(integer n) { + llSensorRemove(); + state NPCGo; + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else { + makeUserMenu(); + } + + } +} + + +state spawn +{ + state_entry() { + // DEBUG("state spawn"); + list name = llParseString2List(sNPCName, [" "], []); + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + vInitialPos += llGetPos(); + } + + // DEBUG("rez:" + (string) vInitialPos); + + KeyValueSet("key", osNpcCreate(llList2String(name, 0), llList2String(name, 1), vInitialPos, "Appearance", NPCOptions)); // no OS_NPC_SENSE_AS_AGENT allowed due to llSensor Use + + llMessageLinked(LINK_SET,2,"Key",NPCKey()); + + osNpcLoadAppearance(NPCKey(), "Appearance"); + TimerEvent(REZTIME); + NPCStart(STAND); + } + link_message(integer sender, integer num, string str, key id) { + ProcessLink(str); + state ProcessNPCLine; + } + timer() { + state ProcessNPCLine; + } + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + on_rez(integer num) { + llResetScript(); + } + state_exit(){ + TimerEvent(0.0); + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + }else { + makeUserMenu(); + } + + } +} + + +state rotate { + state_entry() { + // DEBUG("state rotate"); + osNpcSetRot(NPCKey(), llEuler2Rot(<0,0,RAMrot> * DEG_TO_RAD)); + TimerEvent(TIMER); + } + link_message(integer sender, integer num, string str, key id) { + ProcessLink(str); + state ProcessNPCLine; + } + timer() { + state ProcessNPCLine; + } + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + on_rez(integer num) { + llResetScript(); + } + state_exit() { + TimerEvent(0.0); + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + }else { + makeUserMenu(); + } + } +} + +state sit { + state_entry() { + // DEBUG ("state sit"); + llSensorRepeat(RAMsit, "", PASSIVE|ACTIVE, 96, TWO_PI, 1); + } + sensor(integer num) { + llSensorRemove(); + osNpcSit(NPCKey(), llDetectedKey(0), OS_NPC_SIT_NOW); //V1.2 + TimerEvent(TIMER); + } + no_sensor(){ + state ProcessNPCLine; + + } + timer() { + state ProcessNPCLine; + } + link_message(integer sender, integer num, string str, key id) { + ProcessLink(str); + state ProcessNPCLine; + } + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + on_rez(integer num) { + llResetScript(); + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else { + makeUserMenu(); + } + + } + + + state_exit(){ + TimerEvent(0.0); + } + + +} + +state stand { + state_entry() { + // DEBUG("state stand"); + osNpcStand(NPCKey()); + state ProcessNPCLine; + } + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else { + makeUserMenu(); + } + + } + + + on_rez(integer num) { + llResetScript(); + } + +} + +state animate { + state_entry() { + // DEBUG("state animate"); + NPCStart(RAManimationName); + TimerEvent(RAManimationTime); + } + link_message(integer sender, integer num, string str, key id) { + ProcessLink(str); + state ProcessNPCLine; + } + timer() { + NPCStart(STAND); + state ProcessNPCLine; + } + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else { + makeUserMenu(); + } + + } + + + on_rez(integer num) { + llResetScript(); + } + state_exit() { + TimerEvent(0.0); + } + +} +state walk { + state_entry() { + + DEBUG("NPCWalkOption = " + (string) NPCWalkOption); + + // walk, fly, run, land + if (walkstate == 1) { + NPCStart(WALK); + } else if (walkstate == 2) { + llShout(299,"on"); + NPCStart(FLY); + } else if (walkstate == 3) { + NPCStart(RUN); + } else if (walkstate == 4) { + NPCStart(LAND); + } else { + state ProcessNPCLine; + } + + if (Sensor) { + // DEBUG("Sensor on"); + llSensor("","",AGENT,RANGE,TWO_PI); // sensor survive state switches. + } + + newDest = vDestPos ; + // notecard is stored as offsets from this box with relative addressing. Convert to absolute + if (relAbs == "Relative"){ + newDest += llGetPos(); + } + + DEBUG("Moveto:" + (string) newDest); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + osNpcMoveToTarget(NPCKey(), newDest, NPCWalkOption); + TimerEvent(TIMER); + } + link_message(integer sender, integer num, string str, key id) { + ProcessLink(str); + state ProcessNPCLine; + } + timer() { + if (--iWaitCounter) { + + if (llVecDist(osNpcGetPos(NPCKey()), newDest) > MAXDIST) { + return; + } + } + + // walk, fly, run, land + if (walkstate == 1) { + NPCStart(STAND); + } else if (walkstate == 2) { + // nothing + } else if (walkstate == 3) { + NPCStart(STAND); + } else if (walkstate == 4) { + llShout(299,"off"); + NPCStart(STAND); + } else { + state ProcessNPCLine; + } + + state ProcessNPCLine; + } + sensor(integer n) { + ProcessSensor(n); + } + no_sensor(){ + ProcessSensor(0); + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else { + makeUserMenu(); + } + + } + + + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + on_rez(integer num) { + llResetScript(); + } + state_exit() { + TimerEvent(0.0); + } + +} + +state wander +{ + state_entry() { + DEBUG("state wander"); + if (Sensor) + { + // DEBUG("Sensor on"); + llSensor("","",AGENT,RANGE,TWO_PI); // sensor survive state switches. + } + + vector point = CirclePoint(RAMwd); + DEBUG("CirclePoint:" + (string) point); + vWanderPos = vDestPos + point; + DEBUG("vWanderPos:" + (string) vWanderPos); + + fTimerVal = WANDERTIME; // default time to pause after each wander + if (WANDERRAND) + fTimerVal = llFrand(WANDERTIME); // override, they want random times + + NPCStart(WALK); + + DEBUG("Wander to:" + (string) vWanderPos); + + osNpcMoveToTarget(NPCKey(), vWanderPos, NPCWalkOption); + iWaitCounter = WAIT; // wait 60 seconds to get to a destination. + + TimerEvent(TIMER); // first time we wait for the short timer. + } + link_message(integer sender, integer num, string str, key id) { + ProcessLink(str); + NPCStart(STAND); + state ProcessNPCLine; + } + timer() { + + if (--iWaitCounter) // wait 60 seconds to get to a destination. + if (llVecDist(osNpcGetPos(NPCKey()), vWanderPos) > MAXDIST) return; + + + // see if wander counter == 0, if so, stop walking, go to stand and process next line + if(RAMwc == 0) { + NPCStart(STAND); + state ProcessNPCLine; + } + + // one less time to wander around + RAMwc--; + + NPCStart(STAND); + state wanderhold; + } + sensor(integer n) { + ProcessSensor(n); + } + no_sensor() { + ProcessSensor(0); + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else { + makeUserMenu(); + } + } + + + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + on_rez(integer num) { + llResetScript(); + } + state_exit() { + TimerEvent(0.0); + } +} + + +state wanderhold +{ + state_entry(){ + // now that we have reached a wander spot, slow the timer down to the desired value + TimerEvent(fTimerVal); + if (Sensor) + { + // DEBUG("Sensor on"); + llSensor("","",AGENT,RANGE,TWO_PI); // sensor survive state switches. + } + } + timer() { + state wander; + } + sensor(integer n){ + ProcessSensor(n); + } + no_sensor(){ + ProcessSensor(0); + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else { + makeUserMenu(); + } + + } + + + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + on_rez(integer num) { + llResetScript(); + } + state_exit() { + TimerEvent(0.0); + } + + +} + + + +// @pause=10 will stand for 10 seconds +state pause { + state_entry() { + DEBUG("state pause"); + NPCStart(STAND); + if (Sensor) + { + // DEBUG("Sensor on"); + llSensor("","",AGENT,RANGE,TWO_PI); // sensor survive state switches. + } + llSetTimerEvent(RAMPause); + } + link_message(integer sender, integer num, string str, key id){ + ProcessLink(str); + state ProcessNPCLine; + } + timer() { + NPCStart(STAND); + state ProcessNPCLine; + } + sensor(integer n) + { + ProcessSensor(n); + } + no_sensor() + { + ProcessSensor(0); + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else + makeUserMenu(); + + } + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + on_rez(integer num) { + llResetScript(); + } + state_exit() + { + TimerEvent(0.0); + } +} + +// @stop makes the NPC stand there. You have to linkmessage to get moving again +state stop { + state_entry() { + if (Sensor) + { + // DEBUG("Sensor on"); + llSensor("","",AGENT,RANGE,TWO_PI); // sensor survive state switches. + } + } + link_message(integer sender, integer num, string str, key id){ + if (str=="@go") + state ProcessNPCLine; + ProcessLink(str); + } + // if touched by owner while running code, make a menu + touch_start(integer n) { + if (checkPerms()) { + TimerEvent(0); // stop the NPC from ticking + showMenu = TRUE; + state default; + } else + makeUserMenu(); + + } + sensor(integer n) + { + ProcessSensor(n); + } + no_sensor() + { + ProcessSensor(0); + } + changed(integer change) { + if(change & CHANGED_REGION_RESTART) + state NPCGo; + } + on_rez(integer num) { + llResetScript(); + } +} + + + +state delete { + state_entry() { + // DEBUG("state delete"); + osNpcRemove(NPCKey()); + } + link_message(integer sender, integer num, string str, key id) { + if(str == "@npc_start") + { + state NPCGo; + } + } + + // No on_rez or changed event needed, the only way out is a link message +} + diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Path b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Path new file mode 100644 index 00000000..ea4910bd --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Path @@ -0,0 +1,19 @@ +// :SHOW: +// :CATEGORY:ChatBot +// :NAME:NPC Chatbot for Opensim +// :AUTHOR:Ferd Frederix +// :KEYWORDS: +// :CREATED:2016-07-27 16:14:00 +// :EDITED:2016-07-27 15:14:00 +// :ID:1108 +// :NUM:1908 +// :REV:1.0 +// :WORLD:OpenSim +// :DESCRIPTION: +// Sample Path notecard +// :CODE: +@spawn=Tinker@www.outworldz.com|<0.000000,0.000000,0.500000> +@walk=<0,-8,0.5> +@sit=LayDown +@animate=Sit|100000 +@stop diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/README.txt b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/README.txt new file mode 100644 index 00000000..17a73619 --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/README.txt @@ -0,0 +1,59 @@ +// :SHOW: +// :CATEGORY:ChatBot +// :NAME:NPC Chatbot for Opensim +// :AUTHOR:Ferd Frederix +// :KEYWORDS: +// :CREATED:2016-07-27 16:14:00 +// :EDITED:2016-07-27 15:14:00 +// :ID:1108 +// :NUM:1909 +// :REV:1.0 +// :WORLD:OpenSim +// :DESCRIPTION: +// Read me notecard +// :CODE: +This chatbot is for OpenSim Only. It only works on NPC's with a modified All-In-One NPC script, which is also included. +Upload everything and put it in a prim. + +Step 1: +Go to PersonalityForge.com. Get a free account at http://www.personalityforge.com. The first 5,000 chats are free. + +Get an API ID, and add it to the apiKey in the script "Chatbot Contoller.lsl". + +string apiKey = "BlahBlah"; // your supplied apiKey from your Chat Bot API subscription + +Add the domain for your OpenSim server or IP to the list of authorized domains at http://www.personalityforge.com/botland/myapi.php + Add a checkmark to the "Enable Simple API" in your account. + Click on the Simple API tab and pick a chatbot ID from the list of chatbots under the heading "Selecting A Chat Bot ID" + for example, Countess Elvira is 99232. Put that in chatBot ID below. + + Sex Bot Ciran is 100387. + 754 is Liddora a sexy tart + +Now look for this and add that ID: + +string chatBotID = "23958"; // the ID of the chat bot you're talking to + +Save the script. + +Step 2: +You need to make the "Appearance" notecard with one to your liking. Dress up however you want, take it all off and put it on again so the server has it recorded okay. Now touch the box and select "Appearance" to record your shape. The easy way is to just use a pre- recorded Avatar Appearance and switch back and forth in Firestorm. The positions and what is worn only get saved to the server when you take them off. + +Step 3: +Touch the box again, and make sure it is set to "Relative" and not "Absolute". This is because of the numbers inside the Route notecard. "Absolute" would be used for world positions, relative means relative to the control prim. + +Make sure that "Sensor" has been clicked. No Sensor will leave the NPC in the world at all times. "Sensor" will remove it when no one is around. + +Then click "Start". You NPC should appear, walk 8 meters to one side, and stand there. If you chat with it, the arms should move, and if you can convince it to be happy, it will laugh and animate the face with various emotions. + +This NPC uses the All-In-One NPC controller. So it has a Route notecard. In that notecard is this, which you should probably edit to your liking: + +@spawn=Tinker@www.outworldz.com|<0.000000,0.000000,0.500000> +@walk=<0,-8,0.5> +@stop + +This causes my little fairy chatbot "Tinker@www.outworldz.com" to appear 1/5 meter above the prim, walk 8 to the left, and stop. Any animatons the fairy plays after that is based on her emotional states from the chatbot. + +You can have your NPC do whatever you want, like walk around, drive a car, etc. +More info on this is at http://www.outworldz.com/opensim/posts/npc/ + diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Sit.bvh b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Sit.bvh new file mode 100644 index 00000000..d8e25895 --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Sit.bvh @@ -0,0 +1,179 @@ +HIERARCHY +ROOT hip +{ + OFFSET 0.00 0.00 0.00 + CHANNELS 6 Xposition Yposition Zposition Xrotation Zrotation Yrotation + JOINT abdomen + { + OFFSET 0.000000 0.000000 0.000000 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT chest + { + OFFSET 0.000000 5.018152 -1.882228 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT neckDummy + { + OFFSET 0.000000 8.316447 0.784897 + CHANNELS 3 Xrotation Yrotation Zrotation + JOINT neck + { + OFFSET 0.000000 2.280413 -0.392801 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT head + { + OFFSET 0.000000 3.496879 0.529469 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT figureHair + { + OFFSET 0.000000 4.699570 0.720622 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 0.000000 -6.419331 0.000000 + } + } + } + } + } + JOINT lCollar + { + OFFSET 0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lShldr + { + OFFSET 6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT lForeArm + { + OFFSET 10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lHand + { + OFFSET 11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 10.353753 0.000000 0.000000 + } + } + } + } + } + JOINT rCollar + { + OFFSET -0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rShldr + { + OFFSET -6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT rForeArm + { + OFFSET -10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rHand + { + OFFSET -11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET -10.353753 0.000000 0.000000 + } + } + } + } + } + } + } + JOINT lThigh + { + OFFSET 4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lShin + { + OFFSET -1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lFoot + { + OFFSET -0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } + JOINT rThigh + { + OFFSET -4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rShin + { + OFFSET 1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rFoot + { + OFFSET 0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } +} +MOTION +Frames: 50 +Frame Time: 0.041667 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -70.100700 9.978770 15.991600 -22.515600 -9.303740 0.147736 5.969490 -0.173112 0.175734 -2.021920 5.690310 -0.063351 70.100700 -9.978770 15.991600 22.515600 9.303740 0.147736 -5.969490 0.173112 0.175734 -7.545480 4.001929 0.126583 15.872740 -3.319793 -0.839247 -8.608498 1.050494 -0.878046 -7.531943 -4.331991 0.100592 15.814292 3.299639 0.618600 -8.640055 -1.563356 0.936766 +-0.001136 42.047485 0.258350 0.015281 -0.160640 1.231823 -0.202867 -1.017794 5.550867 -0.022891 -2.631103 2.992019 0.000000 0.000000 0.000000 0.000000 0.000000 1.297549 3.800558 -1.201557 7.998749 0.000000 0.000000 0.000000 1.994514 -5.197196 -0.066307 -67.927406 9.117760 16.272688 -21.930227 -10.127905 0.184120 7.175318 0.005541 -0.197885 -2.073291 5.740149 -0.032077 69.997414 -10.220204 15.994469 22.056313 9.142480 0.185973 -6.503005 1.401555 -2.041011 -7.551804 4.214809 0.125835 15.585843 -3.309215 -0.808465 -8.337039 -0.217005 -0.943522 -7.072927 -4.077958 0.028241 15.140048 3.277331 0.570500 -8.423216 -2.749167 0.862214 +-0.002857 42.096840 0.286087 0.029094 -0.365053 2.705819 -0.405597 -2.258602 12.353542 -0.052194 -5.847550 6.673011 0.000000 0.000000 0.000000 0.000000 0.000000 2.867914 8.444941 -2.649465 17.763105 0.000000 0.000000 0.000000 2.026428 -4.493691 -0.053350 -65.288086 8.063235 16.616686 -21.241461 -11.135085 0.222496 8.258029 0.234520 -0.622607 -2.153154 5.878275 0.045403 70.024467 -10.651922 15.978795 21.412695 9.311210 0.253536 -6.883192 3.187223 -5.134254 -7.501410 4.496881 0.123082 15.118730 -3.299616 -0.766510 -7.970469 -1.727266 -1.048025 -6.452955 -3.748653 -0.055355 14.178856 3.239592 0.472283 -8.083669 -4.153584 0.781128 +-0.003286 42.109127 0.292991 0.061213 -0.535572 4.277362 -0.777409 -3.492378 18.982010 -0.075997 -9.012057 10.205709 0.000000 0.000000 0.000000 0.000000 0.000000 4.480512 13.028363 -4.157663 27.440105 0.000000 0.000000 0.000000 2.106382 -3.666201 -0.027852 -62.624863 7.033216 16.953691 -20.461637 -12.127282 0.283488 9.150728 0.488386 -1.057494 -2.251019 6.080780 0.156168 70.160461 -11.211857 15.948553 20.662586 9.747875 0.340776 -7.102841 5.307372 -8.863679 -7.733775 4.735919 0.120272 15.098766 -3.299485 -0.765173 -7.820042 -3.331604 -1.135538 -6.111829 -3.485498 -0.127818 13.752612 3.218626 0.442000 -8.054342 -5.678007 0.704172 +0.000000 42.014908 0.240040 0.140966 -0.588000 5.920680 -1.579400 -4.545870 24.255800 -0.081138 -11.618200 12.859500 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 16.840300 -5.638830 35.604698 0.000000 0.000000 0.000000 2.188578 -2.810312 -0.001600 -60.240200 6.206450 17.227100 -19.525499 -12.948100 0.400552 10.078557 0.751147 -1.508068 -2.352196 6.289758 0.270502 70.299858 -11.790388 15.917407 19.886646 10.196711 0.430919 -7.332713 7.500043 -13.019673 -8.672421 4.828678 0.146981 16.364857 -3.346981 -0.905014 -8.241468 -4.977678 -1.109998 -6.623362 -3.453089 -0.197466 14.911632 3.268945 0.563573 -8.767126 -7.294611 0.632392 +0.008106 41.758495 0.093278 0.286617 -0.465829 7.598319 -2.919785 -5.289261 27.298862 -0.058123 -13.293894 14.099704 0.000000 0.000000 0.000000 0.000000 0.000000 7.315878 19.311069 -7.011647 41.139530 0.000000 0.000000 0.000000 2.227221 -2.021616 0.013618 -58.374638 5.701050 17.393173 -18.427805 -13.479096 0.587695 11.266666 1.006811 -1.979855 -2.441995 6.447314 0.358690 70.337204 -12.277906 15.899037 19.165552 10.401958 0.507188 -7.743576 9.503284 -17.392633 -10.711632 4.735614 0.181811 19.500193 -3.476861 -1.197509 -9.489000 -6.637327 -0.951120 -8.415224 -3.777928 -0.249301 18.396254 3.414390 0.917017 -10.594095 -8.999483 0.561660 +0.016877 41.339180 -0.160993 0.472185 -0.223303 9.226099 -4.295254 -5.766469 28.452793 -0.012122 -14.204382 14.175374 0.000000 0.000000 0.000000 0.000000 0.000000 8.417012 20.434372 -8.218807 44.157990 0.000000 0.000000 0.000000 2.176512 -1.395702 0.006016 -57.021053 5.392597 17.459612 -17.403440 -13.753652 0.781114 12.940200 1.239383 -2.478377 -2.505727 6.495546 0.391018 70.166992 -12.564794 15.907110 18.579964 10.107853 0.552805 -8.506192 11.055137 -21.772951 -13.706823 4.490720 0.248237 24.247133 -3.662852 -1.674194 -11.342396 -8.183679 -0.657165 -11.571109 -4.258971 -0.275373 23.999399 3.634807 1.505209 -13.201004 -10.669835 0.315946 +0.020842 40.769993 -0.531403 0.660630 0.057650 10.708160 -5.049613 -6.064847 28.363611 0.048028 -14.649241 13.531502 0.000000 0.000000 0.000000 0.000000 0.000000 9.317108 20.344748 -9.209007 45.081150 0.000000 0.000000 0.000000 1.990654 -1.028158 -0.036195 -56.110439 5.096044 17.446981 -16.747332 -13.843108 0.897551 15.324302 1.432872 -3.009158 -2.528701 6.376553 0.337769 69.683716 -12.541431 15.955297 18.210548 9.058629 0.550996 -9.791324 11.893643 -25.951015 -17.437792 4.198074 0.338902 30.074774 -3.858332 -2.266191 -13.475947 -9.548857 -0.221030 -15.383269 -4.977664 -0.287406 30.727306 3.876024 2.184429 -16.246342 -12.078061 0.165571 +0.014530 40.063969 -1.026583 0.814910 0.295098 11.948647 -4.526672 -6.271750 27.677338 0.113491 -14.928055 12.613079 0.000000 0.000000 0.000000 0.000000 0.000000 10.029876 19.176733 -9.930942 44.330078 0.000000 0.000000 0.000000 1.623849 -1.014575 -0.124801 -55.573788 4.626344 17.375854 -16.754408 -13.818810 0.853750 18.644119 1.571285 -3.577721 -2.496229 6.032434 0.169230 68.781883 -12.098205 16.057272 18.137974 6.998525 0.484983 -11.769738 11.756850 -29.717213 -21.666656 3.954324 0.443313 36.503391 -4.044169 -2.934869 -15.638267 -10.672198 0.278965 -19.613991 -5.710900 -0.279835 37.803112 4.065731 2.911026 -19.196899 -13.162488 -0.046318 +-0.007528 39.234142 -1.655163 0.897985 0.407112 12.851700 -2.070240 -6.474530 27.040001 0.175430 -15.340400 11.865100 0.000000 0.000000 0.000000 0.000000 0.000000 10.569020 17.064877 -10.333308 42.325867 0.000000 0.000000 0.000000 1.030300 -1.450540 -0.271591 -55.342098 3.798450 17.266800 -17.719601 -13.752100 0.566455 23.124800 1.638630 -4.189590 -2.393620 5.405290 -0.144315 67.356003 -11.125500 16.226700 18.442900 3.671780 0.337990 -14.612200 10.382800 -32.861942 -26.143826 3.846021 0.554989 43.048153 -4.172040 -3.623220 -17.589991 -11.449199 0.840408 -23.938587 -6.463055 -0.274669 44.984058 4.191748 3.669371 -22.069221 -13.790672 -0.121726 +-0.050137 38.292961 -2.409089 0.882349 0.337312 13.353222 2.706291 -6.743101 26.934940 0.224199 -16.094496 11.606818 0.000000 0.000000 0.000000 0.000000 0.000000 10.948249 14.143720 -10.364807 39.489601 0.000000 0.000000 0.000000 0.198067 -2.374392 -0.480962 -55.373985 2.487314 17.137873 -19.762753 -13.696319 -0.000414 28.751705 1.681599 -4.830937 -2.211814 4.486124 -0.621754 65.330505 -9.567327 16.466475 19.172091 -1.036520 0.114412 -18.264462 7.752028 -35.175598 -30.707300 3.953771 0.675722 49.288216 -4.214429 -4.315293 -19.088308 -11.875370 1.386264 -28.477438 -6.873167 -0.220213 51.558327 4.208741 4.360595 -24.106689 -14.144130 -0.270036 +-0.115429 37.250546 -3.213563 0.778648 0.131524 13.516165 9.111165 -7.077611 27.194798 0.246917 -17.033125 11.654552 0.000000 0.000000 0.000000 0.000000 0.000000 11.181270 10.547808 -9.974133 36.242355 0.000000 0.000000 0.000000 -0.749360 -3.595456 -0.727751 -55.738575 0.807899 16.997055 -22.303387 -13.632792 -0.694226 34.551033 1.997627 -5.410524 -1.964272 3.461572 -1.238661 62.749615 -7.582217 16.736366 20.236719 -6.677859 -0.096668 -21.772221 4.815056 -36.448566 -35.223942 4.236428 0.764493 55.312519 -4.176326 -4.968762 -20.384064 -12.023439 1.903501 -32.657665 -7.230220 -0.219549 57.641293 4.117342 5.020196 -25.918390 -14.136715 -0.290269 +-0.204869 36.116421 -3.977106 0.607063 -0.138876 13.435247 16.183052 -7.460773 27.489546 0.229894 -17.907717 11.698886 0.000000 0.000000 0.000000 0.000000 0.000000 11.281791 6.411681 -9.109984 33.005203 0.000000 0.000000 0.000000 -1.654636 -4.865809 -0.979408 -56.532635 -1.064830 16.849812 -24.585958 -13.524848 -1.315175 39.309212 2.946833 -5.817761 -1.670083 2.567176 -1.959786 59.687500 -5.382332 16.985371 21.514063 -12.662883 -0.184997 -23.956169 2.764890 -36.471245 -39.669811 4.646955 0.772826 61.285667 -4.039305 -5.623230 -21.678022 -11.919246 2.350195 -37.009411 -7.279677 -0.227884 63.486649 3.918202 5.641013 -27.336681 -14.054149 -0.454885 +-0.319923 34.900127 -4.608232 0.387775 -0.402509 13.205188 22.960609 -7.875296 27.489159 0.159439 -18.469700 11.430408 0.000000 0.000000 0.000000 0.000000 0.000000 11.263515 1.869889 -7.721058 30.199228 0.000000 0.000000 0.000000 -2.360411 -5.937526 -1.203382 -57.852928 -2.955908 16.701603 -25.854912 -13.335809 -1.663455 41.812660 4.889338 -5.942060 -1.348339 2.038479 -2.749876 56.218346 -3.179836 17.162485 22.881397 -18.402214 -0.040321 -23.636997 2.794546 -35.034027 -43.965260 5.135311 0.690983 67.382362 -3.814714 -6.268446 -23.232658 -11.684981 2.697291 -41.309090 -7.166585 -0.281345 69.357353 3.652169 6.216343 -28.788540 -13.927116 -0.737134 +-0.462055 33.611195 -5.015463 0.140966 -0.588000 12.920700 28.482500 -8.303890 26.863600 0.021864 -18.470501 10.539700 0.000000 0.000000 0.000000 0.000000 0.000000 11.140156 -2.943030 -5.756050 28.245501 0.000000 0.000000 0.000000 -2.709340 -6.562680 -1.367120 -59.796200 -4.690370 16.557899 -25.354700 -13.029000 -1.539260 40.847801 8.185260 -5.672830 -1.018130 2.111020 -3.573680 52.416302 -1.186890 17.216700 24.216000 -23.306499 0.447615 -19.635401 6.097030 -31.927299 -48.061069 5.653193 0.479244 73.787239 -3.474089 -6.889403 -25.328661 -11.391047 2.863119 -45.139637 -7.147304 -0.481332 75.543465 3.301003 6.828876 -30.997875 -13.621574 -1.176313 +-0.625463 32.258106 -5.221559 -0.087118 -0.647162 12.685126 32.141991 -8.714515 25.368425 -0.278603 -17.744574 8.753790 0.000000 0.000000 0.000000 0.000000 0.000000 10.925414 -7.825219 -3.290900 27.354988 0.000000 0.000000 0.000000 -2.514160 -6.420678 -1.452255 -62.329395 -6.144660 16.428251 -23.208241 -12.761728 -0.993648 36.654705 12.391641 -4.982024 -0.749251 2.890534 -4.389220 48.485493 0.562473 17.124125 25.807608 -26.889833 1.483009 -11.844831 12.917302 -27.275766 -52.032818 6.121557 0.178778 80.399940 -3.065367 -7.491178 -27.786781 -11.096766 2.902039 -48.836628 -7.206628 -0.747539 82.045853 2.900582 7.426325 -33.690441 -13.261812 -1.793520 +-0.775271 30.845148 -5.706260 -0.145974 -0.624573 12.636305 34.750740 -9.016124 23.101532 -1.166061 -16.458477 5.945470 0.000000 0.000000 0.000000 0.000000 0.000000 10.632996 -12.305557 -0.910501 26.898216 0.000000 0.000000 0.000000 -1.467941 -4.900249 -1.497147 -64.900131 -7.400843 16.338558 -23.052319 -13.467224 -1.081142 35.288033 13.853205 -4.171755 -0.814312 3.963524 -5.127613 45.149837 2.746739 16.969330 29.595821 -29.080166 3.645842 -4.449783 19.708128 -22.541378 -56.329060 6.338910 0.136681 85.893959 -2.727632 -7.982375 -28.876787 -11.003044 3.166472 -53.101933 -7.461143 -0.796327 87.790771 2.519392 7.935912 -35.187824 -13.149985 -2.232794 +-0.869335 29.375566 -7.063550 0.140966 -0.588000 12.920700 37.474998 -9.102920 20.246401 -3.146690 -14.861800 2.023970 0.000000 0.000000 0.000000 0.000000 0.000000 10.276609 -15.845600 0.673007 26.035603 0.000000 0.000000 0.000000 0.766166 -1.317450 -1.554340 -66.826202 -8.592390 16.318800 -29.402201 -16.272699 -3.107130 44.256100 8.111580 -3.626680 -1.536630 4.786680 -5.713250 43.263199 6.222520 16.864000 37.932701 -29.908899 7.610040 -2.707540 21.974199 -19.520399 -62.393833 6.131525 0.781529 89.501648 -2.529813 -8.347482 -26.404787 -11.069010 4.096362 -59.449234 -8.153783 -0.226388 92.011993 2.216583 8.261917 -33.339851 -13.439254 -1.951319 +-0.872431 27.886549 -9.542672 0.660576 -0.585714 13.415488 40.882645 -8.875570 17.194075 -6.338554 -13.222828 -2.826497 0.000000 0.000000 0.000000 0.000000 0.000000 9.869966 -17.821077 1.014126 23.927561 0.000000 0.000000 0.000000 4.015821 4.340507 -1.644702 -67.609413 -9.885515 16.389240 -44.205246 -21.322229 -7.541314 66.079781 -6.626896 -3.621811 -3.034421 5.164068 -6.112218 43.356716 11.201074 16.894766 51.570087 -29.110842 13.215491 -9.210017 17.106630 -18.929438 -69.892052 5.336908 2.244351 90.224297 -2.607593 -8.505087 -19.621990 -10.779461 5.738407 -67.848671 -9.353822 1.057089 93.872597 2.023984 8.354570 -27.166733 -13.644540 -0.653342 +-0.777013 26.551064 -12.013938 0.140966 -0.588000 12.920700 43.148102 -8.260590 15.165800 -9.307310 -11.884600 -7.321860 0.000000 0.000000 0.000000 0.000000 0.000000 9.426769 -17.264400 0.733914 19.734501 0.000000 0.000000 0.000000 6.071980 9.401870 -1.662390 -67.487602 -11.577400 16.531200 -59.137402 -24.827400 -11.510700 83.330399 -21.497299 -3.993590 -4.605520 6.289250 -6.457390 44.670601 15.312300 17.048000 64.859100 -25.234400 16.966000 -15.887800 10.042100 -17.166401 -75.341019 4.843800 3.455750 90.097908 -2.695096 -8.565252 -13.262901 -9.457743 7.071873 -74.263962 -10.155553 2.081025 94.466759 1.933840 8.348231 -20.709200 -12.765933 0.540243 +-0.591852 25.530415 -13.328908 -2.455969 -0.557183 10.407695 42.380375 -7.136115 15.093898 -10.760098 -11.018998 -10.140150 0.000000 0.000000 0.000000 0.000000 0.000000 8.960727 -13.584900 0.557259 13.013932 0.000000 0.000000 0.000000 4.952104 11.254337 -1.507222 -66.857559 -13.857865 16.697147 -65.650581 -23.260971 -12.243420 79.201653 -27.589514 -4.296614 -5.578798 9.128095 -6.860391 46.224689 16.194149 17.270897 72.147560 -17.503981 15.621323 -14.526196 6.287201 -10.536071 -76.707176 5.707410 3.380951 92.164139 -2.501134 -8.704925 -11.614241 -7.263399 7.239071 -75.908676 -9.556920 1.998037 95.644653 1.852712 8.464150 -17.665529 -10.838728 0.539092 +-0.363304 24.803457 -13.643139 -6.074385 -0.501732 6.610309 38.820499 -5.160920 15.924700 -11.522500 -10.038500 -10.907800 0.000000 0.000000 0.000000 0.000000 0.000000 8.485547 -8.042975 0.557812 4.911759 0.000000 0.000000 0.000000 1.616479 10.208116 -1.228365 -66.015770 -16.356316 16.763041 -64.572441 -18.073032 -10.714931 59.327023 -26.471737 -3.396677 -6.227700 12.346200 -7.181090 47.448299 14.098300 17.454201 74.171303 -9.034440 10.301300 -6.990950 6.082470 0.710524 -75.496025 6.961439 2.244997 95.905380 -2.133769 -8.915996 -13.544906 -4.234988 6.245570 -74.717163 -8.556355 1.092098 97.846397 1.747047 8.680337 -17.445347 -7.904090 -0.618339 +-0.147123 24.303423 -13.438188 -9.134972 -0.441656 2.702975 33.474945 -2.307904 16.147840 -12.606924 -8.502589 -9.806231 0.000000 0.000000 0.000000 0.000000 0.000000 8.014936 -2.361760 0.646416 -3.029062 0.000000 0.000000 0.000000 -2.238928 7.304027 -0.912318 -65.233643 -18.562061 16.585714 -59.074524 -11.957973 -8.837513 34.949783 -22.331715 0.012631 -6.877466 14.308359 -7.263671 48.239124 10.141443 17.425304 73.165558 -3.010855 3.229143 2.332134 8.351938 15.335871 -73.571877 7.398752 0.799846 99.652397 -1.722067 -9.104954 -16.761017 -0.476882 4.617184 -72.896591 -8.194424 -0.132631 100.280342 1.614837 8.934370 -18.506849 -4.307328 -2.469582 +0.000939 23.963556 -13.195612 -10.058400 -0.396959 -0.139853 28.280100 -0.025860 14.412100 -13.654600 -7.318210 -8.288430 0.000000 0.000000 0.000000 0.000000 0.000000 7.562603 1.735580 0.733914 -9.265530 0.000000 0.000000 0.000000 -4.918130 3.582900 -0.645584 -64.782600 -19.964399 16.021999 -52.328400 -7.610210 -8.523450 17.313299 -19.357201 7.237720 -7.115950 14.476300 -7.141320 49.958801 6.286670 16.814600 70.975098 0.990960 -3.318360 9.057210 12.019637 32.102402 -73.282913 7.460052 -0.364895 101.900253 -1.486730 -9.208735 -18.714811 2.437124 3.106550 -72.886467 -8.456903 -1.185964 101.642441 1.543463 9.101422 -18.670393 -1.253969 -4.131649 +0.043469 23.726555 -13.278124 -7.926306 -0.381788 -1.099397 24.939623 0.396672 9.992074 -14.115564 -7.321980 -7.730533 0.000000 0.000000 0.000000 0.000000 0.000000 7.142253 2.971139 0.751940 -12.647152 0.000000 0.000000 0.000000 -5.233160 -0.038699 -0.496564 -64.868721 -20.131510 15.157438 -47.100723 -6.850621 -10.608710 14.206190 -20.386114 18.689032 -6.521918 12.949107 -6.930665 53.784458 4.296818 15.571449 69.107430 4.158430 -7.350912 9.454207 16.009592 48.685352 -76.245377 7.782739 -0.699248 101.753265 -1.486786 -9.210054 -17.797413 3.157538 2.584072 -75.786819 -8.310682 -1.659614 101.088631 1.648746 9.118819 -17.210026 -0.491356 -4.751955 +0.016426 23.572933 -13.573064 -4.464168 -0.386842 -0.779546 23.296490 -0.211947 4.506510 -14.046229 -7.721753 -7.929712 0.000000 0.000000 0.000000 0.000000 0.000000 6.767593 1.848017 0.715297 -13.593440 0.000000 0.000000 0.000000 -4.028121 -3.141241 -0.461256 -65.436722 -18.947090 14.992432 -44.538521 -8.005962 -11.623996 19.598129 -22.857027 31.193110 -5.375175 11.278348 -6.893106 58.691280 4.287345 15.118093 68.111450 7.122568 -8.077724 2.416154 19.245832 58.411160 -80.572365 7.762822 -0.495983 100.244797 -1.633601 -9.132307 -15.388410 2.853946 2.768085 -80.085068 -8.467069 -1.709246 99.736031 1.785352 9.043935 -15.031303 -0.734781 -4.628127 +-0.025891 23.492668 -13.848934 -2.058400 -0.396959 -0.139853 22.728500 -0.494140 0.160156 -13.654600 -7.318200 -8.288400 0.000000 0.000000 0.000000 0.000000 0.000000 6.452331 -0.685447 0.659579 -12.916411 0.000000 0.000000 0.000000 -2.655120 -5.429470 -0.517557 -66.365997 -16.373699 16.756100 -45.383900 -8.529470 -7.023700 24.004101 -22.858700 40.680599 -4.130780 11.378700 -7.326240 63.104000 5.961870 17.245001 68.296402 10.375300 -5.007880 -12.508200 20.652399 53.519100 -83.582695 7.636213 -0.186658 98.951874 -1.798568 -9.068689 -13.419610 2.309466 3.084131 -83.092674 -8.671844 -1.606984 98.685860 1.894741 8.962910 -13.441343 -1.225798 -4.382638 +-0.041389 23.472105 -13.933654 -2.355244 -0.400345 0.073362 22.663372 0.302029 -1.410207 -12.763442 -5.288787 -8.358323 0.000000 0.000000 0.000000 0.000000 0.000000 6.210174 -3.680905 0.620380 -11.428075 0.000000 0.000000 0.000000 -2.146618 -6.714589 -0.635816 -67.489677 -12.660131 21.005629 -49.690632 -6.675766 5.520680 20.655518 -17.934645 44.302353 -3.244061 14.340141 -8.337900 65.804955 8.829684 22.809927 68.480186 13.839926 1.976072 -29.558062 18.727209 34.185310 -83.444283 7.587450 -0.121380 98.962868 -1.827669 -9.074026 -13.260627 2.131085 3.186827 -82.958527 -8.769772 -1.578251 98.724609 1.903192 8.986553 -13.307418 -1.393921 -4.351883 +-0.036799 23.483084 -13.892812 -4.040154 -0.398677 -0.033274 22.728500 0.505900 -0.839800 -9.654600 -2.318200 -8.288400 0.000000 0.000000 0.000000 0.000000 0.000000 6.054828 -6.190008 0.633294 -9.940445 0.000000 0.000000 0.000000 -2.256451 -7.233702 -0.756190 -68.455856 -9.200068 25.610476 -54.759129 -3.905049 19.469149 13.649653 -11.447479 44.090389 -3.171410 17.953800 -9.276880 67.007080 11.622759 28.939779 61.515598 15.165300 11.497700 -18.124701 10.263800 32.333698 -81.643768 7.596544 -0.201949 99.672813 -1.750242 -9.120222 -14.112836 2.247701 3.139502 -81.158745 -8.759913 -1.593118 99.357018 1.844714 9.036206 -14.052436 -1.301064 -4.417953 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 22.728500 -0.494100 0.160200 -5.654600 -0.318199 -8.288400 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.264420 0.733914 -9.265530 0.000000 0.000000 0.000000 -2.418800 -7.330390 -0.811291 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064671 9.800200 -8.214560 43.297001 -3.707600 19.509300 -9.539490 67.280998 12.878750 31.828800 49.938904 13.843800 18.433800 18.058350 -0.060270 55.341801 -80.529556 7.606574 -0.276037 100.080345 -1.682014 -9.139359 -14.624531 2.390794 3.050730 -80.036728 -8.740204 -1.627717 99.804337 1.786962 9.054121 -14.602128 -1.177025 -4.467085 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 22.796249 -0.312243 0.229236 -5.652178 -0.470930 -8.290670 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.319018 0.942366 -9.268350 0.000000 0.000000 0.000000 -2.418800 -7.330391 -0.811292 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064674 9.800200 -8.214563 43.297001 -3.707600 19.509300 -9.539491 67.280998 12.878745 31.828800 49.938904 13.843800 18.433800 18.058344 -0.060273 55.341801 -80.529556 7.606574 -0.276037 99.948349 -1.583841 -9.135448 -14.457079 2.505192 2.925035 -80.036728 -8.740204 -1.627717 99.899406 1.728640 9.056458 -14.764675 -1.100068 -4.439228 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 22.864000 -0.130386 0.298271 -5.649756 -0.623661 -8.292941 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.373616 1.150817 -9.271170 0.000000 0.000000 0.000000 -2.418800 -7.330392 -0.811293 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064676 9.800200 -8.214567 43.297001 -3.707600 19.509300 -9.539492 67.280998 12.878740 31.828800 49.938904 13.843800 18.433800 18.058338 -0.060276 55.341801 -80.529556 7.606574 -0.276037 99.816490 -1.496572 -9.144343 -14.295455 2.634761 2.830058 -80.036728 -8.740204 -1.627717 99.994888 1.679874 9.059991 -14.916922 -1.023317 -4.411181 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 22.931751 0.051471 0.367307 -5.647335 -0.776392 -8.295212 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.428214 1.359269 -9.273990 0.000000 0.000000 0.000000 -2.418800 -7.330393 -0.811294 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064678 9.800200 -8.214571 43.297001 -3.707600 19.509300 -9.539493 67.280998 12.878736 31.828800 49.938904 13.843800 18.433800 18.058334 -0.060279 55.341801 -80.655678 7.296944 -0.294510 99.830833 -1.392337 -9.151498 -14.162417 3.059085 2.733469 -80.036728 -8.740204 -1.627717 100.089966 1.621550 9.061905 -15.078267 -0.949209 -4.363899 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 22.999500 0.233328 0.436343 -5.644913 -0.929123 -8.297482 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.482811 1.567720 -9.276810 0.000000 0.000000 0.000000 -2.418800 -7.330394 -0.811295 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064682 9.800200 -8.214575 43.297001 -3.707600 19.509300 -9.539494 67.280998 12.878731 31.828800 49.938904 13.843800 18.433800 18.058329 -0.060282 55.341801 -80.684761 7.184387 -0.293389 99.884262 -1.286162 -9.160164 -14.151802 3.289547 2.634885 -79.975204 -8.555390 -1.625069 100.048653 1.587265 9.074759 -15.158584 -1.068617 -4.351100 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 23.067249 0.415185 0.505379 -5.642490 -1.081855 -8.299753 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.537410 1.776172 -9.279630 0.000000 0.000000 0.000000 -2.418800 -7.330395 -0.811295 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064686 9.800200 -8.214579 43.297001 -3.707600 19.509300 -9.539495 67.280998 12.878726 31.828800 49.938904 13.843800 18.433800 18.058323 -0.060285 55.341801 -80.655884 7.065650 -0.297986 99.908813 -1.189191 -9.166738 -14.178167 3.518813 2.556376 -79.944778 -8.463006 -1.618956 99.968964 1.551501 9.063015 -15.176853 -1.087549 -4.304982 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 23.135000 0.597042 0.574414 -5.640069 -1.234586 -8.302025 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.592008 1.984624 -9.282450 0.000000 0.000000 0.000000 -2.418800 -7.330396 -0.811296 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064688 9.800200 -8.214582 43.297001 -3.707600 19.509300 -9.539495 67.280998 12.878721 31.828800 49.938904 13.843800 18.433800 18.058319 -0.060288 55.341801 -80.694763 6.948860 -0.293453 99.864395 -1.083336 -9.174717 -14.068148 3.754606 2.445470 -79.920784 -8.406898 -1.614661 99.976341 1.504053 9.066916 -15.275945 -1.070508 -4.274305 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 23.202751 0.778899 0.643450 -5.637647 -1.387317 -8.304296 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.646605 2.193075 -9.285270 0.000000 0.000000 0.000000 -2.418800 -7.330397 -0.811297 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064690 9.800200 -8.214586 43.297001 -3.707600 19.509300 -9.539496 67.280998 12.878716 31.828800 49.938904 13.843800 18.433800 18.058315 -0.060291 55.341801 -80.723465 6.845056 -0.299076 99.840591 -0.988943 -9.169375 -13.973420 3.955399 2.359292 -79.965065 -8.345485 -1.622173 100.022240 1.433999 9.058948 -15.345372 -1.057141 -4.224343 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 23.270500 0.960756 0.712486 -5.635224 -1.540048 -8.306567 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.701204 2.401527 -9.288090 0.000000 0.000000 0.000000 -2.418800 -7.330398 -0.811298 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064693 9.800200 -8.214591 43.297001 -3.707600 19.509300 -9.539497 67.280998 12.878711 31.828800 49.938904 13.843800 18.433800 18.058310 -0.060294 55.341801 -80.683945 6.726146 -0.294566 99.884666 -0.883093 -9.168114 -14.029733 4.186086 2.272666 -79.959534 -8.302510 -1.617384 99.952438 1.411240 9.063025 -15.346992 -1.032802 -4.191750 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 23.338249 1.142613 0.781521 -5.632802 -1.692779 -8.308838 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.755802 2.609978 -9.290910 0.000000 0.000000 0.000000 -2.418800 -7.330399 -0.811299 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064697 9.800200 -8.214596 43.297001 -3.707600 19.509300 -9.539499 67.280998 12.878706 31.828800 49.938904 13.843800 18.433800 18.058304 -0.060297 55.341801 -80.702011 6.623090 -0.290389 99.850136 -0.781133 -9.181367 -13.942264 4.408222 2.169586 -79.944435 -8.252051 -1.616698 99.978989 1.363760 9.078614 -15.435973 -1.019263 -4.161382 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 23.406000 1.324470 0.850557 -5.630380 -1.845510 -8.311110 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.810400 2.818430 -9.293730 0.000000 0.000000 0.000000 -2.418800 -7.330400 -0.811300 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064699 9.800200 -8.214600 43.297001 -3.707600 19.509300 -9.539500 67.280998 12.878700 31.828800 49.938900 13.843800 18.433800 18.058300 -0.060300 55.341801 -80.710396 6.513686 -0.282871 99.825333 -0.674134 -9.190516 -13.881958 4.629443 2.096669 -80.007927 -8.202291 -1.616939 99.918793 1.317311 9.056993 -15.388410 -0.997557 -4.118979 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 23.344410 1.159146 0.787797 -5.632582 -1.706663 -8.309045 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.760765 2.628929 -9.291166 0.000000 0.000000 0.000000 -2.418800 -7.330400 -0.811300 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064699 9.800200 -8.214600 43.297001 -3.707600 19.509300 -9.539500 67.280998 12.878700 31.828800 49.938900 13.843800 18.433800 18.058300 -0.060300 55.341801 -80.693199 6.612239 -0.291641 99.839989 -0.772778 -9.180444 -13.946154 4.428677 2.172705 -80.003632 -8.245581 -1.621523 99.920021 1.346951 9.062195 -15.328702 -1.012920 -4.140097 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 23.282820 0.993821 0.725038 -5.634784 -1.567817 -8.306980 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.711130 2.439427 -9.288602 0.000000 0.000000 0.000000 -2.418800 -7.330400 -0.811300 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064699 9.800200 -8.214600 43.297001 -3.707600 19.509300 -9.539500 67.280998 12.878700 31.828800 49.938900 13.843800 18.433800 18.058300 -0.060300 55.341801 -80.685219 6.703459 -0.286528 99.863335 -0.854945 -9.181154 -14.003063 4.241853 2.258799 -79.950783 -8.291809 -1.616029 99.952049 1.402634 9.062596 -15.367139 -1.024083 -4.190748 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 23.221230 0.828497 0.662278 -5.636986 -1.428970 -8.304915 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.661495 2.249926 -9.286037 0.000000 0.000000 0.000000 -2.418800 -7.330400 -0.811300 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064699 9.800200 -8.214600 43.297001 -3.707600 19.509300 -9.539500 67.280998 12.878700 31.828800 49.938900 13.843800 18.433800 18.058300 -0.060300 55.341801 -80.667908 6.803130 -0.296163 99.878059 -0.955041 -9.172701 -14.061670 4.039531 2.333687 -79.956932 -8.337340 -1.609672 99.934944 1.455034 9.063181 -15.277460 -1.047969 -4.212713 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 23.159639 0.663172 0.599518 -5.639188 -1.290124 -8.302851 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.611860 2.060424 -9.283474 0.000000 0.000000 0.000000 -2.418800 -7.330400 -0.811300 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064699 9.800200 -8.214600 43.297001 -3.707600 19.509300 -9.539500 67.280998 12.878700 31.828800 49.938900 13.843800 18.433800 18.058300 -0.060300 55.341801 -80.707603 6.914013 -0.294665 99.863510 -1.050708 -9.156631 -14.042909 3.811841 2.412342 -79.990997 -8.387027 -1.618792 99.927116 1.486313 9.050206 -15.169321 -1.054980 -4.241894 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 23.098049 0.497848 0.536759 -5.641390 -1.151277 -8.300785 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.562225 1.870923 -9.280910 0.000000 0.000000 0.000000 -2.418800 -7.330400 -0.811300 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064699 9.800200 -8.214600 43.297001 -3.707600 19.509300 -9.539500 67.280998 12.878700 31.828800 49.938900 13.843800 18.433800 18.058300 -0.060300 55.341801 -80.689377 7.018662 -0.298866 99.809319 -1.149674 -9.158791 -14.033837 3.613069 2.495564 -79.937370 -8.433875 -1.622267 99.967369 1.517037 9.061286 -15.207257 -1.072707 -4.283732 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 23.036459 0.332523 0.473999 -5.643592 -1.012431 -8.298720 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.512590 1.681422 -9.278346 0.000000 0.000000 0.000000 -2.418800 -7.330400 -0.811300 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064699 9.800200 -8.214600 43.297001 -3.707600 19.509300 -9.539500 67.280998 12.878700 31.828800 49.938900 13.843800 18.433800 18.058300 -0.060300 55.341801 -80.709412 7.129354 -0.297808 99.871765 -1.232692 -9.164733 -14.105558 3.402184 2.588746 -79.952232 -8.490499 -1.616791 100.009155 1.569074 9.058808 -15.177814 -1.073583 -4.322686 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 22.974869 0.167199 0.411239 -5.645794 -0.873584 -8.296656 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.462955 1.491920 -9.275782 0.000000 0.000000 0.000000 -2.418800 -7.330400 -0.811300 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064699 9.800200 -8.214600 43.297001 -3.707600 19.509300 -9.539500 67.280998 12.878700 31.828800 49.938900 13.843800 18.433800 18.058300 -0.060300 55.341801 -80.671539 7.231766 -0.300439 99.847214 -1.330432 -9.159117 -14.143842 3.191097 2.671165 -79.983688 -8.573734 -1.620535 100.030708 1.614877 9.066291 -15.109808 -1.065939 -4.360067 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 22.913279 0.001874 0.348479 -5.647996 -0.734738 -8.294590 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.413321 1.302419 -9.273218 0.000000 0.000000 0.000000 -2.418800 -7.330400 -0.811300 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064699 9.800200 -8.214600 43.297001 -3.707600 19.509300 -9.539500 67.280998 12.878700 31.828800 49.938900 13.843800 18.433800 18.058300 -0.060300 55.341801 -80.642693 7.334507 -0.294028 99.842178 -1.424945 -9.151748 -14.196482 2.991758 2.755060 -80.036728 -8.740204 -1.627717 100.061119 1.631236 9.060006 -15.028068 -0.969684 -4.375781 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 22.851688 -0.163450 0.285720 -5.650198 -0.595891 -8.292524 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.363686 1.112917 -9.270655 0.000000 0.000000 0.000000 -2.418800 -7.330400 -0.811300 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064699 9.800200 -8.214600 43.297001 -3.707600 19.509300 -9.539500 67.280998 12.878700 31.828800 49.938900 13.843800 18.433800 18.058300 -0.060300 55.341801 -80.529556 7.606574 -0.276037 99.836754 -1.506150 -9.138556 -14.321285 2.601479 2.836400 -80.036728 -8.740204 -1.627717 99.975456 1.689817 9.069006 -14.886281 -1.042104 -4.423136 +-0.031061 23.493807 -13.851418 -5.058400 -0.397000 -0.139900 22.790100 -0.328775 0.222960 -5.652400 -0.457045 -8.290460 0.000000 0.000000 0.000000 0.000000 0.000000 6.000000 -7.314050 0.923416 -9.268090 0.000000 0.000000 0.000000 -2.418800 -7.330400 -0.811300 -68.866402 -7.673400 27.768200 -57.201500 -2.478900 26.064699 9.800200 -8.214600 43.297001 -3.707600 19.509300 -9.539500 67.280998 12.878700 31.828800 49.938900 13.843800 18.433800 18.058300 -0.060300 55.341801 -80.529556 7.606574 -0.276037 99.958511 -1.593631 -9.138300 -14.467773 2.500639 2.944140 -80.036728 -8.740204 -1.627717 99.890060 1.738380 9.056893 -14.745159 -1.099041 -4.448681 diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Stand.bvh b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Stand.bvh new file mode 100644 index 00000000..eb91d43e --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Stand.bvh @@ -0,0 +1,130 @@ +HIERARCHY +ROOT hip +{ + OFFSET 0.00 0.00 0.00 + CHANNELS 6 Xposition Yposition Zposition Xrotation Zrotation Yrotation + JOINT abdomen + { + OFFSET 0.000000 0.000000 0.000000 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT chest + { + OFFSET 0.000000 5.018152 -1.882228 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT neckDummy + { + OFFSET 0.000000 8.316447 0.784897 + CHANNELS 3 Xrotation Yrotation Zrotation + JOINT neck + { + OFFSET 0.000000 2.280413 -0.392801 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT head + { + OFFSET 0.000000 3.496879 0.529469 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT figureHair + { + OFFSET 0.000000 4.699570 0.720622 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 0.000000 -6.419331 0.000000 + } + } + } + } + } + JOINT lCollar + { + OFFSET 0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lShldr + { + OFFSET 6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT lForeArm + { + OFFSET 10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lHand + { + OFFSET 11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 10.353753 0.000000 0.000000 + } + } + } + } + } + JOINT rCollar + { + OFFSET -0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rShldr + { + OFFSET -6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT rForeArm + { + OFFSET -10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rHand + { + OFFSET -11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET -10.353753 0.000000 0.000000 + } + } + } + } + } + } + } + JOINT lThigh + { + OFFSET 4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lShin + { + OFFSET -1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lFoot + { + OFFSET -0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } + JOINT rThigh + { + OFFSET -4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rShin + { + OFFSET 1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rFoot + { + OFFSET 0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } +} +MOTION +Frames: 1 +Frame Time: 1.000000 +2.898595 42.651405 -1.092219 1.614260 1.650030 -1.630150 0.020136 -1.168250 -2.362130 -4.611110 -3.230870 -5.893670 0.000000 0.000000 0.000000 -0.028617 0.811878 -0.155635 -2.958560 0.903542 -0.252972 0.000000 0.000000 0.000000 -2.279290 -5.924570 -1.065180 -68.580597 13.455016 17.332539 -8.855047 -8.918559 1.811211 11.044344 -4.575229 -14.817387 -1.052490 5.290610 9.980010 70.942596 12.030059 -1.386317 19.091511 13.727674 19.447748 -2.324264 0.808930 0.296090 -1.623250 5.011662 -13.449844 1.484355 -2.759394 -0.959640 -0.469020 21.000858 -0.284256 -11.679746 -6.390209 9.729076 8.974570 -0.723928 0.130789 3.625984 -10.811561 7.444040 diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Walk.bvh b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Walk.bvh new file mode 100644 index 00000000..30178beb --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/Walk.bvh @@ -0,0 +1,133 @@ +HIERARCHY +ROOT hip +{ + OFFSET 0.000000 0.000000 0.000000 + CHANNELS 6 Xposition Yposition Zposition Xrotation Zrotation Yrotation + JOINT abdomen + { + OFFSET 0.000000 0.000000 0.000000 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT chest + { + OFFSET 0.000000 5.018152 -1.882228 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT neck + { + OFFSET 0.000000 2.280413 -0.3928010 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT head + { + OFFSET 0.000000 3.496879 0.5294690 + CHANNELS 3 Xrotation Zrotation Yrotation + End Site + { + OFFSET 0.000000 -6.419331 0.000000 + } + } + } + JOINT lCollar + { + OFFSET 0.5992370 8.316447 0.7848970 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lShldr + { + OFFSET 6.421198 0.0101460 -0.3321280 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT lForeArm + { + OFFSET 10.55278 0.0255740 0.1255080 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lHand + { + OFFSET 11.03596 0.3196190 0.0415200 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 10.35375 0.000000 0.000000 + } + } + } + } + } + JOINT rCollar + { + OFFSET -0.5992370 8.316447 0.7848970 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rShldr + { + OFFSET -6.421198 0.0101460 -0.3321280 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT rForeArm + { + OFFSET -10.55278 0.0255740 0.1255080 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rHand + { + OFFSET -11.03596 0.3196190 0.0415200 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET -10.35375 0.000000 0.000000 + } + } + } + } + } + } + } + JOINT lThigh + { + OFFSET 4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lShin + { + OFFSET -1.359117 -18.91869 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lFoot + { + OFFSET -0.6523800 -17.21519 -0.3121370 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.35375 + } + } + } + } + JOINT rThigh + { + OFFSET -4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rShin + { + OFFSET 1.359117 -18.91869 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rFoot + { + OFFSET 0.6523800 -17.21519 -0.3121370 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.35375 + } + } + } + } +} +MOTION +Frames: 14 +Frame Time: 0.06666667 +-0.0257510 40.58662 2.968130 5.556919 0.000000 2.015870 -0.6797230 1.014860 -1.052490 2.752000 0.6388500 -7.299640 0.4079420 0.0122590 -0.1256210 5.754920 -1.457380 3.998490 -9.241052 -2.655120 -8.994716 -71.74033 -11.76199 4.746030 -31.60425 0.0011650 34.04590 -13.20947 -13.28238 0.0895360 -5.574724 0.4710180 -0.0036540 73.49715 -23.63777 -7.243340 8.720032 0.1163490 30.20142 6.934624 -2.351367 0.2714110 19.70864 0.2635370 -1.303549 16.37695 -5.436259 -0.5345360 4.496281 1.015851 1.747118 -34.91362 -1.222353 -5.287092 -2.923005 1.339154 -2.612716 22.63187 -2.693362 0.4416350 +-0.0427160 39.99832 2.968130 5.983611 0.1952380 2.305610 -0.9075000 1.659612 -0.8255570 3.170562 0.4139390 -6.538830 0.0427510 0.3591020 -0.2041640 4.601790 -1.017530 3.147050 -7.220732 -6.809920 -7.805324 -69.91151 -16.29200 9.884584 -30.28683 0.0011650 34.52690 -12.66613 -12.66293 0.3319030 -3.823218 3.579455 -1.197800 71.22991 -22.17614 -9.132231 8.934833 0.1163490 27.58857 6.341005 -1.810122 0.0889280 31.80497 -0.6573040 -1.730517 2.618905 -2.443246 2.231949 21.05572 1.594669 -3.021200 -29.23277 -0.8716060 -4.452437 -1.019926 1.464713 -1.719640 24.82080 -1.952116 -4.257692 +-0.0490000 40.60387 2.968130 6.780290 0.3518100 1.598240 -2.588980 1.606370 -0.6063710 4.232220 0.1093190 -4.063770 -0.0046320 0.0825280 -0.0927340 3.695360 -0.7544480 1.973470 -3.744470 -8.700970 -4.904962 -70.88610 -17.35770 9.929008 -27.66028 0.0011650 35.16180 -11.80692 -10.87573 0.2852650 2.176580 6.577632 -4.384020 70.63450 -18.15266 -9.667048 10.03265 0.1163490 26.30510 7.008678 -1.223352 0.0747800 -0.7305030 0.4284680 1.743937 54.34729 -4.835621 -1.074371 9.137504 5.289661 -3.020902 -30.70562 -0.8687340 -4.818579 21.60547 1.171606 -0.0342390 -1.272151 -1.886707 -7.032578 +-0.0370750 41.81056 2.968130 7.296476 0.4387100 -0.3847930 -4.810570 0.7177930 -0.4790630 6.622445 -0.7205180 0.2170790 -0.1072710 -0.1669200 0.0205430 3.943000 -0.3966010 0.2499270 0.5136740 -7.977970 -1.134083 -74.42540 -13.28160 5.881170 -21.83660 0.0011650 35.30630 -10.84113 -7.695415 0.2676810 9.603888 7.048002 -9.243760 73.80751 -11.40650 -7.985020 13.65550 0.1163490 26.98030 7.962735 -0.3291820 -0.2501000 -25.45668 1.331627 2.501022 73.94672 -3.461740 -1.227959 6.551764 9.393176 -2.179612 -21.03787 -0.0785040 -4.612796 18.82639 1.075741 0.3011050 -8.326876 -0.7395040 -7.905264 +-0.0492780 42.52045 2.968130 8.028471 0.4387270 -2.183500 -5.438199 0.2072610 -0.4842430 7.701901 -0.9499680 3.168510 -0.0889130 -0.0297360 0.0692490 4.540220 -0.2602800 -2.275510 2.874230 -2.376980 2.091650 -76.07090 -2.581600 0.7454570 -16.12650 0.0011650 34.86560 -9.942211 -3.643180 0.2476490 14.10310 1.174088 -11.53900 76.15389 -2.965070 -5.198220 20.48967 0.1163490 29.01340 9.230290 0.7452390 0.2288370 -38.03374 1.956252 2.239554 62.35056 -2.866381 -0.2397530 8.452842 4.334472 0.6557800 -7.289600 0.3666450 -3.843508 1.867966 1.000802 -0.7417120 -5.670934 1.476608 -7.036381 +-0.1147910 42.30725 2.968130 7.389349 0.3518580 -2.723740 -4.885140 -0.1526010 -0.0863740 6.676330 -0.9908230 5.642550 -0.0815090 0.3846910 0.1674810 4.107840 0.6112240 -3.806190 4.723633 0.3030470 3.157360 -76.51633 9.078669 -2.237584 -11.19450 0.0011650 33.69044 -8.229190 -0.2649510 0.3502730 13.70860 -2.341550 -11.48470 76.44480 4.952410 -2.805780 23.66457 0.1163490 31.16320 11.07391 3.243204 0.1396680 -39.73745 0.9433510 2.634595 37.03880 -0.0079470 0.2421630 3.952889 0.5003140 0.6370110 -2.884728 0.2945820 -4.572917 14.90006 0.3393120 0.5460770 -12.46497 2.812716 -5.142097 +-0.1136690 41.29929 2.968130 7.077470 0.1953070 -3.103870 -2.569706 -0.5870810 0.7460720 4.264240 -0.9203070 6.794440 -0.0655790 0.8732530 0.3329260 4.152214 1.027240 -4.007210 6.108605 0.9400970 2.701448 -74.59380 19.52292 -4.328449 -8.674590 0.0011650 31.67350 -6.320746 1.746516 0.4130220 11.23750 -2.078610 -9.506420 73.19800 10.55287 3.473820 25.37001 0.1163490 33.11210 12.83219 7.515890 0.4558040 -33.10924 0.6728450 2.248022 -2.150151 -1.284785 1.135497 8.195504 0.7814600 0.9302330 6.604897 -0.4295430 -3.435708 18.94620 0.4580620 0.7902670 -11.64451 2.760721 -2.794761 +-0.0257510 40.58662 2.968130 5.315712 0.000000 -2.980694 -0.9209280 -1.497272 1.052490 3.234412 -0.6388500 7.299640 0.4079420 -0.0122590 0.1256210 4.790095 1.457380 -3.998490 5.549260 -3.365490 1.062321 -70.36150 22.98137 -6.453584 -9.202444 -0.1163490 29.47779 -4.281356 2.351367 0.2714110 9.001228 2.655120 -4.562235 69.81071 14.49866 7.158091 26.05653 -0.0011650 34.04590 13.20947 13.28238 0.0895360 -34.63461 1.663542 5.230479 -2.874681 -1.354475 2.571830 22.27972 3.499624 -0.6994310 20.20984 -0.8096520 1.118457 16.39768 5.239849 0.5319330 4.287104 -0.0057910 -1.855253 +-0.0427160 39.99832 2.968130 5.501198 -0.1952380 -2.305610 -0.9075000 -2.142024 1.066763 3.411768 -0.4139390 6.538830 0.0427510 -0.3591020 0.2041640 4.601790 1.017530 -3.147050 3.099600 -8.162370 -1.197800 -69.30029 21.18730 -7.691476 -10.38207 -0.1163490 27.82978 -2.964121 2.533740 0.0889280 5.930410 6.809920 -1.510628 68.94670 16.53321 9.626520 25.46272 -0.0011650 34.76811 12.18372 15.55740 0.3319030 -28.75425 0.7551880 4.375766 -1.009826 -1.458228 1.758046 24.68831 2.019926 4.264540 32.70480 0.5576440 1.612639 2.529472 2.394109 -2.208158 20.77636 -1.529196 3.034380 +-0.0490000 40.60387 2.968130 6.780290 -0.3518100 -1.598240 -2.588980 -1.606370 0.8475770 4.232220 -0.1093190 4.063770 -0.0046320 -0.0825280 0.0927340 3.695360 0.7544480 -1.973470 -3.382610 -9.230900 -4.384020 -70.63450 16.45700 -8.214620 -11.96230 -0.1163490 26.30510 -4.355410 1.223352 0.0747800 2.220852 8.700970 0.7050230 70.88610 16.12165 10.70320 23.80100 -0.0011650 35.40301 10.84210 13.52900 0.2852650 -30.70332 1.151009 4.769948 21.61604 -1.309091 -0.0288900 -1.231163 1.831893 6.845827 -0.7391490 -0.5250250 -1.818685 54.36355 4.687464 1.070386 9.172863 -5.207838 3.084680 +-0.0370750 41.81056 2.968130 7.055270 -0.4387100 0.3847930 -4.569364 -0.7177930 0.4790630 5.657620 0.7205180 -0.4582850 -0.1072710 0.1669200 -0.0205430 3.943000 0.3966010 -0.2499270 -10.08630 -6.565590 -9.243760 -73.08390 11.40650 -7.985020 -17.75600 -0.1163490 26.98030 -8.686354 -1.359260 -0.2501000 -1.313670 7.736764 2.069029 74.42540 9.326259 7.569613 21.11298 -0.0011650 35.30630 9.635085 8.660240 0.2676810 -20.89793 0.0200240 4.532423 18.85304 -1.135874 -0.2918260 -8.274943 0.7717070 7.956114 -25.12860 -1.376650 -2.522182 73.94746 3.378500 1.186994 6.482924 -9.345399 2.210355 +-0.0492780 42.52045 2.968130 6.822440 -0.4387270 2.183500 -4.714581 0.0339450 0.0018310 6.978283 0.9499680 -3.168510 -0.0889130 0.0297360 -0.0692490 4.540220 0.2602800 2.275510 -14.10310 0.0319430 -11.53900 -76.63630 2.965070 -5.714349 -27.72584 -0.1163490 29.01340 -11.88356 -5.810566 0.2288370 -2.874230 2.376980 2.574062 76.07090 -4.814778 2.675105 15.64409 -0.0011650 34.86560 8.494974 2.678356 0.2476490 -5.750584 -0.0682040 3.706347 1.838004 -0.9924500 0.7040120 -6.252903 -1.350606 6.723120 -36.76496 -1.611116 -2.217723 62.39058 2.803816 0.2258220 8.343335 -4.624382 -0.6874000 +-0.1147910 42.30725 2.968130 5.942111 -0.3518580 2.723740 -3.437904 0.3938070 -0.3960380 5.711505 0.9908230 -5.642550 -0.0815090 -0.3846910 -0.1674810 4.107840 -0.6112240 3.806190 -13.70860 2.341550 -11.48470 -76.44480 -4.952410 -2.547715 -31.86555 -0.1163490 31.64561 -12.76236 -9.514564 0.1396680 -3.949440 -0.3030470 2.674948 75.06911 -17.84588 -1.945802 10.71209 -0.0011650 33.44923 7.987984 -0.9410790 0.3502730 -1.522238 0.2477410 4.483660 14.98725 -0.3526480 -0.5609450 -12.46601 -2.716281 4.674154 -37.94170 -0.5235370 -2.521068 37.07784 -0.0044090 -0.2444200 3.539016 -0.8207050 -0.7948700 +-0.1136690 41.29929 2.968130 5.389027 -0.1953070 3.103870 -1.363676 0.5870810 -0.7460720 3.540622 0.9203070 -6.794440 -0.0655790 -0.1496350 -0.3329260 4.875833 -1.027240 4.007210 -9.904170 0.5302230 -9.506420 -73.19800 -10.06840 3.473820 -32.36500 -0.1163490 32.62968 -13.55581 -12.09881 0.4558040 -4.560220 -0.4576850 1.669190 73.62899 -22.59373 -6.134900 8.915796 -0.0011650 31.67350 7.526777 -1.987722 0.4130220 8.712742 0.9255390 3.315778 18.95539 -0.4671390 -0.8017530 -12.08175 -2.643082 2.386326 -31.30434 -0.2056730 -2.097641 -2.062192 1.296254 -1.151119 7.956662 -0.9896620 -1.269012 diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/avatar_type.bvh b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/avatar_type.bvh new file mode 100644 index 00000000..671fc6c1 --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/avatar_type.bvh @@ -0,0 +1,149 @@ +HIERARCHY +ROOT hip +{ + OFFSET 0.00 0.00 0.00 + CHANNELS 6 Xposition Yposition Zposition Xrotation Zrotation Yrotation + JOINT abdomen + { + OFFSET 0.000000 0.000000 0.000000 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT chest + { + OFFSET 0.000000 5.018152 -1.882228 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT neckDummy + { + OFFSET 0.000000 8.316447 0.784897 + CHANNELS 3 Xrotation Yrotation Zrotation + JOINT neck + { + OFFSET 0.000000 2.280413 -0.392801 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT head + { + OFFSET 0.000000 3.496879 0.529469 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT figureHair + { + OFFSET 0.000000 4.699570 0.720622 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 0.000000 -6.419331 0.000000 + } + } + } + } + } + JOINT lCollar + { + OFFSET 0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lShldr + { + OFFSET 6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT lForeArm + { + OFFSET 10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lHand + { + OFFSET 11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 10.353753 0.000000 0.000000 + } + } + } + } + } + JOINT rCollar + { + OFFSET -0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rShldr + { + OFFSET -6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT rForeArm + { + OFFSET -10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rHand + { + OFFSET -11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET -10.353753 0.000000 0.000000 + } + } + } + } + } + } + } + JOINT lThigh + { + OFFSET 4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lShin + { + OFFSET -1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lFoot + { + OFFSET -0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } + JOINT rThigh + { + OFFSET -4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rShin + { + OFFSET 1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rFoot + { + OFFSET 0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } +} +MOTION +Frames: 20 +Frame Time: 0.066667 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -5.602665 0.692895 -0.999750 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -45.312199 -28.361601 -6.437040 -85.572998 -44.321999 4.115680 22.688700 6.434930 24.572500 -2.021920 5.690310 -0.063351 47.524502 17.444599 -9.449780 96.743202 40.100101 -12.457400 -12.207400 -9.114560 50.627300 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.530616 -4.334307 0.100752 15.830232 3.319340 0.622262 -8.660608 -1.559428 0.936809 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -5.802714 0.371659 -0.579152 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -47.180473 -28.228901 -5.594771 -90.299255 -39.289246 1.194210 26.265350 5.033503 24.901260 -2.021920 5.690310 -0.063351 46.979572 18.392992 -9.648436 98.211319 37.028625 -13.372793 -13.185279 -8.174255 50.774910 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.530616 -4.334307 0.100752 15.830232 3.319340 0.622262 -8.660608 -1.559428 0.936809 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -6.063016 -0.046329 -0.031874 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -49.642559 -28.057348 -4.480888 -92.784599 -35.134602 -0.389246 28.351900 4.867320 25.002300 -2.021920 5.690310 -0.063351 46.265060 19.591881 -9.910472 100.083427 32.987583 -14.550499 -15.019100 -6.791880 50.992001 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.530616 -4.334307 0.100752 15.830232 3.319340 0.622262 -8.660608 -1.559428 0.936809 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -6.356364 -0.517383 0.584884 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -51.394981 -27.923710 -3.701625 -86.723595 -36.127731 3.204253 24.722046 8.632764 24.359707 -2.021920 5.690310 -0.063351 45.484287 20.885418 -10.197384 101.633133 30.088182 -15.488061 -18.322517 -4.913835 51.285515 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.541284 -4.335290 0.100323 15.850134 3.319600 0.623621 -8.670751 -1.558202 0.936774 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -6.664823 -1.012702 1.233411 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -50.907700 -27.914900 -3.972350 -78.084198 -39.382198 8.483360 20.478300 12.755100 23.749599 -2.021920 5.690310 -0.063351 44.726017 22.169096 -10.475073 102.068001 30.802200 -15.623200 -20.191601 -4.050860 51.410198 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.541285 -4.335289 0.100323 15.840267 3.319063 0.622893 -8.660734 -1.558720 0.936864 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -6.970458 -1.503486 1.876000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -47.342522 -28.104080 -5.682922 -74.201202 -41.084034 11.101078 21.353376 13.217446 24.008877 -2.021920 5.690310 -0.063351 44.078999 23.338406 -10.709437 100.966911 36.452309 -14.666931 -17.973396 -5.457377 51.154484 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.520178 -4.332916 0.101153 15.810387 3.318801 0.620304 -8.640448 -1.561168 0.936936 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -7.255333 -1.960933 2.474942 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -42.628670 -28.509411 -7.921168 -74.844345 -41.162811 11.071470 25.767128 10.923965 24.848372 -2.021920 5.690310 -0.063351 43.632008 24.288841 -10.866380 99.394066 43.764828 -13.423463 -13.826456 -7.648414 50.717327 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.574976 -4.335261 0.098837 15.919619 3.321326 0.628477 -8.709791 -1.561858 0.916431 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -7.501513 -2.356244 2.992527 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -39.387199 -29.135300 -9.449410 -77.892097 -40.484001 9.498860 30.311199 8.009070 25.697399 -2.021920 5.690310 -0.063351 43.473801 24.915899 -10.911800 98.785004 48.317001 -12.970300 -11.112200 -8.454150 50.400299 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.574976 -4.335261 0.098837 15.919619 3.321326 0.628477 -8.709791 -1.561858 0.916431 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -7.691063 -2.660617 3.391048 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -39.461269 -29.945696 -9.398738 -81.407845 -39.788086 7.429636 32.339588 6.260051 26.103733 -2.021920 5.690310 -0.063351 43.635044 25.165306 -10.834554 100.055038 47.161655 -13.985796 -12.151986 -6.480672 50.415527 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.574976 -4.335261 0.098837 15.919619 3.321326 0.628477 -8.709791 -1.561858 0.916431 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -7.806047 -2.845253 3.632795 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -41.582397 -30.742714 -8.375322 -84.194748 -39.315697 5.678448 32.255730 6.075661 26.088982 -2.021920 5.690308 -0.063351 43.913994 25.183712 -10.715312 102.038620 43.254036 -15.551699 -15.106911 -3.437715 50.617313 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.541285 -4.335289 0.100323 15.840267 3.319063 0.622893 -8.660734 -1.558720 0.936864 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -7.828529 -2.881352 3.680060 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -43.704201 -31.288000 -7.354100 -85.240898 -39.182499 5.002010 31.225401 7.507520 25.793200 -2.021920 5.690307 -0.063351 44.050800 25.167999 -10.657700 103.050003 41.025002 -16.350599 -17.098000 -1.810920 50.770500 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.541285 -4.335289 0.100323 15.840267 3.319063 0.622893 -8.660734 -1.558720 0.936864 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -7.747013 -2.750452 3.508672 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -44.347855 -31.393389 -7.040523 -83.870651 -39.474094 5.904261 30.110575 10.400587 25.342203 -2.021920 5.690308 -0.063351 43.876858 25.242115 -10.729075 101.973473 43.409073 -15.509502 -16.083826 -3.277420 50.707096 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.543339 -4.331701 0.100078 15.860003 3.320137 0.624349 -8.680767 -1.557684 0.936683 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -7.578204 -2.479383 3.153757 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -44.304813 -31.071466 -7.062090 -80.753395 -40.155880 7.878061 28.557922 13.773190 24.804836 -2.021920 5.690308 -0.063351 43.588619 25.238310 -10.851757 99.973595 47.355453 -13.933051 -13.373131 -6.280302 50.527756 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.574975 -4.335263 0.098837 15.919619 3.321328 0.628477 -8.709791 -1.561859 0.916431 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -7.344236 -2.103681 2.661846 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -44.934101 -30.385000 -6.776810 -76.894798 -41.163200 10.163500 25.910299 16.437000 24.235701 -2.021920 5.690308 -0.063351 43.473801 24.915899 -10.911800 98.785004 48.317001 -12.970300 -11.112200 -8.454150 50.400299 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.574975 -4.335263 0.098837 15.919619 3.321328 0.628477 -8.709791 -1.561859 0.916431 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -7.065158 -1.655543 2.075093 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -47.093323 -29.439314 -5.776487 -73.565590 -42.205116 11.896695 22.090277 17.368969 23.721474 -2.021920 5.690308 -0.063351 43.750614 24.101944 -10.822457 99.573265 43.338470 -13.539507 -10.888786 -8.102924 50.446678 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.574975 -4.335263 0.098837 15.919619 3.321328 0.628477 -8.709791 -1.561859 0.916431 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -6.759047 -1.163995 1.431502 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -49.634373 -28.509924 -4.588082 -73.096718 -42.085564 11.797891 19.339241 16.207205 23.477100 -2.021920 5.690309 -0.063351 44.346069 22.908701 -10.610848 101.227570 35.832142 -14.835725 -12.056473 -6.208143 50.605305 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.509626 -4.331718 0.100831 15.810110 3.320156 0.620464 -8.660229 -1.561548 0.936643 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -6.442271 -0.655322 0.765489 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -50.907700 -27.914900 -3.972350 -78.084198 -39.382198 8.483360 20.478300 12.755100 23.749599 -2.021921 5.690310 -0.063351 45.130058 21.501146 -10.326545 102.068001 30.802200 -15.623200 -13.410300 -4.420720 50.768700 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.509626 -4.331718 0.100831 15.810110 3.320156 0.620464 -8.660229 -1.561548 0.936643 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -6.130195 -0.154198 0.109360 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -49.807709 -27.862867 -4.440722 -88.370590 -34.497669 2.186697 26.158653 7.650285 24.557117 -2.021921 5.690310 -0.063351 45.991310 20.022953 -10.011851 100.927116 31.752354 -15.032178 -14.027573 -3.968220 50.855228 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.574975 -4.335263 0.098837 15.919619 3.321328 0.628477 -8.709791 -1.561859 0.916431 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -5.839536 0.312535 -0.501740 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -47.489388 -28.102360 -5.468174 -92.784599 -35.134602 -0.389246 28.351900 4.867320 25.002300 -2.021920 5.690310 -0.063351 46.831421 18.607119 -9.703973 98.757568 35.946148 -13.708339 -14.155356 -4.321314 50.890865 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.530733 -4.334104 0.100738 15.830261 3.319198 0.622245 -8.660609 -1.559427 0.936809 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 7.150620 2.007150 0.929046 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.981501 -1.360380 -0.079195 -5.602665 0.692895 -0.999750 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -45.312199 -28.361601 -6.437040 -85.572998 -44.321999 4.115680 22.688700 6.434930 24.572500 -2.021920 5.690310 -0.063351 47.524502 17.444599 -9.449780 96.743202 40.100101 -12.457400 -14.160000 -4.781410 50.909901 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.530616 -4.334307 0.100752 15.830232 3.319340 0.622262 -8.660608 -1.559428 0.936809 diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_anger.bvh b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_anger.bvh new file mode 100644 index 00000000..f81202dc --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_anger.bvh @@ -0,0 +1,169 @@ +HIERARCHY +ROOT hip +{ + OFFSET 0.00 0.00 0.00 + CHANNELS 6 Xposition Yposition Zposition Xrotation Zrotation Yrotation + JOINT abdomen + { + OFFSET 0.000000 0.000000 0.000000 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT chest + { + OFFSET 0.000000 5.018152 -1.882228 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT neckDummy + { + OFFSET 0.000000 8.316447 0.784897 + CHANNELS 3 Xrotation Yrotation Zrotation + JOINT neck + { + OFFSET 0.000000 2.280413 -0.392801 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT head + { + OFFSET 0.000000 3.496879 0.529469 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT figureHair + { + OFFSET 0.000000 4.699570 0.720622 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 0.000000 -6.419331 0.000000 + } + } + } + } + } + JOINT lCollar + { + OFFSET 0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lShldr + { + OFFSET 6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT lForeArm + { + OFFSET 10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lHand + { + OFFSET 11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 10.353753 0.000000 0.000000 + } + } + } + } + } + JOINT rCollar + { + OFFSET -0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rShldr + { + OFFSET -6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT rForeArm + { + OFFSET -10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rHand + { + OFFSET -11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET -10.353753 0.000000 0.000000 + } + } + } + } + } + } + } + JOINT lThigh + { + OFFSET 4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lShin + { + OFFSET -1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lFoot + { + OFFSET -0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } + JOINT rThigh + { + OFFSET -4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rShin + { + OFFSET 1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rFoot + { + OFFSET 0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } +} +MOTION +Frames: 40 +Frame Time: 0.066667 +-0.000259 40.992298 -0.065304 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -42.331451 30.122858 21.742556 -73.187912 -20.619417 -12.664969 -18.057875 10.992988 -12.288630 -2.021920 5.690310 -0.063351 44.830597 -31.010050 22.083652 69.833801 20.380661 -11.530135 20.500595 -6.896393 -11.278655 -14.567226 4.295753 0.240425 29.368277 -3.848200 -2.171592 -15.066643 0.978629 -0.163683 -14.572109 -4.831408 -0.127276 29.359909 3.695474 2.036771 -15.151767 -1.603219 0.441192 +0.006739 41.085964 0.030897 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -0.242417 0.000000 0.000000 0.000000 0.000000 0.000000 0.969667 0.000000 0.000000 -0.643179 0.000000 -0.395995 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -43.019997 30.853821 22.390961 -67.345261 -19.986040 -11.289976 -18.031061 7.143957 -10.399983 -2.021920 5.690310 -0.063351 45.804729 -32.191044 22.739782 62.148273 20.012609 -10.554276 19.879198 -4.147217 -9.407591 -13.401567 4.179159 0.196498 27.256784 -3.703139 -2.009738 -14.149036 1.081301 -0.295643 -13.408559 -4.738739 -0.097446 27.245335 3.591814 1.857270 -14.209668 -1.680311 0.542519 +0.015343 41.198689 0.142492 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -0.543359 0.000000 0.000000 0.000000 0.000000 0.000000 2.173434 0.000000 0.000000 -1.420075 0.000000 -0.995130 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -43.752831 31.737026 23.197376 -60.454063 -19.254692 -9.646701 -17.979870 2.572375 -8.152661 -2.021920 5.690310 -0.063351 46.864925 -33.662849 23.590199 52.910324 19.632124 -9.424890 19.099083 -0.954613 -7.198907 -12.630443 4.095553 0.173113 26.007265 -3.596300 -1.934293 -13.699943 1.183579 -0.375566 -12.601125 -4.683213 -0.056042 25.877586 3.498527 1.738690 -13.659906 -1.750789 0.620596 +0.023630 41.316502 0.275394 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -0.821700 0.000000 0.000000 0.000000 0.000000 0.000000 3.286799 0.000000 0.000000 -2.224396 0.000000 -1.143928 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -44.873150 32.641819 23.937895 -52.766781 -18.378912 -7.895785 -17.997496 -2.405908 -5.721085 -2.021920 5.690310 -0.063351 48.386597 -35.003456 24.246548 43.266472 19.002905 -8.082515 18.409124 2.797579 -4.742070 -11.660775 4.009772 0.160692 24.463697 -3.483255 -1.810522 -13.136962 1.229451 -0.473702 -11.677361 -4.639621 -0.039084 24.477016 3.431245 1.616233 -13.203639 -1.774991 0.693006 +0.029944 41.433372 0.451217 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -3.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -46.950783 33.491592 24.395847 -43.805382 -17.205227 -6.064105 -18.208458 -7.899927 -3.078514 -2.021920 5.690310 -0.063351 51.024254 -35.798679 24.266848 33.709229 17.747593 -6.307382 18.064169 7.657773 -1.895860 -10.686584 3.951957 0.146177 23.041861 -3.420408 -1.688488 -12.703855 1.244530 -0.535463 -10.707328 -4.609505 -0.028750 22.994225 3.393222 1.456376 -12.681218 -1.774351 0.760005 +0.033044 41.544090 0.685665 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.032480 0.000000 0.000000 0.000000 0.000000 0.000000 4.129919 0.000000 0.000000 -3.700707 0.000000 2.981894 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -49.928089 34.159107 24.448008 -34.124546 -15.828769 -4.382828 -18.625774 -13.275431 -0.537928 -2.021920 5.690310 -0.063351 54.660946 -35.822998 23.511003 25.396132 15.901446 -4.247019 18.185490 13.205486 1.037912 -9.606263 3.901831 0.136394 21.558783 -3.369515 -1.547028 -12.311996 1.237213 -0.589353 -9.601794 -4.564954 -0.023813 21.482492 3.336555 1.312261 -12.277978 -1.765583 0.825781 +0.033359 41.646793 0.970782 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -4.320870 0.000000 7.158385 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -51.237427 34.314533 24.344856 -28.409842 -15.339047 -3.900293 -18.816395 -14.925015 0.228839 -2.021920 5.690310 -0.063351 56.093685 -35.605354 23.046419 22.144815 15.150153 -3.518145 18.360044 15.144616 1.985312 -8.448438 3.852914 0.112322 20.133410 -3.320124 -1.411605 -12.037189 1.236615 -0.650985 -8.443372 -4.517721 -0.026611 20.067644 3.284146 1.177447 -12.022829 -1.755419 0.869844 +0.031737 41.740463 1.292701 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -0.991301 0.000000 0.000000 0.000000 0.000000 0.000000 3.965203 0.000000 0.000000 -4.864906 0.000000 11.588959 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -49.043556 33.817947 24.348745 -30.057076 -16.428291 -5.184398 -18.469398 -10.780025 -1.723916 -2.021920 5.690310 -0.063351 53.169861 -35.673851 23.717209 26.055769 16.644793 -5.144335 18.213938 10.775244 -0.289247 -7.296954 3.808582 0.097759 18.748360 -3.254904 -1.287883 -11.812005 1.230314 -0.702903 -7.252542 -4.470295 -0.036992 18.632507 3.223398 1.051518 -11.786949 -1.748127 0.913578 +0.029024 41.824078 1.637553 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -5.337126 0.000000 15.333096 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -46.950775 33.491596 24.395849 -33.172279 -17.205227 -6.064105 -18.208458 -7.899926 -3.078515 -2.021920 5.690310 -0.063351 51.024254 -35.798679 24.266848 29.700905 17.747591 -6.307381 18.064169 7.657773 -1.895860 -6.018285 3.764982 0.077370 17.251450 -3.199679 -1.140722 -11.596104 1.228959 -0.763960 -6.059710 -4.424530 -0.036438 17.243151 3.178003 0.913263 -11.591909 -1.731413 0.966818 +0.026066 41.896606 1.991470 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.002317 0.000000 0.000000 0.000000 0.000000 0.000000 4.009268 0.000000 0.000000 -5.741735 0.000000 17.450281 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -48.246544 33.990074 24.380360 -32.073433 -16.088469 -4.768785 -18.572514 -12.085689 -1.114198 -2.021920 5.690310 -0.063351 54.015507 -35.693115 23.561459 26.738869 16.209867 -4.649035 18.231943 12.109898 0.385218 -4.850642 3.720255 0.060619 15.914616 -3.120593 -1.032060 -11.437840 1.239424 -0.823186 -4.860820 -4.397773 -0.035430 15.914846 3.164442 0.784160 -11.458105 -1.701172 0.981749 +0.023710 41.957031 2.340584 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -6.082830 0.000000 17.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -49.511368 34.335129 24.354715 -31.216133 -15.319669 -3.868373 -18.827021 -14.976185 0.238721 -2.021920 5.690310 -0.063351 56.110344 -35.600590 23.058363 24.703852 15.128181 -3.492660 18.364401 15.218121 1.967567 -4.069251 3.854725 0.053083 15.716523 -3.172066 -0.996065 -12.019375 1.218500 -0.926562 -4.018046 -4.268292 -0.023060 15.548854 3.100787 0.752603 -11.936100 -1.740779 0.941117 +0.022614 42.004761 2.673515 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -0.999431 0.000000 0.000000 0.000000 0.000000 0.000000 3.997724 0.000000 0.000000 -6.364402 0.000000 13.363604 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -47.572556 33.704422 24.380445 -34.863579 -16.794987 -5.533065 -18.346081 -9.510770 -2.338055 -2.021920 5.690310 -0.063351 52.174721 -35.752113 24.015381 30.255207 17.140644 -5.657907 18.145641 9.420830 -1.033798 -3.672854 3.591626 0.039363 15.737794 -3.108595 -1.019015 -12.434631 1.286870 -0.709473 -3.612864 -4.527207 -0.037079 15.558730 3.153802 0.749764 -12.337193 -1.694081 1.154860 +0.022684 42.040924 2.988836 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -6.590335 0.000000 7.209916 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -46.951542 33.532112 24.397163 -36.371738 -17.205553 -5.993508 -18.211832 -7.992868 -3.063682 -2.021920 5.690310 -0.063351 51.063354 -35.798649 24.301096 32.677277 17.706329 -6.267941 18.081657 7.795164 -1.891956 -3.158323 3.862517 0.047803 15.706032 -3.173103 -1.005270 -12.908832 1.255913 -0.922547 -3.103389 -4.256107 -0.001016 15.528662 3.105638 0.732402 -12.824089 -1.738642 0.937447 +0.023637 42.067085 3.287609 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -6.764404 0.000000 -0.470364 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -49.507641 34.367409 24.374365 -33.499466 -15.299516 -3.808254 -18.837563 -15.091851 0.259433 -2.021920 5.690310 -0.063351 56.148804 -35.599682 23.101868 28.029850 15.090601 -3.458313 18.377787 15.327561 1.947400 -2.546106 3.769590 0.050351 15.559607 -3.157843 -0.993741 -13.378804 1.266193 -0.838025 -2.553675 -4.326663 0.015453 15.450936 3.149675 0.712937 -13.285528 -1.751598 0.997286 +0.025190 42.084808 3.570895 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -6.890279 0.000000 -8.686537 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -46.952190 33.572407 24.418051 -38.971329 -17.185450 -5.920504 -18.230640 -8.098764 -3.035490 -2.021920 5.690310 -0.063351 51.091347 -35.796139 24.348770 35.946274 17.667980 -6.216280 18.109661 7.906057 -1.930624 -1.796069 3.770880 0.050777 14.945673 -3.138704 -0.941107 -13.505573 1.274398 -0.855160 -1.822508 -4.356344 0.038940 14.958000 3.173843 0.663260 -13.523480 -1.739380 1.024458 +0.027061 42.095650 3.839756 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -6.971517 0.000000 -16.447908 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -49.508789 34.408554 24.394091 -35.790516 -15.261117 -3.743187 -18.858076 -15.210570 0.284557 -2.021920 5.690310 -0.063351 56.187393 -35.598801 23.135592 30.560951 15.052306 -3.413388 18.387112 15.457133 1.931090 -1.124403 3.767987 0.043605 14.420887 -3.121117 -0.884951 -13.631931 1.287036 -0.881506 -1.167741 -4.333697 0.062362 14.447000 3.140420 0.586949 -13.669477 -1.753003 1.059619 +0.028968 42.101177 4.095254 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -7.011572 0.000000 -22.763781 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -46.952869 33.612823 24.429132 -43.176193 -17.176863 -5.856393 -18.225534 -8.184731 -3.011435 -2.021920 5.690310 -0.063351 51.130245 -35.795963 24.402557 41.802326 17.619980 -6.167955 18.128744 8.036629 -1.957155 -0.464807 3.767637 0.018149 13.912747 -3.119129 -0.812366 -13.788229 1.294156 -0.888627 -0.508672 -4.322178 0.095715 13.927742 3.139735 0.533211 -13.806795 -1.757252 1.076519 +0.030627 42.102951 4.338450 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -7.013786 0.000000 -26.643456 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -49.509941 34.449673 24.413832 -40.050438 -15.240892 -3.673402 -18.868021 -15.326096 0.285872 -2.021920 5.690310 -0.063351 56.225849 -35.597885 23.179085 35.316559 15.013844 -3.364903 18.407974 15.603470 1.908960 0.151253 3.773188 0.004236 13.443955 -3.118004 -0.732734 -13.927717 1.270197 -0.919098 0.106344 -4.300940 0.118111 13.490003 3.130690 0.474112 -13.982650 -1.768234 1.091963 +0.031756 42.102531 4.570406 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -6.981394 0.000000 -27.096235 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -46.948891 33.644356 24.430380 -48.305878 -17.177174 -5.773202 -18.232101 -8.292139 -2.975133 -2.021920 5.690310 -0.063351 51.169346 -35.795902 24.436806 45.773281 17.581015 -6.130011 18.134945 8.170565 -1.934694 0.686256 3.782122 -0.006043 13.073858 -3.120581 -0.659906 -14.086390 1.250037 -0.939392 0.699691 -4.293428 0.148739 13.029859 3.128884 0.414482 -14.129008 -1.778813 1.107909 +0.032072 42.101486 4.792185 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -6.917522 0.000000 -23.515991 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -49.511047 34.490814 24.433542 -45.535191 -15.211849 -3.621885 -18.892197 -15.439448 0.336494 -2.021920 5.690310 -0.063351 56.264378 -35.596878 23.222588 38.762005 14.979831 -3.331327 18.419365 15.729469 1.904275 1.266863 3.783352 -0.028858 12.646737 -3.106908 -0.582271 -14.243688 1.245023 -0.967595 1.213092 -4.277662 0.177165 12.659503 3.123916 0.379885 -14.263927 -1.802340 1.122304 +0.031292 42.101376 5.004848 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -6.825188 0.000000 -16.834841 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -46.943413 33.691387 24.429667 -51.663223 -17.175354 -5.698703 -18.235018 -8.406681 -2.935859 -2.021920 5.690310 -0.063351 51.208263 -35.795681 24.490599 52.358463 17.530718 -6.077814 18.140766 8.303623 -1.962564 1.740700 3.793891 -0.026506 12.369511 -3.092632 -0.533269 -14.430095 1.243275 -1.004843 1.809334 -4.250860 0.209857 12.152494 3.102942 0.305715 -14.341961 -1.808202 1.139841 +0.029226 42.103424 5.208362 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -6.707298 0.000000 -8.369495 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -49.507450 34.523235 24.433622 -48.730022 -15.166630 -3.553019 -18.940149 -15.570738 0.394968 -2.021920 5.690310 -0.063351 56.308197 -35.604679 23.266142 41.446434 14.935187 -3.293698 18.424816 15.861948 1.896166 2.437388 3.788526 -0.034579 11.602357 -3.061652 -0.441878 -14.352474 1.233780 -1.036200 2.290525 -4.233191 0.238202 11.832858 3.093203 0.264328 -14.488435 -1.817891 1.155785 +0.026044 42.107506 5.398320 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -6.566653 0.000000 0.563356 0.000000 0.000000 0.000000 2.021900 -5.690300 -0.063400 -46.952171 33.572430 24.418039 -54.052418 -17.185452 -5.920504 -18.230642 -8.098764 -3.035490 -2.021900 5.690300 -0.063400 51.091347 -35.796143 24.348768 58.442944 17.667978 -6.216279 18.109661 7.906057 -1.930624 2.908850 3.652744 0.033378 11.097987 -2.958264 -0.585957 -14.360667 1.252786 -1.004381 2.804711 -4.226768 0.108838 11.267623 2.963277 0.314369 -14.467041 -1.831672 1.173876 +0.022009 42.113163 5.569219 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -6.405948 0.000000 8.647017 0.000000 0.000000 0.000000 2.021900 -5.690300 -0.063400 -49.508774 34.408585 24.394083 -51.590542 -15.261115 -3.743186 -18.858074 -15.210570 0.284557 -2.021900 5.690300 -0.063400 56.187401 -35.598785 23.135601 46.951572 15.052304 -3.413388 18.387112 15.457133 1.931090 3.292500 3.673456 0.030176 10.876436 -2.954922 -0.571355 -14.516000 1.270627 -1.029660 3.411831 -4.202161 0.132600 10.586290 2.941232 0.249929 -14.397570 -1.836100 1.193932 +0.017384 42.119930 5.715559 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -6.227769 0.000000 14.564796 0.000000 0.000000 0.000000 2.021900 -5.690300 -0.063400 -46.952869 33.612820 24.429132 -58.360420 -17.176838 -5.856377 -18.225534 -8.184731 -3.011435 -2.021900 5.690300 -0.063400 51.130268 -35.795937 24.402571 63.038475 17.619980 -6.167955 18.128746 8.036614 -1.957158 3.714949 3.689238 0.014637 10.476422 -2.940713 -0.505706 -14.536287 1.262653 -1.049995 3.684524 -4.174878 0.154654 10.475910 2.938234 0.232563 -14.554720 -1.839163 1.181242 +0.012431 42.127350 5.831838 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -6.034600 0.000000 17.000000 0.000000 0.000000 0.000000 2.021900 -5.690300 -0.063400 -49.509918 34.449699 24.413816 -55.013088 -15.240892 -3.673402 -18.868021 -15.326094 0.285872 -2.021900 5.690300 -0.063400 56.225834 -35.597893 23.179079 50.978668 15.013844 -3.364902 18.407974 15.603470 1.908961 4.214084 3.682723 -0.005977 9.842402 -2.924398 -0.415350 -14.390280 1.250420 -1.082479 4.055943 -4.161688 0.179088 10.101669 2.936195 0.179439 -14.553778 -1.846782 1.199776 +0.007413 42.134960 5.912555 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -5.828822 0.000000 15.064427 0.000000 0.000000 0.000000 2.021900 -5.690300 -0.063400 -46.948879 33.644360 24.430384 -62.737583 -17.177174 -5.773203 -18.232101 -8.292139 -2.975133 -2.021900 5.690300 -0.063400 51.169346 -35.795898 24.436806 66.381187 17.581013 -6.130011 18.134945 8.170565 -1.934694 4.409898 3.708984 -0.021020 9.722369 -2.923157 -0.349275 -14.460335 1.233355 -1.122968 4.487801 -4.121367 0.208714 9.467156 2.914512 0.098533 -14.357194 -1.843985 1.203326 +0.002593 42.142296 5.952209 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -5.612718 0.000000 9.583826 0.000000 0.000000 0.000000 2.021900 -5.690300 -0.063400 -49.511047 34.490814 24.433542 -58.191349 -15.211849 -3.621885 -18.892195 -15.439448 0.336494 -2.021900 5.690300 -0.063400 56.264381 -35.596874 23.222586 54.253033 14.979829 -3.331327 18.419369 15.729469 1.904275 4.635258 3.726478 -0.038068 9.378403 -2.916700 -0.288080 -14.342960 1.230370 -1.163686 4.647041 -4.118287 0.234721 9.283290 2.915766 0.067341 -14.317491 -1.846455 1.203636 +-0.001767 42.148899 5.945296 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -5.388474 0.000000 1.812436 0.000000 0.000000 0.000000 2.021900 -5.690300 -0.063400 -46.943413 33.691387 24.429667 -66.728951 -17.175350 -5.698703 -18.235014 -8.406696 -2.935856 -2.021900 5.690300 -0.063400 51.208260 -35.795681 24.490595 68.712982 17.530720 -6.077815 18.140764 8.303623 -1.962564 4.627248 3.752095 -0.035218 9.408084 -2.922998 -0.261101 -14.353622 1.220079 -1.174655 4.528723 -4.104073 0.251524 9.510933 2.941518 0.073586 -14.416327 -1.843583 1.173121 +-0.005404 42.154305 5.886317 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -5.158190 0.000000 -6.995502 0.000000 0.000000 0.000000 2.021900 -5.690300 -0.063400 -49.507446 34.523239 24.433620 -60.466301 -15.166600 -3.553008 -18.940136 -15.570753 0.394972 -2.021900 5.690300 -0.063400 56.308174 -35.604710 23.266127 56.771698 14.935188 -3.293698 18.424801 15.861963 1.896170 4.544484 3.760371 -0.050521 9.374872 -2.934200 -0.230152 -14.226212 1.219891 -1.185808 4.451054 -4.102248 0.268635 9.507806 2.952692 0.064524 -14.328244 -1.839263 1.184858 +-0.008056 42.158054 5.769769 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -4.923891 0.000000 -15.585747 0.000000 0.000000 0.000000 2.021900 -5.690300 -0.063400 -46.950756 33.491619 24.395838 -69.694580 -17.205227 -6.064106 -18.208458 -7.899926 -3.078515 -2.021900 5.690300 -0.063400 51.024273 -35.798653 24.266859 67.401962 17.747564 -6.307365 18.064169 7.657773 -1.895860 4.285230 3.584888 0.020602 9.329579 -2.824524 -0.444898 -13.991389 1.214678 -1.110846 4.138386 -4.122305 0.038395 9.564675 2.811084 0.244228 -14.118240 -1.864033 1.185379 +-0.009460 42.159687 5.590151 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -4.687536 0.000000 -22.704060 0.000000 0.000000 0.000000 2.021900 -5.690300 -0.063400 -47.511024 33.615776 24.355812 -70.259018 -16.855566 -5.680249 -18.300262 -9.253335 -2.400551 -2.021900 5.690300 -0.063400 52.073601 -35.756409 23.942532 65.511658 17.235678 -5.755857 18.112858 9.099952 -1.021586 3.796003 3.549007 0.047007 9.708584 -2.810287 -0.526324 -13.913440 1.209105 -1.092837 3.778204 -4.130238 -0.024557 9.666372 2.770130 0.296446 -13.862628 -1.859589 1.180326 +-0.009353 42.158741 5.341961 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -4.451044 0.000000 -27.096201 0.000000 0.000000 0.000000 2.021900 -5.690300 -0.063400 -49.510777 34.314556 24.344845 -66.242790 -15.339021 -3.900281 -18.816393 -14.925015 0.228840 -2.021900 5.690300 -0.063400 56.093685 -35.605358 23.046415 55.908508 15.150152 -3.518146 18.360046 15.144616 1.985312 3.107002 3.615362 0.032349 10.380980 -2.876608 -0.544092 -13.873069 1.222581 -1.081838 3.090353 -4.143022 0.018217 10.355350 2.849011 0.316066 -13.865157 -1.840263 1.153416 +-0.007589 42.154957 5.024200 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -4.216331 0.000000 -27.869003 0.000000 0.000000 0.000000 2.021900 -5.690300 -0.063400 -48.489845 33.999813 24.371933 -69.937347 -16.069435 -4.741448 -18.583988 -12.168928 -1.078568 -2.021900 5.690300 -0.063400 54.087051 -35.682915 23.547680 56.516357 16.172480 -4.616714 18.246147 12.205967 0.432784 2.282232 3.643124 0.018433 11.086915 -2.924556 -0.572914 -13.745469 1.224186 -1.053715 2.297998 -4.168285 0.017172 10.982110 2.887627 0.358527 -13.691579 -1.811249 1.139961 +-0.004532 42.148960 4.655094 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -3.985368 0.000000 -25.686733 0.000000 0.000000 0.000000 2.021900 -5.690300 -0.063400 -46.950756 33.491619 24.395838 -74.635147 -17.205227 -6.064106 -18.208458 -7.899926 -3.078515 -2.021900 5.690300 -0.063400 51.024273 -35.798653 24.266859 59.935162 17.747564 -6.307365 18.064169 7.657773 -1.895860 1.331639 3.654365 0.037976 11.843727 -2.955997 -0.662606 -13.549383 1.223870 -1.016800 1.382919 -4.197028 -0.007491 11.679148 2.918952 0.424711 -13.475364 -1.806946 1.114905 +-0.000629 42.141529 4.255953 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -3.760293 0.000000 -21.503040 0.000000 0.000000 0.000000 2.021900 -5.690300 -0.063400 -47.914249 33.806065 24.379728 -71.845123 -16.497021 -5.243128 -18.439663 -10.552166 -1.832966 -2.021900 5.690300 -0.063400 52.934147 -35.723351 23.808060 56.184723 16.764805 -5.250633 18.175739 10.492533 -0.443412 0.285399 3.674641 0.041917 12.739137 -2.988226 -0.752424 -13.400500 1.243613 -0.986743 0.291145 -4.234769 -0.018829 12.669580 2.977325 0.503377 -13.361413 -1.774170 1.081282 +0.003727 42.133354 3.846196 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -3.543623 0.000000 -16.144390 0.000000 0.000000 0.000000 2.021900 -5.690300 -0.063400 -49.511349 34.335152 24.354704 -64.941162 -15.319669 -3.868373 -18.827021 -14.976185 0.238722 -2.021900 5.690300 -0.063400 56.110363 -35.600559 23.058376 50.288288 15.128181 -3.492660 18.364405 15.218119 1.967567 -0.753508 3.709093 0.045511 13.591206 -3.027980 -0.820999 -13.203533 1.252100 -0.948829 -0.724433 -4.264571 -0.006824 13.468734 3.032239 0.560430 -13.146027 -1.763521 1.046808 +0.008184 42.125034 3.444262 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -3.338778 0.000000 -10.319963 0.000000 0.000000 0.000000 2.021900 -5.690300 -0.063400 -49.382538 34.304199 24.357370 -59.085121 -15.414222 -3.958852 -18.797352 -14.647636 0.076464 -2.021900 5.690300 -0.063400 55.865688 -35.610847 23.129667 48.993824 15.248464 -3.623441 18.354313 14.876363 1.774439 -1.697771 3.730811 0.044988 14.252238 -3.068228 -0.868367 -12.920597 1.235322 -0.934339 -1.685744 -4.290917 -0.012252 14.169457 3.073518 0.619695 -12.873878 -1.734805 1.034805 +0.012408 42.117176 3.070656 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -3.151666 0.000000 -4.662398 0.000000 0.000000 0.000000 2.021900 -5.690300 -0.063400 -48.176270 33.922119 24.377167 -54.586708 -16.303040 -4.966682 -18.506954 -11.348000 -1.481251 -2.021900 5.690300 -0.063400 53.483784 -35.704056 23.711872 50.709900 16.467041 -4.934688 18.219463 11.366086 -0.044704 -2.614905 3.758886 0.042817 14.881805 -3.109483 -0.933374 -12.624902 1.249118 -0.887363 -2.579241 -4.319739 -0.014329 14.792453 3.102239 0.663768 -12.600780 -1.713210 1.021857 +0.015866 42.110748 2.766356 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 -3.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021900 -5.690300 -0.063400 -46.951527 33.532143 24.397154 -51.133438 -17.205553 -5.993508 -18.211832 -7.992869 -3.063682 -2.021900 5.690300 -0.063400 51.063374 -35.798618 24.301107 52.758518 17.706329 -6.267941 18.081657 7.795164 -1.891956 -3.250168 3.772683 0.048499 15.262290 -3.149484 -0.972778 -12.368585 1.260381 -0.859619 -3.284225 -4.340009 -0.009787 15.249444 3.108859 0.704436 -12.353666 -1.717927 1.034756 diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_bored.bvh b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_bored.bvh new file mode 100644 index 00000000..a9a7222b --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_bored.bvh @@ -0,0 +1,189 @@ +HIERARCHY +ROOT hip +{ + OFFSET 0.00 0.00 0.00 + CHANNELS 6 Xposition Yposition Zposition Xrotation Zrotation Yrotation + JOINT abdomen + { + OFFSET 0.000000 0.000000 0.000000 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT chest + { + OFFSET 0.000000 5.018152 -1.882228 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT neckDummy + { + OFFSET 0.000000 8.316447 0.784897 + CHANNELS 3 Xrotation Yrotation Zrotation + JOINT neck + { + OFFSET 0.000000 2.280413 -0.392801 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT head + { + OFFSET 0.000000 3.496879 0.529469 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT figureHair + { + OFFSET 0.000000 4.699570 0.720622 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 0.000000 -6.419331 0.000000 + } + } + } + } + } + JOINT lCollar + { + OFFSET 0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lShldr + { + OFFSET 6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT lForeArm + { + OFFSET 10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lHand + { + OFFSET 11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 10.353753 0.000000 0.000000 + } + } + } + } + } + JOINT rCollar + { + OFFSET -0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rShldr + { + OFFSET -6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT rForeArm + { + OFFSET -10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rHand + { + OFFSET -11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET -10.353753 0.000000 0.000000 + } + } + } + } + } + } + } + JOINT lThigh + { + OFFSET 4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lShin + { + OFFSET -1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lFoot + { + OFFSET -0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } + JOINT rThigh + { + OFFSET -4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rShin + { + OFFSET 1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rFoot + { + OFFSET 0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } +} +MOTION +Frames: 60 +Frame Time: 0.083333 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -70.100700 9.978770 15.991600 -22.515600 -9.303740 0.147736 5.969490 -0.173112 0.175734 -2.021920 5.690310 -0.063351 70.100700 -9.978770 15.991600 22.515600 9.303740 0.147736 -5.969490 0.173112 0.175734 -7.542277 3.922175 0.136309 15.800026 -3.271755 -0.906147 -8.555586 1.080559 -0.817622 -7.531943 -4.331991 0.100592 15.738582 3.231687 0.595472 -8.598962 -1.571022 0.966009 +-0.025525 42.039791 0.286326 0.000000 0.000000 0.000000 0.164151 0.082075 0.000000 0.013679 0.041038 0.000000 0.000000 0.000000 0.000000 -3.251416 0.053857 0.000000 -1.583342 0.427537 -0.082565 0.000000 0.000000 0.000000 2.021920 0.259061 -0.063351 -76.171272 -8.096824 14.095987 -33.259880 -27.503336 -21.499949 7.207664 -0.173112 -14.673234 -2.024868 -0.934707 -0.064933 83.670708 9.072489 13.463067 54.456032 11.323364 -1.747074 -22.242167 0.173112 0.175734 -6.887450 3.921698 0.121431 14.636279 -3.203040 -0.820422 -8.052237 1.088543 -0.929341 -6.989171 -4.246102 0.069956 14.812192 3.170732 0.555790 -8.208910 -1.584346 0.941148 +-0.063561 42.075356 0.344249 0.000000 0.000000 0.000000 0.314078 0.157039 0.000000 0.026173 0.078520 0.000000 0.000000 0.000000 0.000000 -7.149925 0.103047 0.000000 -3.451682 0.818029 -0.157976 0.000000 0.000000 0.000000 2.021920 7.381697 -0.063351 -83.404617 -29.419189 11.857997 -46.028534 -48.938957 -47.013714 8.338551 -0.173112 -32.204166 -2.028348 -8.844054 -0.066801 99.779434 31.539125 10.477841 91.986176 13.761707 -3.984117 -41.411205 0.173112 0.175734 -6.135922 3.936444 0.122717 13.301806 -3.127203 -0.714853 -7.472733 1.072202 -1.043292 -6.454054 -4.140182 0.049926 13.887718 3.095662 0.516324 -7.815825 -1.607995 0.915625 +-0.174362 42.166893 0.425365 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -11.000000 0.000000 0.000000 -5.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 14.309690 -0.063351 -90.100708 -47.021229 9.991600 -57.515602 -66.303741 -67.852264 5.969490 -0.173112 -46.824265 -2.031250 -16.318357 -0.068359 114.091698 50.019253 7.988281 121.490631 16.335060 -5.849720 -56.969490 0.173112 0.175734 -5.260192 4.093336 0.112324 11.778833 -3.068163 -0.561075 -6.829396 1.016649 -1.296813 -5.521290 -3.928602 0.027853 12.310772 3.022128 0.386699 -7.162434 -1.581109 0.809349 +-0.394709 42.349735 0.539901 0.000000 0.000000 0.000000 -1.071947 -0.535974 0.000000 -0.089329 -0.267987 0.000000 0.000000 0.000000 0.000000 -14.384474 -0.375628 0.000000 -5.814901 -2.898738 0.566092 0.000000 0.000000 0.000000 2.021920 20.023392 -0.063351 -95.060928 -55.991470 9.001054 -65.768600 -74.535049 -77.930862 -2.112660 -0.173112 -54.583542 -2.032790 -22.095690 -0.069186 123.498154 59.299084 6.667004 133.740372 18.979420 -6.839846 -64.342110 0.173112 0.175734 -2.790858 4.342592 0.081856 7.004411 -2.835210 -0.104600 -4.521477 0.896814 -1.849508 -2.949885 -3.494060 -0.006466 7.316742 2.805355 -0.091752 -4.757495 -1.407730 0.644681 +-0.598189 42.564510 0.659854 0.000000 0.000000 0.000000 -2.223003 -1.111501 0.000000 -0.185250 -0.555751 0.000000 0.000000 0.000000 0.000000 -17.116863 -0.920783 0.000000 -6.072363 -6.644365 1.333489 0.000000 0.000000 0.000000 2.021920 23.371328 -0.063351 -97.824783 -57.675724 8.773636 -72.288063 -75.845520 -78.824661 -10.770855 -0.173112 -56.364990 -2.033144 -25.232006 -0.069376 127.467735 60.901749 6.363654 134.816956 21.820499 -7.067167 -65.136719 0.173112 0.175734 -0.946854 4.618401 0.044213 3.373016 -2.690716 0.271100 -2.725524 0.804901 -2.295308 -1.033870 -3.181044 -0.048352 3.492281 2.671813 -0.469077 -2.864719 -1.199383 0.487657 +-0.617594 42.728176 0.747664 0.000000 0.000000 0.000000 -2.531250 -1.265625 0.000000 -0.210938 -0.632813 0.000000 0.000000 0.000000 0.000000 -19.068361 -1.476563 0.000000 -6.095703 -9.476563 2.000000 0.000000 0.000000 0.000000 2.021920 23.169073 -0.063351 -98.116333 -54.984104 9.042382 -79.437767 -74.266609 -74.023811 -13.030510 -0.173112 -54.259842 -2.032726 -24.862728 -0.069152 126.113937 58.034603 6.722131 134.629532 25.031452 -6.798537 -62.506615 0.173112 0.175734 -0.194947 4.632156 0.031150 2.250534 -2.631128 0.369417 -2.358733 0.798765 -2.376203 -0.204244 -3.130905 -0.057851 2.204102 2.622326 -0.606664 -2.418142 -1.122932 0.503761 +-0.355084 42.774021 0.768876 0.000000 0.000000 0.000000 -1.458316 -0.729158 0.000000 -0.121526 -0.364579 0.000000 0.000000 0.000000 0.000000 -19.979523 -1.820592 0.000000 -6.128539 -10.149662 2.285732 0.000000 0.000000 0.000000 2.021920 19.098873 -0.063351 -95.906624 -50.690159 9.539212 -88.760605 -73.068497 -66.966255 -4.863868 -0.173112 -50.368015 -2.031954 -20.894442 -0.068737 120.325455 53.692360 7.384845 140.261215 28.545359 -6.301919 -59.278084 0.173112 0.175734 -1.561654 4.240941 0.045050 4.861164 -2.729166 0.100902 -3.613499 0.887317 -1.886067 -1.600190 -3.528353 -0.041123 4.897441 2.715071 -0.313551 -3.699872 -1.283907 0.788795 +0.009704 42.700687 0.701466 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -19.068399 -1.476600 0.000000 -6.095700 -9.476600 2.000000 0.000000 0.000000 0.000000 2.021920 14.309700 -0.063351 -92.154808 -47.021198 9.991600 -98.515999 -72.476280 -60.881371 5.969490 -0.173112 -46.824299 -2.031250 -16.318399 -0.068359 114.092003 50.019299 7.988280 147.490997 31.335100 -5.849720 -56.969501 0.173112 0.175734 -3.706082 3.703728 0.093402 9.182920 -2.880150 -0.341650 -5.801322 1.012243 -1.149885 -3.825616 -4.132122 0.016805 9.387017 2.871627 0.129804 -5.958655 -1.494581 1.211308 +0.279002 42.523483 0.537177 0.000000 0.000000 0.000000 0.855581 0.427790 0.000000 0.071298 0.213895 0.000000 0.000000 0.000000 0.000000 -15.639620 -0.166487 0.000000 -6.126044 -8.542055 1.109547 0.000000 0.000000 0.000000 2.021920 11.719099 -0.063351 -87.877792 -45.574013 10.191261 -106.423004 -72.040154 -58.185680 11.045262 -0.173112 -45.260269 -2.030940 -13.874852 -0.068193 110.916939 48.521816 8.254606 150.816635 32.464756 -5.650141 -56.473770 0.173112 0.175734 -5.703916 3.350936 0.128369 12.989969 -3.042648 -0.695995 -7.613444 1.122830 -0.579700 -5.824788 -4.635722 0.067042 13.232792 3.020066 0.495276 -7.788126 -1.597167 1.502725 +0.459999 42.259026 0.310410 0.000000 0.000000 0.000000 1.685242 0.842621 0.000000 0.140437 0.421311 0.000000 0.000000 0.000000 0.000000 -9.866585 1.341283 0.000000 -7.483357 -7.459047 0.121614 0.000000 0.000000 0.000000 2.021920 9.852161 -0.063351 -83.335243 -45.969463 10.191321 -111.322845 -71.655785 -58.252773 11.067672 -0.173112 -45.259800 -2.030940 -12.215309 -0.068193 109.257156 49.005188 8.254685 150.915359 32.323433 -5.650082 -57.489796 0.173112 0.175734 -7.328657 3.137949 0.158914 15.680449 -3.168071 -0.905374 -8.664661 1.151297 -0.196029 -7.415544 -5.003680 0.135557 15.865156 3.120954 0.726960 -8.812177 -1.653958 1.737884 +0.611125 41.924244 0.066229 0.000000 0.000000 0.000000 3.457030 1.728515 0.000000 0.288086 0.864257 0.000000 0.000000 0.000000 0.000000 -2.139896 2.016601 0.000000 -11.715155 -6.097685 -0.321429 0.000000 0.000000 0.000000 2.021920 6.135873 -0.063351 -78.597534 -47.334438 10.110252 -112.337257 -71.305176 -59.695499 9.023061 -0.173112 -45.894848 -2.031065 -8.969101 -0.068260 106.307930 50.849403 8.146549 150.009140 31.631485 -5.731118 -59.417984 0.173112 0.175734 -9.412795 3.013391 0.224908 19.235327 -3.326326 -1.234323 -10.133042 1.216781 0.166346 -9.500023 -5.373948 0.191511 19.399351 3.268992 1.061750 -10.255182 -1.681262 1.880393 +0.776504 41.542706 -0.157439 0.000000 0.000000 0.000000 6.769111 3.384555 0.000000 0.564093 1.692278 0.000000 0.000000 0.000000 0.000000 6.964393 1.649775 0.000000 -19.625237 -4.150682 0.205256 0.000000 0.000000 0.000000 2.021920 -1.096595 -0.063351 -73.794228 -48.913174 10.044337 -109.190483 -70.976067 -61.338375 7.340632 -0.173112 -46.411171 -2.031168 -2.586709 -0.068315 100.166954 53.440567 8.058627 149.845215 30.982458 -5.797005 -61.731079 0.173112 0.175734 -11.979342 2.921765 0.316417 23.914553 -3.560365 -1.669340 -12.220441 1.269012 0.633810 -12.140481 -5.832448 0.243642 24.125208 3.506042 1.508788 -12.323003 -1.652776 1.950686 +0.943929 41.161968 -0.354599 0.000000 0.000000 0.000000 10.713293 5.356647 0.000000 0.892774 2.678323 0.000000 0.000000 0.000000 0.000000 16.177275 3.312778 0.000000 -28.983105 -0.601201 1.222725 0.000000 0.000000 0.000000 2.021920 -9.820320 -0.063351 -69.242767 -50.433594 9.999131 -104.140572 -70.674965 -62.871174 6.171816 -0.173112 -46.765274 -2.031238 5.135849 -0.068353 92.609924 56.193375 7.998328 150.229401 30.449879 -5.842191 -64.191216 0.173112 0.175734 -14.339316 2.852916 0.420566 28.258116 -3.824986 -2.072606 -14.191872 1.277170 1.145257 -14.502175 -6.330727 0.255328 28.505028 3.792742 1.898805 -14.318812 -1.490216 2.000335 +1.083351 40.846039 -0.512790 0.000000 0.000000 0.000000 14.118802 7.059401 0.000000 1.176567 3.529701 0.000000 0.000000 0.000000 0.000000 23.848434 8.162499 0.000000 -37.052170 4.241448 2.169152 0.000000 0.000000 0.000000 2.021920 -17.371922 -0.063351 -65.516281 -51.683781 9.965892 -99.553650 -70.430794 -64.120911 5.307891 -0.173112 -47.025639 -2.031290 11.824957 -0.068381 86.042519 58.512287 7.953990 150.661972 30.031855 -5.875416 -66.632896 0.173112 0.175734 -16.181515 2.812330 0.491572 31.630043 -4.069919 -2.323525 -15.697102 1.205880 1.582137 -16.381325 -6.794040 0.212058 31.933296 4.051900 2.177439 -15.864264 -1.197050 2.050098 +1.066383 40.753220 -0.570747 0.000000 0.000000 0.000000 13.695042 6.847521 0.000000 1.141253 3.423760 0.000000 0.000000 0.000000 0.000000 23.278748 9.330000 0.000000 -36.241737 4.175381 1.735321 0.000000 0.000000 0.000000 2.021920 -16.435596 -0.063351 -66.553490 -51.751263 10.104365 -99.946037 -70.205376 -65.982185 5.440211 -0.173112 -46.985371 -2.031282 10.996294 -0.068377 86.852356 60.288990 7.960848 150.627777 30.092505 -5.870277 -69.802589 0.173112 0.175734 -16.696877 2.867364 0.501694 32.513680 -4.085912 -2.417038 -16.068527 1.216266 1.587597 -16.895769 -6.784358 0.253827 32.807751 4.054103 2.285840 -16.212317 -1.258346 1.978965 +1.049416 40.660404 -0.628705 0.000000 0.000000 0.000000 13.271281 6.635641 0.000000 1.105940 3.317820 0.000000 0.000000 0.000000 0.000000 22.709061 10.497499 0.000000 -35.431305 4.109313 1.301491 0.000000 0.000000 0.000000 2.021920 -15.499272 -0.063351 -67.590698 -51.818748 10.242840 -100.338425 -69.979958 -67.843460 5.572531 -0.173112 -46.945103 -2.031274 10.167630 -0.068372 87.662193 62.065693 7.967706 150.593582 30.153152 -5.865138 -72.972282 0.173112 0.175734 -17.242298 2.919623 0.513036 33.466934 -4.086272 -2.531565 -16.477579 1.247623 1.606366 -17.439917 -6.772808 0.293692 33.740910 4.059411 2.390362 -16.619925 -1.308706 1.937935 +1.032449 40.567585 -0.686663 0.000000 0.000000 0.000000 12.847521 6.423760 0.000000 1.070627 3.211880 0.000000 0.000000 0.000000 0.000000 22.139374 11.665000 0.000000 -34.620869 4.043246 0.867661 0.000000 0.000000 0.000000 2.021920 -14.562948 -0.063351 -68.627907 -51.886230 10.381313 -100.730820 -69.754539 -69.704735 5.704851 -0.173112 -46.904835 -2.031266 9.338966 -0.068368 88.472031 63.842396 7.974564 150.559387 30.213802 -5.859998 -76.141975 0.173112 0.175734 -17.729174 2.967118 0.521618 34.262314 -4.084273 -2.642320 -16.769073 1.279358 1.614290 -17.920319 -6.757700 0.335684 34.537369 4.051848 2.480012 -16.919832 -1.358102 1.887938 +1.015482 40.474766 -0.744620 0.000000 0.000000 0.000000 12.423760 6.211880 0.000000 1.035313 3.105940 0.000000 0.000000 0.000000 0.000000 21.569687 12.832500 0.000000 -33.810432 3.977179 0.433830 0.000000 0.000000 0.000000 2.021920 -13.626624 -0.063351 -69.665115 -51.953712 10.519787 -101.123215 -69.529121 -71.566010 5.837171 -0.173112 -46.864567 -2.031258 8.510303 -0.068364 89.281860 65.619095 7.981421 150.525192 30.274452 -5.854859 -79.311661 0.173112 0.175734 -18.255720 3.018156 0.521597 35.165821 -4.093555 -2.726399 -17.140629 1.287945 1.619830 -18.458227 -6.748211 0.366561 35.440125 4.052962 2.601019 -17.297585 -1.413937 1.835764 +0.998515 40.381947 -0.802578 0.000000 0.000000 0.000000 12.000000 6.000000 0.000000 1.000000 3.000000 0.000000 0.000000 0.000000 0.000000 21.000000 14.000000 0.000000 -33.000000 3.911111 0.000000 0.000000 0.000000 0.000000 2.021920 -12.690300 -0.063351 -70.702316 -52.021198 10.658261 -101.515602 -69.303703 -73.427277 5.969490 -0.173112 -46.824299 -2.031250 7.681640 -0.068359 90.091698 67.395798 7.988280 150.490997 30.335100 -5.849720 -82.481354 0.173112 0.175734 -18.752369 3.065695 0.529831 36.011265 -4.080306 -2.829204 -17.491385 1.313067 1.617990 -18.945677 -6.731642 0.407161 36.265465 4.045628 2.693439 -17.627043 -1.460740 1.785193 +0.987809 40.319992 -0.841508 0.000000 0.000000 0.000000 11.732624 5.866312 0.000000 0.977719 2.933156 0.000000 0.000000 0.000000 0.000000 20.602505 14.603489 0.000000 -32.472828 3.870161 -0.273459 0.000000 0.000000 0.000000 2.021920 -12.099516 -0.063351 -71.413292 -52.056873 10.760280 -101.717094 -69.109161 -74.625900 6.052859 -0.173112 -46.798927 -2.031245 7.158786 -0.068357 90.602676 68.601372 7.992608 150.470200 30.372297 -5.846477 -79.135597 0.173112 0.175734 -19.054680 3.093732 0.530955 36.502190 -4.078513 -2.887266 -17.676250 1.329829 1.613020 -19.241522 -6.721488 0.430981 36.727287 4.046072 2.730352 -17.791967 -1.481633 1.760446 +0.980811 40.272224 -0.872020 0.000000 0.000000 0.000000 11.557841 5.778921 0.000000 0.963153 2.889460 0.000000 0.000000 0.000000 0.000000 20.261417 14.713627 0.000000 -32.093685 3.845876 -0.451701 0.000000 0.000000 0.000000 2.021920 -11.713324 -0.063351 -71.998627 -52.067055 10.857392 -101.752251 -68.871231 -75.466293 6.107130 -0.173112 -46.782410 -2.031241 6.816998 -0.068355 90.936691 69.570663 7.995436 150.458084 30.394579 -5.844357 -75.789841 0.173112 0.175734 -19.337399 3.115749 0.541418 36.914467 -4.076159 -2.939635 -17.812536 1.341258 1.616412 -19.474356 -6.710100 0.446223 37.110909 4.030344 2.785783 -17.955700 -1.517205 1.742872 +0.977022 40.236954 -0.895100 0.000000 0.000000 0.000000 11.463211 5.731606 0.000000 0.955268 2.865803 0.000000 0.000000 0.000000 0.000000 19.972042 14.406796 0.000000 -31.842663 3.837458 -0.547645 0.000000 0.000000 0.000000 2.021920 -11.504233 -0.063351 -72.470642 -52.058331 10.947752 -101.649963 -68.601273 -76.003120 6.136266 -0.173112 -46.773533 -2.031239 6.631949 -0.068354 91.117523 70.330124 7.996967 150.453125 30.404438 -5.843208 -72.444084 0.173112 0.175734 -19.523405 3.130178 0.538568 37.218685 -4.076704 -2.973909 -17.929630 1.347244 1.628302 -19.718540 -6.722867 0.454054 37.463760 4.039162 2.816819 -18.063959 -1.511718 1.732537 +0.975944 40.212494 -0.911734 0.000000 0.000000 0.000000 11.436294 5.718147 0.000000 0.953024 2.859073 0.000000 0.000000 0.000000 0.000000 19.729687 13.759382 0.000000 -31.699850 3.844106 -0.574209 0.000000 0.000000 0.000000 2.021920 -11.444756 -0.063351 -72.841652 -52.037292 11.029512 -101.439217 -68.310646 -76.291046 6.144234 -0.173112 -46.771114 -2.031238 6.579309 -0.068354 91.168968 70.906219 7.997403 150.453812 30.404375 -5.842882 -69.098328 0.173112 0.175734 -19.592945 3.127127 0.542103 37.375851 -4.073401 -2.995175 -18.017202 1.355157 1.640384 -19.863316 -6.724028 0.462144 37.699352 4.033437 2.853253 -18.150358 -1.533980 1.708233 +0.977080 40.197144 -0.922909 0.000000 0.000000 0.000000 11.464646 5.732323 0.000000 0.955387 2.866162 0.000000 0.000000 0.000000 0.000000 19.529657 12.847766 0.000000 -31.645329 3.865019 -0.544310 0.000000 0.000000 0.000000 2.021920 -11.507401 -0.063351 -73.123978 -52.010529 11.100825 -101.148880 -68.010704 -76.384720 6.134996 -0.173112 -46.773926 -2.031239 6.634750 -0.068354 91.114799 71.325386 7.996945 150.458618 30.396879 -5.843226 -73.388718 0.173112 0.175734 -19.749369 3.136304 0.548165 37.600986 -4.078715 -3.024706 -18.085600 1.357398 1.651340 -19.943457 -6.730891 0.461593 37.836643 4.035933 2.865067 -18.209780 -1.526469 1.718415 +0.979930 40.189213 -0.929611 0.000000 0.000000 0.000000 11.535828 5.767914 0.000000 0.961319 2.883957 0.000000 0.000000 0.000000 0.000000 19.367254 11.748327 0.000000 -31.659180 3.899398 -0.470867 0.000000 0.000000 0.000000 2.021920 -11.664677 -0.063351 -73.329964 -51.984619 11.159848 -100.807884 -67.712799 -76.338814 6.112518 -0.173112 -46.780769 -2.031240 6.773943 -0.068355 90.978783 71.614067 7.995794 150.466049 30.384441 -5.844090 -77.679108 0.173112 0.175734 -19.740498 3.129911 0.548518 37.630375 -4.083414 -3.018880 -18.124962 1.354806 1.670931 -19.931065 -6.734530 0.451584 37.827873 4.028038 2.852055 -18.210985 -1.511566 1.720773 +0.983996 40.187016 -0.932827 0.000000 0.000000 0.000000 11.637395 5.818697 0.000000 0.969783 2.909349 0.000000 0.000000 0.000000 0.000000 19.237780 10.537448 0.000000 -31.721487 3.946441 -0.366796 0.000000 0.000000 0.000000 2.021920 -11.889094 -0.063351 -73.471878 -51.966141 11.204729 -100.445152 -67.428284 -76.207954 6.080764 -0.173112 -46.790432 -2.031243 6.972558 -0.068356 90.784676 71.798698 7.994149 150.474518 30.369547 -5.845322 -81.969498 0.173112 0.175734 -19.760805 3.121071 0.560191 37.650082 -4.079052 -3.028765 -18.125271 1.350521 1.660712 -19.916777 -6.746716 0.453676 37.807362 4.037657 2.853563 -18.201530 -1.507248 1.721605 +0.988782 40.188854 -0.933544 0.000000 0.000000 0.000000 11.756907 5.878453 0.000000 0.979742 2.939227 0.000000 0.000000 0.000000 0.000000 19.136543 9.291512 0.000000 -31.812336 4.005348 -0.245016 0.000000 0.000000 0.000000 2.021920 -12.153164 -0.063351 -73.562050 -51.961689 11.233621 -100.089584 -67.168533 -76.046806 6.043698 -0.173112 -46.801712 -2.031245 7.206264 -0.068357 90.556267 71.905746 7.992214 150.482513 30.354694 -5.846771 -77.636162 0.173112 0.175734 -19.781559 3.114418 0.561931 37.620342 -4.081919 -3.027311 -18.076511 1.347633 1.669426 -19.923277 -6.755539 0.445215 37.837234 4.033159 2.854484 -18.222076 -1.495356 1.742800 +0.993787 40.193039 -0.932747 0.000000 0.000000 0.000000 11.881923 5.940961 0.000000 0.990160 2.970481 0.000000 0.000000 0.000000 0.000000 19.058849 8.086903 0.000000 -31.911812 4.075320 -0.118445 0.000000 0.000000 0.000000 2.021920 -12.429396 -0.063351 -73.612808 -51.977848 11.244678 -99.770096 -66.944908 -75.910042 6.005286 -0.173112 -46.813404 -2.031248 7.450735 -0.068358 90.317345 71.961655 7.990191 150.488510 30.342381 -5.848288 -73.302826 0.173112 0.175734 -19.685673 3.096618 0.559639 37.501865 -4.088297 -3.019854 -18.056458 1.354100 1.679755 -19.937189 -6.773157 0.436810 37.846222 4.042453 2.858254 -18.223614 -1.475835 1.745713 +0.998515 40.197880 -0.931425 0.000000 0.000000 0.000000 12.000000 6.000000 0.000000 1.000000 3.000000 0.000000 0.000000 0.000000 0.000000 19.000000 7.000000 0.000000 -32.000000 4.155556 0.000000 0.000000 0.000000 0.000000 2.021920 -12.690300 -0.063351 -73.636490 -52.021198 11.236053 -99.515602 -66.768776 -75.852303 5.969490 -0.173112 -46.824299 -2.031250 7.681640 -0.068359 90.091698 71.992874 7.988280 150.490997 30.335100 -5.849720 -68.969498 0.173112 0.175734 -19.685507 3.092587 0.569789 37.511917 -4.089489 -3.011332 -18.067400 1.338125 1.697089 -19.891724 -6.783272 0.428388 37.738132 4.046666 2.841241 -18.166637 -1.452491 1.750254 +1.002559 40.201973 -0.930391 0.000000 0.000000 0.000000 12.100996 6.050498 0.000000 1.008417 3.025249 0.000000 0.000000 0.000000 0.000000 18.955889 6.092118 0.000000 -32.060745 4.245046 0.099805 0.000000 0.000000 0.000000 2.021920 -12.913460 -0.063351 -73.655464 -52.095982 11.210612 -99.348267 -66.648804 -75.852303 5.939527 -0.173112 -46.833431 -2.031252 7.879141 -0.068360 89.898712 72.021423 7.986648 150.491287 30.334816 -5.850946 -73.265656 0.173112 0.175734 -19.744637 3.092891 0.572472 37.550182 -4.097017 -3.026582 -18.047445 1.343247 1.707439 -19.948191 -6.796838 0.419719 37.797325 4.040080 2.853555 -18.166439 -1.455029 1.759614 +1.005880 40.205116 -0.929776 0.000000 0.000000 0.000000 12.183942 6.091971 0.000000 1.015329 3.045985 0.000000 0.000000 0.000000 0.000000 18.924746 5.364294 0.000000 -32.092876 4.341934 0.180078 0.000000 0.000000 0.000000 2.021921 -13.096734 -0.063351 -73.674438 -52.197006 11.185171 -99.263283 -66.583015 -75.852303 5.915505 -0.173112 -46.840752 -2.031255 8.041343 -0.068361 89.740227 72.051460 7.985308 150.491577 30.341352 -5.851954 -77.561813 0.173112 0.175734 -19.696648 3.084265 0.571283 37.442406 -4.097444 -3.008321 -17.988600 1.344403 1.706917 -19.894188 -6.804252 0.421853 37.766792 4.059406 2.837988 -18.177452 -1.439314 1.761968 +1.008532 40.207390 -0.929538 0.000000 0.000000 0.000000 12.250164 6.125082 0.000000 1.020847 3.062541 0.000000 0.000000 0.000000 0.000000 18.905390 4.802495 0.000000 -32.098980 4.444156 0.242330 0.000000 0.000000 0.000000 2.021922 -13.243053 -0.063351 -73.693413 -52.316746 11.159730 -99.249084 -66.566772 -75.852303 5.896784 -0.173112 -46.846458 -2.031257 8.170838 -0.068362 89.613708 72.082695 7.984240 150.491867 30.354010 -5.852758 -81.857964 0.173112 0.175734 -19.638386 3.078361 0.569293 37.392666 -4.107718 -2.997922 -17.999796 1.324846 1.713694 -19.841513 -6.804855 0.412141 37.639957 4.053599 2.816186 -18.110031 -1.424089 1.765294 +1.010567 40.208874 -0.929637 0.000000 0.000000 0.000000 12.300987 6.150494 0.000000 1.025083 3.075247 0.000000 0.000000 0.000000 0.000000 18.896639 4.392687 0.000000 -32.081638 4.549644 0.288072 0.000000 0.000000 0.000000 2.021923 -13.355349 -0.063351 -73.712387 -52.447674 11.134289 -99.294113 -66.595421 -75.852303 5.882751 -0.173112 -46.850723 -2.031259 8.270223 -0.068363 89.516624 72.114830 7.983420 150.492157 30.372084 -5.853375 -77.381737 0.173112 0.175734 -19.638979 3.074491 0.569250 37.403080 -4.101413 -2.996720 -17.999388 1.330570 1.714601 -19.849186 -6.812822 0.413216 37.659000 4.060253 2.819884 -18.120216 -1.418991 1.775757 +1.012039 40.209656 -0.930031 0.000000 0.000000 0.000000 12.337740 6.168870 0.000000 1.028145 3.084435 0.000000 0.000000 0.000000 0.000000 18.897312 4.120841 0.000000 -32.043434 4.656333 0.318816 0.000000 0.000000 0.000000 2.021924 -13.436552 -0.063351 -73.731361 -52.582268 11.108848 -99.386803 -66.664307 -75.852303 5.872830 -0.173112 -46.853729 -2.031261 8.342090 -0.068363 89.446442 72.147583 7.982830 150.492447 30.394880 -5.853823 -72.905518 0.173112 0.175734 -19.649149 3.072490 0.569954 37.422733 -4.101367 -2.998287 -18.008608 1.338547 1.715985 -19.858456 -6.815967 0.413507 37.678440 4.058759 2.830679 -18.129459 -1.426289 1.764694 +1.013000 40.209824 -0.930678 0.000000 0.000000 0.000000 12.361746 6.180873 0.000000 1.030146 3.090436 0.000000 0.000000 0.000000 0.000000 18.906221 3.972920 0.000000 -31.986944 4.762157 0.336075 0.000000 0.000000 0.000000 2.021924 -13.489593 -0.063351 -73.750336 -52.712990 11.083406 -99.515602 -66.768799 -75.852303 5.866476 -0.173112 -46.855656 -2.031262 8.389030 -0.068363 89.400597 72.180641 7.982443 150.492737 30.421692 -5.854115 -68.429291 0.173112 0.175734 -19.649292 3.071561 0.570069 37.422363 -4.101637 -3.008067 -18.008158 1.344808 1.726747 -19.906706 -6.825974 0.414089 37.716911 4.067855 2.836741 -18.119793 -1.424552 1.765100 +1.013505 40.209454 -0.931537 0.000000 0.000000 0.000000 12.374334 6.187167 0.000000 1.031195 3.093584 0.000000 0.000000 0.000000 0.000000 18.922190 3.934895 0.000000 -31.914766 4.865050 0.341359 0.000000 0.000000 0.000000 2.021925 -13.517403 -0.063351 -73.769310 -52.832310 11.057965 -99.664841 -66.899086 -75.852303 5.863174 -0.173112 -46.856659 -2.031263 8.413642 -0.068363 89.376579 72.213737 7.982242 150.493027 30.451822 -5.854268 -72.400681 0.173112 0.175734 -19.658360 3.076721 0.569883 37.431515 -4.112633 -3.001946 -17.999447 1.329733 1.724237 -19.906534 -6.826496 0.414169 37.716599 4.075054 2.829346 -18.120955 -1.409166 1.767576 +1.013605 40.208633 -0.932566 0.000000 0.000000 0.000000 12.376830 6.188415 0.000000 1.031403 3.094208 0.000000 0.000000 0.000000 0.000000 18.944035 3.992731 0.000000 -31.829481 4.962945 0.336180 0.000000 0.000000 0.000000 2.021926 -13.522912 -0.063351 -73.788284 -52.932701 11.032524 -99.802505 -67.024727 -75.852303 5.862443 -0.173112 -46.856884 -2.031264 8.418517 -0.068363 89.371841 72.246574 7.982203 150.493317 30.484570 -5.854298 -76.372070 0.173112 0.175734 -19.657982 3.079172 0.570101 37.421658 -4.112985 -3.001266 -17.999413 1.330191 1.724310 -19.856270 -6.822533 0.414528 37.677635 4.071320 2.824993 -18.129929 -1.420102 1.765692 +1.013353 40.207447 -0.933725 0.000000 0.000000 0.000000 12.370558 6.185279 0.000000 1.030880 3.092639 0.000000 0.000000 0.000000 0.000000 18.970572 4.132397 0.000000 -31.733673 5.053777 0.322049 0.000000 0.000000 0.000000 2.021926 -13.509050 -0.063351 -73.807259 -53.006638 11.007083 -99.892509 -67.110123 -75.852303 5.863835 -0.173112 -46.856457 -2.031265 8.406249 -0.068363 89.383835 72.278870 7.982305 150.493607 30.519230 -5.854221 -80.343452 0.173112 0.175734 -19.657539 3.082065 0.569726 37.431625 -4.111417 -3.001562 -18.009268 1.329371 1.724296 -19.868465 -6.819617 0.423511 37.687271 4.073399 2.826447 -18.129555 -1.425024 1.764897 +1.012804 40.205982 -0.934973 0.000000 0.000000 0.000000 12.356844 6.178422 0.000000 1.029737 3.089211 0.000000 0.000000 0.000000 0.000000 19.000618 4.339859 0.000000 -31.629929 5.135479 0.300480 0.000000 0.000000 0.000000 2.021926 -13.478750 -0.063351 -73.826233 -53.046593 10.981642 -99.898773 -67.119667 -75.852303 5.866935 -0.173112 -46.855515 -2.031264 8.379434 -0.068363 89.410027 72.310341 7.982525 150.493896 30.555103 -5.854053 -76.123077 0.173112 0.175734 -19.676533 3.086832 0.570040 37.450485 -4.116269 -3.014377 -17.999081 1.334868 1.725054 -19.869061 -6.817822 0.423232 37.696659 4.074522 2.837290 -18.138712 -1.433418 1.763422 +1.012010 40.204315 -0.936267 0.000000 0.000000 0.000000 12.337016 6.168508 0.000000 1.028085 3.084254 0.000000 0.000000 0.000000 0.000000 19.032993 4.601086 0.000000 -31.520832 5.205986 0.272982 0.000000 0.000000 0.000000 2.021925 -13.434943 -0.063351 -73.845207 -53.045044 10.956201 -99.785172 -67.017754 -75.852303 5.871359 -0.173112 -46.854172 -2.031263 8.340664 -0.068363 89.447891 72.340698 7.982843 150.494186 30.591494 -5.853811 -71.902695 0.173112 0.175734 -19.685661 3.091576 0.569902 37.470367 -4.113850 -3.015196 -18.008268 1.343298 1.716744 -19.921560 -6.817762 0.431836 37.735592 4.078460 2.841711 -18.128590 -1.437683 1.762857 +1.011024 40.202534 -0.937566 0.000000 0.000000 0.000000 12.312402 6.156201 0.000000 1.026034 3.078100 0.000000 0.000000 0.000000 0.000000 19.066517 4.902044 0.000000 -31.408974 5.263233 0.241069 0.000000 0.000000 0.000000 2.021924 -13.380561 -0.063351 -73.864182 -52.994450 10.930759 -99.515602 -66.768799 -75.852303 5.876756 -0.173112 -46.852524 -2.031262 8.292534 -0.068363 89.494896 72.369659 7.983239 150.494476 30.627701 -5.853511 -67.682320 0.173112 0.175734 -19.733667 3.100090 0.571104 37.509758 -4.116610 -3.009547 -17.998810 1.338608 1.715883 -19.880484 -6.817216 0.432537 37.705582 4.088073 2.832715 -18.138338 -1.438337 1.752862 +1.009900 40.200726 -0.938830 0.000000 0.000000 0.000000 12.284328 6.142164 0.000000 1.023694 3.071082 0.000000 0.000000 0.000000 0.000000 19.100008 5.228702 0.000000 -31.296942 5.305154 0.206250 0.000000 0.000000 0.000000 2.021924 -13.318535 -0.063351 -73.883156 -52.887272 10.905318 -99.069969 -66.366333 -76.008949 5.882808 -0.173112 -46.850677 -2.031260 8.237638 -0.068362 89.548515 72.396957 7.983690 150.494781 30.663023 -5.853169 -71.826324 0.173112 0.175734 -19.685551 3.097427 0.559525 37.470314 -4.118086 -3.006844 -18.008507 1.339954 1.706445 -19.881432 -6.814360 0.432092 37.706146 4.081931 2.830753 -18.138569 -1.435338 1.753343 +1.008690 40.198967 -0.940018 0.000000 0.000000 0.000000 12.254121 6.127060 0.000000 1.021177 3.063530 0.000000 0.000000 0.000000 0.000000 19.132282 5.567027 0.000000 -31.187321 5.329683 0.170039 0.000000 0.000000 0.000000 2.021923 -13.251796 -0.063351 -73.902130 -52.715984 10.879877 -98.496552 -65.920479 -76.165596 5.889222 -0.173112 -46.848717 -2.031258 8.178573 -0.068362 89.606194 72.422295 7.984175 150.495071 30.696760 -5.852801 -75.970329 0.173112 0.175734 -19.744005 3.102109 0.561657 37.588787 -4.108281 -3.023638 -18.076128 1.352939 1.709105 -19.944450 -6.813651 0.441600 37.843300 4.082376 2.851669 -18.215300 -1.456687 1.739179 +1.007448 40.197346 -0.941087 0.000000 0.000000 0.000000 12.223108 6.111554 0.000000 1.018593 3.055777 0.000000 0.000000 0.000000 0.000000 19.162163 5.902988 0.000000 -31.082703 5.334756 0.133947 0.000000 0.000000 0.000000 2.021922 -13.183276 -0.063351 -73.921104 -52.473061 10.854436 -97.854523 -65.570503 -76.322243 5.895733 -0.173112 -46.846733 -2.031256 8.117931 -0.068362 89.665413 72.445389 7.984674 150.495361 30.728218 -5.852424 -80.114334 0.173112 0.175734 -19.752968 3.107959 0.561376 37.539303 -4.112191 -3.020917 -18.017490 1.351186 1.708120 -19.946215 -6.811059 0.450823 37.852428 4.090052 2.854924 -18.224466 -1.464893 1.737721 +1.006227 40.195946 -0.941997 0.000000 0.000000 0.000000 12.192617 6.096309 0.000000 1.016052 3.048154 0.000000 0.000000 0.000000 0.000000 19.188469 6.222551 0.000000 -30.985674 5.318306 0.099485 0.000000 0.000000 0.000000 2.021921 -13.115907 -0.063351 -73.940079 -52.150967 10.828995 -97.196259 -65.455666 -76.478889 5.902079 -0.173112 -46.844810 -2.031255 8.058309 -0.068361 89.723648 72.465950 7.985165 150.495667 30.756695 -5.852053 -75.632553 0.173110 0.175728 -19.693880 3.107368 0.558736 37.510170 -4.112158 -3.008835 -18.047516 1.342260 1.697517 -19.947058 -6.808503 0.450427 37.852276 4.091702 2.855453 -18.224466 -1.464895 1.737721 +1.005080 40.194851 -0.942706 0.000000 0.000000 0.000000 12.163976 6.081988 0.000000 1.013665 3.040994 0.000000 0.000000 0.000000 0.000000 19.210020 6.511685 0.000000 -30.898817 5.278267 0.068166 0.000000 0.000000 0.000000 2.021921 -13.052621 -0.063351 -73.959061 -51.742180 10.803554 -96.572151 -65.623604 -76.635536 5.907961 -0.173112 -46.843021 -2.031253 8.002300 -0.068361 89.778351 72.483696 7.985627 150.495972 30.781488 -5.851706 -71.150772 0.173108 0.175723 -19.762560 3.114823 0.551320 37.618092 -4.110145 -3.026611 -18.085623 1.357083 1.690351 -19.947966 -6.805761 0.449999 37.843029 4.085350 2.852622 -18.214352 -1.468910 1.746963 +1.004061 40.194145 -0.943174 0.000000 0.000000 0.000000 12.138510 6.069255 0.000000 1.011542 3.034627 0.000000 0.000000 0.000000 0.000000 19.225637 6.756359 0.000000 -30.824720 5.212575 0.041500 0.000000 0.000000 0.000000 2.021920 -12.996351 -0.063351 -73.978035 -51.239166 10.778112 -96.061096 -65.755371 -76.792183 5.912747 -0.173112 -46.841568 -2.031253 7.952500 -0.068361 89.827003 72.498352 7.986038 150.496262 30.801903 -5.851397 -66.668983 0.173106 0.175717 -19.800898 3.122037 0.552219 37.637764 -4.113653 -3.019619 -18.066502 1.350650 1.699088 -19.948755 -6.803367 0.449625 37.852726 4.086725 2.853856 -18.224215 -1.468113 1.746964 +1.003221 40.193913 -0.943358 0.000000 0.000000 0.000000 12.117544 6.058772 0.000000 1.009795 3.029386 0.000000 0.000000 0.000000 0.000000 19.234138 6.942536 0.000000 -30.765965 5.119163 0.020999 0.000000 0.000000 0.000000 2.021920 -12.950026 -0.063351 -73.978027 -50.687088 10.752671 -96.061096 -65.559494 -76.792191 5.912732 -0.173108 -46.841576 -2.031252 7.911502 -0.068361 89.867058 72.509621 7.986377 150.496552 30.817238 -5.851143 -67.946503 0.173104 0.175711 -19.799726 3.124527 0.561550 37.638130 -4.105915 -3.026847 -18.066238 1.354258 1.699433 -19.940672 -6.799363 0.458794 37.832577 4.088450 2.862519 -18.213551 -1.479201 1.735533 +1.002615 40.194233 -0.943218 0.000000 0.000000 0.000000 12.102407 6.051204 0.000000 1.008534 3.025602 0.000000 0.000000 0.000000 0.000000 19.234339 7.056187 0.000000 -30.725143 4.995964 0.008176 0.000000 0.000000 0.000000 2.021920 -12.916575 -0.063351 -73.978012 -50.341824 10.727230 -96.061096 -65.220757 -76.792191 5.912716 -0.173104 -46.841587 -2.031252 7.881898 -0.068360 89.895996 72.517220 7.986622 150.496857 30.826792 -5.850962 -69.224022 0.173102 0.175706 -19.740990 3.121639 0.559206 37.588909 -4.106975 -3.023221 -18.075891 1.356230 1.699865 -19.941076 -6.798136 0.458603 37.832863 4.089121 2.853040 -18.214268 -1.470015 1.746784 +1.002253 40.195213 -0.942704 0.000000 0.000000 0.000000 12.093350 6.046675 0.000000 1.007779 3.023338 0.000000 0.000000 0.000000 0.000000 19.225101 7.091433 0.000000 -30.758383 4.831508 0.003622 0.000000 0.000000 0.000000 2.021920 -12.896563 -0.063351 -73.978004 -50.347340 10.718750 -96.061096 -65.012093 -76.792191 5.912711 -0.173103 -46.841591 -2.031252 7.864186 -0.068360 89.913307 72.518417 7.986770 150.496948 30.811726 -5.850852 -69.649864 0.173101 0.175704 -19.740753 3.123168 0.559014 37.588985 -4.106116 -3.022948 -18.075891 1.356229 1.699865 -19.931349 -6.796385 0.458525 37.813843 4.082233 2.849248 -18.204786 -1.465947 1.737804 +1.001972 40.197025 -0.941731 0.000000 0.000000 0.000000 12.086341 6.043170 0.000000 1.007195 3.021585 0.000000 0.000000 0.000000 0.000000 19.205471 7.075020 0.000000 -31.136003 4.576701 0.004260 0.000000 0.000000 0.000000 2.021920 -12.881076 -0.063351 -73.977997 -50.189327 10.710270 -96.061096 -65.082718 -76.792191 5.912705 -0.173101 -46.841595 -2.031252 7.850480 -0.068360 89.926697 72.500710 7.986883 150.497040 30.680683 -5.850767 -70.075699 0.173101 0.175702 -19.730820 3.123613 0.558507 37.579224 -4.105491 -3.021957 -18.075857 1.356695 1.699940 -19.911366 -6.794457 0.458619 37.784229 4.083811 2.847380 -18.194756 -1.468951 1.737445 +1.001569 40.199860 -0.940209 0.000000 0.000000 0.000000 12.076277 6.038138 0.000000 1.006356 3.019069 0.000000 0.000000 0.000000 0.000000 19.174543 7.041850 0.000000 -32.181877 4.173048 0.006089 0.000000 0.000000 0.000000 2.021920 -12.858838 -0.063351 -73.977997 -49.188911 10.701789 -96.061096 -65.550926 -76.792198 5.912700 -0.173100 -46.841599 -2.031251 7.830800 -0.068360 89.945930 72.449188 7.987045 150.497147 30.324184 -5.850645 -70.501541 0.173100 0.175700 -19.711040 3.123944 0.557563 37.540020 -4.104424 -3.018448 -18.056080 1.359265 1.700112 -19.951931 -6.796487 0.459304 37.813427 4.086766 2.850702 -18.174759 -1.474028 1.736877 +1.000900 40.203766 -0.938117 0.000000 0.000000 0.000000 12.059563 6.029781 0.000000 1.004964 3.014891 0.000000 0.000000 0.000000 0.000000 19.132662 7.019955 0.000000 -34.086670 3.589655 0.005967 0.000000 0.000000 0.000000 2.021920 -12.821907 -0.063351 -66.508675 -46.897438 10.774745 -96.260246 -65.995079 -66.595352 5.926898 -0.173103 -46.837273 -2.031251 7.798115 -0.068360 89.977867 72.355293 7.987316 148.335159 29.677755 -5.850442 -66.109192 0.173103 0.175709 -19.749393 3.131068 0.558473 37.559322 -4.108144 -3.021215 -18.036741 1.355831 1.689564 -19.942213 -6.794687 0.459224 37.803471 4.088223 2.850375 -18.174673 -1.475130 1.736699 +1.000069 40.208221 -0.935733 0.000000 0.000000 0.000000 12.038811 6.019405 0.000000 1.003234 3.009703 0.000000 0.000000 0.000000 0.000000 19.085321 7.009079 0.000000 -36.486935 2.909111 0.004262 0.000000 0.000000 0.000000 2.021919 -12.776052 -0.063351 -59.039349 -43.824520 10.914568 -96.459396 -63.833939 -56.398502 5.941095 -0.173106 -46.832947 -2.031251 7.757533 -0.068360 90.017525 72.237061 7.987651 141.719666 28.864164 -5.850190 -61.716846 0.173106 0.175717 -19.670828 3.128782 0.555155 37.480453 -4.114704 -3.006562 -18.027515 1.348004 1.688429 -19.864059 -6.784369 0.468826 37.715355 4.088666 2.833697 -18.163877 -1.487783 1.735034 +0.999222 40.212631 -0.933376 0.000000 0.000000 0.000000 12.017651 6.008825 0.000000 1.001471 3.004413 0.000000 0.000000 0.000000 0.000000 19.038630 7.003517 0.000000 -38.946133 2.230086 0.001996 0.000000 0.000000 0.000000 2.021920 -12.729300 -0.063351 -51.570023 -40.614258 11.064763 -52.524841 -57.387028 -20.229925 5.955293 -0.173109 -46.828621 -2.031250 7.716156 -0.068360 90.057968 72.115936 7.987994 130.456619 28.030930 -5.849934 -57.324501 0.173109 0.175725 -19.661663 3.129355 0.544986 37.460850 -4.114183 -3.004812 -18.016966 1.358397 1.679965 -19.844591 -6.780895 0.468682 37.685547 4.084788 2.849472 -18.153826 -1.490967 1.734655 +0.998515 40.216286 -0.931425 0.000000 0.000000 0.000000 12.000000 6.000000 0.000000 1.000000 3.000000 0.000000 0.000000 0.000000 0.000000 19.000000 7.000000 0.000000 -41.000000 1.666667 0.000000 0.000000 0.000000 0.000000 2.021920 -12.690300 -0.063351 -44.100700 -37.920605 11.191607 -8.515602 -50.736427 12.114834 5.969490 -0.173112 -46.824299 -2.031250 7.681640 -0.068359 90.091698 72.014793 7.988280 114.351898 27.335098 -5.849720 -52.932152 0.173112 0.175734 -19.631876 3.130562 0.543483 37.411842 -4.112855 -3.000429 -17.997156 1.361441 1.680210 -19.824808 -6.778360 0.468689 37.655876 4.086925 2.847084 -18.133923 -1.494761 1.734302 +0.656816 40.856964 -0.517020 0.000000 0.000000 0.000000 8.121597 4.060798 0.000000 0.676800 2.030399 0.000000 0.000000 0.000000 0.000000 11.010576 4.718423 0.000000 -28.180910 1.437062 -0.068549 0.000000 0.000000 0.000000 2.021920 -7.257287 -0.063351 -55.907600 -31.618670 11.779637 -4.845869 -40.590050 17.652456 6.867444 -0.173112 -39.084831 -2.029713 3.548990 -0.067535 86.604530 54.874031 9.306187 93.939568 22.296532 -4.862123 -40.373749 0.173112 0.175734 -16.295046 3.421061 0.438420 31.797228 -3.822108 -2.494989 -15.766621 1.319138 0.807549 -16.477676 -5.884224 0.389803 32.044353 3.782028 2.308734 -15.905137 -1.816431 1.445628 +0.315117 41.497643 -0.102615 0.000000 0.000000 0.000000 4.243194 2.121597 0.000000 0.353599 1.060799 0.000000 0.000000 0.000000 0.000000 3.021153 2.436846 0.000000 -15.361820 1.207458 -0.137097 0.000000 0.000000 0.000000 2.021920 -1.824273 -0.063351 -67.714500 -25.316734 12.367668 -1.176135 -30.443674 23.190079 7.765397 -0.173112 -31.345366 -2.028177 -0.583660 -0.066710 83.117371 37.733265 10.624094 72.607376 17.257965 -3.874527 -23.808958 0.173112 0.175734 -11.574896 3.679221 0.277933 23.191488 -3.496631 -1.644848 -11.884295 1.194957 -0.139481 -11.774915 -5.125874 0.222036 23.488432 3.471651 1.457255 -12.083987 -1.810005 1.322199 +-0.026582 42.138321 0.311790 0.000000 0.000000 0.000000 0.364791 0.182395 0.000000 0.030399 0.091198 0.000000 0.000000 0.000000 0.000000 -4.968270 0.155268 0.000000 -2.542730 0.977853 -0.205646 0.000000 0.000000 0.000000 2.021920 3.608740 -0.063351 -79.521400 -19.014799 12.955700 2.493599 -20.297298 28.727699 8.663350 -0.173112 -23.605900 -2.026640 -4.716310 -0.065885 79.630203 20.592501 11.942000 54.706497 12.219400 -2.886930 -10.139900 0.173112 0.175734 -6.647755 3.904616 0.132234 14.232718 -3.173281 -0.790579 -7.886950 1.071780 -0.951619 -6.823235 -4.216930 0.066024 14.567674 3.141394 0.565607 -8.124894 -1.607035 0.960337 diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_cry.bvh b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_cry.bvh new file mode 100644 index 00000000..a70f0c8f --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_cry.bvh @@ -0,0 +1,249 @@ +HIERARCHY +ROOT hip +{ + OFFSET 0.00 0.00 0.00 + CHANNELS 6 Xposition Yposition Zposition Xrotation Zrotation Yrotation + JOINT abdomen + { + OFFSET 0.000000 0.000000 0.000000 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT chest + { + OFFSET 0.000000 5.018152 -1.882228 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT neckDummy + { + OFFSET 0.000000 8.316447 0.784897 + CHANNELS 3 Xrotation Yrotation Zrotation + JOINT neck + { + OFFSET 0.000000 2.280413 -0.392801 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT head + { + OFFSET 0.000000 3.496879 0.529469 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT figureHair + { + OFFSET 0.000000 4.699570 0.720622 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 0.000000 -6.419331 0.000000 + } + } + } + } + } + JOINT lCollar + { + OFFSET 0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lShldr + { + OFFSET 6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT lForeArm + { + OFFSET 10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lHand + { + OFFSET 11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 10.353753 0.000000 0.000000 + } + } + } + } + } + JOINT rCollar + { + OFFSET -0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rShldr + { + OFFSET -6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT rForeArm + { + OFFSET -10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rHand + { + OFFSET -11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET -10.353753 0.000000 0.000000 + } + } + } + } + } + } + } + JOINT lThigh + { + OFFSET 4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lShin + { + OFFSET -1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lFoot + { + OFFSET -0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } + JOINT rThigh + { + OFFSET -4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rShin + { + OFFSET 1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rFoot + { + OFFSET 0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } +} +MOTION +Frames: 120 +Frame Time: 0.050000 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -70.100700 9.978770 15.991600 -22.515600 -9.303740 0.147736 5.969490 -0.173112 0.175734 -2.021920 5.690310 -0.063351 70.025291 -9.978496 15.899026 22.669645 9.345270 0.121616 -5.927727 -0.009578 0.195807 -7.541017 3.726345 0.264145 15.588717 -3.091945 -1.095025 -8.382813 1.045269 -0.743771 -7.531943 -4.331991 0.100592 15.540622 3.074890 0.554129 -8.443594 -1.605291 1.033999 +0.000019 42.067165 0.212358 0.000000 0.000000 0.000000 -0.780029 0.000000 0.000000 0.430324 0.000000 -0.000000 0.000000 0.000000 0.000000 0.276668 0.000000 0.000000 -4.112352 0.000000 0.000000 0.000000 0.000000 0.000000 3.634888 -5.214703 -0.466385 -70.120880 6.802692 16.230499 -31.261179 -9.830895 -1.873094 8.857805 -0.272899 -2.069665 -2.843143 5.541447 -0.063351 70.044884 -6.337014 15.899711 33.210896 10.096720 -2.959646 -8.385094 -0.515216 -3.193567 -7.173937 3.699082 0.240199 14.683834 -3.036666 -1.009890 -7.850093 1.052688 -0.806822 -7.159451 -4.301536 0.054629 14.642860 3.023678 0.528568 -7.916223 -1.604488 1.051248 +0.003350 42.140240 0.175805 0.000000 0.000000 0.000000 -1.840344 0.000000 0.000000 0.869424 0.000000 -0.000000 0.000000 0.000000 0.000000 0.534749 0.000000 0.000000 -9.231783 0.000000 0.000000 0.000000 0.000000 0.000000 5.749265 -4.809306 -0.994544 -70.138893 3.094322 16.730745 -41.736835 -10.467624 -4.302903 12.340313 -0.361629 -4.769518 -3.901931 5.580458 -0.063351 70.062027 -1.840675 15.899734 46.008480 11.137873 -6.709976 -11.312582 -1.055159 -7.229813 -6.631275 3.637162 0.237711 13.403262 -2.955712 -0.908958 -7.101416 1.046608 -0.862816 -6.636842 -4.265091 0.013617 13.371022 2.945111 0.448040 -7.164529 -1.571539 1.112716 +0.008207 42.221771 0.135766 0.000000 0.000000 0.000000 -3.012878 0.000000 0.000000 1.303136 0.000000 -0.000000 0.000000 0.000000 0.000000 0.778187 0.000000 0.000000 -14.725705 0.000000 0.000000 0.000000 0.000000 0.000000 8.059620 -4.446731 -1.571598 -70.155464 -0.790003 17.346338 -52.818981 -11.143351 -6.877102 16.033648 -0.443071 -7.629820 -5.052323 5.709417 -0.063351 70.077614 2.970247 15.899434 59.615993 12.296215 -10.701450 -14.403100 -1.599843 -11.490206 -6.033436 3.582804 0.223513 11.980614 -2.870705 -0.790700 -6.282634 1.036293 -0.949037 -6.052147 -4.216943 -0.034349 11.957492 2.857863 0.369219 -6.320821 -1.535448 1.165273 +0.010884 42.298153 0.097035 0.000000 0.000000 0.000000 -4.128572 0.000000 0.000000 1.801706 0.000000 -0.000000 0.000000 0.000000 0.000000 1.079307 0.000000 0.000000 -20.230402 0.000000 0.000000 0.000000 0.000000 0.000000 10.304009 -3.959762 -2.132276 -70.176781 -4.844602 17.828751 -64.195602 -11.833339 -9.513267 19.809177 -0.548187 -10.558954 -6.180820 5.690004 -0.063351 70.098022 7.815058 15.899686 73.465607 13.386814 -14.757404 -17.586916 -2.204906 -15.880303 -5.470705 3.530067 0.199557 10.641871 -2.792462 -0.680696 -5.499310 1.035750 -1.004962 -5.495022 -4.177372 -0.082837 10.637929 2.779470 0.289726 -5.554121 -1.497919 1.216578 +0.007671 42.355774 0.064403 0.000000 0.000000 0.000000 -5.018363 0.000000 0.000000 2.435374 0.000000 -0.000000 0.000000 0.000000 0.000000 1.510432 0.000000 0.000000 -25.382156 0.000000 0.000000 0.000000 0.000000 0.000000 12.220485 -3.181180 -2.611307 -70.209015 -9.063789 17.929449 -75.554649 -12.512850 -12.128970 23.538273 -0.707943 -13.465302 -7.173920 5.283895 -0.063351 70.129662 12.413069 15.901357 86.989487 14.224733 -18.701174 -20.794292 -2.925988 -20.305662 -5.073351 3.492726 0.192581 9.656575 -2.733860 -0.595697 -4.905209 1.019426 -1.050133 -5.101159 -4.135585 -0.116953 9.673667 2.713716 0.244523 -4.975415 -1.497380 1.263188 +-0.005140 42.381023 0.042664 0.000000 0.000000 0.000000 -5.513192 0.000000 0.000000 3.274386 0.000000 -0.000000 0.000000 0.000000 0.000000 2.143889 0.000000 0.000000 -29.817261 0.000000 0.000000 0.000000 0.000000 0.000000 13.547104 -1.943769 -2.943422 -70.258362 -13.441889 17.399908 -86.584091 -13.157144 -14.641785 27.092310 -0.953303 -16.257252 -7.918120 4.252771 -0.063351 70.178925 16.483589 15.905319 99.619804 14.625040 -22.356096 -23.955490 -3.818726 -24.671835 -4.932858 3.489937 0.186494 9.258925 -2.701216 -0.588857 -4.648473 1.051342 -1.090136 -4.964010 -4.096052 -0.160304 9.285015 2.683348 0.257497 -4.713937 -1.483672 1.257459 +-0.031257 42.360298 0.036612 0.000000 0.000000 0.000000 -5.444000 0.000000 0.000000 4.388985 0.000000 0.000000 0.000000 0.000000 0.000000 3.052001 0.000000 0.000000 -33.172001 0.000000 0.000000 0.000000 0.000000 0.000000 14.021920 -0.080311 -3.063351 -70.330986 -17.973213 15.991600 -96.971909 -13.741488 -16.969290 30.342661 -1.315232 -18.843182 -8.299920 2.358311 -0.063351 70.252205 19.745926 15.912447 110.788712 14.402799 -25.545506 -27.000784 -4.938759 -28.884392 -5.171671 3.541960 0.177933 9.720609 -2.721253 -0.608780 -4.868991 1.049125 -1.117600 -5.201677 -4.059840 -0.197907 9.728270 2.691394 0.314850 -4.927111 -1.488409 1.205618 +-0.072502 42.282375 0.050039 0.000000 0.000000 0.000000 -4.698589 -0.000000 -0.000000 5.811747 -0.000000 0.000000 0.000000 0.000000 0.000000 4.314877 0.000000 0.000000 -35.146339 0.000000 0.000000 0.000000 0.000000 0.000000 13.464965 2.417609 -2.926152 -70.426125 -22.619801 13.598684 -106.462402 -14.249018 -19.049547 33.200989 -1.789992 -21.154263 -8.240068 -0.447181 -0.063351 70.348801 22.059727 15.923216 120.055328 13.461332 -28.133654 -29.855686 -6.329955 -32.849304 -5.851437 3.647218 0.167484 11.201345 -2.810648 -0.727230 -5.670475 1.076822 -1.118659 -5.881972 -4.038422 -0.212360 11.202619 2.761685 0.440661 -5.721230 -1.515766 1.096344 +-0.123143 42.145603 0.082739 0.000000 0.000000 0.000000 -3.392231 -0.000000 -0.000000 7.424582 -0.000000 0.000000 0.000000 0.000000 0.000000 6.043762 0.000000 0.000000 -35.694973 0.000000 0.000000 0.000000 0.000000 0.000000 12.024202 4.923179 -2.568213 -70.515221 -27.214540 10.686103 -115.025116 -14.694356 -20.902567 35.740189 -2.235037 -23.212828 -7.796305 -3.448905 -0.063351 70.439728 23.845980 15.936509 127.486420 12.056977 -30.148411 -32.426689 -7.989092 -36.474190 -6.937224 3.805117 0.162331 13.597161 -2.938309 -0.909991 -6.974202 1.103573 -1.085115 -6.970128 -4.031584 -0.232804 13.587861 2.877406 0.669403 -7.032958 -1.578398 0.938200 +-0.175564 41.950722 0.133509 0.000000 0.000000 0.000000 -1.697058 -0.000000 -0.000000 9.071734 -0.000000 0.000000 0.000000 0.000000 0.000000 8.357687 0.000000 0.000000 -34.836273 0.000000 0.000000 0.000000 0.000000 0.000000 9.929573 6.650785 -2.046247 -70.562744 -31.558044 7.861478 -122.685898 -15.099997 -22.568848 38.073448 -2.473119 -25.063993 -7.060619 -5.741441 -0.063351 70.488884 25.665997 15.950813 133.275620 10.534322 -31.658548 -34.615528 -9.901178 -39.667088 -8.356124 3.992327 0.166423 16.766150 -3.122238 -1.176059 -8.728294 1.116202 -0.998940 -8.368327 -4.042577 -0.235044 16.731833 3.023353 0.937407 -8.787015 -1.628860 0.744197 +-0.222145 41.698460 0.201142 0.000000 0.000000 0.000000 0.214795 -0.000000 -0.000000 10.597450 -0.000000 0.000000 0.000000 0.000000 0.000000 11.375681 0.000000 0.000000 -32.588627 0.000000 0.000000 0.000000 0.000000 0.000000 7.411021 6.814816 -1.416971 -70.533180 -35.450924 5.732435 -129.470642 -15.488441 -24.088890 40.313957 -2.326991 -26.752874 -6.124999 -6.419365 -0.063351 70.460167 28.081104 15.964621 137.616623 9.237956 -32.732845 -36.323948 -12.051224 -42.336037 -10.015359 4.207023 0.173519 20.516310 -3.330481 -1.478308 -10.814568 1.094375 -0.882801 -10.012256 -4.098610 -0.234589 20.472368 3.208572 1.261267 -10.876534 -1.692469 0.522672 +-0.255268 41.389561 0.284433 0.000000 0.000000 0.000000 2.171192 -0.000000 -0.000000 11.845972 -0.000000 0.000000 0.000000 0.000000 0.000000 15.216778 0.000000 0.000000 -28.970409 0.000000 0.000000 0.000000 0.000000 0.000000 4.698489 4.629655 -0.737100 -70.390999 -38.693783 4.906600 -135.405243 -15.882190 -25.503197 42.574905 -1.619404 -28.324591 -5.081437 -4.577256 -0.063351 70.317482 31.652618 15.976419 140.703125 8.512474 -33.440083 -37.453690 -14.424237 -44.389084 -11.828053 4.430223 0.188828 24.681581 -3.550707 -1.839217 -13.161494 1.057035 -0.737545 -11.822182 -4.207497 -0.237120 24.638620 3.404104 1.612172 -13.232539 -1.703871 0.310165 +-0.267317 41.024761 0.382178 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 12.661540 0.000000 0.000000 0.000000 0.000000 0.000000 20.000000 0.000000 0.000000 -24.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -0.690310 -0.063351 -70.100700 -41.087234 5.991600 -140.515594 -16.303740 -26.852264 44.969490 -0.173111 -29.824265 -4.021920 0.690310 -0.063351 70.024750 36.941860 15.984700 142.728760 8.702466 -33.849052 -37.906498 -17.005228 -45.734268 -13.738516 4.657444 0.191027 29.116396 -3.789706 -2.216130 -15.692704 0.982453 -0.538576 -13.716253 -4.373569 -0.225963 29.044374 3.617020 1.985104 -15.734435 -1.667365 0.091907 +-0.252010 40.617123 0.490100 0.000000 0.000000 0.000000 5.524832 0.000000 0.000000 12.921827 0.000000 -0.000000 0.000000 0.000000 0.000000 25.609043 0.000000 0.000000 -17.940689 0.000000 0.000000 0.000000 0.000000 0.000000 -0.323769 -9.139868 0.530688 -69.665565 -42.531548 9.195004 -144.717361 -16.737293 -28.104082 47.478394 2.099466 -31.216307 -3.066781 9.434553 -0.063351 69.585266 44.044693 15.988464 143.917648 9.981306 -33.990685 -37.606247 -19.731361 -46.338985 -15.612423 4.862041 0.205354 33.551018 -3.999800 -2.620278 -18.260357 0.889045 -0.316219 -15.588444 -4.607350 -0.203625 33.486710 3.827065 2.382790 -18.290714 -1.614179 -0.074067 +-0.208420 40.229012 0.591640 0.000000 0.000000 0.000000 6.552301 0.000000 0.000000 12.638206 0.000000 -0.000000 0.000000 0.000000 0.000000 30.986208 0.000000 0.000000 -12.035405 0.000000 0.000000 0.000000 0.000000 0.000000 -1.783766 -17.550514 0.903936 -69.244072 -43.325638 13.124158 -147.485382 -17.013876 -28.936558 49.552246 4.927227 -32.142284 -2.449716 18.289890 -0.063351 69.159882 51.195107 15.988770 144.615540 11.837497 -33.744553 -36.565296 -22.348398 -46.408012 -17.226891 4.987271 0.212412 37.408054 -4.171602 -2.970548 -20.492533 0.809096 -0.068646 -17.209301 -4.851499 -0.165589 37.362755 3.984295 2.732663 -20.520905 -1.540677 -0.181163 +-0.136959 39.935120 0.667166 0.000000 0.000000 0.000000 6.884765 0.000000 0.000000 11.855470 0.000000 0.000000 0.000000 0.000000 0.000000 34.838467 0.000000 0.000000 -7.772004 0.000000 0.000000 0.000000 0.000000 0.000000 -1.738281 -21.962893 0.898438 -69.033478 -43.868088 15.986333 -148.184326 -16.926228 -28.955091 50.509148 7.949394 -32.163055 -2.432765 23.036533 -0.063351 68.948868 56.161655 15.987190 145.198608 13.588324 -32.952393 -34.818157 -24.554277 -46.205494 -18.338499 4.970268 0.207670 40.024849 -4.240129 -3.218983 -21.978550 0.794248 0.134622 -18.332424 -5.066293 -0.090363 39.990158 4.036550 2.952231 -22.020935 -1.513609 -0.167323 +-0.047248 39.790878 0.701654 0.000000 0.000000 0.000000 6.401859 -0.000000 -0.000000 10.664240 -0.000000 0.000000 0.000000 0.000000 0.000000 36.273262 0.000000 0.000000 -6.248044 0.000000 0.000000 0.000000 0.000000 0.000000 0.016674 -20.009525 0.458397 -69.239372 -44.465145 16.570404 -146.639114 -16.451403 -28.000124 49.995331 10.766827 -31.100964 -3.124787 21.250412 -0.063352 69.159195 57.233650 15.985300 145.936859 14.770011 -31.597172 -32.538971 -26.108685 -45.960556 -18.750591 4.792098 0.198128 40.960564 -4.175310 -3.352235 -22.452400 0.931136 0.253153 -18.772840 -5.203340 0.047591 40.966225 3.978038 3.021245 -22.572382 -1.613245 -0.009364 +0.014232 39.774685 0.698508 0.000000 0.000000 0.000000 5.292308 0.000000 0.000000 9.338461 0.000000 0.000000 0.000000 0.000000 0.000000 36.000000 0.000000 0.000000 -7.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -15.690310 -0.063351 -70.100700 -45.053795 15.991600 -144.515594 -16.303740 -26.852264 48.969490 12.826889 -29.824265 -4.021920 17.690310 -0.063351 70.024750 54.783550 15.984696 146.675430 15.794548 -30.226763 -30.460417 -27.018377 -45.762291 -18.697699 4.608089 0.186434 40.741528 -4.068078 -3.354266 -22.251463 1.059459 0.286382 -18.743950 -5.242704 0.188751 40.757893 3.886556 2.962811 -22.415812 -1.749481 0.190528 +0.010670 39.851231 0.666517 0.000000 0.000000 0.000000 3.807929 0.000000 0.000000 8.149942 0.000000 -0.000000 0.000000 0.000000 0.000000 34.987576 0.000000 0.000000 -9.210148 0.000000 0.000000 0.000000 0.000000 0.000000 2.808350 -13.286060 -0.308623 -71.756226 -45.513054 15.634354 -143.498520 -17.059179 -26.311655 48.460411 13.712852 -29.222967 -4.599954 17.252762 -0.063347 71.679268 49.850132 15.986306 147.205414 17.060564 -29.383070 -29.257114 -27.373665 -45.651989 -18.399199 4.548339 0.201805 39.970135 -4.006059 -3.298873 -21.770926 1.090113 0.248641 -18.462301 -5.184166 0.258501 39.977783 3.821624 2.887556 -21.936321 -1.866986 0.263216 +-0.019226 40.007381 0.617602 0.000000 0.000000 0.000000 2.143811 0.000000 0.000000 7.178617 0.000000 -0.000000 0.000000 0.000000 0.000000 33.640858 0.000000 0.000000 -12.205083 0.000000 0.000000 0.000000 0.000000 0.000000 2.530335 -11.833870 -0.306472 -73.910629 -45.859379 15.633582 -143.507385 -18.002773 -26.316391 48.464874 13.705083 -29.228239 -4.866001 18.202442 -0.063344 73.828987 44.054325 15.988324 147.526428 18.037466 -29.019199 -28.812811 -27.351982 -45.619694 -17.873255 4.548517 0.223715 38.687447 -3.966642 -3.182334 -21.038019 1.079715 0.180905 -17.923792 -5.086353 0.283479 38.674232 3.808012 2.770459 -21.175997 -1.930291 0.264274 +-0.017868 40.235550 0.564462 0.000000 0.000000 0.000000 0.480866 0.000000 0.000000 6.456444 0.000000 -0.000000 0.000000 0.000000 0.000000 32.223713 0.000000 0.000000 -15.347477 0.000000 0.000000 0.000000 0.000000 0.000000 1.748112 -9.059898 -0.182761 -76.160072 -46.143600 15.811819 -144.020340 -18.096851 -26.589062 48.721645 13.258215 -29.531521 -4.960008 17.146061 -0.063344 76.073257 39.162590 15.988262 147.690277 17.962360 -28.941065 -28.813536 -27.152540 -45.642643 -17.058788 4.491447 0.241605 36.785099 -3.946988 -2.995184 -19.992958 1.052899 0.136715 -17.090565 -5.036561 0.244259 36.760674 3.798310 2.627202 -20.086241 -1.939176 0.320869 +0.072332 40.528149 0.519799 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 6.015381 0.000000 0.000000 0.000000 0.000000 0.000000 31.000000 0.000000 0.000000 -18.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.021920 -2.690310 -0.063351 -78.100700 -46.416542 15.991600 -144.515594 -16.303740 -26.852264 48.969490 12.826889 -29.824265 -5.021920 10.690310 -0.063351 78.011436 36.941387 15.983623 147.748703 16.072346 -28.954573 -28.945332 -26.974552 -45.698082 -15.884778 4.266353 0.249208 34.146706 -3.917244 -2.721047 -18.554235 1.070082 0.174625 -15.923319 -5.115859 0.156332 34.160038 3.779252 2.410561 -18.634346 -1.828842 0.520281 +0.260289 40.822456 0.498571 0.000000 0.000000 0.000000 -2.004472 -0.000000 -0.000000 5.910875 -0.000000 0.000000 0.000000 0.000000 0.000000 30.335041 0.000000 0.000000 -19.364559 0.000000 0.000000 0.000000 0.000000 0.000000 0.792415 7.096063 -0.039414 -79.161240 -46.707161 16.038666 -144.615082 -12.510576 -26.905045 49.019176 12.740428 -29.882965 -5.118267 -1.472739 -0.063363 79.074310 38.455853 15.974219 147.751617 12.423500 -28.915081 -28.967215 -26.958151 -45.759148 -14.577338 3.866274 0.239442 31.272917 -3.858238 -2.435187 -17.001980 1.170204 0.301865 -14.627975 -5.360775 0.022367 31.354895 3.715202 2.190315 -17.109968 -1.655631 0.903275 +0.360236 40.835182 0.524777 0.000000 0.000000 0.000000 -1.784616 0.000000 0.000000 6.292309 0.000000 0.000000 0.000000 0.000000 0.000000 31.000000 0.000000 0.000000 -18.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.021920 10.309690 -0.063351 -78.100700 -46.957001 15.991600 -144.516006 -10.303699 -26.852301 48.969501 12.826900 -29.824301 -5.021920 -7.309700 -0.063351 78.018417 41.965893 15.969081 147.741547 10.347745 -28.875769 -28.930157 -27.007166 -45.782619 -14.414228 3.688577 0.214775 31.027596 -3.858117 -2.397117 -16.899927 1.230465 0.407292 -14.471190 -5.516973 -0.022167 31.148739 3.714993 2.165166 -17.050898 -1.550236 1.056644 +0.219720 40.371704 0.608923 0.000000 0.000000 0.000000 0.114613 0.000000 0.000000 7.256994 0.000000 -0.000000 0.000000 0.000000 0.000000 33.391220 0.000000 0.000000 -13.094919 0.000000 0.000000 0.000000 0.000000 0.000000 1.527300 -0.859155 -0.070081 -74.275406 -46.955498 15.938358 -144.488129 -12.645546 -26.837471 48.955536 12.851212 -29.807806 -4.553955 2.950780 -0.063310 74.197052 45.351002 15.975508 147.748932 12.566304 -28.909039 -28.930328 -27.002522 -45.740211 -16.339401 4.089540 0.201040 35.420643 -3.956117 -2.832502 -19.329180 1.204381 0.351527 -16.391712 -5.418512 0.070486 35.502605 3.817855 2.515948 -19.495718 -1.623106 0.668500 +0.014232 39.812618 0.698508 0.000000 0.000000 0.000000 2.523077 0.000000 0.000000 8.600001 0.000000 0.000000 0.000000 0.000000 0.000000 36.000000 0.000000 0.000000 -7.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -15.690300 -0.063351 -70.100700 -46.953995 15.991600 -144.516006 -16.303699 -26.852301 48.969501 12.826900 -29.824301 -4.021920 17.690300 -0.063351 70.024742 47.774342 15.984711 147.762863 16.081656 -28.966406 -28.952724 -26.969847 -45.679802 -18.693228 4.626644 0.184059 40.760296 -4.074469 -3.367789 -22.270269 1.075894 0.289809 -18.743950 -5.242704 0.188751 40.775166 3.925373 2.958556 -22.447054 -1.724267 0.165802 +-0.056841 39.570061 0.739394 0.000000 0.000000 0.000000 4.159745 -0.000000 -0.000000 10.041920 -0.000000 0.000000 0.000000 0.000000 0.000000 37.238350 0.000000 0.000000 -2.338362 0.000000 0.000000 0.000000 0.000000 0.000000 2.256450 -22.055510 -0.060092 -68.120369 -46.952492 16.196571 -144.529510 -17.568832 -26.859480 48.976265 12.815129 -29.832287 -3.769390 23.593519 -0.063541 68.045158 48.902725 15.986985 147.766907 17.444710 -28.986586 -28.962872 -26.958035 -45.653820 -19.678881 4.831614 0.183201 43.012623 -4.123365 -3.601876 -23.514414 1.017193 0.299451 -19.729961 -5.203599 0.226264 42.998325 3.983753 3.142215 -23.680038 -1.740363 -0.042373 +-0.026482 39.607136 0.733912 0.000000 0.000000 0.000000 4.925189 -0.000000 -0.000000 11.307627 -0.000000 0.000000 0.000000 0.000000 0.000000 37.106091 0.000000 0.000000 0.339207 0.000000 0.000000 0.000000 0.000000 0.000000 2.234267 -20.724222 -0.061151 -68.332954 -46.950989 16.304144 -144.525131 -17.018904 -26.857147 48.974068 12.818954 -29.829697 -3.797534 21.947603 -0.063645 68.257477 49.133991 15.985040 147.764221 17.118971 -28.977978 -28.959648 -26.964298 -45.656738 -19.454313 4.763245 0.183826 42.533318 -4.103762 -3.554573 -23.268938 1.043284 0.312339 -19.505468 -5.242685 0.207385 42.537651 3.974403 3.109906 -23.436819 -1.717045 0.034705 +0.014232 39.774681 0.698508 0.000000 0.000000 0.000000 5.015384 0.000000 0.000000 12.123077 0.000000 0.000000 0.000000 0.000000 0.000000 36.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -15.690300 -0.063351 -70.100700 -46.949486 15.991600 -144.516006 -16.303699 -26.852301 48.969501 12.826900 -29.824301 -4.021920 17.690300 -0.063351 70.024757 49.048721 15.984692 147.762863 16.546080 -28.966415 -28.950266 -26.972931 -45.668522 -18.708267 4.647506 0.182835 40.789398 -4.074512 -3.379904 -22.288937 1.095094 0.284024 -18.743950 -5.242704 0.188751 40.793262 3.944776 2.966914 -22.467350 -1.714550 0.167439 +0.003283 39.944328 0.648209 0.000000 0.000000 0.000000 4.608281 0.000000 0.000000 12.283582 0.000000 -0.000000 0.000000 0.000000 0.000000 34.324028 0.000000 0.000000 -0.224049 0.000000 0.000000 0.000000 0.000000 0.000000 1.690129 -10.369040 -0.064195 -72.776367 -46.947983 15.183835 -144.512512 -16.578159 -26.850439 48.967751 12.829947 -29.822231 -4.357885 14.724633 -0.062584 72.699829 49.115868 15.989244 147.767197 16.734764 -28.969658 -28.940695 -26.972435 -45.674362 -17.986624 4.628279 0.191057 39.026112 -4.044704 -3.187253 -21.282671 1.075990 0.182581 -17.990946 -5.144764 0.199564 39.018490 3.925535 2.817172 -21.434784 -1.764864 0.183788 +-0.005109 40.070850 0.592367 0.000000 0.000000 0.000000 3.809764 0.000000 0.000000 11.861862 0.000000 -0.000000 0.000000 0.000000 0.000000 32.510769 0.000000 0.000000 -2.542431 0.000000 0.000000 0.000000 0.000000 0.000000 1.326279 -5.861539 -0.063897 -75.674652 -46.946480 14.796188 -144.513733 -17.017900 -26.851093 48.968369 12.828873 -29.822964 -4.719829 12.814810 -0.062215 75.594765 49.357857 15.991974 147.767090 16.962124 -28.973227 -28.931959 -26.968140 -45.680298 -17.465586 4.607643 0.205279 37.693764 -4.019233 -3.041925 -20.482292 1.045477 0.110699 -17.442287 -5.075838 0.208555 37.655518 3.906348 2.702058 -20.609205 -1.792018 0.201608 +0.072332 40.129810 0.538913 0.000000 0.000000 0.000000 2.707692 0.000000 0.000000 11.000000 0.000000 0.000000 0.000000 0.000000 0.000000 31.000000 0.000000 0.000000 -5.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.021920 -2.690310 -0.063351 -78.100700 -46.944977 15.991600 -144.516006 -16.303699 -26.852301 48.969501 12.826900 -29.824301 -5.021920 10.690300 -0.063351 78.011429 49.685486 15.983640 147.748703 16.072350 -28.954578 -28.923849 -26.969582 -45.697575 -17.229410 4.431520 0.203418 36.998390 -4.015249 -2.936592 -20.040445 1.080599 0.210442 -17.207996 -5.202640 0.177624 36.949570 3.886522 2.659604 -20.132364 -1.749308 0.382961 +0.263395 40.114418 0.498595 0.000000 0.000000 0.000000 1.548253 -0.000000 -0.000000 9.981828 -0.000000 0.000000 0.000000 0.000000 0.000000 30.275864 0.000000 0.000000 -6.827596 0.000000 0.000000 0.000000 0.000000 0.000000 0.876608 -1.533319 -0.063232 -79.277679 -46.943474 19.084044 -144.516510 -13.887232 -26.852562 48.969749 12.826469 -29.824589 -5.169384 7.950781 -0.066291 79.172691 50.021114 15.961275 147.708954 13.632845 -28.905855 -28.917612 -26.981646 -45.729652 -17.319756 4.071060 0.199828 37.107327 -4.005738 -2.942211 -20.042547 1.220086 0.528032 -17.331129 -5.594622 0.072411 37.085377 3.889932 2.710237 -20.098042 -1.563405 0.709248 +0.373912 40.088432 0.493410 0.000000 0.000000 0.000000 1.210938 0.000000 0.000000 9.658202 0.000000 0.000000 0.000000 0.000000 0.000000 31.000000 0.000000 0.000000 -8.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.021920 -3.690310 -0.063351 -78.100700 -46.941971 20.991600 -144.516006 -12.303699 -26.852301 48.969501 12.826900 -29.824301 -5.031688 7.676662 -0.068105 77.985382 50.333454 15.946996 147.687607 12.103814 -28.877934 -28.920383 -26.990618 -45.748917 -17.656567 3.874698 0.191031 37.891071 -4.024854 -3.021332 -20.477304 1.313453 0.754632 -17.696541 -5.846913 0.029345 37.907726 3.906001 2.809350 -20.525326 -1.477874 0.894684 +0.236120 40.095921 0.545618 0.000000 0.000000 0.000000 2.339320 0.000000 0.000000 10.648221 0.000000 -0.000000 0.000000 0.000000 0.000000 33.426292 0.000000 0.000000 -8.425192 0.000000 0.000000 0.000000 0.000000 0.000000 1.507334 -9.606884 -0.063385 -74.153267 -46.940468 19.091263 -144.515869 -13.789696 -26.852226 48.969425 12.827021 -29.824219 -4.554234 12.238956 -0.066299 74.045883 50.606640 15.960249 147.717773 13.615035 -28.913849 -28.936411 -26.983654 -45.731468 -17.975456 4.194003 0.173416 38.839535 -4.056654 -3.147066 -21.087196 1.259203 0.546802 -18.053442 -5.615727 0.086789 38.917561 3.941987 2.853565 -21.216560 -1.536022 0.610862 +0.009843 40.031612 0.667256 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 12.076924 0.000000 0.000000 0.000000 0.000000 0.000000 36.000000 0.000000 0.000000 -7.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -15.690300 -0.063351 -70.100700 -46.938965 15.991600 -144.516006 -16.303699 -26.852301 48.969501 12.826900 -29.824301 -4.021920 17.690300 -0.063351 70.024750 50.840286 15.984694 147.762878 16.081688 -28.966515 -28.952496 -26.969969 -45.699314 -18.067148 4.678326 0.158998 39.483109 -4.093340 -3.250632 -21.632418 1.123083 0.214545 -18.100163 -5.183131 0.180607 39.486797 3.963936 2.858007 -21.772314 -1.707712 0.179493 +-0.112796 39.802368 0.849957 0.000000 0.000000 0.000000 5.122050 -0.000000 -0.000000 12.937906 -0.000000 0.000000 0.000000 0.000000 0.000000 37.138813 0.000000 0.000000 -3.032819 0.000000 0.000000 0.000000 0.000000 0.000000 2.249517 -18.329782 -0.063332 -68.579887 -46.937462 14.769460 -144.516068 -17.379122 -26.852335 48.969551 12.826839 -29.824339 -3.738908 19.747454 -0.062187 68.552261 51.037872 15.999207 147.780594 17.041298 -28.982525 -28.955685 -26.961912 -45.679638 -18.719097 5.004677 0.146956 41.530502 -4.117812 -3.495305 -23.023117 1.075888 0.082304 -18.746616 -5.011149 0.184255 41.474205 3.993676 3.097349 -23.107891 -1.796822 -0.152440 +-0.138038 39.512920 1.013950 0.000000 0.000000 0.000000 5.661417 -0.000001 -0.000000 13.193013 -0.000001 0.000000 0.000000 0.000000 0.000000 36.958652 0.000000 0.000000 1.510561 0.000000 0.000000 0.000000 0.000000 0.000000 2.213451 -17.880783 -0.063336 -69.032333 -46.935959 15.143210 -144.516052 -17.127220 -26.852324 48.969551 12.826859 -29.824326 -3.746885 19.102257 -0.062541 69.023499 51.202877 15.999311 147.775253 16.735432 -28.973293 -28.951466 -26.962336 -45.674400 -19.566422 5.160550 0.154005 43.892330 -4.140266 -3.740405 -24.529654 1.051357 0.150288 -19.592247 -5.043746 0.134659 43.902023 4.005006 3.418545 -24.644821 -1.809608 -0.346310 +-0.121722 39.317471 1.061612 0.000000 0.000000 0.000000 5.830768 0.000000 0.000000 13.046155 0.000000 0.000000 0.000000 0.000000 0.000000 36.000000 0.000000 0.000000 4.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -15.690300 -0.063351 -70.100700 -46.934456 15.991600 -144.516006 -16.303699 -26.852301 48.969501 12.826900 -29.824301 -4.021920 17.690300 -0.063351 70.024757 51.338776 15.984692 147.762878 16.081665 -28.966433 -28.949928 -26.971720 -45.679260 -19.828968 5.125339 0.145522 44.569729 -4.123878 -3.810583 -24.938686 1.089122 0.221183 -19.849995 -5.116296 0.066938 44.575851 4.006379 3.552788 -25.039209 -1.769863 -0.373499 +-0.106714 39.327133 0.932559 0.000000 0.000000 0.000000 5.794933 0.000002 0.000001 12.671766 0.000002 -0.000001 0.000000 0.000000 0.000000 34.737885 0.000000 0.000000 2.573865 0.000000 0.000000 0.000000 0.000000 0.000000 1.769946 -12.890279 -0.063368 -70.813789 -46.932953 16.416576 -144.515976 -15.568898 -26.852287 48.969429 12.826919 -29.824287 -4.504272 16.940979 -0.063766 70.563477 51.449051 15.952639 147.756104 15.805897 -28.980797 -28.957680 -26.988455 -45.689320 -19.663992 5.057109 0.158307 43.708759 -4.097345 -3.718179 -24.243959 1.104265 0.188248 -19.704748 -5.116341 0.022195 43.724400 3.976989 3.480442 -24.334312 -1.767655 -0.322306 +-0.084000 39.480705 0.715344 0.000000 0.000000 0.000000 5.527415 0.000003 0.000001 12.126372 0.000004 -0.000001 0.000000 0.000000 0.000000 33.385422 0.000000 0.000000 -1.555448 0.000000 0.000000 0.000000 0.000000 0.000000 1.499853 -9.752472 -0.063383 -71.745071 -46.931450 16.412918 -144.515976 -15.201655 -26.852287 48.969379 12.826919 -29.824289 -4.990931 16.258923 -0.063777 71.331886 51.537189 15.890917 147.754211 15.867371 -29.000219 -28.967377 -27.002590 -45.697437 -19.241276 4.929391 0.179212 42.004494 -4.067840 -3.546052 -22.981686 1.127133 0.141187 -19.312616 -5.106191 0.012651 42.050995 3.948402 3.283941 -23.072901 -1.738937 -0.198523 +-0.031598 39.673901 0.535758 0.000000 0.000000 0.000000 4.953881 0.000003 0.000001 11.437023 0.000004 -0.000001 0.000000 0.000000 0.000000 32.090244 0.000000 0.000000 -6.407038 0.000000 0.000000 0.000000 0.000000 0.000000 1.240789 -6.333578 -0.063394 -73.854164 -46.929947 16.198601 -144.515991 -15.385435 -26.852293 48.969391 12.826909 -29.824295 -5.243081 14.542553 -0.063587 73.443405 51.606667 15.784909 147.753113 16.033665 -28.999786 -28.968212 -27.002100 -45.695923 -18.710257 4.755458 0.191573 40.191536 -4.054839 -3.343563 -21.719400 1.143896 0.151080 -18.789587 -5.134377 0.020825 40.251064 3.915647 3.048361 -21.802353 -1.698982 -0.014576 +0.072476 39.802441 0.519592 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 10.630770 0.000000 0.000000 0.000000 0.000000 0.000000 31.000000 0.000000 0.000000 -10.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.021900 -2.690300 -0.063400 -78.100700 -46.928444 15.991600 -144.516006 -16.303699 -26.852301 48.969501 12.826900 -29.824301 -5.021900 10.690300 -0.063400 78.011429 51.660969 15.619997 147.748703 16.072348 -28.954578 -28.949364 -26.974958 -45.677090 -18.176809 4.509519 0.208224 38.976196 -4.038352 -3.219945 -21.042175 1.188972 0.259740 -18.274431 -5.271552 0.028760 39.037647 3.889839 2.903799 -21.131535 -1.629559 0.243137 +0.218309 39.789494 0.735315 0.000000 0.000000 0.000000 2.863414 -0.000005 -0.000002 9.779999 -0.000006 0.000002 0.000000 0.000000 0.000000 30.384218 0.000000 0.000000 -10.917629 0.000000 0.000000 0.000000 0.000000 0.000000 0.897417 0.654050 -0.063400 -84.101303 -46.926941 15.949913 -144.516006 -17.793182 -26.852303 48.969669 12.826897 -29.824301 -4.315772 4.790395 -0.063362 84.649902 51.703568 15.470215 147.741837 15.778905 -28.898895 -28.924185 -26.937366 -45.648270 -17.807486 4.256437 0.200394 38.946388 -4.054275 -3.193769 -21.400961 1.246810 0.499180 -17.891558 -5.534724 0.054177 38.988754 3.895928 2.882541 -21.459970 -1.556349 0.545013 +0.268403 39.668072 1.022117 0.000000 0.000000 0.000000 2.553846 0.000000 0.000000 9.138458 0.000000 0.000000 0.000000 0.000000 0.000000 31.000000 0.000000 0.000000 -10.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.021900 1.309700 -0.063400 -86.100700 -46.925438 15.991600 -144.516006 -18.303699 -26.852301 48.969501 12.826900 -29.824301 -4.021900 1.690300 -0.063400 87.005043 51.737946 15.605665 147.745544 15.076430 -28.970974 -28.954136 -26.965252 -45.653416 -17.867468 4.217439 0.196531 40.132927 -4.067859 -3.304471 -22.515314 1.262236 0.622221 -17.922510 -5.661786 0.045847 40.143967 3.909368 3.027866 -22.567291 -1.542375 0.590887 +0.115011 39.502117 1.202217 0.000000 0.000000 0.000000 3.143023 0.000017 0.000006 8.927999 0.000022 -0.000005 0.000000 0.000000 0.000000 33.296051 0.000000 0.000000 -8.491877 0.000000 0.000000 0.000000 0.000000 0.000000 1.485687 -2.432191 -0.063402 -79.550354 -46.923935 16.004009 -144.516006 -16.626284 -26.852301 48.968910 12.826899 -29.824306 -4.871359 5.383711 -0.063411 80.101852 51.767582 15.815006 147.750870 14.050402 -28.952662 -28.962000 -26.980892 -45.666725 -18.514040 4.589186 0.153353 42.239548 -4.113412 -3.494892 -23.957516 1.169806 0.472759 -18.522448 -5.467646 0.031780 42.189758 3.947764 3.256145 -24.001009 -1.625423 0.221069 +-0.103026 39.369503 1.259218 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 9.061540 0.000000 0.000000 0.000000 0.000000 0.000000 36.000000 0.000000 0.000000 -7.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021900 -7.690300 -0.063400 -70.100700 -46.922432 15.991600 -144.516006 -14.303699 -26.852301 48.969501 12.826900 -29.824301 -6.021900 11.690300 -0.063400 70.024757 51.795956 15.984690 147.749115 13.084374 -28.957411 -28.947575 -26.976831 -45.676254 -19.291471 5.066572 0.117455 44.188961 -4.146286 -3.690081 -25.086760 1.053064 0.224377 -19.245268 -5.135960 0.027348 44.097725 3.986955 3.476343 -25.157152 -1.763049 -0.295742 +-0.223970 39.333317 1.218347 0.000000 0.000000 0.000000 4.527250 -0.000089 -0.000029 9.389661 -0.000111 0.000028 0.000000 0.000000 0.000000 37.728844 0.000000 0.000000 -5.896106 0.000000 0.000000 0.000000 0.000000 0.000000 2.343950 -11.187572 -0.063386 -64.381775 -46.920929 15.982133 -144.516006 -13.112394 -26.852301 48.972553 12.826914 -29.824280 -6.485753 15.555025 -0.063391 63.923790 51.826553 16.077076 147.736206 12.536720 -29.147562 -28.936451 -26.972439 -45.680275 -19.709332 5.319770 0.110758 44.992332 -4.155787 -3.772298 -25.460831 0.982413 0.065669 -19.657808 -4.950900 0.034327 44.890312 4.006599 3.559706 -25.533558 -1.845519 -0.554719 +-0.241087 39.383541 1.109941 0.000000 0.000000 0.000000 4.687758 -0.000202 -0.000065 9.822517 -0.000253 0.000064 0.000000 0.000000 0.000000 38.378101 0.000000 0.000000 -5.249927 0.000000 0.000000 0.000000 0.000000 0.000000 2.443611 -12.654203 -0.063368 -62.743011 -46.919426 15.979488 -144.516022 -13.011697 -26.852303 48.976433 12.826933 -29.824253 -6.266395 16.598215 -0.063389 62.182003 51.862846 16.101809 147.719543 12.383018 -29.416498 -28.931801 -26.970938 -45.680473 -19.775160 5.341631 0.100952 44.717525 -4.162519 -3.741894 -25.128962 0.970650 0.030761 -19.708900 -4.920052 0.068983 44.635925 4.023082 3.496405 -25.229147 -1.857497 -0.542533 +-0.186394 39.491901 0.965608 0.000000 0.000000 0.000000 4.584642 -0.000270 -0.000088 10.285161 -0.000340 0.000086 0.000000 0.000000 0.000000 38.162945 0.000000 0.000000 -5.055695 0.000000 0.000000 0.000000 0.000000 0.000000 2.382247 -12.572200 -0.063356 -63.963718 -46.917923 15.981578 -144.516022 -13.506649 -26.852303 48.978794 12.826946 -29.824242 -5.615110 15.609049 -0.063391 63.490700 51.908321 16.080351 147.709351 12.503141 -29.590359 -28.931192 -26.971516 -45.679382 -19.558537 5.204474 0.110203 43.727009 -4.152900 -3.663366 -24.354519 1.030956 0.085602 -19.523760 -4.988610 0.111109 43.657261 4.022883 3.356549 -24.448627 -1.814186 -0.383146 +-0.091908 39.630119 0.816959 0.000000 0.000000 0.000000 4.321018 -0.000226 -0.000073 10.702639 -0.000284 0.000072 0.000000 0.000000 0.000000 37.298523 0.000000 0.000000 -5.307642 0.000000 0.000000 0.000000 0.000000 0.000000 2.221222 -11.423563 -0.063363 -66.823181 -46.916420 15.986312 -144.516006 -14.102301 -26.852301 48.977272 12.826939 -29.824253 -4.783183 13.376686 -0.063395 66.541183 51.966454 16.034161 147.715790 12.776968 -29.495281 -28.932188 -26.973362 -45.679527 -19.161943 4.978234 0.132672 42.315933 -4.123088 -3.543670 -23.344826 1.096913 0.167928 -19.172661 -5.105536 0.143369 42.296696 4.006330 3.189409 -23.462971 -1.763203 -0.151161 +0.010354 39.769909 0.695606 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 11.000000 0.000000 0.000000 0.000000 0.000000 0.000000 36.000000 0.000000 0.000000 -6.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021900 -9.690300 -0.063400 -70.100700 -46.914917 15.991600 -144.516006 -14.303699 -26.852301 48.969501 12.826900 -29.824301 -4.021900 10.690300 -0.063400 70.024750 52.040722 15.984700 147.749115 13.084374 -28.957411 -28.932358 -26.975668 -45.683449 -18.701353 4.723861 0.154833 40.865208 -4.103608 -3.406197 -22.363710 1.166972 0.269744 -18.743950 -5.242704 0.188751 40.876995 3.993842 3.009922 -22.506508 -1.714856 0.127712 +0.094229 39.888195 0.626214 0.000000 0.000000 0.000000 3.706967 0.000370 0.000120 11.120661 0.000477 -0.000124 0.000000 0.000000 0.000000 34.458595 0.000000 0.000000 -7.110358 0.000000 0.000000 0.000000 0.000000 0.000000 1.835354 -7.783293 -0.063470 -72.796875 -46.913414 15.995672 -144.516006 -14.089414 -26.852301 48.956688 12.826816 -29.824398 -3.531840 8.204600 -0.063403 72.870064 52.134609 15.949427 147.803848 13.322378 -27.853662 -28.930950 -26.978683 -45.692314 -18.255651 4.529634 0.169955 39.630329 -4.074003 -3.304542 -21.597942 1.222471 0.350240 -18.315069 -5.359768 0.201902 39.662334 3.977669 2.876848 -21.726997 -1.657958 0.326553 +0.156974 39.982735 0.605678 0.000000 0.000000 0.000000 3.456345 0.000427 0.000137 11.081515 0.000630 -0.000178 0.000000 0.000000 0.000000 32.769855 0.000000 0.000000 -8.549736 0.000000 0.000000 0.000000 0.000000 0.000000 1.671485 -5.828933 -0.063549 -74.797531 -46.911911 15.998045 -144.516006 -13.875128 -26.852301 48.954266 12.826681 -29.824554 -3.310734 6.036367 -0.063405 74.955231 52.251583 15.929766 147.811829 13.456571 -26.264006 -28.929543 -26.981699 -45.701180 -17.850540 4.374533 0.181368 38.649872 -4.064386 -3.201702 -21.029346 1.244142 0.416387 -17.915140 -5.437898 0.209772 38.692471 3.958097 2.782703 -21.179478 -1.643597 0.493692 +0.201697 40.056480 0.623948 0.000000 0.000000 0.000000 3.244820 -0.000395 -0.000133 10.917827 -0.000180 -0.000013 0.000000 0.000000 0.000000 31.005384 0.000000 0.000000 -10.212513 0.000000 0.000000 0.000000 0.000000 0.000000 1.529903 -3.882491 -0.063605 -76.209801 -46.910408 15.998549 -144.516006 -13.660842 -26.852301 48.981236 12.826490 -29.824774 -3.305614 4.167944 -0.063406 76.395714 52.395138 15.923136 147.689240 13.469685 -24.319199 -28.928135 -26.984715 -45.710045 -17.453636 4.265353 0.196722 37.886410 -4.038617 -3.122007 -20.656990 1.254053 0.433568 -17.542646 -5.486427 0.213875 37.947384 3.949050 2.709965 -20.808645 -1.624296 0.590634 +0.231508 40.112392 0.670972 0.000000 0.000000 0.000000 3.069082 -0.002660 -0.000875 10.664860 -0.002592 0.000519 0.000000 0.000000 0.000000 29.236797 0.000000 0.000000 -11.993066 0.000000 0.000000 0.000000 0.000000 0.000000 1.410216 -1.999237 -0.063607 -77.140839 -46.908905 15.997020 -144.516006 -13.446556 -26.852301 49.056599 12.826240 -29.825068 -3.463505 2.581663 -0.063406 77.306992 52.568745 15.926952 147.352219 13.344450 -22.149990 -28.926727 -26.987730 -45.718910 -17.110401 4.187120 0.201173 37.307899 -4.034627 -3.054982 -20.431787 1.256694 0.470578 -17.194061 -5.516638 0.205292 37.369904 3.935383 2.640314 -20.584429 -1.609493 0.664975 +0.249517 40.153423 0.736702 0.000000 0.000000 0.000000 2.925816 -0.006931 -0.002274 10.357878 -0.007244 0.001568 0.000000 0.000000 0.000000 27.535702 0.000000 0.000000 -13.785775 0.000000 0.000000 0.000000 0.000000 0.000000 1.312034 -0.234439 -0.063523 -77.697777 -46.907402 15.993293 -144.516006 -13.232271 -26.852301 49.199345 12.825924 -29.825438 -3.731434 1.259862 -0.063405 77.804520 52.775871 15.938632 146.716949 13.063603 -19.887152 -28.925320 -26.990746 -45.727776 -16.800142 4.138686 0.204096 36.887039 -4.024792 -2.998836 -20.324615 1.248827 0.487478 -16.889111 -5.535431 0.194973 36.938499 3.919611 2.620677 -20.447384 -1.607971 0.706262 +0.258834 40.182533 0.811087 0.000000 0.000000 0.000000 2.811711 -0.013773 -0.004512 10.032143 -0.014774 0.003283 0.000000 0.000000 0.000000 25.973715 0.000000 0.000000 -15.485021 0.000000 0.000000 0.000000 0.000000 0.000000 1.234965 1.356632 -0.063320 -77.987762 -46.905895 15.987202 -144.516006 -13.017985 -26.852301 49.428482 12.825538 -29.825891 -4.056431 0.184859 -0.063404 78.003761 53.020004 15.955591 145.699554 12.609873 -17.661411 -28.923912 -26.993761 -45.736637 -16.535479 4.109017 0.206654 36.593739 -4.009168 -2.970579 -20.295353 1.247293 0.477108 -16.619984 -5.536634 0.181613 36.634590 3.909618 2.603347 -20.417660 -1.612378 0.725447 +0.262569 40.202679 0.884076 0.000000 0.000000 0.000000 2.723454 -0.023751 -0.007775 9.722919 -0.025822 0.005814 0.000000 0.000000 0.000000 24.622444 0.000000 0.000000 -16.985180 0.000000 0.000000 0.000000 0.000000 0.000000 1.178620 2.718708 -0.062969 -78.117928 -46.904388 15.978578 -144.516006 -12.803699 -26.852301 49.763000 12.825077 -29.826431 -4.385523 -0.661007 -0.063402 78.020172 53.304626 15.975252 144.216217 11.965995 -15.603537 -28.922504 -26.996777 -45.745499 -16.326534 4.100985 0.200114 36.388462 -4.005228 -2.933626 -20.305775 1.236387 0.465491 -16.392231 -5.535830 0.167783 36.429214 3.896087 2.592716 -20.436668 -1.620103 0.753060 +0.263831 40.216816 0.945621 0.000000 0.000000 0.000000 2.657732 -0.037427 -0.012248 9.465465 -0.041026 0.009310 0.000000 0.000000 0.000000 23.553495 0.000000 0.000000 -18.180634 0.000000 0.000000 0.000000 0.000000 0.000000 1.142605 3.796521 -0.062435 -78.195412 -46.902885 15.967253 -144.516006 -12.589415 -26.852301 50.221897 12.824534 -29.827066 -4.665736 -1.295406 -0.063401 77.969246 53.633213 15.995029 142.183121 11.114701 -13.844281 -28.921097 -26.999794 -45.754364 -16.147465 4.090225 0.203957 36.261066 -4.005165 -2.913801 -20.355154 1.228557 0.464624 -16.215576 -5.535314 0.152537 36.291557 3.890166 2.599544 -20.474827 -1.633673 0.750028 +0.265142 40.227394 0.988007 0.000000 0.000000 0.000000 2.611253 -0.053919 -0.017640 9.286642 -0.059411 0.013547 0.000000 0.000000 0.000000 22.814882 0.000000 0.000000 -18.998629 0.000000 0.000000 0.000000 0.000000 0.000000 1.124676 4.553377 -0.061749 -78.299805 -46.521034 15.954080 -142.316010 -11.732272 -26.852301 50.775547 12.823956 -29.827744 -4.856435 -1.739169 -0.063401 77.944557 54.009243 16.012169 139.569061 10.054364 -12.440172 -28.920721 -27.000599 -45.756729 -16.029289 4.080369 0.200341 36.154251 -3.995397 -2.892582 -20.365234 1.223359 0.454030 -16.094687 -5.524401 0.145159 36.184765 3.880202 2.578372 -20.475761 -1.621431 0.752222 +0.266672 40.234821 1.012874 0.000000 0.000000 0.000000 2.580811 -0.066548 -0.021768 9.179693 -0.073545 0.016817 0.000000 0.000000 0.000000 22.360220 0.000000 0.000000 -19.497929 0.000000 0.000000 0.000000 0.000000 0.000000 1.115164 5.026911 -0.061176 -78.400589 -45.457794 15.943984 -140.116013 -10.875130 -26.852301 51.199852 12.823597 -29.828165 -4.966344 -2.025809 -0.063400 77.952194 54.436207 16.023222 136.553406 8.845877 -11.150791 -28.920345 -27.001404 -45.759094 -15.948249 4.079330 0.207002 36.085663 -3.989678 -2.895110 -20.375107 1.221862 0.453868 -16.021910 -5.526221 0.146547 36.105656 3.886011 2.574012 -20.475138 -1.629605 0.760531 +0.268004 40.238987 1.024197 0.000000 0.000000 0.000000 2.563220 -0.067189 -0.021976 9.129455 -0.074384 0.017037 0.000000 0.000000 0.000000 22.119513 0.000000 0.000000 -19.770168 0.000000 0.000000 0.000000 0.000000 0.000000 1.102547 5.273335 -0.061043 -78.439713 -43.833267 15.942910 -137.916016 -10.017986 -26.852301 51.222095 12.823764 -29.827972 -5.016518 -2.191995 -0.063400 77.976395 54.917583 16.024565 133.368179 7.565783 -9.661502 -28.919970 -27.002207 -45.761456 -15.909597 4.069695 0.216106 36.046703 -3.989615 -2.882293 -20.375862 1.208655 0.461254 -15.969785 -5.525172 0.138267 36.066910 3.876356 2.577713 -20.485094 -1.627497 0.770539 +0.268720 40.239792 1.025953 0.000000 0.000000 0.000000 2.555295 -0.047715 -0.015605 9.120764 -0.052884 0.012125 0.000000 0.000000 0.000000 22.022768 0.000000 0.000000 -19.906979 0.000000 0.000000 0.000000 0.000000 0.000000 1.075300 5.348860 -0.061675 -78.359100 -41.767548 15.956800 -135.716003 -9.160843 -26.852301 50.569550 12.824762 -29.826805 -5.028018 -2.274401 -0.063400 78.001404 55.456856 16.012577 130.245377 6.290621 -7.657664 -28.919594 -27.003010 -45.763817 -15.899550 4.069640 0.215722 36.027058 -3.989568 -2.880729 -20.366510 1.200989 0.459767 -15.959520 -5.525014 0.138547 36.046909 3.876507 2.585926 -20.474480 -1.638233 0.768729 +0.268403 40.237129 1.022117 0.000000 0.000000 0.000000 2.553850 0.000000 0.000000 9.138460 0.000000 0.000000 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -20.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.021900 5.309700 -0.063400 -78.100700 -39.380733 15.991600 -133.516006 -8.303700 -26.852301 48.969501 12.826900 -29.824301 -5.021900 -2.309700 -0.063400 78.011436 56.057507 15.983633 127.417007 5.096930 -4.824638 -28.919220 -27.003815 -45.766182 -15.899550 4.069639 0.215722 36.027058 -3.989569 -2.880729 -20.366510 1.200990 0.459767 -15.970601 -5.525443 0.147951 36.046909 3.876507 2.585926 -20.463984 -1.647330 0.767216 +0.266811 40.231209 1.016187 0.000000 0.000000 0.000000 2.556075 0.081338 0.026596 9.169409 0.090336 -0.020761 0.000000 0.000000 0.000000 21.992777 0.000000 0.000000 -20.121017 0.000000 0.000000 0.000000 0.000000 0.000000 0.934298 5.204816 -0.066497 -77.626846 -36.785038 16.051495 -130.795135 -7.911441 -26.407307 46.248135 12.830298 -29.820324 -5.015624 -2.328731 -0.063400 78.007835 56.745384 15.936543 125.055420 4.066480 -0.933100 -27.038599 -24.939163 -44.135284 -15.919640 4.069749 0.216489 36.036880 -3.989594 -2.881511 -20.356239 1.209609 0.461213 -15.991124 -5.525755 0.147388 36.056190 3.886093 2.579904 -20.464310 -1.643057 0.758228 +0.264403 40.223473 1.009745 0.000000 0.000000 0.000000 2.560653 0.190712 0.062336 9.208582 0.212284 -0.048947 0.000000 0.000000 0.000000 21.988895 0.000000 0.000000 -20.262405 0.000000 0.000000 0.000000 0.000000 0.000000 0.818334 5.054157 -0.071059 -76.981331 -34.061134 16.133642 -126.133736 -7.957548 -25.172319 42.627228 12.834337 -29.815598 -5.012240 -2.338994 -0.063400 78.004234 57.635887 15.879825 123.094162 3.301935 3.905152 -22.132702 -19.470097 -39.697132 -15.947449 4.079130 0.216682 36.066353 -3.989661 -2.883857 -20.356501 1.205048 0.450627 -16.011646 -5.526067 0.146827 36.085651 3.886161 2.582223 -20.474306 -1.640487 0.758552 +0.261815 40.215672 1.003894 0.000000 0.000000 0.000000 2.566642 0.319791 0.104468 9.252977 0.357025 -0.082686 0.000000 0.000000 0.000000 21.987717 0.000000 0.000000 -20.396692 0.000000 0.000000 0.000000 0.000000 0.000000 0.683325 4.870421 -0.077131 -76.228333 -31.281824 16.233442 -119.833611 -8.347777 -23.297333 38.427464 12.838210 -29.811066 -5.011199 -2.342154 -0.063400 78.000633 58.866772 15.824419 121.407135 2.911205 9.492968 -15.304631 -11.685770 -33.138866 -15.977576 4.079292 0.217830 36.105309 -3.989722 -2.896674 -20.365919 1.211405 0.451878 -16.043242 -5.526801 0.155670 36.125122 3.880468 2.593252 -20.483675 -1.646084 0.757390 +0.259681 40.209564 0.999737 0.000000 0.000000 0.000000 2.573102 0.460242 0.150245 9.299597 0.515744 -0.120109 0.000000 0.000000 0.000000 21.988605 0.000000 0.000000 -20.496405 0.000000 0.000000 0.000000 0.000000 0.000000 0.538585 4.666308 -0.084762 -75.432045 -28.519909 16.346294 -112.196602 -8.987887 -20.932344 33.969521 12.841113 -29.807671 -5.011950 -2.339876 -0.063400 77.997032 60.575794 15.781267 119.868187 3.002189 15.633210 -7.657493 -2.675338 -25.147635 -16.005514 4.091577 0.208735 36.125118 -3.995349 -2.880543 -20.376633 1.195022 0.449032 -16.057451 -5.515243 0.154922 36.145126 3.880314 2.585040 -20.484312 -1.637782 0.749134 +0.258638 40.206902 0.998378 0.000000 0.000000 0.000000 2.579088 0.603736 0.196916 9.345441 0.679621 -0.159344 0.000000 0.000000 0.000000 21.990921 0.000000 0.000000 -20.534065 0.000000 0.000000 0.000000 0.000000 0.000000 0.393430 4.454516 -0.093995 -74.656647 -25.848190 16.467596 -103.524536 -9.783635 -18.227352 29.574072 12.842239 -29.806355 -5.013946 -2.333826 -0.063400 77.993431 62.900719 15.761313 118.351227 3.682786 22.128712 -0.294396 6.472043 -16.410591 -16.005514 4.091577 0.208736 36.144768 -3.995399 -2.882110 -20.395777 1.202535 0.450597 -16.067707 -5.515396 0.154640 36.154606 3.880307 2.595501 -20.483686 -1.645949 0.747648 +0.259321 40.209442 1.000919 0.000000 0.000000 0.000000 2.583661 0.741941 0.241733 9.387511 0.839841 -0.198521 0.000000 0.000000 0.000000 21.994019 0.000000 0.000000 -20.482201 0.000000 0.000000 0.000000 0.000000 0.000000 0.257175 4.247742 -0.104879 -73.966331 -23.339476 16.592749 -94.119202 -10.640778 -15.332349 25.561800 12.840784 -29.808062 -5.016635 -2.325669 -0.063400 77.989830 65.979332 15.775497 116.730118 5.060905 28.782404 5.681551 14.667213 -7.614883 -16.005514 4.091577 0.208736 36.134937 -3.995375 -2.881327 -20.385948 1.203340 0.450636 -16.057451 -5.515243 0.154922 36.154606 3.880307 2.595501 -20.493473 -1.646090 0.747478 +0.262364 40.218933 1.008465 0.000000 0.000000 0.000000 2.585878 0.866525 0.281945 9.422805 0.987585 -0.235770 0.000000 0.000000 0.000000 21.997261 0.000000 0.000000 -20.313337 0.000000 0.000000 0.000000 0.000000 0.000000 0.139134 4.058685 -0.117458 -73.425262 -21.066568 16.717152 -84.282417 -11.465071 -12.397333 22.253384 12.835939 -29.813728 -5.019469 -2.317072 -0.063400 77.986237 69.949394 15.834764 114.878754 7.244447 35.397121 9.167250 20.821030 0.552359 -15.957494 4.079182 0.217064 36.095482 -3.989699 -2.895892 -20.375679 1.211910 0.452075 -16.032984 -5.526646 0.155949 36.115303 3.880447 2.592481 -20.483608 -1.646988 0.757225 +0.268403 40.237129 1.022117 0.000000 0.000000 0.000000 2.584797 0.969159 0.314804 9.448320 1.114037 -0.269218 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -20.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.048624 3.900043 -0.131780 -73.097641 -19.102268 16.836205 -74.316002 -12.162271 -9.572301 19.969501 12.826900 -29.824301 -5.021900 -2.309700 -0.063400 77.982635 74.948677 15.950056 112.671036 10.341314 41.775726 9.059593 23.844332 7.403990 -15.899550 4.069639 0.215722 36.027058 -3.989569 -2.880729 -20.366510 1.200990 0.459767 -15.970601 -5.525443 0.147951 36.046909 3.876507 2.585926 -20.463984 -1.647330 0.767216 +0.277812 40.264977 1.042561 0.000000 0.000000 0.000000 2.579744 1.043572 0.338251 9.461839 1.212492 -0.297392 0.000000 0.000000 0.000000 22.001741 0.000000 0.000000 -19.520584 0.000000 0.000000 0.000000 0.000000 0.000000 -0.007540 3.781479 -0.147759 -73.029556 -17.499443 16.946182 -64.499100 -12.658545 -6.979751 18.919321 12.813484 -29.839987 -5.023497 -2.304857 -0.063400 77.988159 81.027840 16.124151 110.023178 14.401119 47.702980 4.789122 23.116499 12.419645 -15.812270 4.060131 0.203536 35.908936 -3.995275 -2.863459 -20.335634 1.227701 0.464253 -15.882150 -5.534741 0.121564 35.929951 3.870317 2.565177 -20.427757 -1.608388 0.774833 +0.289912 40.300148 1.068799 0.000000 0.000000 0.000000 2.571117 1.091741 0.352999 9.464260 1.284700 -0.320395 0.000000 0.000000 0.000000 22.002590 0.000000 0.000000 -18.876959 0.000000 0.000000 0.000000 0.000000 0.000000 -0.032532 3.700506 -0.164785 -73.194794 -16.231178 17.046858 -55.020046 -12.961682 -4.632192 18.865965 12.798013 -29.858072 -5.024307 -2.302403 -0.063400 77.993683 87.889328 16.327190 107.020584 19.240467 52.891441 -2.079048 19.891027 15.746076 -15.698709 4.031830 0.201733 35.761875 -3.995167 -2.842107 -20.306301 1.227373 0.473635 -15.769707 -5.556012 0.105896 35.782249 3.870419 2.563451 -20.399878 -1.588252 0.798438 +0.303764 40.339504 1.099417 0.000000 0.000000 0.000000 2.559583 1.117706 0.360449 9.457267 1.334526 -0.338725 0.000000 0.000000 0.000000 22.002777 0.000000 0.000000 -18.076860 0.000000 0.000000 0.000000 0.000000 0.000000 -0.032025 3.651601 -0.182116 -73.549065 -15.250610 17.138880 -46.044460 -13.099880 -2.514635 19.461048 12.783430 -29.875114 -5.024495 -2.301835 -0.063400 77.999207 95.148438 16.521151 103.791016 24.617636 57.035500 -9.446151 15.889950 17.696808 -15.562719 4.012639 0.198167 35.595089 -3.995778 -2.818763 -20.267744 1.217354 0.471408 -15.629599 -5.564394 0.080881 35.606335 3.860727 2.546815 -20.362186 -1.568160 0.821893 +0.318428 40.379913 1.133000 0.000000 0.000000 0.000000 2.545809 1.125505 0.362004 9.442540 1.365833 -0.352881 0.000000 0.000000 0.000000 22.002510 0.000000 0.000000 -17.128023 0.000000 0.000000 0.000000 0.000000 0.000000 -0.011693 3.629242 -0.199012 -74.048073 -14.510874 17.222897 -37.737984 -13.101336 -0.612092 20.356184 12.772680 -29.887672 -5.024225 -2.302650 -0.063400 78.004738 102.420464 16.668005 100.462219 30.290916 59.829586 -15.586458 12.522607 18.581146 -15.419118 3.983778 0.195117 35.399475 -3.985994 -2.800386 -20.227098 1.243234 0.485382 -15.485868 -5.585040 0.066002 35.429440 3.861356 2.532638 -20.314442 -1.551331 0.835353 +0.332965 40.418236 1.168133 0.000000 0.000000 0.000000 2.530460 1.119176 0.359066 9.421760 1.382486 -0.363363 0.000000 0.000000 0.000000 22.001963 0.000000 0.000000 -16.038181 0.000000 0.000000 0.000000 0.000000 0.000000 0.022791 3.627907 -0.214731 -74.647522 -13.965107 17.299553 -30.266264 -12.994247 1.090425 21.202984 12.768707 -29.892307 -5.023666 -2.304346 -0.063400 78.010269 109.320694 16.729734 97.161972 36.018581 61.096203 -20.266346 9.947609 18.691486 -15.255903 3.952896 0.190733 35.193077 -3.985938 -2.784163 -20.177425 1.255820 0.506613 -15.330836 -5.604815 0.041649 35.223686 3.851800 2.523538 -20.256475 -1.540323 0.867450 +0.346435 40.451336 1.203400 0.000000 0.000000 0.000000 2.514204 1.102759 0.353039 9.396608 1.388347 -0.370668 0.000000 0.000000 0.000000 22.001280 0.000000 0.000000 -14.815074 0.000000 0.000000 0.000000 0.000000 0.000000 0.065753 3.642072 -0.228531 -75.303131 -13.566448 17.369501 -23.794943 -12.806814 2.607903 21.653065 12.774458 -29.885586 -5.022982 -2.306422 -0.063400 78.015793 115.464516 16.668314 94.017998 41.558979 61.170212 -23.625202 8.010895 18.315994 -15.101444 3.923780 0.196816 34.987209 -3.980285 -2.766314 -20.128078 1.262833 0.507309 -15.175381 -5.624808 0.017300 35.027554 3.851635 2.498607 -20.220343 -1.497980 0.895127 +0.357899 40.476074 1.237387 0.000000 0.000000 0.000000 2.497706 1.080293 0.345325 9.368767 1.387281 -0.375296 0.000000 0.000000 0.000000 22.000584 0.000000 0.000000 -13.466434 0.000000 0.000000 0.000000 0.000000 0.000000 0.111521 3.666216 -0.239671 -75.970612 -13.268038 17.433390 -18.489639 -12.567232 3.955332 21.358032 12.792874 -29.864065 -5.022338 -2.308373 -0.063400 78.021317 120.467216 16.445721 91.158066 46.670372 60.514565 -25.802435 6.558393 17.742840 -14.958538 3.895545 0.183814 34.800591 -3.985705 -2.733871 -20.089010 1.261625 0.516415 -15.021581 -5.641854 0.003195 34.841263 3.847504 2.482993 -20.182079 -1.485158 0.937012 +0.366416 40.489311 1.268677 0.000000 0.000000 0.000000 2.481632 1.055816 0.337326 9.339914 1.383152 -0.377746 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -12.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.154421 3.694816 -0.247410 -76.605659 -13.023010 17.491861 -14.516006 -12.303700 5.147697 19.969501 12.826900 -29.824301 -5.021900 -2.309700 -0.063400 78.026848 123.944138 16.023933 88.709946 51.111061 59.592224 -26.937437 5.436038 17.260193 -14.814727 3.864164 0.189718 34.623844 -3.980139 -2.728106 -20.048429 1.285248 0.539483 -14.889551 -5.653094 -0.022771 34.664970 3.841548 2.467632 -20.135452 -1.451684 0.943612 +0.371256 40.488655 1.296120 0.000000 0.000000 0.000000 2.466562 1.032696 0.330207 9.311522 1.379159 -0.378445 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -10.428469 0.000000 0.000000 0.000000 0.000000 0.000000 0.189820 3.723258 -0.251188 -77.171959 -12.792320 17.545477 -11.962116 -12.039910 6.198586 17.271996 12.878655 -29.763815 -5.021776 -2.310076 -0.063400 75.836334 125.719635 15.399824 86.757301 54.714401 58.781940 -27.221825 4.511591 17.077349 -14.708867 3.845149 0.187014 34.476730 -3.980046 -2.706854 -20.009493 1.281794 0.548186 -14.776694 -5.670719 -0.038029 34.517006 3.847430 2.457990 -20.096975 -1.441670 0.965440 +0.372516 40.474651 1.319620 0.000000 0.000000 0.000000 2.452723 1.011617 0.324179 9.284204 1.375839 -0.377540 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -8.784399 0.000000 0.000000 0.000000 0.000000 0.000000 0.217248 3.750563 -0.251179 -77.665184 -12.568201 17.594442 -10.605815 -11.781528 7.115973 13.581693 12.946978 -29.683973 -5.021824 -2.309930 -0.063400 72.449203 126.537743 14.710812 85.167786 57.684444 58.110138 -27.089233 3.724003 17.073463 -14.613861 3.826399 0.174992 34.349689 -3.975762 -2.685941 -19.979282 1.295568 0.540513 -14.686558 -5.683038 -0.055441 34.400597 3.831895 2.444445 -20.068710 -1.425470 0.987994 +0.370504 40.448589 1.339346 0.000000 0.000000 0.000000 2.440255 0.992591 0.319216 9.258366 1.373068 -0.375104 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -7.105315 0.000000 0.000000 0.000000 0.000000 0.000000 0.237271 3.776662 -0.247736 -78.088989 -12.350712 17.638878 -10.147392 -11.529716 7.906425 9.347685 13.029875 -29.587103 -5.021900 -2.309700 -0.063400 69.570602 127.018539 14.125336 83.923409 60.018955 57.581093 -26.892738 3.098502 17.107323 -14.599536 3.878110 0.181168 34.328194 -3.990550 -2.698359 -19.979706 1.288732 0.500246 -14.669394 -5.620616 -0.048702 34.381310 3.828123 2.441850 -20.056961 -1.453924 0.944230 +0.365528 40.411755 1.355467 0.000000 0.000000 0.000000 2.429299 0.975630 0.315292 9.234408 1.370717 -0.371211 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -5.428743 0.000000 0.000000 0.000000 0.000000 0.000000 0.250460 3.801484 -0.241213 -78.447037 -12.139909 17.678904 -10.287130 -11.285638 8.576517 5.019061 13.125356 -29.475529 -5.021900 -2.309700 -0.063400 73.798706 125.481270 13.983709 86.316650 62.175758 57.269646 -26.915070 3.089066 17.183762 -14.721113 3.878933 0.175655 34.711273 -3.994092 -2.729383 -20.233667 1.296727 0.514382 -14.823074 -5.653525 -0.060489 34.763096 3.839398 2.484272 -20.293854 -1.426211 0.926396 +0.357894 40.365437 1.368150 0.000000 0.000000 0.000000 2.419994 0.960746 0.312378 9.212735 1.368662 -0.365938 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -3.792208 0.000000 0.000000 0.000000 0.000000 0.000000 0.257384 3.824960 -0.231965 -78.742973 -11.935844 17.714636 -10.725321 -11.050448 9.132816 1.044910 13.231429 -29.351572 -5.021900 -2.309700 -0.063400 78.026802 123.944000 13.842083 88.709900 64.332558 56.958199 -26.937401 3.079630 17.260201 -14.973778 3.914565 0.182803 35.260956 -3.998872 -2.783688 -20.517836 1.290646 0.526560 -15.039925 -5.659194 -0.064251 35.301895 3.852282 2.539456 -20.597185 -1.428799 0.892717 +0.347910 40.310925 1.377564 0.000000 0.000000 0.000000 2.412483 0.947953 0.310449 9.193748 1.366774 -0.359358 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -2.233234 0.000000 0.000000 0.000000 0.000000 0.000000 0.258610 3.847019 -0.220347 -78.980438 -11.738571 17.746195 -11.211750 -10.825313 9.581894 -2.209444 13.346106 -29.217560 -5.022722 -2.310289 -0.063951 79.513344 120.986183 13.489099 90.864464 61.807667 56.652386 -23.479990 6.239428 17.368711 -15.206594 3.952240 0.179126 35.780098 -4.013735 -2.838864 -20.802189 1.280963 0.537835 -15.270244 -5.658063 -0.060353 35.801502 3.856096 2.609155 -20.879751 -1.449082 0.856026 +0.335882 40.249500 1.383878 0.000000 0.000000 0.000000 2.406903 0.937262 0.309477 9.177851 1.364928 -0.351545 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -0.789347 0.000000 0.000000 0.000000 0.000000 0.000000 0.254708 3.867593 -0.206713 -79.163101 -11.548143 17.773705 -11.694201 -10.611390 9.930320 -4.713735 13.467397 -29.075823 -5.024486 -2.311550 -0.065135 78.813690 116.015312 12.866486 93.264694 54.408951 56.287159 -16.067133 13.022047 17.534004 -15.468181 3.992053 0.186622 36.368549 -4.018920 -2.907182 -21.134935 1.279736 0.541431 -15.542678 -5.656614 -0.047022 36.409370 3.871837 2.651615 -21.212864 -1.445142 0.823141 +0.322118 40.182461 1.387260 0.000000 0.000000 0.000000 2.403397 0.928686 0.309437 9.165445 1.362998 -0.342575 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 0.501928 0.000000 0.000000 0.000000 0.000000 0.000000 0.246247 3.886611 -0.191417 -79.294609 -11.364614 17.797279 -12.169957 -10.409843 10.184664 -6.521460 13.593310 -28.928684 -5.026142 -2.312722 -0.066250 77.702171 111.426445 12.310102 95.200241 47.253178 55.990105 -9.188150 19.361095 17.687710 -15.699166 4.033385 0.191922 36.897160 -4.036395 -2.964453 -21.428762 1.274407 0.543805 -15.774418 -5.648846 -0.042848 36.938694 3.871413 2.721995 -21.505205 -1.465716 0.776337 +0.306924 40.111088 1.387879 0.000000 0.000000 0.000000 2.402104 0.922238 0.310301 9.156936 1.360857 -0.332522 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 1.603067 0.000000 0.000000 0.000000 0.000000 0.000000 0.233796 3.904004 -0.174814 -79.378624 -11.188036 17.817039 -12.636298 -10.221831 10.351497 -7.686117 13.721856 -28.778471 -5.026897 -2.313242 -0.066763 77.490158 108.958130 12.063833 96.168549 44.169567 55.849495 -6.163510 22.211990 17.772253 -15.999082 4.083937 0.189137 37.534286 -4.048579 -3.028998 -21.761480 1.272986 0.547356 -16.055788 -5.645681 -0.039578 37.565361 3.883478 2.794465 -21.846880 -1.480460 0.720135 +0.290608 40.036667 1.385903 0.000000 0.000000 0.000000 2.403165 0.917930 0.312042 9.152725 1.358379 -0.321461 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 2.476544 0.000000 0.000000 0.000000 0.000000 0.000000 0.217923 3.919701 -0.157259 -79.418793 -11.018466 17.833103 -13.090510 -10.048517 10.437390 -8.261203 13.851043 -28.627508 -5.026990 -2.313327 -0.066820 77.637245 107.722931 12.003706 96.498314 43.837303 55.796486 -5.638300 22.617388 17.773212 -16.259041 4.129948 0.195413 38.162357 -4.047410 -3.098453 -22.123762 1.267177 0.550370 -16.387779 -5.643609 -0.037560 38.242298 3.889014 2.850280 -22.199663 -1.474313 0.667820 +0.273476 39.960495 1.381500 0.000000 0.000000 0.000000 2.406720 0.915774 0.314635 9.153218 1.355437 -0.309466 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 3.084833 0.000000 0.000000 0.000000 0.000000 0.000000 0.199198 3.933634 -0.139105 -79.418755 -10.855956 17.845587 -13.529876 -9.891062 10.448916 -8.300215 13.978879 -28.478119 -5.026825 -2.313293 -0.066681 77.419144 106.560371 11.968391 96.608604 44.192265 55.753029 -5.592155 22.257479 17.700537 -16.598717 4.182109 0.193478 38.857918 -4.063268 -3.170222 -22.485996 1.261743 0.563201 -16.653557 -5.627158 -0.015970 38.800266 3.899232 2.917296 -22.491293 -1.506236 0.618471 +0.255836 39.883850 1.374840 0.000000 0.000000 0.000000 2.412910 0.915783 0.318051 9.158816 1.351905 -0.296612 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 3.390410 0.000000 0.000000 0.000000 0.000000 0.000000 0.178188 3.945730 -0.120707 -79.382172 -10.700560 17.854607 -13.951679 -9.750624 10.392644 -7.856650 14.103374 -28.332626 -5.026425 -2.313054 -0.066397 77.227386 105.843430 12.014954 96.448441 45.346977 55.761246 -6.018269 21.275324 17.618454 -16.918076 4.235004 0.190404 39.456261 -4.066819 -3.229622 -22.750420 1.255617 0.545443 -16.985838 -5.622664 -0.004533 39.486309 3.907112 2.984254 -22.842974 -1.517436 0.562577 +0.237995 39.808029 1.366089 0.000000 0.000000 0.000000 2.421875 0.917969 0.322266 9.169923 1.347656 -0.282973 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 3.355749 0.000000 0.000000 0.000000 0.000000 0.000000 0.155464 3.955922 -0.102420 -79.312698 -10.552332 17.860287 -14.353202 -9.628365 10.275142 -6.984005 14.222538 -28.193359 -5.025718 -2.312420 -0.065965 77.732437 106.328445 12.255054 95.849289 47.958134 55.893288 -7.413225 19.429691 17.604753 -17.207504 4.283559 0.196084 40.044853 -4.064497 -3.296125 -23.044178 1.249293 0.547492 -17.279152 -5.609540 0.007002 40.054592 3.909675 3.049968 -23.115492 -1.542176 0.514670 +0.220260 39.734314 1.355418 0.000000 0.000000 0.000000 2.433650 0.922283 0.327221 9.186719 1.342587 -0.268668 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 2.943326 0.000000 0.000000 0.000000 0.000000 0.000000 0.131593 3.964139 -0.084598 -79.213997 -10.411329 17.862745 -14.731727 -9.525445 10.102978 -5.735780 14.334383 -28.062647 -5.024685 -2.311307 -0.065397 79.315552 108.542458 12.745587 94.717659 52.353275 56.188251 -10.095977 16.604397 17.712915 -17.517443 4.333763 0.193127 40.672153 -4.072011 -3.359694 -23.366522 1.257434 0.543072 -17.591887 -5.597780 0.018129 40.701633 3.912494 3.112572 -23.447733 -1.551154 0.469091 +0.202938 39.663990 1.342994 0.000000 0.000000 0.000000 2.447850 0.928432 0.332742 9.208504 1.336680 -0.253985 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 2.115616 0.000000 0.000000 0.000000 0.000000 0.000000 0.107145 3.970311 -0.067596 -79.089729 -10.277606 17.862103 -15.084537 -9.443027 9.882725 -4.165473 14.436918 -27.942818 -5.023529 -2.310045 -0.064768 81.201149 112.095291 13.324380 93.260147 57.543385 56.552959 -13.674967 13.183434 17.899149 -17.797773 4.381806 0.188329 41.211178 -4.073674 -3.424606 -23.621241 1.248911 0.534410 -17.852732 -5.586558 0.030734 41.210499 3.929335 3.159597 -23.691616 -1.564342 0.414043 +0.186336 39.598351 1.328987 0.000000 0.000000 0.000000 2.463984 0.936059 0.338625 9.234356 1.329943 -0.239259 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 0.835093 0.000000 0.000000 0.000000 0.000000 0.000000 0.082688 3.974370 -0.051767 -78.943550 -10.151214 17.858477 -15.408918 -9.382270 9.620954 -2.326580 14.528153 -27.836197 -5.022508 -2.309068 -0.064166 82.324448 116.367477 13.774495 91.758362 62.210300 56.861187 -17.581011 9.675850 18.095346 -18.029648 4.422672 0.182408 41.662365 -4.077087 -3.462953 -23.836536 1.246138 0.526510 -18.094427 -5.569664 0.042209 41.671509 3.925839 3.206013 -23.925411 -1.582369 0.368079 +0.170762 39.538681 1.313564 0.000000 0.000000 0.000000 2.481561 0.944810 0.344664 9.263352 1.322381 -0.224820 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -0.910775 0.000000 0.000000 0.000000 0.000000 0.000000 0.058792 3.976244 -0.037467 -78.779114 -10.032207 17.851988 -15.702156 -9.344338 9.324237 -0.272599 14.606097 -27.745108 -5.021879 -2.308808 -0.063680 81.620667 120.739540 13.878994 90.493904 65.035873 56.986710 -21.244923 6.590691 18.233402 -18.259777 4.470821 0.176148 42.082985 -4.090118 -3.512167 -24.032516 1.238192 0.527036 -18.324871 -5.554928 0.055193 42.093399 3.920017 3.247798 -24.110317 -1.599590 0.332416 +0.156521 39.486271 1.296894 0.000000 0.000000 0.000000 2.500091 0.954328 0.350655 9.294571 1.313999 -0.211004 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -3.034539 0.000000 0.000000 0.000000 0.000000 0.000000 0.036025 3.975864 -0.025050 -78.600067 -9.920640 17.842752 -15.961532 -9.330393 8.999144 1.942973 14.668759 -27.671875 -5.021900 -2.309700 -0.063400 78.025040 124.591988 13.420940 89.748360 64.701958 56.803299 -24.097521 4.437000 18.245209 -18.450834 4.507500 0.188284 42.436092 -4.087636 -3.550210 -24.189676 1.223695 0.516125 -18.511780 -5.545627 0.059426 42.426033 3.931567 3.279114 -24.256811 -1.604909 0.290074 +0.143922 39.442406 1.279145 0.000000 0.000000 0.000000 2.519083 0.964260 0.356393 9.327088 1.304804 -0.198141 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -5.423756 0.000000 0.000000 0.000000 0.000000 0.000000 0.014956 3.973161 -0.014870 -78.410065 -9.816567 17.830891 -16.184328 -9.341592 8.652244 4.266639 14.714150 -27.618826 -5.022648 -2.311840 -0.063363 71.349663 127.472748 12.350361 89.656097 60.797337 56.276756 -25.793518 3.481084 18.103058 -18.614180 4.537719 0.190421 42.720459 -4.085540 -3.582736 -24.307722 1.208769 0.514213 -18.672356 -5.527201 0.083471 42.710224 3.930254 3.311513 -24.391024 -1.649929 0.258792 +0.133270 39.408375 1.260486 0.000000 0.000000 0.000000 2.538046 0.974248 0.361673 9.359983 1.294802 -0.186565 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -7.965983 0.000000 0.000000 0.000000 0.000000 0.000000 -0.003846 3.968065 -0.007282 -78.212761 -9.720043 17.816523 -16.367830 -9.379098 8.290108 6.644901 14.740280 -27.588289 -5.023475 -2.313975 -0.063400 64.914261 129.599304 11.285139 89.762634 56.538616 55.741016 -26.883230 3.018300 17.940851 -18.759132 4.564473 0.183342 42.945511 -4.093608 -3.604486 -24.395515 1.213360 0.506412 -18.810715 -5.511574 0.097847 42.925499 3.937011 3.331628 -24.468332 -1.665763 0.234635 +0.124875 39.385468 1.241086 0.000000 0.000000 0.000000 2.556490 0.983938 0.366290 9.392334 1.283999 -0.176610 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -10.548779 0.000000 0.000000 0.000000 0.000000 0.000000 -0.019812 3.960505 -0.002640 -78.011818 -9.631121 17.799768 -16.509321 -9.444072 7.919308 9.024263 14.745160 -27.582592 -5.023738 -2.314687 -0.063400 62.729130 130.433853 10.929173 89.765015 55.178059 55.563969 -27.347515 2.781850 17.890125 -18.845816 4.579628 0.184520 43.054131 -4.084472 -3.610073 -24.415415 1.206005 0.495268 -18.904743 -5.505463 0.104101 43.052917 3.938090 3.342460 -24.507454 -1.666292 0.214396 +0.119041 39.374969 1.221113 0.000000 0.000000 0.000000 2.573925 0.992974 0.370041 9.423216 1.272401 -0.168606 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -13.059700 0.000000 0.000000 0.000000 0.000000 0.000000 -0.032374 3.950413 -0.001298 -77.810875 -9.549855 17.780745 -16.606083 -9.537675 7.546412 11.351228 14.726797 -27.604057 -5.024000 -2.315400 -0.063400 60.543999 131.268402 10.573206 89.767387 53.817501 55.386921 -27.811800 2.545400 17.839399 -18.903521 4.590088 0.185232 43.112717 -4.088158 -3.616357 -24.415493 1.204351 0.494911 -18.959044 -5.496031 0.111961 43.082287 3.938787 3.345120 -24.477486 -1.675655 0.203033 +0.116078 39.378166 1.200735 0.000000 0.000000 0.000000 2.589860 1.001002 0.372719 9.451707 1.260014 -0.162889 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -15.401827 0.000000 0.000000 0.000000 0.000000 0.000000 -0.040963 3.937717 -0.003612 -77.613594 -9.476300 17.759571 -16.655399 -9.661066 7.177991 13.572296 14.683200 -27.655012 -5.023981 -2.315349 -0.063400 60.698307 128.643433 9.471822 90.324951 51.451027 55.181625 -23.781614 4.472782 17.608641 -18.901751 4.597549 0.184269 43.024490 -4.091703 -3.600640 -24.327942 1.194561 0.482065 -18.954710 -5.481573 0.129527 43.003689 3.940713 3.339420 -24.417456 -1.695583 0.209378 +0.116291 39.396351 1.180121 0.000000 0.000000 0.000000 2.603803 1.007665 0.374120 9.476884 1.246843 -0.159790 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -17.540323 0.000000 0.000000 0.000000 0.000000 0.000000 -0.045009 3.922349 -0.009936 -77.423630 -9.410508 17.736370 -16.654556 -9.815409 6.820615 15.633970 14.612378 -27.737780 -5.023697 -2.314578 -0.063400 63.057266 122.353828 8.370438 91.493622 47.748451 54.915382 -14.885859 8.740479 17.171288 -18.851578 4.594066 0.192632 42.838024 -4.092330 -3.585344 -24.191774 1.178803 0.486958 -18.846006 -5.474198 0.141279 42.680202 3.947728 3.296161 -24.201996 -1.696504 0.222260 +0.119987 39.430805 1.159440 0.000000 0.000000 0.000000 2.615265 1.012608 0.374040 9.497825 1.232896 -0.159642 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -19.455875 0.000000 0.000000 0.000000 0.000000 0.000000 -0.043945 3.904238 -0.020623 -77.244629 -9.352536 17.711256 -16.600834 -10.001863 6.480855 17.482754 14.512341 -27.854687 -5.023273 -2.313425 -0.063400 66.586273 114.286201 7.269053 92.950325 43.496952 54.630955 -3.667848 14.125954 16.639532 -18.676186 4.568695 0.199322 42.387501 -4.077050 -3.551976 -23.917519 1.188832 0.466616 -18.735699 -5.469298 0.143772 42.376308 3.945399 3.270483 -24.006184 -1.696306 0.254612 +0.127474 39.482822 1.138859 0.000000 0.000000 0.000000 2.623754 1.015476 0.372274 9.513606 1.218176 -0.162778 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -21.129169 0.000000 0.000000 0.000000 0.000000 0.000000 -0.037200 3.883314 -0.036029 -77.080246 -9.302437 17.684347 -16.491516 -10.221590 6.165281 19.065147 14.381099 -28.008055 -5.022784 -2.312101 -0.063400 70.639137 105.512573 6.167669 94.516426 39.086102 54.346024 8.449615 19.944832 16.073730 -18.511898 4.542353 0.196760 41.975258 -4.082853 -3.510315 -23.673023 1.189494 0.464112 -18.564541 -5.466923 0.157985 41.945683 3.946064 3.206509 -23.740782 -1.711459 0.284767 +0.139059 39.553688 1.118547 0.000000 0.000000 0.000000 2.628780 1.015913 0.368617 9.523306 1.202692 -0.169531 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -22.540894 0.000000 0.000000 0.000000 0.000000 0.000000 -0.024207 3.859507 -0.056508 -76.934135 -9.260263 17.655762 -16.323889 -10.475752 5.880464 20.327656 14.216660 -28.200212 -5.022301 -2.310788 -0.063400 74.659927 96.988480 5.066284 96.031006 34.882984 54.078640 20.190653 25.583574 15.528855 -18.280136 4.500884 0.203175 41.388119 -4.070134 -3.437868 -23.330322 1.198648 0.452548 -18.328173 -5.472520 0.153886 41.366840 3.946489 3.158993 -23.398420 -1.705846 0.320834 +0.155049 39.644691 1.098673 0.000000 0.000000 0.000000 2.629853 1.013564 0.362864 9.526002 1.186448 -0.180234 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -23.671732 0.000000 0.000000 0.000000 0.000000 0.000000 -0.004396 3.832749 -0.082414 -76.809952 -9.226069 17.625622 -16.095236 -10.765510 5.632976 21.216780 14.017037 -28.433487 -5.021900 -2.309700 -0.063400 77.991402 89.963379 3.964900 97.277763 31.436552 53.860298 29.860201 30.227600 15.080831 -17.921957 4.445969 0.196022 40.554836 -4.070414 -3.339819 -22.842096 1.183457 0.444155 -17.981892 -5.472805 0.162864 40.543510 3.944207 3.072200 -22.928007 -1.710387 0.385768 +0.175751 39.757122 1.079406 0.000000 0.000000 0.000000 2.626482 1.008074 0.354810 9.520771 1.169451 -0.195220 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -24.502375 0.000000 0.000000 0.000000 0.000000 0.000000 0.022801 3.802968 -0.114101 -76.711357 -9.199909 17.594048 -15.802838 -11.092022 5.429384 21.679022 13.780240 -28.710205 -5.021900 -2.309700 -0.063400 77.989197 83.275948 3.211200 91.376068 27.412739 53.666672 26.660051 28.424351 12.565763 -17.494652 4.379107 0.207461 39.564552 -4.059392 -3.245574 -22.293739 1.197094 0.450549 -17.493464 -5.465701 0.164459 39.515686 3.924719 2.953765 -22.389896 -1.702015 0.464099 +0.201471 39.892262 1.060913 0.000000 0.000000 0.000000 2.618176 0.999086 0.344252 9.506692 1.151706 -0.214821 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -25.013510 0.000000 0.000000 0.000000 0.000000 0.000000 0.057954 3.770097 -0.151925 -76.642021 -9.181838 17.561157 -15.443975 -11.456450 5.276260 21.660887 13.504279 -29.032698 -5.021900 -2.309700 -0.063400 77.987000 76.588516 2.457500 85.474380 23.388926 53.473049 23.459902 26.621099 10.050696 -16.912848 4.293337 0.195306 38.299400 -4.060330 -3.094315 -21.609102 1.196628 0.433290 -16.967489 -5.473960 0.158502 38.299992 3.919222 2.825309 -21.705282 -1.686927 0.545865 +0.232518 40.051399 1.043363 0.000000 0.000000 0.000000 2.604446 0.986247 0.330983 9.482842 1.133221 -0.239370 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -25.185823 0.000000 0.000000 0.000000 0.000000 0.000000 0.101631 3.734064 -0.196240 -76.605583 -9.171907 17.527069 -15.015934 -11.859956 5.180175 21.108879 13.187162 -29.403290 -5.021900 -2.309700 -0.063400 77.984802 69.901085 1.703800 79.572693 19.365112 53.279427 20.259750 24.817848 7.535629 -16.313028 4.191906 0.201806 36.888084 -4.031963 -2.952595 -20.806345 1.208274 0.417027 -16.366299 -5.484231 0.144368 36.888947 3.897809 2.677895 -20.913908 -1.657658 0.660998 +0.269198 40.235828 1.026926 0.000000 0.000000 0.000000 2.584800 0.969200 0.314800 9.448300 1.114000 -0.269200 0.000000 0.000000 0.000000 22.000000 0.000000 0.000000 -25.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.154400 3.694800 -0.247400 -76.605698 -9.170176 17.491899 -14.516000 -12.303700 5.147700 19.969500 12.826900 -29.824301 -5.021900 -2.309700 -0.063400 77.982597 63.213654 0.950100 73.670998 15.341300 53.085800 17.059601 23.014599 5.020561 -15.916009 4.090882 0.195659 36.055382 -4.008984 -2.869552 -20.385242 1.215727 0.452869 -15.970601 -5.525442 0.147951 36.065128 3.895652 2.583573 -20.484213 -1.639068 0.758667 +0.311369 40.444775 1.011730 0.000000 0.000000 0.000000 2.559196 0.947920 0.295730 9.402960 1.094143 -0.304228 0.000000 0.000000 0.000000 21.407406 0.000000 0.000000 -24.458569 0.000000 0.000000 0.000000 0.000000 0.000000 0.216112 3.652526 -0.305198 -76.643471 -9.176294 17.455902 -13.947018 -12.785302 5.181056 18.232313 12.425101 -30.293850 -5.068048 -2.306993 -0.071010 77.617317 55.983643 0.586592 66.522591 13.722964 49.821491 12.800263 21.630960 1.948322 -15.447251 3.995199 0.185514 35.044647 -4.002907 -2.758178 -19.845861 1.236780 0.470229 -15.509201 -5.566498 0.132997 35.073273 3.894467 2.495605 -19.947491 -1.610598 0.849733 +0.357066 40.669189 0.997658 0.000000 0.000000 0.000000 2.529492 0.923765 0.274763 9.350167 1.074073 -0.342661 0.000000 0.000000 0.000000 20.162960 0.000000 0.000000 -23.661045 0.000000 0.000000 0.000000 0.000000 0.000000 0.283661 3.608575 -0.367169 -76.708801 -9.188096 17.419771 -13.334341 -13.288659 5.263038 16.072577 11.997733 -30.793274 -5.164957 -2.301308 -0.086990 76.852280 47.028297 0.525109 57.006901 14.071634 43.146763 6.835794 20.404598 -2.161224 -14.427745 3.841285 0.176552 32.859039 -3.945449 -2.531689 -18.681004 1.240888 0.457816 -14.493304 -5.573404 0.108610 32.896667 3.855606 2.267344 -18.783842 -1.578388 0.998787 +0.404033 40.898682 0.984589 0.000000 0.000000 0.000000 2.497821 0.898300 0.253037 9.293777 1.054288 -0.382439 0.000000 0.000000 0.000000 18.611105 0.000000 0.000000 -22.718649 0.000000 0.000000 0.000000 0.000000 0.000000 0.353483 3.564484 -0.430479 -76.790154 -9.203237 17.384308 -12.706887 -13.795239 5.373975 13.691399 11.563153 -31.301125 -5.285805 -2.294219 -0.106918 75.898849 37.658260 0.651023 46.726902 15.587980 34.875263 0.258118 19.359985 -6.609907 -13.376683 3.689278 0.164035 30.505575 -3.891205 -2.268284 -17.399187 1.232049 0.422760 -13.388244 -5.568290 0.084606 30.484524 3.798897 2.020113 -17.484383 -1.526641 1.161788 +0.450133 41.123314 0.972504 0.000000 0.000000 0.000000 2.466127 0.872966 0.231617 9.237292 1.035317 -0.421630 0.000000 0.000000 0.000000 16.942413 0.000000 0.000000 -21.728205 0.000000 0.000000 0.000000 0.000000 0.000000 0.422226 3.521784 -0.492415 -76.877586 -9.219704 17.350395 -12.092223 -14.286720 5.497095 11.268101 11.139092 -31.796688 -5.415751 -2.286596 -0.128347 74.873901 28.372833 0.875462 36.370174 17.693880 26.003878 -6.436709 18.449766 -11.096389 -12.225321 3.529493 0.144813 28.072163 -3.822703 -2.029018 -16.125780 1.236680 0.389977 -12.248204 -5.561399 0.053093 28.032803 3.728593 1.771268 -16.173323 -1.492766 1.330889 +0.492997 41.331909 0.961587 0.000000 0.000000 0.000000 2.436398 0.849265 0.211661 9.184286 1.017871 -0.458133 0.000000 0.000000 0.000000 15.328519 0.000000 0.000000 -20.779242 0.000000 0.000000 0.000000 0.000000 0.000000 0.486233 3.482328 -0.549915 -76.962128 -9.235703 17.319248 -11.521231 -14.741232 5.617670 8.978033 10.745872 -32.256207 -5.541432 -2.279224 -0.149072 73.882736 19.701412 1.127370 26.626308 19.916624 17.432743 -12.763790 17.652790 -15.319304 -11.079326 3.375834 0.131961 25.590658 -3.730510 -1.776320 -14.794729 1.219017 0.353377 -11.157713 -5.551943 0.029133 25.677666 3.654841 1.543418 -14.910841 -1.459330 1.469368 +0.527912 41.501766 0.952765 0.000000 0.000000 0.000000 2.412123 0.829926 0.195397 9.141000 1.003703 -0.487881 0.000000 0.000000 0.000000 14.000000 0.000000 0.000000 -20.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.538390 3.450245 -0.596733 -77.031731 -9.248889 17.293959 -11.056236 -15.110909 5.717247 7.104405 10.425808 -32.630241 -5.644889 -2.273156 -0.166132 73.066849 12.629538 1.342199 18.663837 21.786192 10.379103 -17.940399 17.014599 -18.770599 -10.096684 3.248585 0.113217 23.479816 -3.651798 -1.568336 -13.687186 1.217914 0.321836 -10.166306 -5.527973 0.013141 23.567812 3.580069 1.317980 -13.796142 -1.415725 1.616001 diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_embarrased.bvh b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_embarrased.bvh new file mode 100644 index 00000000..0d1357c0 --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_embarrased.bvh @@ -0,0 +1,174 @@ +HIERARCHY +ROOT hip +{ + OFFSET 0.00 0.00 0.00 + CHANNELS 6 Xposition Yposition Zposition Xrotation Zrotation Yrotation + JOINT abdomen + { + OFFSET 0.000000 0.000000 0.000000 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT chest + { + OFFSET 0.000000 5.018152 -1.882228 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT neckDummy + { + OFFSET 0.000000 8.316447 0.784897 + CHANNELS 3 Xrotation Yrotation Zrotation + JOINT neck + { + OFFSET 0.000000 2.280413 -0.392801 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT head + { + OFFSET 0.000000 3.496879 0.529469 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT figureHair + { + OFFSET 0.000000 4.699570 0.720622 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 0.000000 -6.419331 0.000000 + } + } + } + } + } + JOINT lCollar + { + OFFSET 0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lShldr + { + OFFSET 6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT lForeArm + { + OFFSET 10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lHand + { + OFFSET 11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 10.353753 0.000000 0.000000 + } + } + } + } + } + JOINT rCollar + { + OFFSET -0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rShldr + { + OFFSET -6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT rForeArm + { + OFFSET -10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rHand + { + OFFSET -11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET -10.353753 0.000000 0.000000 + } + } + } + } + } + } + } + JOINT lThigh + { + OFFSET 4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lShin + { + OFFSET -1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lFoot + { + OFFSET -0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } + JOINT rThigh + { + OFFSET -4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rShin + { + OFFSET 1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rFoot + { + OFFSET 0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } +} +MOTION +Frames: 45 +Frame Time: 0.066667 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -70.100700 9.978770 15.991600 -22.515600 -9.303740 0.147736 5.969490 -0.173112 0.175734 -2.021920 5.690310 -0.063351 70.100700 -9.978770 15.991600 22.515600 9.303740 0.147736 -5.969490 0.173112 0.175734 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.530616 -4.334307 0.100752 15.830232 3.319340 0.622262 -8.660608 -1.559428 0.936809 +0.039814 41.899296 0.241190 0.000000 0.000000 -0.501519 0.080437 -0.040918 -0.185089 0.076089 -0.047977 0.086760 0.000000 0.000000 0.000000 1.543135 0.000000 0.000000 -1.337809 0.013589 -0.084929 0.000000 0.000000 0.000000 1.698423 -6.145940 -0.170759 -69.713493 10.010641 15.406242 -21.605762 -9.211841 -0.046929 8.410601 -5.364861 -0.319513 -0.776169 5.691003 -0.063361 70.377159 -7.381076 15.714259 39.191650 5.745263 0.147736 9.688475 1.353782 -1.636086 -8.434450 4.282907 0.126939 17.845293 -3.418611 -3.342519 -9.443543 1.141979 -0.628322 -8.724339 -4.317830 0.098728 18.069643 3.376410 3.702412 -9.394203 -1.296290 1.260884 +0.089033 41.756374 0.242611 0.000000 0.000000 -1.031836 0.170631 -0.089783 -0.366195 0.160111 -0.108203 0.144972 0.000000 0.000000 0.000000 3.452946 0.000000 0.000000 -2.996245 0.028841 -0.180255 0.000000 0.000000 0.000000 1.353956 -6.713018 -0.295988 -69.194130 10.026111 14.734116 -20.453989 -9.016167 -0.262993 11.011240 -11.341043 -0.829138 0.770202 5.764425 -0.063373 70.640648 -4.160726 15.355293 59.582611 1.390090 0.147736 28.328529 2.797449 -3.793892 -9.450768 4.590892 0.106941 20.059561 -3.476677 -6.451475 -10.327104 1.153454 -0.276719 -10.037220 -4.262142 0.071489 20.498079 3.364482 7.514089 -10.060794 -1.072294 1.595087 +0.152735 41.571396 0.244451 0.000000 0.000000 -0.846192 0.197459 -0.136292 -0.136715 0.171204 -0.195037 -0.256536 0.000000 0.000000 0.000000 5.945064 0.000000 0.000000 -5.186948 0.033540 -0.209627 0.000000 0.000000 0.000000 1.447323 -7.483898 -0.384617 -68.126434 9.813471 14.365194 -18.701052 -7.965080 -0.303546 10.320845 -14.776716 -0.490915 2.832814 6.564942 -0.063391 70.220604 0.093946 14.734175 83.786072 -3.818466 0.147736 45.479752 4.510845 -5.788650 -10.643839 4.978059 0.074565 22.449301 -3.467690 -10.473202 -11.090033 0.289025 0.194043 -11.529180 -4.114105 0.043295 23.422285 3.258556 12.424737 -10.827029 -1.627814 1.965040 +0.236278 41.328808 0.246863 0.000000 0.000000 0.277499 0.126242 -0.196218 0.491244 0.041446 -0.346489 -1.135812 0.000000 0.000000 0.000000 9.234416 0.000000 0.000000 -8.113848 0.019523 -0.122022 0.000000 0.000000 0.000000 2.016382 -8.166621 -0.401768 -66.648834 9.373969 14.484484 -16.131882 -5.597216 -0.018365 3.986723 -13.372799 1.258861 5.612359 8.044829 -0.063414 69.215096 5.807666 13.831058 111.841072 -9.864959 0.147736 58.326874 6.496727 -7.313967 -12.277314 5.509349 -0.001191 25.453333 -3.451756 -15.734137 -11.828375 -1.801828 0.926675 -13.106681 -3.834708 0.010947 26.704674 3.028259 18.804417 -11.575487 -3.229861 2.358238 +0.322353 41.078865 0.249349 0.000000 0.000000 0.000000 0.107429 -0.379944 -0.468471 -0.204512 -0.658627 -0.488950 0.000000 0.000000 0.000000 12.592593 0.000000 0.000000 -11.111111 0.000000 0.000000 0.000000 0.000000 0.000000 1.132182 -6.626923 -0.391431 -67.699158 9.747208 14.364408 -13.883741 -3.372201 0.461128 -3.827750 -9.628258 3.204261 8.450939 6.724223 -0.063427 71.304001 11.827765 13.572943 135.515594 -14.696260 0.147736 67.477890 8.173111 -8.495905 -13.575980 5.950140 -0.092779 28.163332 -3.325263 -21.057272 -12.544304 -2.530447 1.782613 -14.755357 -3.507474 -0.055722 29.778540 2.653540 25.256170 -11.854495 -3.430288 2.808297 +0.391381 40.878422 0.251342 0.000000 0.000000 -3.708260 0.275930 -0.762068 -4.633492 -0.510066 -1.180497 3.269981 0.000000 0.000000 0.000000 15.210903 0.000000 0.000000 -13.439645 -0.010435 0.065217 0.000000 0.000000 0.000000 -2.728906 -1.332951 -0.402916 -73.533775 11.750221 13.354638 -13.060403 -2.744397 1.176265 -8.517013 -6.617537 4.058332 10.623753 -0.111750 -0.063418 79.310555 16.811852 14.721362 147.208282 -16.482080 0.147735 74.162857 9.002047 -9.507215 -13.972370 6.134489 -0.173463 30.142418 -3.175998 -25.162302 -13.696976 0.342596 2.697333 -16.380077 -3.290063 -0.111433 32.075344 2.295804 30.232996 -11.151580 -0.131768 3.219561 +0.437374 40.744869 0.252670 0.000000 0.000000 -9.076838 0.519381 -1.179417 -10.173292 -0.783346 -1.715001 8.033052 0.000000 0.000000 0.000000 16.902855 0.000000 0.000000 -14.937064 -0.013018 0.081365 0.000000 0.000000 0.000000 -7.502430 4.995176 -0.427956 -80.883812 14.271429 12.026385 -13.279365 -3.226116 3.141023 -10.222770 -4.918960 4.029654 11.996926 -8.685838 -0.063397 89.049713 20.236025 16.429125 150.111420 -16.321115 0.147736 78.676651 9.206444 -10.274950 -13.732016 6.056817 -0.203365 31.440699 -3.056568 -27.818184 -15.151702 5.158724 3.605977 -17.671932 -3.125036 -0.154059 33.334335 2.021921 33.398579 -9.794173 4.892537 3.543650 +0.459448 40.680775 0.253308 0.000000 0.000000 -13.874084 0.697151 -1.455288 -14.893601 -0.946842 -2.058257 11.367829 0.000000 0.000000 0.000000 17.690443 0.000000 0.000000 -15.630610 -0.012227 0.076416 0.000000 0.000000 0.000000 -10.815484 9.332779 -0.448062 -86.019188 16.032480 11.084456 -13.894051 -3.995624 7.250385 -10.141155 -4.428786 3.621523 12.621324 -14.667305 -0.063381 95.769180 21.927347 17.686445 149.292892 -15.747929 0.147744 81.172073 9.142193 -10.705463 -13.293406 5.838333 -0.190106 32.102772 -3.002146 -29.044096 -16.443802 9.641053 4.353858 -18.519234 -3.030650 -0.182216 33.902229 1.899208 34.872696 -8.542339 9.466275 3.627312 +0.464512 40.666069 0.253454 0.000000 0.000000 -17.883171 0.807047 -1.604288 -18.661230 -1.021021 -2.235370 13.322445 0.000000 0.000000 0.000000 17.843428 0.000000 0.000000 -15.761244 -0.009739 0.060870 0.000000 0.000000 0.000000 -12.734796 11.802892 -0.461855 -89.020905 17.061476 10.523019 -14.681281 -4.836326 12.887268 -8.993822 -4.766160 3.028580 12.725297 -18.156483 -0.063370 99.630508 22.369762 18.471334 146.622391 -15.112501 0.147757 82.252151 8.942979 -10.882832 -12.714261 5.544820 -0.148182 32.186352 -2.986802 -29.277328 -17.443403 13.558492 4.862410 -18.980970 -2.985097 -0.198651 33.886356 1.882450 35.157616 -7.482285 13.353349 3.562209 +0.460082 40.678932 0.253326 0.000000 0.000000 -21.326618 0.876069 -1.678765 -21.781054 -1.043758 -2.315491 14.455241 0.000000 0.000000 0.000000 17.643372 0.000000 0.000000 -15.578891 -0.006405 0.040031 0.000000 0.000000 0.000000 -13.826016 13.166821 -0.471727 -90.752800 17.654829 10.188898 -15.536903 -5.688068 19.173975 -7.300369 -5.546037 2.354053 12.540463 -20.162970 -0.063362 101.796165 22.112682 18.971060 143.025406 -14.464108 0.147772 82.520241 8.676402 -10.915497 -12.128986 5.241267 -0.110492 31.995041 -3.026831 -28.966869 -18.246965 17.038897 5.254713 -19.211849 -2.957827 -0.212114 33.561810 1.916283 34.773254 -6.610342 16.746107 3.412826 +0.451933 40.702595 0.253091 0.000000 0.000000 -24.317600 0.923594 -1.717250 -24.434000 -1.043437 -2.349816 15.171728 0.000000 0.000000 0.000000 17.307249 0.000000 0.000000 -15.276217 -0.002922 0.018264 0.000000 0.000000 0.000000 -14.500880 13.980410 -0.479336 -91.842598 18.027945 9.971223 -16.367998 -6.491399 25.342457 -5.482647 -6.463499 1.687219 12.245640 -21.420691 -0.063356 103.113548 21.577330 19.319685 139.262695 -13.850647 0.147787 82.430008 8.398090 -10.885249 -11.569575 4.922412 -0.053521 31.653347 -3.040873 -28.436520 -18.893555 20.113087 5.555738 -19.321302 -2.950808 -0.218092 33.103703 2.003809 34.145603 -5.862864 19.747831 3.236964 +0.444397 40.724476 0.252873 0.000000 0.000000 -26.706978 0.958596 -1.741741 -26.539749 -1.038392 -2.368821 15.680286 0.000000 0.000000 0.000000 17.000000 0.000000 0.000000 -15.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -14.974874 14.541804 -0.485183 -92.614288 18.292067 9.814640 -17.052900 -7.148300 30.439100 -3.947800 -7.253700 1.135200 11.978081 -22.309690 -0.063351 104.031441 21.075205 19.577801 136.104507 -13.348584 0.147800 82.280853 8.164600 -10.847100 -11.125762 4.659925 -0.018511 31.359020 -3.066173 -27.950672 -19.403463 22.576035 5.809713 -19.453791 -2.920936 -0.227311 32.841743 2.038306 33.560890 -5.332605 22.132433 3.035631 +0.443225 40.727879 0.252839 0.200000 -0.200000 -28.082533 1.073241 -1.611276 -27.871878 -1.133323 -2.161842 16.879065 0.000000 0.000000 0.000000 16.250370 0.000000 0.000000 -13.758941 -1.289352 2.462991 0.000000 0.000000 0.000000 -15.422813 16.192276 -0.433638 -94.454033 19.211071 9.318990 -17.052908 -7.148307 30.439096 -3.947803 -7.253709 1.135194 11.910701 -24.059505 -0.063471 105.831177 20.770346 18.435923 136.104507 -12.703799 0.147801 82.031624 8.164605 -10.847102 -11.084137 4.837399 -0.045725 31.467707 -3.063722 -27.899378 -19.850582 23.915907 6.019325 -19.511450 -2.567319 -0.278522 32.461876 2.062439 33.460968 -4.833064 23.410805 2.971002 +0.442053 40.731281 0.252805 0.400000 -0.400000 -29.458088 1.187886 -1.480810 -29.204006 -1.228254 -1.954862 18.077843 0.000000 0.000000 0.000000 15.500741 0.000000 0.000000 -12.517881 -2.578703 4.925982 0.000000 0.000000 0.000000 -15.870752 17.842747 -0.382093 -96.293777 20.130075 8.823339 -17.052917 -7.148314 30.439093 -3.947806 -7.253719 1.135188 11.843321 -25.809320 -0.063591 107.630913 20.465487 17.294044 136.104507 -12.059014 0.147802 81.782394 8.164610 -10.847104 -11.053614 5.007577 -0.071310 31.576910 -3.063643 -27.857309 -20.298296 25.261049 6.242358 -19.562288 -2.211441 -0.338894 32.090645 2.077425 33.378960 -4.342978 24.683500 2.939901 +0.440881 40.734688 0.252771 0.600000 -0.600000 -30.833643 1.302530 -1.350345 -30.536135 -1.323185 -1.747883 19.276623 0.000000 0.000000 0.000000 14.751112 0.000000 0.000000 -11.276822 -3.868055 7.388972 0.000000 0.000000 0.000000 -16.318691 19.493219 -0.330548 -98.133530 21.049080 8.327689 -17.052925 -7.148322 30.439089 -3.947809 -7.253728 1.135182 11.775942 -27.559135 -0.063711 109.430649 20.160627 16.152166 136.104507 -11.414229 0.147803 81.533165 8.164616 -10.847106 -11.004392 5.191419 -0.108309 31.685549 -3.068331 -27.807384 -20.749128 26.598074 6.466248 -19.560669 -1.833741 -0.389548 31.651302 2.096663 33.284470 -3.828803 25.959257 2.894242 +0.439709 40.738091 0.252738 0.800000 -0.800000 -32.209198 1.417175 -1.219879 -31.868263 -1.418116 -1.540903 20.475403 0.000000 0.000000 0.000000 14.001483 0.000000 0.000000 -10.035763 -5.157406 9.851963 0.000000 0.000000 0.000000 -16.766632 21.143692 -0.279004 -99.973282 21.968084 7.832039 -17.052933 -7.148329 30.439083 -3.947811 -7.253738 1.135176 11.708563 -29.308952 -0.063830 111.230377 19.855768 15.010288 136.104523 -10.769444 0.147803 81.283936 8.164621 -10.847107 -10.957583 5.361717 -0.135559 31.833452 -3.069676 -27.778009 -21.245178 27.948532 6.728825 -19.570843 -1.457111 -0.450552 31.252838 2.099632 33.195946 -3.318430 27.245663 2.822287 +0.438537 40.741493 0.252704 1.000000 -1.000000 -33.584755 1.531820 -1.089413 -33.200394 -1.513047 -1.333923 21.674181 0.000000 0.000000 0.000000 13.251854 0.000000 0.000000 -8.794704 -6.446758 12.314954 0.000000 0.000000 0.000000 -17.214571 22.794163 -0.227459 -101.813026 22.887089 7.336388 -17.052942 -7.148335 30.439079 -3.947814 -7.253747 1.135170 11.641183 -30.000000 -0.063950 113.030113 19.550909 13.868409 136.104523 -10.124660 0.147804 81.034698 8.164626 -10.847109 -10.879811 5.544608 -0.163078 31.932899 -3.066984 -27.734819 -21.718058 29.288513 6.974961 -19.622885 -1.080372 -0.514288 30.979832 2.136173 33.122868 -2.830688 28.514160 2.707527 +0.439474 40.741482 0.248964 0.891030 -0.891030 -34.456684 1.597484 -1.055714 -34.025394 -1.600788 -1.274902 22.220331 0.000000 0.000000 0.000000 13.046968 0.000000 0.000000 -7.395352 -6.481889 16.260767 0.000000 0.000000 0.000000 -17.439814 20.521940 -0.374703 -101.639893 23.537153 7.133646 -16.549248 -7.007628 35.139809 -3.693110 -6.844335 1.108464 11.474746 -26.418991 -0.064141 107.007828 19.601173 11.233108 136.187439 -9.541294 0.147804 77.942612 8.149011 -10.836998 -10.652431 5.270885 -0.120197 31.775898 -3.065546 -27.743917 -21.912508 30.156275 7.148563 -19.703762 -1.212122 -0.495282 31.057205 2.145386 33.158161 -2.618176 29.395966 2.600384 +0.440249 40.741936 0.245220 0.459838 -0.459838 -34.939415 1.626854 -1.105960 -34.514900 -1.635415 -1.395581 22.301561 0.000000 0.000000 0.000000 14.049818 0.000000 0.000000 -5.373023 -5.328621 21.793983 0.000000 0.000000 0.000000 -17.301842 13.903116 -0.764093 -99.240189 24.052284 7.133935 -15.450068 -6.859040 45.857651 -2.866984 -6.324612 0.987807 11.416395 -14.446802 -0.064416 92.345406 19.935740 6.536719 136.328400 -8.863396 0.147787 70.751984 8.135279 -10.821810 -10.280283 4.520496 -0.001724 31.420290 -3.063262 -27.828537 -21.903217 30.673986 7.321356 -19.822660 -1.865006 -0.391505 31.474737 2.098708 33.323822 -2.651770 29.991522 2.504657 +0.435177 40.751251 0.252607 0.000000 0.000000 -34.928368 1.626446 -1.173623 -34.687962 -1.487629 -1.676875 22.279297 0.000000 0.000000 0.000000 17.000000 0.000000 0.000000 -3.198930 -4.000000 25.000000 0.000000 0.000000 0.000000 -16.587980 6.948016 -1.201141 -95.932907 24.347652 7.134810 -14.373280 -7.112891 57.516087 -1.376421 -6.757378 0.712382 11.975971 -2.000000 -0.064599 78.198914 20.144346 2.024292 136.365814 -8.248498 0.147736 62.030510 8.173111 -10.824266 -9.823216 3.758822 0.108958 30.771587 -3.065833 -27.913715 -21.555408 30.684587 7.306053 -19.940411 -2.605087 -0.276388 32.019329 2.065034 33.507626 -2.861785 30.101583 2.429578 +0.421064 40.774040 0.277511 -0.255278 0.255278 -34.328850 1.611664 -1.207529 -34.572216 -1.065917 -2.095243 22.425764 0.000000 0.000000 0.000000 22.343418 0.000000 0.000000 -1.229210 -3.298606 22.972792 0.000000 0.000000 0.000000 -15.169353 2.844899 -1.529837 -92.815834 24.358356 6.980086 -13.806469 -8.058139 66.021072 0.792933 -8.875546 0.245702 13.512051 5.469095 -0.064555 71.766869 19.913652 -0.532650 136.187302 -7.815894 0.147637 53.916225 8.294292 -10.861056 -9.484675 3.397242 0.151580 30.211863 -3.065088 -27.917633 -21.070120 30.020897 7.113064 -19.831112 -3.045026 -0.212173 32.195076 2.049767 33.598469 -3.165616 29.572861 2.485369 +0.404704 40.799782 0.307321 -0.314271 0.314271 -33.085739 1.633463 -1.217941 -34.229607 -0.429915 -2.609335 22.656399 0.000000 0.000000 0.000000 29.351212 0.000000 0.000000 0.640299 -3.185144 16.840670 0.000000 0.000000 0.000000 -13.252295 1.493759 -1.748087 -90.102058 24.099243 6.698617 -13.716088 -9.498306 71.208527 3.340781 -12.092505 -0.351397 15.778172 8.130061 -0.064322 72.417526 19.318024 -1.256674 135.877441 -7.531899 0.147504 46.828590 8.459020 -10.924747 -9.416102 3.446296 0.137911 29.926901 -3.070609 -27.920759 -20.550138 28.691727 6.801458 -19.581873 -3.190480 -0.184551 32.135532 2.048406 33.614986 -3.559412 28.340677 2.635011 +0.395389 40.814163 0.324680 -0.245626 0.245626 -31.153795 1.751685 -1.230480 -33.730648 0.322956 -3.173349 22.797438 0.000000 0.000000 0.000000 37.000824 0.000000 0.000000 2.628833 -3.409849 8.740512 0.000000 0.000000 0.000000 -11.126942 1.972520 -1.892272 -87.783470 23.605091 6.365511 -13.938302 -11.115559 73.896835 5.888166 -15.491755 -0.993747 18.376617 7.557948 -0.063981 77.561531 18.528736 -0.743865 135.570007 -7.324585 0.147357 40.757397 8.609591 -11.001871 -9.619162 3.773347 0.100087 29.917847 -3.067703 -27.909410 -19.982067 26.721586 6.392630 -19.300711 -3.153566 -0.185730 32.038136 2.049878 33.591061 -4.079814 26.437998 2.830332 +0.402407 40.802876 0.312227 -0.117987 0.117987 -28.487782 2.026173 -1.270766 -33.145859 1.095273 -3.741480 22.675117 0.000000 0.000000 0.000000 44.269691 0.000000 0.000000 4.955626 -3.722959 0.809218 0.000000 0.000000 0.000000 -9.083441 3.359107 -1.998778 -85.851997 22.910686 6.055881 -14.309278 -12.592058 74.904396 8.056128 -18.156801 -1.596178 20.909658 5.327807 -0.063613 84.609558 17.717079 0.409689 135.398834 -7.122025 0.147216 35.692451 8.688311 -11.078964 -10.249552 4.287585 0.032841 30.378178 -3.080978 -27.912056 -19.451603 24.131620 5.950874 -19.130785 -3.036833 -0.200383 32.146778 2.052031 33.558075 -4.769036 23.812254 3.026150 +0.435050 40.751617 0.252603 0.000000 0.000000 -25.042461 2.516771 -1.364421 -32.545757 1.789612 -4.267927 22.115681 0.000000 0.000000 0.000000 50.135277 0.000000 0.000000 7.839917 -3.874708 -4.816322 0.000000 0.000000 0.000000 -7.411933 4.731445 -2.103987 -84.299568 22.050814 5.844838 -14.665185 -13.609970 75.049644 9.465706 -19.171148 -2.073525 22.979582 3.014687 -0.063299 90.972298 17.054344 1.607901 135.497742 -6.852290 0.147103 31.623562 8.637476 -11.142563 -11.307056 4.839589 -0.048267 31.270321 -3.066207 -27.955242 -18.906475 20.947475 5.498624 -19.172878 -2.954813 -0.210619 32.664921 2.049928 33.555561 -5.690563 20.497791 3.185477 +0.498761 40.652039 0.135581 0.055274 -0.055274 -20.842527 3.255013 -1.523302 -31.982306 2.331389 -4.710682 21.042410 0.000000 0.000000 0.000000 53.834980 0.000000 0.000000 11.377082 -3.675429 -6.566319 0.000000 0.000000 0.000000 -6.333158 5.364536 -2.233806 -83.105949 21.072687 5.786435 -14.890245 -13.972694 75.016174 9.868559 -17.919401 -2.363852 24.286791 1.864895 -0.063100 94.626137 16.670488 2.375342 135.931244 -6.461394 0.147031 28.490606 8.387367 -11.182465 -12.678375 5.296801 -0.108270 32.436821 -3.048922 -28.023516 -18.258253 17.232038 5.092428 -19.414871 -2.989370 -0.208401 33.623749 2.009930 33.584663 -6.857108 16.564213 3.323049 +0.583604 40.519638 -0.020539 0.057120 -0.057120 -16.192343 4.159200 -1.704214 -31.433228 2.737365 -5.042911 19.766754 0.000000 0.000000 0.000000 55.646030 0.000000 0.000000 15.167067 -3.175826 -5.139406 0.000000 0.000000 0.000000 -5.790238 5.321677 -2.372233 -82.202263 20.073227 5.850482 -15.060892 -13.968556 74.948349 9.538803 -14.990552 -2.498159 24.924177 1.809755 -0.063005 95.810287 16.530146 2.719214 136.486404 -5.967106 0.146997 26.033682 7.820174 -11.201507 -14.285220 5.607652 -0.154055 33.760723 -3.013231 -28.125162 -17.535034 13.156110 4.761034 -19.810429 -3.121750 -0.192923 34.915253 1.932957 33.647846 -8.218153 12.238897 3.410752 +0.675794 40.375877 -0.190325 0.030405 -0.030405 -11.466179 5.119328 -1.850198 -30.857685 3.047137 -5.241574 18.697205 0.000000 0.000000 0.000000 56.105629 0.000000 0.000000 18.685966 -2.486696 -1.801315 0.000000 0.000000 0.000000 -5.656893 4.863243 -2.492790 -81.507477 19.161781 5.985724 -15.301617 -14.007114 74.855728 8.881170 -11.274687 -2.530679 25.082756 2.451849 -0.062983 95.329674 16.556618 2.767382 136.881012 -5.405135 0.146988 23.942942 6.806063 -11.205789 -15.904510 5.809041 -0.190719 35.042770 -3.015275 -28.225218 -16.743683 8.909066 4.574556 -20.227528 -3.304211 -0.171309 36.293613 1.871534 33.728474 -9.650249 7.843258 3.455826 +0.761548 40.242218 -0.348345 0.000000 0.000000 -7.038322 6.025391 -1.904297 -30.214848 3.300305 -5.283634 18.242262 0.000000 0.000000 0.000000 55.750980 0.000000 0.000000 21.409872 -1.718840 2.182217 0.000000 0.000000 0.000000 -5.806845 4.249609 -2.568999 -80.940559 18.447695 6.140914 -15.736910 -14.497932 74.747864 8.300396 -7.661902 -2.515645 24.953547 3.393759 -0.063003 93.989243 16.673210 2.647705 136.832855 -4.811193 0.146995 21.908546 5.215205 -11.201411 -17.415304 5.870840 -0.193317 36.275295 -3.004167 -28.329586 -16.003214 4.658356 4.521770 -20.623251 -3.503098 -0.126567 37.700111 1.814066 33.802189 -11.147262 3.638024 3.411468 +0.829677 40.136070 -0.473948 -0.014522 0.014522 -3.199644 6.791725 -1.832988 -29.464466 3.527801 -5.165472 18.671148 0.000000 0.000000 0.000000 55.057819 0.000000 0.000000 22.963762 -1.044367 5.822702 0.000000 0.000000 0.000000 -6.119375 3.701756 -2.581769 -80.440536 18.008343 6.275897 -16.435217 -15.660154 74.629707 8.101975 -4.894483 -2.495756 24.705614 4.297266 -0.063039 92.485481 16.813078 2.471904 136.145950 -4.206642 0.147009 19.708994 2.998885 -11.193735 -18.550482 5.884942 -0.180361 36.980377 -2.993659 -28.380457 -15.152935 0.637448 4.488984 -20.792084 -3.626629 -0.098985 38.617973 1.752908 33.868069 -12.411256 -0.147479 3.382389 +0.879370 40.058681 -0.565612 -0.014763 0.014763 0.092625 7.430037 -1.696485 -28.568640 3.725903 -4.961151 19.696026 0.000000 0.000000 0.000000 54.256004 0.000000 0.000000 23.568159 -0.880628 9.240652 0.000000 0.000000 0.000000 -6.496013 3.283086 -2.541557 -80.026657 17.793217 6.394912 -17.240793 -16.951269 74.487801 8.194463 -3.123487 -2.467577 24.420227 5.060951 -0.063080 91.081108 16.948801 2.287128 134.969284 -3.555459 0.147024 17.476177 0.432852 -11.185169 -19.497650 5.860481 -0.167585 37.577370 -2.978438 -28.433208 -14.422805 -3.104085 4.519626 -20.916275 -3.720029 -0.073790 39.418755 1.733950 33.911983 -13.606051 -3.468920 3.238523 +0.912411 40.007252 -0.626595 -0.007623 0.007623 2.964670 7.976378 -1.578438 -27.490057 3.882223 -4.764155 20.889803 0.000000 0.000000 0.000000 53.513931 0.000000 0.000000 23.592482 -1.706286 12.833835 0.000000 0.000000 0.000000 -6.843852 3.017610 -2.466207 -79.738251 17.719837 6.513300 -17.941858 -17.638355 74.304092 8.387179 -2.352163 -2.416136 24.156715 5.642602 -0.063121 89.930420 17.062819 2.124384 133.538132 -2.807274 0.147038 15.430337 -2.126038 -11.177381 -20.204197 5.842831 -0.150197 37.899891 -2.989820 -28.466436 -13.706679 -6.508090 4.578886 -20.910503 -3.758066 -0.058851 39.937027 1.710370 33.948524 -14.616339 -6.423910 3.092063 +0.930585 39.978973 -0.660156 0.000000 0.000000 5.542659 8.466797 -1.562500 -26.191406 3.984375 -4.667969 21.825378 0.000000 0.000000 0.000000 53.000000 0.000000 0.000000 23.406145 -4.000000 17.000000 0.000000 0.000000 0.000000 -7.069983 2.929340 -2.373564 -79.614639 17.705727 6.646399 -18.326628 -16.988489 74.060539 8.489443 -2.583763 -2.326463 23.974407 6.000000 -0.063156 89.187721 17.137562 2.014681 132.087738 -1.911720 0.147048 13.791723 -4.320911 -11.172037 -20.723753 5.793715 -0.124233 38.037983 -2.971742 -28.478882 -13.049350 -9.468545 4.608392 -20.788992 -3.773575 -0.052491 40.239925 1.700753 33.969852 -15.491291 -9.061366 2.935368 +0.936300 39.970085 -0.670710 0.002809 -0.002809 7.921697 8.927903 -1.699793 -24.635502 4.025173 -4.736463 22.189476 0.000000 0.000000 0.000000 52.826649 0.000000 0.000000 23.300879 -7.926503 21.917875 0.000000 0.000000 0.000000 -7.122876 3.015210 -2.283912 -79.665283 17.681093 6.807752 -18.391747 -14.596915 73.749619 8.375860 -3.736151 -2.206354 23.912865 6.116689 -0.063180 88.941994 17.162401 1.977944 130.815308 -0.856014 0.147051 12.718997 -5.875210 -11.170239 -21.085445 5.765340 -0.112808 37.998344 -2.966746 -28.466522 -12.422726 -11.958517 4.611843 -20.555992 -3.742503 -0.056697 40.357639 1.697483 33.974030 -16.206682 -11.418052 2.793804 +0.934458 39.972950 -0.667308 0.001908 -0.001908 10.072580 9.348542 -1.911336 -22.785669 4.018242 -4.915042 22.124107 0.000000 0.000000 0.000000 52.882446 0.000000 0.000000 23.257671 -12.394814 26.890038 0.000000 0.000000 0.000000 -7.116507 3.163858 -2.227287 -79.780334 17.626921 7.003706 -18.967575 -11.371519 73.405937 8.182178 -5.385648 -2.154660 23.932611 6.079244 -0.063193 89.021126 17.154404 1.989771 129.765564 0.222274 0.147050 12.124515 -6.833568 -11.170818 -21.335756 5.732106 -0.092764 37.832581 -2.967739 -28.455387 -11.832419 -14.010556 4.606756 -20.275524 -3.699869 -0.059656 40.385796 1.684032 33.981934 -16.833061 -13.516422 2.650775 +0.930585 39.978973 -0.660156 0.000000 0.000000 11.935019 9.708116 -2.085619 -20.605366 3.982408 -5.119493 21.885099 0.000000 0.000000 0.000000 53.000000 0.000000 0.000000 23.179821 -16.000000 31.000000 0.000000 0.000000 0.000000 -7.206223 3.236848 -2.236164 -79.820114 17.536880 7.238812 -21.092892 -8.548364 73.074638 8.109430 -7.023182 -2.292999 23.974400 6.000000 -0.063200 89.187721 17.137562 2.014681 128.945129 1.147982 0.147048 11.859055 -7.320911 -11.172037 -21.508814 5.683632 -0.073265 37.645924 -2.973973 -28.445702 -11.317247 -15.745324 4.604300 -20.024160 -3.660713 -0.063805 40.376274 1.686285 33.972488 -17.334816 -15.291568 2.518762 +0.929044 39.981373 -0.657309 -0.000776 0.000776 13.434295 9.992224 -2.139067 -18.087845 3.935362 -5.279402 21.684196 0.000000 0.000000 0.000000 53.047127 0.000000 0.000000 22.771767 -17.648718 33.405666 0.000000 0.000000 0.000000 -7.494186 3.137851 -2.327735 -79.695984 17.416449 7.503244 -25.330870 -7.057624 72.789017 8.315252 -8.237947 -2.689349 23.991390 5.967780 -0.063202 89.254364 17.130821 2.024658 128.355988 1.787205 0.147047 11.785039 -7.466425 -11.172525 -21.667589 5.653803 -0.065565 37.528786 -2.984096 -28.440336 -10.897429 -17.153862 4.633348 -19.813492 -3.615506 -0.070262 40.366272 1.689904 33.982853 -17.767721 -16.745951 2.394616 +0.929533 39.980614 -0.658212 -0.000545 0.000545 14.437952 10.211246 -2.099829 -15.345579 3.890263 -5.379535 21.556784 0.000000 0.000000 0.000000 53.032497 0.000000 0.000000 20.942482 -17.493889 33.562416 0.000000 0.000000 0.000000 -7.869791 2.938975 -2.458056 -79.523407 17.318317 7.729671 -30.342262 -6.605986 72.534981 8.783695 -9.012175 -3.197145 23.986340 5.977359 -0.063201 89.233543 17.132925 2.021552 127.981659 2.171047 0.147047 11.811484 -7.416284 -11.172375 -21.786493 5.618001 -0.048294 37.469818 -2.976783 -28.435179 -10.627962 -18.156303 4.645494 -19.699268 -3.589468 -0.068015 40.396660 1.699873 33.967449 -18.065901 -17.721729 2.300058 +0.930585 39.978973 -0.660156 0.000000 0.000000 14.799090 10.381752 -2.023986 -12.520864 3.859134 -5.418454 21.494156 0.000000 0.000000 0.000000 53.000000 0.000000 0.000000 16.402079 -16.000000 31.000000 0.000000 0.000000 0.000000 -8.169237 2.754441 -2.567903 -79.468872 17.306995 7.836381 -34.312187 -6.594261 72.286621 9.455410 -9.426353 -3.616180 23.974400 6.000000 -0.063200 89.187721 17.137562 2.014681 127.801003 2.371861 0.147048 11.859055 -7.320911 -11.172037 -21.850426 5.603789 -0.045396 37.459957 -2.981227 -28.435757 -10.515847 -18.537258 4.668390 -19.669695 -3.584147 -0.077084 40.416252 1.697770 33.977047 -18.188982 -18.082060 2.269024 +0.931026 39.978291 -0.660970 0.000302 -0.000302 14.439198 10.518651 -1.957524 -9.741471 3.850642 -5.398408 21.486094 0.000000 0.000000 0.000000 52.984886 0.000000 0.000000 8.326033 -13.611635 25.521845 0.000000 0.000000 0.000000 -8.268438 2.672907 -2.611992 -79.655083 17.427591 7.766389 -35.874310 -6.531935 72.024597 10.269599 -9.561929 -3.794300 23.967785 6.012539 -0.063199 89.167023 17.139673 2.011527 127.787270 2.455498 0.147048 11.864728 -7.300119 -11.171880 -21.815908 5.621211 -0.048016 37.489944 -2.971294 -28.434286 -10.619726 -18.195202 4.663099 -19.719046 -3.585048 -0.079059 40.406311 1.691617 33.984161 -18.069109 -17.732782 2.305481 +0.930875 39.978523 -0.660692 0.000354 -0.000354 13.577949 10.631968 -1.905071 -7.061139 3.859102 -5.338387 21.514381 0.000000 0.000000 0.000000 52.986889 0.000000 0.000000 -2.155053 -10.711112 18.105618 0.000000 0.000000 0.000000 -8.210705 2.676070 -2.603713 -80.020798 17.643166 7.567997 -35.560055 -6.368227 71.755219 11.158912 -9.514235 -3.782156 23.966644 6.014696 -0.063199 89.170929 17.139307 2.012023 127.885155 2.465930 0.147048 11.832729 -7.347632 -11.171903 -21.717731 5.654793 -0.064414 37.557430 -2.991464 -28.445015 -10.860588 -17.362843 4.645657 -19.824614 -3.608608 -0.070951 40.405712 1.688091 33.974365 -17.821579 -16.893003 2.383784 +0.930405 39.979256 -0.659824 0.000267 -0.000267 12.470488 10.728580 -1.862045 -4.524374 3.876576 -5.258447 21.561659 0.000000 0.000000 0.000000 52.998211 0.000000 0.000000 -13.605795 -7.626362 9.873714 0.000000 0.000000 0.000000 -8.068848 2.725566 -2.566996 -80.472763 17.903635 7.305810 -34.227467 -6.154383 71.490784 12.059801 -9.367645 -3.666096 23.968546 6.011087 -0.063199 89.188194 17.137596 2.014503 128.040970 2.435875 0.147048 11.781141 -7.431013 -11.172022 -21.581308 5.676165 -0.070265 37.617188 -2.964632 -28.441149 -11.182381 -16.260401 4.608535 -19.958200 -3.637171 -0.073652 40.367329 1.690979 33.972511 -17.475471 -15.809285 2.478091 +0.929830 39.980152 -0.658762 0.000127 -0.000127 11.328428 10.812147 -1.825665 -2.206026 3.896753 -5.175105 21.613983 0.000000 0.000000 0.000000 53.012753 0.000000 0.000000 -24.751202 -4.656258 1.811421 0.000000 0.000000 0.000000 -7.900434 2.791473 -2.520603 -80.932861 18.166771 7.033116 -32.549465 -5.932767 71.244888 12.909443 -9.188578 -3.513547 23.971613 6.005279 -0.063200 89.210014 17.135422 2.017664 128.211472 2.390661 0.147048 11.724524 -7.524292 -11.172175 -21.441837 5.712199 -0.088014 37.685543 -2.972154 -28.437721 -11.478888 -15.137405 4.593740 -20.083246 -3.662597 -0.066032 40.346756 1.695134 33.974163 -17.149721 -14.697734 2.566909 +0.929330 39.980930 -0.657840 0.000000 0.000000 10.373108 10.878822 -1.796840 -0.326574 3.914065 -5.105209 21.658464 0.000000 0.000000 0.000000 53.025490 0.000000 0.000000 -33.940956 -2.214205 -4.846828 0.000000 0.000000 0.000000 -7.755113 2.849590 -2.480082 -81.316513 18.385778 6.804546 -31.084784 -5.747169 71.044601 13.604204 -9.033183 -3.379337 23.974400 6.000000 -0.063200 89.229065 17.133520 2.020430 128.356064 2.349981 0.147047 11.676479 -7.603782 -11.172309 -21.316114 5.729973 -0.092934 37.733761 -2.981133 -28.453396 -11.734806 -14.207223 4.588701 -20.197590 -3.692569 -0.057347 40.327522 1.698581 33.973930 -16.869005 -13.773573 2.646024 diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_laugh.bvh b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_laugh.bvh new file mode 100644 index 00000000..efb95a13 --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_laugh.bvh @@ -0,0 +1,219 @@ +HIERARCHY +ROOT hip +{ + OFFSET 0.00 0.00 0.00 + CHANNELS 6 Xposition Yposition Zposition Xrotation Zrotation Yrotation + JOINT abdomen + { + OFFSET 0.000000 0.000000 0.000000 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT chest + { + OFFSET 0.000000 5.018152 -1.882228 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT neckDummy + { + OFFSET 0.000000 8.316447 0.784897 + CHANNELS 3 Xrotation Yrotation Zrotation + JOINT neck + { + OFFSET 0.000000 2.280413 -0.392801 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT head + { + OFFSET 0.000000 3.496879 0.529469 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT figureHair + { + OFFSET 0.000000 4.699570 0.720622 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 0.000000 -6.419331 0.000000 + } + } + } + } + } + JOINT lCollar + { + OFFSET 0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lShldr + { + OFFSET 6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT lForeArm + { + OFFSET 10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lHand + { + OFFSET 11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 10.353753 0.000000 0.000000 + } + } + } + } + } + JOINT rCollar + { + OFFSET -0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rShldr + { + OFFSET -6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT rForeArm + { + OFFSET -10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rHand + { + OFFSET -11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET -10.353753 0.000000 0.000000 + } + } + } + } + } + } + } + JOINT lThigh + { + OFFSET 4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lShin + { + OFFSET -1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lFoot + { + OFFSET -0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } + JOINT rThigh + { + OFFSET -4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rShin + { + OFFSET 1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rFoot + { + OFFSET 0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } +} +MOTION +Frames: 90 +Frame Time: 0.041667 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -70.100098 9.898810 15.947100 -22.679001 -9.378360 0.076935 5.966730 0.027485 0.177213 -2.021920 5.690310 -0.063351 69.986099 -9.978440 15.864300 22.774000 9.377360 0.099237 -5.916610 -0.127070 0.211624 -7.540078 3.882017 0.146008 15.744670 -3.241251 -0.947839 -8.514585 1.093365 -0.807438 -7.531943 -4.331991 0.100592 15.702465 3.212883 0.590639 -8.576411 -1.585766 0.965128 +-0.007763 41.202133 0.377828 3.378041 0.000000 0.000000 1.867097 0.013030 -0.049459 0.371404 0.051674 -0.079469 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.101358 0.000000 0.000000 0.000000 0.000000 0.000000 1.959826 -5.709412 -0.088406 -67.510201 8.108236 17.391031 -27.469555 -9.094725 -1.038337 6.552986 0.614804 -2.061286 -1.989409 5.773344 -0.161082 69.285812 -7.528024 20.315123 24.419685 7.517776 -1.334625 -6.715847 -2.028328 -3.975180 -15.382716 4.193429 0.197635 24.302586 -3.595066 -1.762370 -12.575332 1.149907 -0.488666 -15.380059 -4.595361 0.045558 24.241297 3.545599 1.437316 -12.618499 -1.653347 0.647292 +-0.016822 40.174915 0.551590 7.655489 0.000000 0.000000 4.276233 0.030508 -0.112124 0.913601 0.117397 -0.180374 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.336546 0.000000 0.000000 0.000000 0.000000 0.000000 1.880434 -5.728514 -0.120223 -64.735252 5.903098 19.200861 -32.194229 -8.431575 -2.272046 7.303011 1.245942 -4.759040 -1.945491 5.856378 -0.284635 68.999092 -4.227843 25.686790 24.998230 5.264006 -3.389036 -7.719694 -4.372683 -10.276937 -24.486282 4.528811 0.249542 33.366535 -3.837736 -2.686700 -16.784464 1.201417 -0.154931 -24.488138 -4.882802 0.008333 33.315388 3.774428 2.344963 -16.832546 -1.683098 0.307774 +-0.026518 39.129559 0.728662 12.003304 0.000000 0.000000 6.696535 0.047653 -0.175796 1.419154 0.184017 -0.282763 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.507900 0.000000 0.000000 0.000000 0.000000 0.000000 1.800221 -5.747616 -0.152506 -61.594975 3.622284 21.052217 -37.846603 -7.950148 -3.639162 8.060510 1.958784 -7.587826 -1.902594 5.939412 -0.410347 68.327461 -0.998419 31.314236 26.540150 2.909205 -5.325936 -8.745147 -6.795598 -16.048565 -32.748177 4.803167 0.272618 40.472713 -3.938229 -3.413484 -19.956066 1.192845 0.131640 -32.760994 -5.105226 -0.020696 40.439823 3.850960 3.119125 -20.017311 -1.718044 0.019261 +-0.037113 38.236206 0.881153 15.693977 0.000000 0.000000 8.613239 0.059203 -0.229731 1.627745 0.239678 -0.368831 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.325644 0.000000 0.000000 0.000000 0.000000 0.000000 1.734482 -5.766718 -0.179626 -57.381886 1.495487 22.680651 -46.758923 -8.473905 -5.347159 8.679971 2.909119 -10.408497 -1.874623 6.022446 -0.517666 65.916977 1.137621 36.901474 32.466095 0.600745 -6.237697 -9.640488 -9.045897 -17.880007 -39.314583 5.020599 0.296957 45.615627 -3.966668 -3.963514 -22.217361 1.160076 0.325432 -39.328918 -5.284064 -0.037560 45.579880 3.901473 3.682645 -22.252253 -1.708900 -0.228503 +-0.048866 37.665001 0.981171 18.000000 0.000000 0.000000 9.511580 0.059897 -0.263183 1.279060 0.272524 -0.420770 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -0.500000 0.000000 0.000000 0.000000 0.000000 0.000000 1.698510 -5.785820 -0.195958 -51.388500 -0.247604 23.821699 -61.263401 -10.826300 -7.603510 9.015880 4.252730 -13.081900 -1.875480 6.105480 -0.586040 60.413700 1.157650 42.152500 46.196701 -1.514000 -5.216690 -10.254000 -10.872400 -12.361200 -43.303322 5.162341 0.306947 48.613049 -3.961893 -4.272691 -23.499552 1.134922 0.431307 -43.305683 -5.379415 -0.053492 48.557144 3.893440 3.997210 -23.556156 -1.690374 -0.352444 +-0.061362 37.539368 1.016482 18.413717 0.000000 0.000000 9.021501 0.046373 -0.269565 0.190223 0.274980 -0.426820 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -2.204584 0.000000 0.000000 0.000000 0.000000 0.000000 1.701133 -6.879439 -0.197796 -43.484703 -1.478406 24.345739 -82.157516 -15.430352 -10.421200 8.988295 5.992272 -15.504165 -1.908242 7.967278 -0.600653 51.313896 -1.420104 46.835083 69.153519 -3.271086 -1.864137 -10.503002 -12.026495 1.957980 -44.065708 5.213066 0.293809 49.327824 -3.965021 -4.345573 -23.871794 1.119238 0.461119 -44.071869 -5.388297 -0.062882 49.261738 3.895544 4.077314 -23.889294 -1.687165 -0.415456 +-0.071476 37.795902 1.037465 17.306860 0.000000 0.000000 7.351742 0.022867 -0.258913 -1.511880 0.256597 -0.399400 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -4.806764 0.000000 0.000000 0.000000 0.000000 0.000000 1.725313 -9.787790 -0.189126 -35.849598 -2.472785 24.662422 -104.099571 -21.107294 -13.035254 8.779539 7.517868 -17.712507 -1.932666 11.493606 -0.569621 41.514427 -4.913999 50.971897 94.761650 -4.440273 2.183356 -10.580967 -12.269804 18.687979 -42.102257 5.175671 0.285892 48.035156 -3.968607 -4.206966 -23.431400 1.128545 0.360917 -42.119053 -5.319654 -0.087557 47.988628 3.885627 3.965288 -23.476259 -1.713202 -0.375250 +-0.075405 38.324493 1.110154 15.271000 0.000000 0.000000 4.855750 -0.004484 -0.245423 -3.622920 0.231206 -0.356976 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -8.270970 0.000000 0.000000 0.000000 0.000000 0.000000 1.747540 -12.972100 -0.175854 -31.239599 -3.607715 25.316200 -120.212997 -26.277901 -14.486200 8.637500 8.066500 -19.779400 -1.897680 13.782700 -0.506794 34.762299 -7.101530 54.649300 114.446999 -4.774750 4.780330 -10.750400 -11.366500 29.479300 -38.237156 5.071612 0.249277 45.271954 -3.994971 -3.906636 -22.511040 1.153950 0.249163 -38.233212 -5.204162 -0.067275 45.207504 3.889437 3.666423 -22.534662 -1.731875 -0.276542 +-0.070540 39.021591 1.282500 12.828098 0.000000 0.000000 1.866734 -0.030571 -0.240336 -5.951271 0.210063 -0.314938 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -12.463415 0.000000 0.000000 0.000000 0.000000 0.000000 1.749581 -12.200910 -0.162890 -31.640205 -5.162677 26.707363 -125.424759 -29.722507 -14.089963 8.751387 7.099856 -21.760101 -1.767226 12.643237 -0.425041 33.820251 -6.323139 57.944553 121.808311 -4.129660 4.333545 -11.153959 -9.203780 28.145445 -33.103325 4.897071 0.223865 41.206219 -3.973284 -3.475525 -21.150114 1.182659 0.074168 -33.101036 -5.060833 -0.060048 41.152409 3.860977 3.257327 -21.191643 -1.741094 -0.091354 +-0.059339 39.807980 1.527042 10.220687 0.000000 0.000000 -1.362220 -0.054613 -0.242684 -8.360951 0.193781 -0.276048 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -16.857430 0.000000 0.000000 0.000000 0.000000 0.000000 1.735157 -7.992557 -0.151050 -35.761303 -7.017631 28.636892 -122.328064 -31.746952 -12.333237 9.065720 5.031918 -23.653229 -1.568348 8.858811 -0.333492 37.281208 -3.285488 60.927509 119.658737 -2.800998 1.576998 -11.557520 -6.196405 17.624437 -27.014368 4.679688 0.200846 35.804630 -3.922783 -2.920387 -19.251453 1.195103 -0.119636 -27.008385 -4.892077 -0.047274 35.733803 3.803466 2.694692 -19.279596 -1.745614 0.142998 +-0.045037 40.617142 1.803024 7.609903 0.000000 0.000000 -4.615206 -0.076732 -0.249031 -10.734983 0.180707 -0.240178 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -20.828125 0.000000 0.000000 0.000000 0.000000 0.000000 1.712185 -2.039775 -0.140221 -41.785088 -8.975299 30.797354 -114.779030 -32.925320 -9.889064 9.479490 2.429010 -25.435301 -1.338575 3.750196 -0.239620 43.041054 0.889745 63.639904 112.365990 -1.141783 -2.354182 -11.961080 -2.826057 2.416528 -20.358097 4.424375 0.163927 29.242819 -3.800440 -2.237937 -16.765934 1.186196 -0.352694 -20.346016 -4.702146 -0.033767 29.163849 3.685490 2.029600 -16.789431 -1.722225 0.419723 +-0.030322 41.385479 2.075043 5.160333 0.000000 0.000000 -7.675667 -0.096665 -0.256664 -12.946133 0.169797 -0.207814 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -23.750610 0.000000 0.000000 0.000000 0.000000 0.000000 1.687048 4.276088 -0.130491 -48.234108 -10.854231 32.920387 -105.827118 -33.674335 -7.307931 9.909321 -0.236823 -27.059639 -1.110117 -1.597289 -0.150619 49.409256 5.283483 66.069519 103.363747 0.553142 -6.534656 -12.364639 0.487051 -13.815860 -13.201231 4.120883 0.124443 21.163668 -3.526132 -1.410039 -13.430083 1.128725 -0.648397 -13.222383 -4.465384 -0.009350 21.142309 3.444188 1.238659 -13.451520 -1.684808 0.738909 +-0.018020 42.014900 2.300054 3.160080 0.000000 0.000000 -10.176600 -0.112760 -0.263268 -14.748100 0.161188 -0.181671 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -25.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.665730 9.594840 -0.122641 -53.676300 -12.397826 34.675201 -98.104401 -34.207199 -5.136660 10.269500 -2.463070 -28.375500 -0.920722 -6.086340 -0.077739 54.822300 8.976500 68.028000 95.535698 1.967690 -10.057000 -12.768200 3.225770 -27.504499 -7.880398 3.915570 0.080944 15.648969 -3.277269 -0.906632 -11.244464 1.114255 -0.847415 -7.862768 -4.302692 0.001045 15.581241 3.199330 0.707775 -11.260010 -1.637632 0.961605 +-0.018043 41.525448 2.468624 1.480060 0.000000 -0.398741 -10.206751 -0.209333 -0.344057 -14.768801 0.037642 -0.197522 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -25.272728 0.000000 0.000000 0.000000 0.000000 0.000000 1.526150 -1.588180 -0.182168 -37.960751 -12.625547 33.129601 -109.932205 -34.993050 -12.215130 10.512650 2.828640 -27.813099 -0.921894 2.853530 -0.136104 38.881599 9.290850 68.328247 104.299347 2.273175 -10.807800 -11.026930 3.051320 -26.905899 -8.095902 4.074898 0.077331 21.001083 -3.550109 -1.412081 -14.681169 1.594624 -0.585671 -8.180668 -4.495108 0.001237 20.947487 3.426659 1.212982 -14.630376 -1.308505 0.808601 +-0.018065 41.035995 2.637193 -0.199959 0.000000 -0.797482 -10.236900 -0.305905 -0.424846 -14.789500 -0.085904 -0.213373 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -25.545456 0.000000 0.000000 0.000000 0.000000 0.000000 1.386570 -12.771200 -0.241696 -22.245199 -12.853270 31.584000 -121.760002 -35.778900 -19.293600 10.755800 8.120350 -27.250700 -0.923067 11.793400 -0.194470 22.940901 9.605200 68.628502 113.063004 2.578660 -11.558600 -9.285660 2.876870 -26.307301 -8.960182 4.240427 0.086898 27.796972 -3.789084 -2.098041 -18.924828 2.066440 -0.261339 -9.176728 -4.772339 0.032317 27.809912 3.655836 1.883835 -18.803745 -0.975655 0.600243 +0.038192 41.471085 2.057007 -1.496943 0.000000 -1.196221 -10.252334 -0.298338 -0.416694 -14.801033 -0.050870 -0.243151 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -25.818184 0.000000 0.000000 0.000000 0.000000 0.000000 1.447707 -2.939800 -0.232839 -33.380798 -13.221693 33.708599 -113.311005 -35.821999 -15.230530 11.237433 5.057523 -27.951233 -0.856010 3.223666 -0.155402 35.114735 9.550272 69.209137 105.660500 3.089367 -10.950534 -8.928170 4.537006 -26.906200 -6.086387 3.930225 0.081548 22.988529 -3.613573 -1.603875 -15.705381 2.437302 -0.337716 -6.497812 -4.763773 0.035401 23.227152 3.506649 1.435476 -15.616465 -0.522953 0.885323 +0.094449 41.906174 1.476821 -2.793926 0.000000 -1.594961 -10.267767 -0.290770 -0.408543 -14.812567 -0.015836 -0.272929 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -26.090912 0.000000 0.000000 0.000000 0.000000 0.000000 1.508843 6.891600 -0.223982 -44.516399 -13.590117 35.833199 -104.862000 -35.865097 -11.167459 11.719067 1.994697 -28.651768 -0.788953 -5.346067 -0.116335 47.288567 9.495344 69.789764 98.257996 3.600073 -10.342466 -8.570681 6.197143 -27.505100 -2.742939 3.579852 0.050781 17.177063 -3.352096 -1.058313 -11.953518 2.813145 -0.476925 -3.257348 -4.725174 0.026907 17.475887 3.275719 0.883656 -11.826106 -0.039904 1.197031 +0.150706 42.341263 0.896635 -4.090910 0.000000 -1.993700 -10.283200 -0.283203 -0.400391 -14.824100 0.019197 -0.302707 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -26.363638 0.000000 0.000000 0.000000 0.000000 0.000000 1.569980 16.723000 -0.215125 -55.652000 -13.958539 37.957802 -96.413002 -35.908199 -7.104390 12.200700 -1.068130 -29.352301 -0.721896 -13.915800 -0.077267 59.462399 9.440415 70.370399 90.855499 4.110780 -9.734400 -8.213190 7.857280 -28.104000 -0.375701 3.296150 0.006268 13.537068 -3.155069 -0.703840 -9.401193 3.186299 -0.529320 -1.094880 -4.781661 0.021777 14.074674 3.149752 0.573154 -9.316360 0.429646 1.382580 +0.107543 41.960567 1.027737 -4.909090 0.000000 -2.709273 -10.266967 -0.239772 -0.354023 -14.811366 0.089448 -0.309889 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -26.636364 0.000000 0.000000 0.000000 0.000000 0.000000 1.645300 7.327666 -0.189838 -43.532299 -13.455216 35.444237 -103.758003 -35.857632 -11.692594 12.216166 2.005773 -28.595266 -0.764895 -3.687000 -0.170667 46.471367 9.088806 68.059433 97.917664 4.675523 -10.554000 -7.526874 6.964780 -26.813801 -0.769901 3.326045 0.034977 16.981026 -3.339981 -1.023925 -11.626110 3.936039 -0.390481 -1.753491 -4.960847 0.061884 17.732185 3.284690 0.911829 -11.505191 1.054161 1.268269 +0.064380 41.579868 1.158840 -5.727270 0.000000 -3.424847 -10.250733 -0.196342 -0.307654 -14.798634 0.159698 -0.317071 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -26.909092 0.000000 0.000000 0.000000 0.000000 0.000000 1.720620 -2.067667 -0.164550 -31.412600 -12.951894 32.930668 -111.102997 -35.807068 -16.280796 12.231633 5.079677 -27.838234 -0.807893 6.541800 -0.264067 33.480331 8.737197 65.748466 104.979828 5.240267 -11.373600 -6.840557 6.072280 -25.523602 -2.188499 3.405670 0.069325 22.713871 -3.599106 -1.581029 -15.116010 4.723222 -0.145142 -3.445345 -5.246276 0.131703 23.639799 3.518912 1.476614 -14.909132 1.667600 1.057848 +0.021217 41.199169 1.289942 -6.545450 0.000000 -4.140420 -10.234500 -0.152911 -0.261286 -14.785900 0.229948 -0.324253 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -27.181820 0.000000 0.000000 0.000000 0.000000 0.000000 1.795940 -11.463000 -0.139262 -19.292900 -12.448571 30.417101 -118.447998 -35.756500 -20.868999 12.247100 8.153580 -27.081200 -0.850892 16.770599 -0.357467 20.489300 8.385588 63.437500 112.042000 5.805010 -12.193200 -6.154240 5.179780 -24.233400 -3.167391 3.420480 0.101391 27.493752 -3.773138 -2.062191 -18.117531 5.496895 0.076065 -4.665108 -5.539508 0.211345 28.544991 3.682571 1.954261 -17.783964 2.319096 0.880416 +0.007242 41.471672 1.626774 -7.051547 0.000000 -4.423646 -10.250734 -0.098685 -0.219763 -14.850720 0.260555 -0.277981 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -27.454546 0.000000 0.000000 0.000000 0.000000 0.000000 1.871260 -1.709167 -0.113975 -30.949833 -11.690501 31.835600 -113.273666 -36.231434 -16.535166 11.587900 4.614686 -27.512632 -1.270599 6.352559 -0.306652 33.480331 8.230560 65.748466 104.979836 5.240273 -11.373600 -6.840560 6.072287 -25.523600 -0.371504 3.175510 0.047830 24.029158 -3.655766 -1.705860 -16.952326 5.772558 -0.018836 -2.050309 -5.552422 0.203551 25.355631 3.589886 1.652461 -16.730209 2.589948 1.044887 +-0.006733 41.744171 1.963606 -7.557643 0.000000 -4.706873 -10.266968 -0.044460 -0.178240 -14.915541 0.291162 -0.231709 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -27.727272 0.000000 0.000000 0.000000 0.000000 0.000000 1.946580 8.044666 -0.088687 -42.606766 -10.932432 33.254101 -108.099335 -36.706367 -12.201333 10.928699 1.075793 -27.944065 -1.690306 -4.065482 -0.255837 46.471367 8.075533 68.059433 97.917664 4.675536 -10.554000 -7.526880 6.964793 -26.813801 2.706488 2.911489 -0.012344 19.901608 -3.489492 -1.315023 -15.417785 6.043613 -0.129231 0.712115 -5.559559 0.180312 21.841925 3.458894 1.300035 -15.491706 2.887088 1.232441 +-0.020708 42.016674 2.300437 -8.063740 0.000000 -4.990100 -10.283202 0.009766 -0.136717 -14.980362 0.321768 -0.185438 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -28.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021900 17.798500 -0.063400 -54.263699 -10.174362 34.672600 -102.925003 -37.181301 -7.867500 10.269500 -2.463100 -28.375500 -2.110013 -14.483522 -0.205022 59.462399 7.920506 70.370399 90.855499 4.110800 -9.734400 -8.213200 7.857300 -28.104000 5.841412 2.623147 -0.112891 15.954415 -3.297374 -0.919763 -14.108712 6.310980 -0.215114 3.742163 -5.565496 0.141830 17.712967 3.281099 0.910020 -13.924023 3.188266 1.443657 +-0.020708 41.524868 2.471274 -8.881940 0.000000 -5.270015 -10.252451 0.034896 -0.128511 -14.916381 0.465426 -0.213858 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -29.900000 0.000000 0.000000 0.000000 0.000000 0.000000 1.929275 2.496600 -0.151850 -38.283951 -9.455569 33.118549 -111.544998 -36.648949 -13.108601 10.512650 2.828650 -27.813099 -1.705931 0.492289 -0.205094 40.963398 7.459847 69.527954 100.158249 1.984278 -10.656900 -8.748970 5.367690 -27.205799 3.991428 2.655051 -0.058238 22.367792 -3.603345 -1.537873 -17.877544 6.669509 0.121723 1.720152 -5.976177 0.210200 24.630613 3.557737 1.574585 -17.990969 3.410054 1.262458 +-0.020708 41.033066 2.642111 -9.700140 0.000000 -5.549930 -10.221700 0.060026 -0.120305 -14.852400 0.609084 -0.242278 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -31.799999 0.000000 0.000000 0.000000 0.000000 0.000000 1.836650 -12.805300 -0.240300 -22.304199 -8.736776 31.564501 -120.165001 -36.116600 -18.349701 10.755800 8.120400 -27.250700 -1.301850 15.468100 -0.205167 22.464399 6.999188 68.685501 109.460999 -0.142244 -11.579400 -9.284740 2.878080 -26.307600 2.669042 2.620372 -0.025904 27.973152 -3.807163 -2.086144 -21.371916 7.011542 0.454951 0.262074 -6.352538 0.305270 30.369459 3.722419 2.147469 -21.435307 3.644404 1.128842 +0.037964 41.467922 2.058850 -10.889060 0.000000 -5.473423 -10.237166 0.079586 -0.117439 -14.839334 0.722808 -0.270226 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -33.700001 0.000000 0.000000 0.000000 0.000000 0.000000 1.915328 -2.948800 -0.268399 -33.428566 -9.218025 33.709999 -112.978264 -36.187965 -15.018234 11.237433 5.057567 -27.951233 -1.102974 5.776200 -0.148530 34.771034 7.283706 69.237297 102.625732 1.141544 -10.934770 -8.925303 4.535596 -26.902666 5.332249 2.348735 -0.127625 23.094963 -3.638269 -1.576617 -17.967844 6.935839 0.247169 2.821374 -6.339568 0.220756 25.845047 3.612662 1.711913 -18.301689 3.611175 1.304474 +0.096635 41.902782 1.475588 -12.077980 0.000000 -5.396916 -10.252633 0.099146 -0.114574 -14.826267 0.836531 -0.298173 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -35.600002 0.000000 0.000000 0.000000 0.000000 0.000000 1.994005 6.907700 -0.296497 -44.552933 -9.699274 35.855499 -105.791534 -36.259331 -11.686768 11.719067 1.994734 -28.651768 -0.904098 -3.915700 -0.091894 47.077667 7.568224 69.789093 95.790466 2.425332 -10.290140 -8.565866 6.193113 -27.497734 8.560331 2.044545 -0.258475 17.037975 -3.361432 -0.991764 -13.953043 6.836172 -0.003245 5.862287 -6.265770 0.121333 20.348700 3.395305 1.165909 -14.696783 3.621928 1.531099 +0.155306 42.337639 0.892327 -13.266900 0.000000 -5.320410 -10.268100 0.118706 -0.111708 -14.813200 0.950255 -0.326121 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -37.500000 0.000000 0.000000 0.000000 0.000000 0.000000 2.072683 16.764200 -0.324596 -55.677299 -10.180522 38.000999 -98.604797 -36.330700 -8.355300 12.200700 -1.068100 -29.352301 -0.705222 -13.607600 -0.035257 59.384300 7.852741 70.340897 88.955200 3.709120 -9.645510 -8.206430 7.850630 -28.092800 10.853699 1.817155 -0.371001 13.087765 -3.155122 -0.605988 -11.111426 6.730118 -0.156081 7.911712 -6.282657 0.065533 17.008259 3.280087 0.842812 -12.226395 3.623309 1.657100 +0.110440 41.958000 1.023474 -13.946051 0.000000 -5.243906 -10.271151 0.169478 -0.081662 -14.775900 1.088503 -0.354775 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -39.400002 0.000000 0.000000 0.000000 0.000000 0.000000 2.151360 7.355134 -0.352694 -43.549168 -11.114489 35.473034 -105.219200 -36.139301 -12.526533 12.216166 2.005800 -28.595266 -0.585793 -3.239890 -0.139027 46.447502 8.188747 68.021950 96.739601 4.619295 -10.494655 -7.519275 6.961465 -26.810450 10.421952 1.906360 -0.352265 16.189476 -3.328331 -0.881010 -13.092058 6.694577 -0.071479 7.675427 -6.357283 0.082227 19.690773 3.362915 1.105891 -13.973329 3.491621 1.521247 +0.065574 41.578362 1.154622 -14.625200 0.000000 -5.167403 -10.274200 0.220250 -0.051616 -14.738600 1.226750 -0.383428 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -41.300003 0.000000 0.000000 0.000000 0.000000 0.000000 2.230037 -2.053933 -0.380793 -31.421034 -12.048455 32.945068 -111.833603 -35.947899 -16.697765 12.231633 5.079700 -27.838234 -0.466364 7.127820 -0.242796 33.510700 8.524753 65.703003 104.524002 5.529470 -11.343800 -6.832120 6.072300 -25.528099 8.851945 2.077691 -0.289483 21.700237 -3.584562 -1.419106 -16.372498 6.701849 0.124732 6.278644 -6.531195 0.147225 24.826099 3.568857 1.600528 -17.013657 3.367167 1.284902 +0.020708 41.198727 1.285769 -15.267900 0.000000 -5.090900 -10.320200 0.131340 -0.066692 -14.831800 1.105600 -0.342588 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -43.200001 0.000000 0.000000 0.000000 0.000000 0.000000 2.308715 -11.463000 -0.408892 -19.292900 -12.982422 30.417101 -118.447998 -35.756500 -20.868999 12.247100 8.153600 -27.081200 -0.610501 16.605700 -0.286345 20.547600 9.235399 63.505798 109.705002 5.406020 -11.957700 -6.154870 5.178810 -24.233400 7.621700 2.230913 -0.242101 26.384827 -3.760605 -1.870104 -19.173220 6.653936 0.265310 5.296667 -6.654920 0.207212 29.045773 3.685088 2.020826 -19.587538 3.242809 1.096585 +-0.084239 41.465382 1.060259 -15.102000 -0.001894 -4.649400 -10.345250 0.124025 -0.079809 -14.946251 1.057980 -0.310459 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -45.099998 0.000000 0.000000 0.000000 0.000000 0.000000 2.387393 3.749700 -0.436990 -38.800350 -13.936411 36.696850 -105.113548 -36.647900 -14.486364 14.040400 1.419850 -29.608799 -1.026680 0.060550 -0.115622 44.227551 12.046650 69.449402 96.024551 6.811015 -10.537605 -5.738880 10.241055 -26.781050 8.485855 2.534263 -0.305734 23.232321 -3.654449 -1.550571 -16.997084 6.186409 -0.139671 6.314042 -6.177738 0.110257 25.835337 3.614105 1.701788 -17.531443 2.846798 0.946746 +-0.189186 41.732040 0.834749 -14.936100 -0.003787 -4.207900 -10.370300 0.116711 -0.092926 -15.060700 1.010360 -0.278330 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -47.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.466070 18.962400 -0.465089 -58.307800 -14.890400 42.976601 -91.779099 -37.539299 -8.103730 15.833700 -5.313900 -32.136398 -1.442860 -16.484600 0.055102 67.907501 14.857900 75.392998 82.344101 8.216010 -9.117510 -5.322890 15.303300 -29.328699 9.536154 2.797378 -0.349649 19.726030 -3.492203 -1.205839 -14.679217 5.695245 -0.545255 7.521450 -5.684236 0.017749 22.183722 3.477913 1.366273 -15.229716 2.443558 0.834319 +-0.182070 41.877159 0.689803 -15.164215 -0.213923 -3.490290 -9.862570 -0.082934 -0.231601 -14.134594 1.123208 -0.331027 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -49.714794 0.000000 0.000000 0.000000 0.000000 0.000000 3.008265 7.035531 -0.308185 -50.000828 -15.730734 40.237038 -95.269836 -37.822754 -10.554369 16.072233 -0.572926 -25.281216 -1.449353 -7.718672 0.017445 57.863258 14.876156 72.189941 85.598831 9.473660 -9.526638 -4.884637 17.277172 -24.915184 10.260930 3.226435 -0.388229 18.150398 -3.425919 -1.057527 -13.578481 5.027452 -0.719820 8.805866 -5.145471 -0.025300 19.824869 3.388922 1.129055 -13.909285 1.803536 0.815612 +-0.095254 41.980186 0.560812 -14.352100 -0.502553 -2.403780 -8.339840 -0.380544 -0.419869 -11.543600 1.212520 -0.410261 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -49.627102 0.000000 0.000000 0.000000 0.000000 0.000000 3.915500 -10.596100 0.012034 -27.793200 -16.800623 33.254200 -107.098000 -37.566399 -17.327400 15.361700 10.605200 -15.067600 -0.897905 13.151300 -0.167353 31.600401 14.034200 65.135696 96.665298 10.421400 -10.571400 -4.387690 17.371599 -16.499599 9.283363 3.836304 -0.375046 17.711395 -3.378975 -1.030501 -12.937297 4.012670 -0.785600 8.728212 -4.451676 -0.029060 17.956526 3.307378 0.930210 -12.738710 0.804520 0.861226 +-0.039410 42.104290 0.416062 -10.641242 -0.481442 -1.443663 -5.923904 -0.432964 -0.413718 -7.857103 0.925848 -0.366145 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -40.855148 0.000000 0.000000 0.000000 0.000000 0.000000 4.455257 -2.447666 0.257696 -28.451525 -18.044142 34.179886 -105.801025 -37.059437 -16.749224 15.188931 12.618129 -17.344431 0.101571 11.415614 -0.274500 34.271275 16.193756 67.182701 93.588402 10.299767 -9.638507 -4.058613 17.668491 -13.885813 5.262649 4.157248 -0.203520 16.321987 -3.305057 -0.936041 -11.237991 2.860517 -0.880988 4.949526 -4.053814 -0.003878 16.705240 3.250009 0.828229 -11.404780 -0.184407 0.860508 +-0.016192 42.159290 0.291512 -5.210951 -0.243047 -0.661990 -2.995475 -0.266541 -0.241581 -3.767984 0.424918 -0.211541 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -26.282459 0.000000 0.000000 0.000000 0.000000 0.000000 4.572973 5.700767 0.395298 -43.962082 -19.302429 39.840164 -95.940262 -36.365536 -11.368818 15.405130 6.326621 -26.496101 1.319574 -5.000998 -0.285561 55.298824 20.742498 74.271332 81.902702 9.617770 -7.538126 -3.867269 17.980318 -14.214466 -0.711339 4.148232 0.000275 15.253574 -3.258711 -0.877584 -9.620513 1.848898 -0.957721 -1.100045 -4.055513 0.030222 15.798344 3.210161 0.723436 -9.881114 -1.005551 0.899538 +0.000000 42.016674 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -10.983900 0.000000 0.000000 0.000000 0.000000 0.000000 4.383572 13.849200 0.442429 -55.116100 -20.390900 43.229698 -88.583099 -35.492001 -7.290810 15.452600 -3.292790 -31.540899 2.496704 -17.515200 -0.233693 70.173698 25.949600 78.088997 74.015198 9.201540 -5.936290 -3.719350 17.552200 -11.460400 -7.430140 3.915114 0.083477 15.896773 -3.281548 -0.943115 -8.765495 1.133335 -0.860512 -7.396369 -4.312926 -0.002671 15.818346 3.209798 0.724702 -8.801898 -1.601695 0.951016 +0.029060 41.603088 0.294792 3.523463 0.085782 0.566996 2.701996 0.258554 0.223536 2.869862 -0.131830 0.214630 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.935441 0.000000 0.000000 0.000000 0.000000 0.000000 4.001977 8.529915 0.416680 -48.044556 -21.168816 39.384979 -91.896301 -34.506035 -9.020999 14.926503 -11.638951 -25.000729 3.373562 -12.668963 -0.152052 61.496494 30.350168 72.948936 78.631317 9.567046 -6.021570 -3.543121 15.897134 -2.408482 -12.823112 3.850041 0.143296 18.627081 -3.403686 -1.204162 -9.601346 0.587599 -0.722142 -12.858790 -4.585247 -0.020442 18.938248 3.368288 1.006336 -9.980528 -2.139884 0.877580 +0.068065 41.065826 0.409978 5.773809 0.055233 0.927403 5.089682 0.443489 0.377760 4.851710 -0.046270 0.377315 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 9.249642 0.000000 0.000000 0.000000 0.000000 0.000000 3.543113 -4.942948 0.335638 -30.237488 -21.670845 31.509851 -102.444061 -33.714409 -14.669849 14.033470 -15.612284 -13.411978 3.690750 1.800127 -0.073794 40.307724 33.543106 63.667847 89.650146 9.989624 -7.072688 -3.357148 13.599610 4.916301 -18.142630 3.968752 0.230429 24.475430 -3.635016 -1.763413 -12.380342 0.249269 -0.422214 -18.179785 -4.878015 0.002512 24.930601 3.608948 1.576792 -12.882393 -2.533409 0.710092 +0.108388 40.607342 0.520079 7.636040 0.000000 0.935553 7.227150 0.499795 0.420458 6.102422 0.107791 0.432723 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 14.702564 0.000000 0.000000 0.000000 0.000000 0.000000 3.121903 -17.144600 0.216892 -14.524700 -21.975523 24.850000 -113.889999 -33.483799 -20.749001 13.133000 -12.488600 -6.814660 3.188869 15.806800 -0.032075 24.757900 35.393272 57.688301 97.269203 9.434450 -7.890910 -3.202570 11.512000 -0.321065 -22.149660 4.087665 0.307727 28.584379 -3.796450 -2.158777 -14.314969 0.204958 -0.189132 -22.164961 -5.057658 0.043192 28.964855 3.721422 1.965395 -14.791068 -2.581884 0.631875 +0.144110 40.397415 0.564873 9.778135 -0.011028 0.531728 9.178493 0.372458 0.309418 6.778876 0.181464 0.325522 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 18.038063 0.000000 0.000000 0.000000 0.000000 0.000000 2.853270 -11.000755 0.078033 -12.072336 -22.134117 24.147966 -119.376099 -33.702316 -23.484198 12.835510 -2.122300 -12.449687 1.608520 8.932060 -0.060051 28.055134 35.991131 60.334099 94.602188 7.429358 -7.630134 -3.013051 10.138238 -22.965494 -24.968624 4.108780 0.370772 29.320526 -3.824021 -2.200923 -14.385321 0.520408 -0.061282 -25.045212 -5.110860 0.076041 29.657570 3.775901 2.029663 -14.753456 -2.193968 0.673228 +0.180153 40.475163 0.505332 12.000000 0.000000 0.000000 11.007800 0.006465 0.002427 7.037950 0.025857 0.000381 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 20.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.734790 -4.856910 -0.063351 -27.391899 -22.088877 32.133801 -109.958000 -32.343800 -17.957600 14.755100 5.317840 -26.361601 -1.309700 2.057320 -0.190878 43.638000 36.329601 68.454102 86.427597 5.752800 -6.854810 -2.292350 8.588530 -43.901501 -26.908091 4.070908 0.449262 27.808828 -3.794881 -2.022376 -13.153146 0.903479 -0.032689 -27.027296 -5.067805 0.099519 27.957970 3.759760 1.830948 -13.297956 -1.652794 0.803603 +0.221601 40.655266 0.378869 13.993500 0.000000 -0.370993 12.773200 -0.478160 -0.429553 7.072980 -0.261707 -0.449919 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 21.220512 0.000000 0.000000 0.000000 0.000000 0.000000 2.388516 6.552380 -0.191437 -53.381302 -21.809000 45.737999 -86.740501 -28.666401 -4.795950 19.000700 3.329060 -40.711102 -5.116100 -6.659830 -0.415846 54.852699 36.895546 73.544800 81.613403 5.342070 -6.169930 -0.839051 7.041250 -45.606998 -28.095022 4.024812 0.522324 25.059540 -3.721517 -1.716357 -11.225605 1.106352 -0.076908 -28.231707 -4.951017 0.110345 25.022881 3.678614 1.510395 -11.172546 -1.239609 0.982274 +0.265033 40.255253 0.417905 15.845757 -0.001386 -0.600934 14.609800 -0.590747 -0.647241 7.252190 -0.071493 -0.602980 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 21.884851 0.000000 0.000000 0.000000 0.000000 0.000000 1.694641 -0.380313 -0.297468 -55.560001 -21.421879 47.437599 -81.885399 -27.333799 -1.734330 20.798100 5.521560 -46.669998 -7.138570 0.340200 -0.558523 39.592300 36.583599 64.329697 88.041603 2.969980 -5.857980 -0.001773 8.126340 -38.720299 -31.686081 4.182431 0.616133 28.130840 -3.834610 -2.007008 -12.536910 1.245655 0.117136 -31.757992 -5.030227 0.147433 27.955036 3.791789 1.809110 -12.414899 -1.078691 0.917866 +0.311186 39.480507 0.567722 17.590132 -0.000939 -0.722001 16.887091 -0.772151 -0.832354 7.944838 -0.121813 -0.777741 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 22.066536 0.000000 0.000000 0.000000 0.000000 0.000000 0.627230 -7.313006 -0.374453 -39.430954 -20.804831 40.754486 -93.242783 -28.200529 -7.525003 21.276611 12.016464 -46.794415 -6.796228 7.078100 -0.473700 24.257891 37.388023 59.806423 95.032906 -0.495765 -8.375908 -0.113883 5.442149 -31.141003 -36.534611 4.484515 0.718774 34.633156 -4.005862 -2.678133 -15.914652 1.306395 0.416841 -36.744991 -5.283128 0.218053 34.485855 3.971036 2.472109 -15.698849 -1.040435 0.755081 +0.362476 38.806316 0.684030 19.219299 0.000000 -0.749149 19.423599 -0.947112 -0.937441 8.942690 -0.341369 -0.908436 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 21.839092 0.000000 0.000000 0.000000 0.000000 0.000000 -0.839652 -14.245700 -0.415399 -23.914400 -19.497572 33.592701 -107.522003 -29.521500 -14.869300 20.085699 16.984200 -43.268299 -5.500660 13.816000 -0.312353 22.683300 36.611198 60.581402 98.150497 -3.954970 -12.238500 3.274230 -0.983606 -22.088699 -39.894325 4.491755 0.787754 37.918022 -4.060559 -3.015096 -17.461912 1.314309 0.719408 -40.126598 -5.464939 0.262521 37.770088 4.026675 2.817820 -17.226969 -1.013632 0.725362 +0.418806 38.570408 0.659856 20.722483 0.000371 -0.698398 21.925980 -0.897968 -0.854108 9.943990 -0.421739 -0.826378 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 21.276041 0.000000 0.000000 0.000000 0.000000 0.000000 -2.636787 -12.108424 -0.415865 -23.380148 -17.147974 31.376001 -114.426384 -29.904379 -18.148598 16.188793 16.090122 -37.242729 -4.624525 10.406150 -0.250793 38.003132 31.348013 61.227314 96.909836 -6.732482 -15.239376 13.659540 -8.586813 -10.386688 -42.184616 4.455307 0.853177 38.898209 -4.071307 -3.127602 -17.642931 1.247033 0.847686 -42.339138 -5.527383 0.299698 38.712227 4.026630 2.913550 -17.437935 -1.086546 0.751437 +0.470027 38.560295 0.537500 22.075094 0.000252 -0.590022 24.305149 -0.683051 -0.643738 10.879402 -0.368050 -0.598724 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 20.450905 0.000000 0.000000 0.000000 0.000000 0.000000 -4.314326 -2.061120 -0.381605 -33.000000 -14.115550 31.957067 -115.549866 -29.321629 -18.301893 9.426320 12.064445 -29.459377 -4.006223 -1.396652 -0.270224 58.268818 23.889788 60.734619 94.714233 -8.634965 -17.155527 26.004545 -14.301908 0.220719 -44.144146 4.275061 0.927850 39.428989 -4.053267 -3.193609 -17.550016 1.172234 1.050050 -44.356495 -5.704026 0.315349 39.388184 4.040677 2.982593 -17.444700 -1.135513 0.841461 +0.503479 38.425930 0.396578 23.249100 0.000000 -0.445360 26.523100 -0.429688 -0.410156 11.737700 -0.263812 -0.351591 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 19.437208 0.000000 0.000000 0.000000 0.000000 0.000000 -5.327276 5.750870 -0.320920 -43.146301 -10.937700 31.295799 -115.459000 -28.086901 -17.907600 -0.142099 9.403570 -20.557501 -3.100580 -8.792010 -0.303078 67.761101 17.826899 59.198200 95.938904 -9.589550 -18.259800 33.138199 -14.938000 4.759030 -45.834064 4.314866 0.989211 39.711548 -4.078915 -3.225394 -17.307428 0.974181 1.027117 -46.021740 -5.792509 0.342220 39.634609 4.016811 3.023484 -17.199602 -1.285044 0.879907 +0.513450 37.915600 0.290780 24.237976 -0.000100 -0.285489 28.545115 -0.241154 -0.236883 12.513763 -0.177837 -0.183135 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 18.308477 0.000000 0.000000 0.000000 0.000000 0.000000 -5.130635 3.922504 -0.242115 -46.501369 -8.108588 26.624149 -117.628578 -26.474400 -18.918341 -12.060907 11.380739 -11.356322 -1.703540 -2.893601 -0.296581 56.383961 15.731756 56.932026 103.243416 -9.643962 -18.837109 30.335001 -8.900452 0.226712 -48.200451 4.258675 1.055037 41.682308 -4.077388 -3.455001 -17.890198 0.859501 1.189828 -48.604504 -5.799381 0.395878 42.007233 4.021275 3.277323 -17.956818 -1.503436 0.700125 +0.522027 37.170944 0.170087 25.121262 -0.000068 -0.130444 30.349710 -0.124492 -0.126212 13.226919 -0.120129 -0.079662 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.138233 0.000000 0.000000 0.000000 0.000000 0.000000 -3.179403 -3.990044 -0.153491 -44.987671 -5.949343 20.262224 -121.166283 -24.600517 -20.783607 -24.291092 16.376520 -3.394674 -0.975486 9.528618 -0.257151 36.534626 16.104755 55.126442 112.424713 -9.328341 -19.220699 22.651859 -0.979683 -8.485764 -51.859070 4.438196 1.099959 46.572193 -4.087337 -3.985937 -19.966703 0.757214 1.383199 -52.109440 -6.162226 0.477151 46.690975 4.015291 3.793008 -20.015800 -1.614220 0.662537 +0.558247 36.431931 -0.041448 26.000000 0.000000 0.000000 31.918699 -0.062693 -0.060130 13.902600 -0.085991 0.000482 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 16.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.071420 -11.690300 -0.063351 -42.837700 -4.737850 15.802200 -124.087997 -22.542200 -22.327101 -34.397701 21.548300 1.608650 -2.417920 17.790600 -0.206006 26.233700 16.428301 55.190899 117.564003 -9.293430 -19.755899 17.591299 2.437580 -14.514900 -55.492226 4.464437 1.146454 51.078640 -4.042045 -4.493260 -21.696751 0.747065 1.666472 -55.763271 -6.441991 0.570450 51.275867 3.965986 4.282466 -21.820293 -1.721154 0.556999 +0.639662 35.895744 -0.387532 26.940039 0.000028 0.090328 33.221195 -0.033057 -0.022501 14.522595 -0.059874 0.072901 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 14.972808 0.000000 0.000000 0.000000 0.000000 0.000000 7.618388 -14.320208 0.019939 -43.347652 -4.910519 16.090668 -124.726074 -20.399120 -22.639198 -40.471943 24.431778 2.512934 -6.845184 14.331100 -0.165234 37.446007 15.306452 58.204987 114.521805 -10.054216 -20.697397 20.345261 -2.441846 -13.228558 -58.544132 4.376616 1.217638 53.752823 -4.004569 -4.771261 -22.243958 0.746998 1.953391 -58.840797 -6.700554 0.682637 53.998302 3.911438 4.583740 -22.403524 -1.782796 0.613730 +0.737887 35.588436 -0.782908 27.866472 0.000020 0.142056 34.175549 0.009865 -0.004705 14.894111 0.017177 0.048998 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 14.157692 0.000000 0.000000 0.000000 0.000000 0.000000 14.264354 -12.775360 0.087764 -46.068596 -7.537896 20.991905 -122.678810 -18.361824 -21.876980 -42.709629 24.075920 0.489690 -12.323046 4.535568 -0.160419 57.913517 15.829904 63.928867 106.275597 -11.582669 -21.937353 26.863382 -9.037084 -8.919993 -60.880535 4.233061 1.332180 54.849899 -3.978914 -4.886033 -21.911282 0.760629 2.188157 -61.214237 -6.925313 0.794454 55.124454 3.901663 4.688744 -22.089235 -1.792314 0.744170 +0.813051 35.493271 -1.110079 28.669201 0.000000 0.160958 34.687401 0.117208 0.000000 14.780700 0.214966 -0.185878 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 13.661200 0.000000 0.000000 0.000000 0.000000 0.000000 18.263700 -9.389770 0.131443 -49.615299 -13.849045 29.624599 -117.861000 -16.643600 -20.464199 -41.832699 19.908001 -2.711510 -16.230101 -4.909890 -0.218015 69.322403 22.211000 71.792801 97.582100 -13.715000 -23.277300 30.784700 -8.173720 -8.113820 -62.332798 4.107049 1.444678 54.702892 -3.981383 -4.874022 -21.109999 0.760024 2.319222 -62.689785 -7.058155 0.861145 55.016376 3.909845 4.683179 -21.305292 -1.791056 0.883963 +0.834620 35.586926 -1.276706 29.267477 -0.000014 0.152605 34.808998 0.283463 0.000050 14.222600 0.507619 -0.596118 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 13.555470 0.000000 0.000000 0.000000 0.000000 0.000000 17.166201 -6.362800 0.142711 -53.065102 -21.918442 38.018902 -112.271004 -15.286300 -19.111601 -39.258999 14.039100 -4.716430 -15.883200 -4.287800 -0.320764 62.588402 32.918598 78.588600 93.205704 -15.934800 -24.120501 28.354200 2.286700 -12.616700 -62.803925 4.064565 1.479046 53.703365 -4.014335 -4.771540 -20.231604 0.727960 2.317249 -63.162815 -7.045812 0.856827 54.007954 3.928659 4.573606 -20.423819 -1.781332 0.958461 +0.809399 35.819733 -1.291084 29.697927 -0.000019 0.121751 35.035187 0.333867 0.006350 14.087456 0.588127 -0.705156 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 13.775038 0.000000 0.000000 0.000000 0.000000 0.000000 10.549014 -4.979941 0.118097 -56.990944 -21.154224 34.425945 -113.396606 -13.829512 -19.171337 -38.207901 15.874632 -2.063887 -9.595161 -1.793272 -0.325915 58.718178 29.992090 74.418198 96.448013 -16.790462 -22.911884 24.766823 2.957112 -9.876057 -62.442818 4.061372 1.463756 51.950195 -4.049381 -4.573466 -19.284386 0.707823 2.180685 -62.796303 -6.933875 0.793625 52.244663 3.964457 4.395602 -19.463221 -1.776723 0.974561 +0.753529 36.135437 -1.186670 30.026520 -0.000017 0.072943 35.432514 0.266337 0.014287 14.402391 0.460175 -0.526458 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 14.220030 0.000000 0.000000 0.000000 0.000000 0.000000 1.668525 -4.890748 0.067112 -61.010052 -13.618633 22.309624 -119.429283 -12.374996 -20.256250 -38.666340 23.739910 3.684849 -0.589281 0.701255 -0.244478 60.639538 15.905934 62.202148 104.643127 -16.379120 -20.237059 21.928497 -6.112171 -0.671522 -61.570660 4.102689 1.421050 49.892696 -4.083106 -4.349771 -18.445383 0.667347 1.973480 -61.865585 -6.756322 0.715531 50.148361 4.011855 4.156655 -18.622873 -1.740674 0.935559 +0.683150 36.477779 -0.996916 30.319223 -0.000010 0.010730 35.923809 0.136125 0.014940 14.915233 0.229040 -0.233560 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 14.790575 0.000000 0.000000 0.000000 0.000000 0.000000 -5.372969 -5.369459 0.002412 -64.385086 -5.326040 9.709088 -125.715576 -11.207907 -21.472614 -39.639160 32.519321 9.556761 6.668138 3.195783 -0.136831 64.453209 -0.320848 48.725239 113.631363 -15.273243 -17.316353 20.271395 -18.252558 9.704787 -60.385437 4.151328 1.360970 47.590019 -4.104626 -4.100489 -17.625320 0.644346 1.730630 -60.702446 -6.538654 0.623847 47.826157 4.034183 3.916989 -17.760040 -1.734279 0.891291 +0.614402 36.790512 -0.755278 30.642000 0.000000 -0.060339 36.431900 -0.001520 -0.000608 15.373800 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 15.386800 0.000000 0.000000 0.000000 0.000000 0.000000 -6.473130 -5.690310 -0.063351 -66.378700 -2.290852 4.663550 -127.601997 -10.613400 -21.926701 -40.131199 37.097198 12.578800 7.710750 5.690310 -0.063351 66.259903 -9.669160 40.772301 119.252998 -14.045300 -15.370100 20.227699 -26.795401 15.960700 -59.840107 4.264082 1.318510 46.442722 -4.127481 -3.971994 -17.352133 0.631946 1.551404 -60.158974 -6.349164 0.577841 46.678535 4.071331 3.785304 -17.468437 -1.704612 0.802750 +0.560351 37.028580 -0.492357 31.043547 0.000011 -0.136003 36.897694 -0.101680 -0.036965 15.589375 -0.144005 0.048215 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 15.938090 0.000000 0.000000 0.000000 0.000000 0.000000 0.547383 -5.690310 -0.119038 -66.451721 -8.227328 12.233951 -122.240677 -10.745245 -21.055971 -39.401493 34.077438 10.831822 0.114345 5.714427 -0.066069 63.290668 -6.204918 42.867119 118.768959 -13.130219 -15.213999 21.871471 -27.046083 14.558911 -59.060230 4.341172 1.304022 45.246178 -4.157879 -3.823872 -17.343874 0.587569 1.398188 -59.324413 -6.216154 0.529597 45.423248 4.104024 3.633646 -17.462452 -1.663637 0.750375 +0.521760 37.191750 -0.227335 31.503473 0.000020 -0.213146 37.334423 -0.160773 -0.081487 15.627058 -0.209382 -0.024806 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 16.490868 0.000000 0.000000 0.000000 0.000000 0.000000 10.176128 -5.690310 -0.159578 -64.857582 -17.649378 25.568535 -114.006012 -11.231691 -19.622635 -37.725807 26.941868 6.612137 -10.376976 5.738544 -0.113622 57.297760 3.666332 50.489632 115.122612 -12.412799 -16.045225 23.844316 -22.205784 8.981297 -58.535275 4.395329 1.312089 44.108704 -4.170279 -3.692605 -17.178604 0.561525 1.276189 -58.835331 -6.086086 0.505916 44.266079 4.115435 3.510509 -17.249807 -1.628922 0.729566 +0.496315 37.291000 0.023456 31.984100 0.000027 -0.288942 37.773399 -0.185547 -0.117219 15.615400 -0.224873 -0.107422 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.120800 0.000000 0.000000 0.000000 0.000000 0.000000 14.977600 -5.690310 -0.181413 -62.047901 -22.770700 34.837200 -109.078003 -11.569600 -18.720100 -35.634102 20.891899 3.269970 -15.976900 5.762660 -0.156299 51.163799 10.454000 56.858700 112.678001 -11.640300 -16.656300 24.429701 -17.449699 4.464610 -58.253098 4.448759 1.350890 43.304169 -4.178583 -3.608409 -17.150145 0.533996 1.213296 -58.579376 -5.989334 0.493922 43.461964 4.124775 3.417379 -17.194435 -1.590487 0.726508 +0.481706 37.337307 0.243688 32.443253 0.000030 -0.360561 38.230701 -0.185507 -0.134339 15.654752 -0.217554 -0.117926 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.843176 0.000000 0.000000 0.000000 0.000000 0.000000 10.054251 -5.690310 -0.184905 -58.637482 -18.413109 33.196072 -111.637154 -11.390344 -19.096989 -33.602322 19.759195 3.245021 -11.517047 5.800663 -0.157073 47.231953 7.643353 57.004669 114.456764 -10.653253 -16.178144 22.715996 -16.645267 4.698306 -58.206238 4.500359 1.390919 42.920765 -4.200592 -3.555289 -17.278471 0.488165 1.187417 -58.524742 -5.938144 0.479697 43.039410 4.146776 3.361155 -17.285810 -1.555374 0.720593 +0.475619 37.341640 0.417032 32.820801 0.000029 -0.425168 38.661518 -0.181174 -0.151561 15.732667 -0.207826 -0.094339 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 18.431730 0.000000 0.000000 0.000000 0.000000 0.000000 0.659846 -5.690310 -0.186082 -55.894051 -9.830338 25.745522 -117.866348 -10.863310 -20.122862 -31.890451 21.896811 5.335100 -2.300193 5.838667 -0.129653 45.687840 0.622562 53.203472 118.111389 -9.665274 -15.095224 21.011145 -18.429129 7.182963 -58.307816 4.544366 1.421744 42.899792 -4.222138 -3.551213 -17.513250 0.476647 1.167114 -58.585941 -5.913530 0.476447 42.891804 4.165473 3.326683 -17.448513 -1.486626 0.719305 +0.475743 37.314980 0.527156 33.052101 0.000026 -0.479928 39.005798 -0.195827 -0.194736 15.808500 -0.214422 -0.104612 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 18.599800 0.000000 0.000000 0.000000 0.000000 0.000000 -5.413890 -5.690310 -0.204886 -55.248600 -4.884220 20.572100 -121.948997 -10.292400 -20.822500 -30.704500 24.288099 7.427510 3.752970 5.876670 -0.100433 46.177700 -2.244370 49.542500 119.952003 -8.983260 -14.230400 22.427999 -20.130199 7.871900 -58.430923 4.578373 1.438483 42.977543 -4.240786 -3.545383 -17.698814 0.478726 1.187765 -58.811337 -5.914156 0.470761 43.097290 4.182164 3.330838 -17.659328 -1.424249 0.716317 +0.479763 37.268307 0.557732 33.090874 0.000022 -0.522005 39.207417 -0.244060 -0.278288 15.845605 -0.249251 -0.193149 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 18.259571 0.000000 0.000000 0.000000 0.000000 0.000000 -2.768985 -5.714527 -0.251854 -57.546078 -8.918501 23.370146 -119.833763 -9.931825 -20.508673 -30.256172 24.693995 7.942932 1.128711 5.907727 -0.089387 48.214436 4.592823 49.011223 117.487335 -8.829416 -14.146097 28.944483 -19.765036 4.056622 -58.651756 4.613183 1.459369 43.456902 -4.265545 -3.585806 -18.001877 0.470216 1.226790 -58.926174 -5.933749 0.458554 43.400658 4.193230 3.360643 -17.878738 -1.373332 0.702105 +0.485369 37.212589 0.492430 32.964252 0.000017 -0.548565 39.225883 -0.305746 -0.370950 15.823350 -0.296928 -0.310157 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 18.118599 0.000000 0.000000 0.000000 0.000000 0.000000 4.418012 -5.738743 -0.299887 -61.287403 -17.205011 30.265554 -114.530182 -9.837060 -19.646080 -30.780045 23.985655 7.435464 -6.059362 5.938784 -0.090809 50.777718 15.429856 50.207623 113.020447 -9.087234 -14.363057 37.998932 -18.100681 -1.618742 -58.816406 4.628808 1.467613 43.839432 -4.264156 -3.628343 -18.098989 0.492629 1.260071 -59.158756 -5.962941 0.456441 43.929287 4.205361 3.419809 -18.048483 -1.328730 0.687418 +0.490248 37.158806 0.314919 32.717701 0.000012 -0.556775 39.024601 -0.352076 -0.430032 15.725100 -0.335241 -0.382298 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 19.083300 0.000000 0.000000 0.000000 0.000000 0.000000 9.576920 -5.762960 -0.312478 -64.387497 -22.497601 34.992100 -110.813004 -10.013900 -18.987400 -32.516399 23.811800 6.992560 -11.290800 5.969840 -0.092574 52.713902 21.748800 50.631802 110.053001 -9.555530 -14.141600 45.894798 -16.591801 -5.171910 -59.011475 4.637550 1.470954 44.162991 -4.268200 -3.657583 -17.971624 0.506263 1.290936 -59.364426 -5.976933 0.467565 44.252796 4.200095 3.464688 -17.921499 -1.324184 0.679880 +0.492087 37.117931 0.008871 32.369793 0.000007 -0.543800 38.567776 -0.362332 -0.425297 15.538086 -0.350139 -0.358340 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 21.325083 0.000000 0.000000 0.000000 0.000000 0.000000 8.021036 -5.738743 -0.265622 -65.303970 -19.641037 33.022362 -112.110893 -10.446970 -19.081141 -35.501492 25.356705 7.414450 -9.890306 6.000900 -0.084983 53.318142 17.628624 48.538265 111.032448 -10.110886 -12.950554 49.797039 -16.382801 -3.757221 -59.200127 4.623494 1.456201 44.280888 -4.257296 -3.682862 -17.550425 0.544121 1.294908 -59.551476 -5.987535 0.488065 44.370564 4.194978 3.482425 -17.498554 -1.348681 0.681286 +0.488574 37.100941 -0.442045 31.831457 0.000003 -0.506807 37.822762 -0.348161 -0.376322 15.265001 -0.360207 -0.275498 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 22.075424 0.000000 0.000000 0.000000 0.000000 0.000000 2.597881 -5.714527 -0.185320 -64.665436 -11.844074 26.784403 -116.468140 -11.036236 -19.659075 -38.955498 27.946854 8.352452 -4.563497 6.031960 -0.068037 53.680908 7.536244 45.199200 114.189323 -10.940988 -11.092796 50.317028 -17.376986 0.924309 -59.370853 4.605515 1.424640 44.251911 -4.241940 -3.693805 -16.816029 0.592825 1.308205 -59.702320 -5.974428 0.515208 44.342781 4.168086 3.479269 -16.789198 -1.398893 0.682267 +0.477396 37.118809 -1.054158 30.986700 0.000000 -0.442961 36.757702 -0.329301 -0.315138 14.912400 -0.392188 -0.193097 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.830799 0.000000 0.000000 0.000000 0.000000 0.000000 -1.961520 -5.690310 -0.110075 -63.643200 -4.406400 20.445101 -120.583000 -11.660500 -20.248800 -41.894600 30.444300 9.170660 0.138835 6.063020 -0.044165 55.341499 -1.464510 42.641201 116.699997 -12.311300 -9.079710 48.927700 -19.167400 6.035040 -59.241955 4.563055 1.364247 43.773506 -4.205196 -3.648562 -15.650778 0.653181 1.261569 -59.625229 -5.954108 0.507074 43.922283 4.144802 3.444372 -15.611598 -1.413009 0.665806 +0.456361 37.188595 -1.807649 29.739758 -0.000001 -0.347132 35.361153 -0.316358 -0.266988 14.497412 -0.452312 -0.155822 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 6.491713 0.000000 0.000000 0.000000 0.000000 0.000000 -2.145736 -5.690310 -0.069637 -63.198685 -1.442783 17.239557 -121.764198 -12.227523 -20.441139 -43.494373 31.970634 9.397632 0.839722 5.931317 -0.023833 59.220589 -3.978403 42.334686 116.279892 -14.358999 -7.444512 46.852718 -21.213804 9.338622 -58.751251 4.523546 1.287549 43.020611 -4.165269 -3.579515 -14.143859 0.686232 1.178833 -58.999508 -5.895900 0.466246 42.993542 4.095813 3.357506 -14.056696 -1.460657 0.659840 +0.423758 37.351707 -2.538123 28.075747 -0.000001 -0.205013 33.703262 -0.283405 -0.229956 14.079426 -0.464758 -0.149801 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -8.425364 0.000000 0.000000 0.000000 0.000000 0.000000 0.678018 -5.690310 -0.058737 -63.453545 -2.327879 16.675438 -119.762711 -12.760953 -20.079823 -43.568153 32.685726 9.219824 -1.142243 5.799613 -0.049665 63.764431 -1.285069 43.525227 112.800903 -16.708189 -6.807645 44.318607 -22.442896 11.004137 -57.418251 4.462357 1.225144 41.641399 -4.106916 -3.442951 -12.443637 0.661695 1.058427 -57.684608 -5.840333 0.407250 41.769703 4.056232 3.251174 -12.486420 -1.528291 0.643490 +0.377994 37.655628 -3.045040 26.000000 0.000000 0.000000 31.874599 -0.195382 -0.195338 13.728400 -0.333192 -0.146524 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -22.000000 0.000000 0.000000 0.000000 0.000000 0.000000 3.922910 -5.690310 -0.063351 -64.319504 -5.251380 17.328600 -114.940002 -13.313400 -19.071800 -42.088699 33.008999 8.988160 -3.314610 5.667910 -0.172323 66.800697 3.667220 44.902199 106.674004 -18.854700 -7.811380 41.302601 -21.648100 11.802000 -54.968609 4.389430 1.159202 39.771160 -4.054286 -3.260601 -10.962905 0.550791 0.892637 -55.195572 -5.752457 0.367366 39.928886 4.007060 3.073056 -11.057323 -1.673188 0.638880 +0.318953 38.127720 -3.179467 23.546251 0.000000 0.273976 29.924931 -0.030935 -0.157063 13.479135 -0.000680 -0.125960 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -30.323940 0.000000 0.000000 0.000000 0.000000 0.000000 5.541530 -5.841119 -0.072284 -65.646683 -8.691671 17.952320 -107.635605 -13.936303 -17.411045 -39.041691 33.216839 9.045874 -3.737565 6.011180 -0.420637 66.712090 8.408029 45.481140 98.416550 -20.358728 -10.833906 37.755501 -18.030050 12.257562 -51.215187 4.328967 1.061903 37.548306 -3.990722 -3.040487 -10.041930 0.374176 0.677386 -51.441826 -5.616601 0.305826 37.745670 3.935127 2.874119 -10.202601 -1.925733 0.638864 +0.252422 38.714821 -2.998926 20.861759 0.000000 0.580853 27.740824 0.176460 -0.119596 13.225813 0.432118 -0.102007 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -33.538361 0.000000 0.000000 0.000000 0.000000 0.000000 5.644354 -6.309535 -0.085651 -67.038956 -12.282095 18.009619 -98.100990 -14.676424 -15.439550 -34.464466 33.013550 9.705404 -2.681954 7.052293 -0.736100 64.101685 12.378549 45.582348 88.971260 -21.038000 -15.197161 33.522255 -12.418194 11.915957 -46.431751 4.284894 0.917936 34.835548 -3.919546 -2.746640 -9.452044 0.143635 0.412241 -46.578945 -5.437628 0.229181 35.149723 3.866679 2.629311 -9.785072 -2.210605 0.631433 +0.185663 39.343632 -2.612547 18.122173 0.000000 0.874034 25.168043 0.379624 -0.090040 12.827464 0.825142 -0.097040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -32.796707 0.000000 0.000000 0.000000 0.000000 0.000000 4.881308 -7.119538 -0.106392 -68.038574 -15.944714 17.140951 -86.565628 -15.579352 -13.586312 -28.407269 31.960405 11.271490 -0.971273 8.511870 -1.038376 60.127617 15.497853 45.852283 79.387169 -20.774611 -19.959013 28.421350 -6.049170 10.077263 -41.180023 4.282103 0.754514 31.943272 -3.855413 -2.456086 -9.081546 -0.094212 0.139016 -41.215866 -5.220684 0.158131 32.208858 3.804297 2.336999 -9.467841 -2.483042 0.624633 +0.125937 39.940872 -2.129459 15.503130 0.000000 1.106926 22.052338 0.531375 -0.075492 12.143113 1.038333 -0.133439 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -29.252394 0.000000 0.000000 0.000000 0.000000 0.000000 3.902315 -8.295110 -0.137448 -68.187790 -19.601603 14.986756 -73.258911 -16.690681 -12.280324 -20.920311 29.618658 14.048881 0.570988 10.110532 -1.247126 55.947994 17.685017 46.937408 70.713303 -19.450640 -24.177347 22.271254 -0.159605 6.041534 -35.829792 4.298052 0.597802 28.951580 -3.782035 -2.153308 -8.843410 -0.275160 -0.099375 -35.751656 -4.981123 0.081476 29.088823 3.741333 2.027508 -9.197730 -2.691096 0.623719 +0.080506 40.433243 -1.658797 13.180300 0.000000 1.232930 18.239500 0.584530 -0.083055 11.031800 0.931629 -0.233580 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -24.058901 0.000000 0.000000 0.000000 0.000000 0.000000 3.357310 -9.860230 -0.181762 -67.028900 -23.174801 11.187500 -58.410400 -18.056000 -11.950600 -12.053900 25.549601 18.342300 1.121320 11.568900 -1.282010 52.721001 18.859100 49.484200 63.998798 -16.948200 -26.910000 14.890500 4.013810 -0.891128 -31.084150 4.331954 0.474518 26.331446 -3.705852 -1.893604 -8.654295 -0.369265 -0.320894 -30.861492 -4.758641 0.019813 26.311203 3.670491 1.748519 -8.989630 -2.806402 0.629204 +0.054092 40.771393 -1.284184 11.256510 -0.000000 1.219992 13.736386 0.511658 -0.114541 9.422005 0.440367 -0.401351 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -18.295893 0.000000 0.000000 0.000000 0.000000 0.000000 3.676138 -11.709208 -0.237709 -64.442574 -26.315805 5.835930 -42.696476 -19.584053 -12.739058 -2.221019 19.646055 23.945627 0.166148 12.619338 -1.097777 51.375637 18.885536 53.518074 59.784973 -13.267807 -27.411766 6.440372 5.612268 -10.636000 -27.359102 4.368839 0.393770 24.582582 -3.657655 -1.727046 -8.733997 -0.331417 -0.454976 -27.095798 -4.590034 -0.006301 24.416021 3.613992 1.560569 -8.943833 -2.789047 0.631835 +0.041244 41.001762 -0.987220 9.543337 -0.000000 1.094216 9.194213 0.364321 -0.150611 7.520013 -0.198535 -0.566678 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -12.747946 0.000000 0.000000 0.000000 0.000000 0.000000 4.408341 -13.217650 -0.285403 -61.663124 -27.593782 0.833991 -28.581322 -20.636215 -13.639316 6.714330 13.127028 28.609266 -1.568454 13.041178 -0.789523 51.924416 17.415142 56.580261 56.582333 -8.883669 -25.725058 -1.546638 5.288215 -19.969751 -24.399946 4.366141 0.339478 23.610546 -3.622101 -1.630248 -9.011787 -0.185034 -0.532132 -24.075653 -4.493885 -0.008025 23.278545 3.564061 1.439948 -9.124274 -2.698539 0.653922 +0.033975 41.194717 -0.724004 7.779560 0.000000 0.896246 5.425330 0.213830 -0.166640 5.601580 -0.672758 -0.640996 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -8.125920 0.000000 0.000000 0.000000 0.000000 0.000000 4.883370 -13.631500 -0.300393 -60.263302 -25.307301 -1.464020 -18.976200 -20.437000 -13.357900 12.525300 7.543140 29.572701 -3.046480 12.625500 -0.487431 54.150700 14.045100 55.590900 52.393700 -4.388460 -22.089199 -7.195160 4.071920 -24.884300 -21.419527 4.309119 0.301695 22.356434 -3.549819 -1.517888 -8.974406 0.060557 -0.600719 -21.092758 -4.425129 0.015271 21.985689 3.495845 1.287565 -9.059346 -2.497507 0.710597 +0.025842 41.405251 -0.460464 5.782166 0.000000 0.663674 3.018154 0.115769 -0.145223 3.891223 -0.753167 -0.562978 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -4.935722 0.000000 0.000000 0.000000 0.000000 0.000000 4.606015 -12.453421 -0.266338 -61.349983 -18.436403 0.553622 -15.835979 -18.488461 -10.997862 13.703527 4.045840 24.996763 -3.487393 11.277147 -0.292293 57.751736 8.630548 48.506786 45.799057 -0.272832 -16.853827 -9.208316 2.821516 -22.615387 -17.631901 4.210936 0.266604 20.657158 -3.469625 -1.384510 -9.095663 0.329034 -0.637911 -17.383837 -4.384878 0.040699 20.384604 3.428974 1.125338 -9.163843 -2.290382 0.773589 +0.016626 41.627163 -0.200273 3.677310 0.000000 0.421283 1.590950 0.059646 -0.099280 2.386564 -0.560990 -0.386076 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -2.781436 0.000000 0.000000 0.000000 0.000000 0.000000 3.813470 -10.270302 -0.201128 -64.069176 -8.823978 5.362802 -17.001925 -15.460677 -7.319203 11.814213 2.075272 16.924261 -3.181946 9.383406 -0.181013 62.054840 2.100458 37.633282 37.744560 3.428364 -10.831960 -8.768463 1.692340 -15.657921 -13.941450 4.107474 0.229931 18.867973 -3.386038 -1.228101 -8.895804 0.602425 -0.714949 -13.791641 -4.348664 0.063143 18.705713 3.347848 0.928864 -8.972164 -2.039609 0.855833 +0.007529 41.840046 0.042303 1.658353 0.000000 0.189858 0.664927 0.024663 -0.045879 1.062167 -0.266103 -0.178592 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.197155 0.000000 0.000000 0.000000 0.000000 0.000000 2.853545 -7.800343 -0.126873 -67.305794 1.343083 11.046847 -19.906881 -12.167443 -3.314929 8.752039 0.869760 7.883547 -2.581525 7.378178 -0.111944 66.385269 -4.492196 25.842848 29.577593 6.724659 -4.854303 -7.324007 0.684501 -7.161310 -10.317179 3.980504 0.180560 17.144051 -3.310687 -1.080024 -8.784680 0.878212 -0.743167 -10.235554 -4.346062 0.077142 17.041887 3.277640 0.747702 -8.858278 -1.776194 0.917111 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -70.100098 9.898810 15.947100 -22.679001 -9.378360 0.076935 5.966730 0.027485 0.177213 -2.021920 5.690310 -0.063351 69.986099 -9.978440 15.864300 22.774000 9.377360 0.099237 -5.916610 -0.127070 0.211624 -7.540078 3.882017 0.146008 15.744670 -3.241251 -0.947839 -8.514585 1.093365 -0.807438 -7.531943 -4.331991 0.100592 15.702465 3.212883 0.590639 -8.576411 -1.585766 0.965128 diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_repulsed.bvh b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_repulsed.bvh new file mode 100644 index 00000000..cf0f2100 --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_repulsed.bvh @@ -0,0 +1,184 @@ +HIERARCHY +ROOT hip +{ + OFFSET 0.00 0.00 0.00 + CHANNELS 6 Xposition Yposition Zposition Xrotation Zrotation Yrotation + JOINT abdomen + { + OFFSET 0.000000 0.000000 0.000000 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT chest + { + OFFSET 0.000000 5.018152 -1.882228 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT neckDummy + { + OFFSET 0.000000 8.316447 0.784897 + CHANNELS 3 Xrotation Yrotation Zrotation + JOINT neck + { + OFFSET 0.000000 2.280413 -0.392801 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT head + { + OFFSET 0.000000 3.496879 0.529469 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT figureHair + { + OFFSET 0.000000 4.699570 0.720622 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 0.000000 -6.419331 0.000000 + } + } + } + } + } + JOINT lCollar + { + OFFSET 0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lShldr + { + OFFSET 6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT lForeArm + { + OFFSET 10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lHand + { + OFFSET 11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 10.353753 0.000000 0.000000 + } + } + } + } + } + JOINT rCollar + { + OFFSET -0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rShldr + { + OFFSET -6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT rForeArm + { + OFFSET -10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rHand + { + OFFSET -11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET -10.353753 0.000000 0.000000 + } + } + } + } + } + } + } + JOINT lThigh + { + OFFSET 4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lShin + { + OFFSET -1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lFoot + { + OFFSET -0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } + JOINT rThigh + { + OFFSET -4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rShin + { + OFFSET 1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rFoot + { + OFFSET 0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } +} +MOTION +Frames: 55 +Frame Time: 0.050000 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -70.104897 9.959680 15.983900 -22.552299 -9.319900 0.134635 5.975360 -0.119941 0.169518 -2.021920 5.690310 -0.063351 70.083900 -9.978520 15.970600 22.553400 9.316290 0.143662 -5.965430 0.128090 0.169127 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.530616 -4.334307 0.100752 15.830232 3.319340 0.622262 -8.660608 -1.559428 0.936809 +-0.003575 41.069645 0.291618 0.000000 0.000000 0.000000 1.018161 -0.015709 0.001127 1.616875 -0.068631 0.011327 0.000000 0.000000 0.000000 1.733998 -0.325004 -0.010468 -0.086501 0.091221 -0.014684 0.000000 0.000000 0.000000 1.873724 -5.416935 -0.064403 -59.415142 16.754374 17.667694 -35.989731 -7.771534 -4.311195 5.133619 5.700052 -1.063449 -2.173924 5.290259 -0.001181 59.900959 -15.646652 17.166435 32.362957 12.635512 -2.539090 -3.524905 -2.122834 -2.028380 -13.612045 4.497028 0.137584 28.831387 -3.899776 -2.104432 -15.464003 1.179360 -0.367304 -13.610057 -4.784067 0.123067 28.780521 3.882394 1.921730 -15.512794 -1.719447 0.420218 +-0.008042 39.988041 0.350131 0.000000 0.000000 0.000000 2.064468 -0.034970 -0.001957 3.427592 -0.139406 0.018348 0.000000 0.000000 0.000000 3.768334 -0.706301 -0.022749 -0.294115 0.198243 -0.034790 0.000000 0.000000 0.000000 1.738459 -5.167413 -0.065364 -47.092705 24.572634 19.594475 -51.540859 -5.989342 -9.520329 4.156883 12.460003 -2.539742 -2.312666 4.925114 0.055565 48.093208 -22.120895 18.542141 43.764084 16.499969 -5.745087 -0.625117 -4.786094 -4.496925 -18.451998 4.881024 0.112347 39.233753 -4.149398 -3.219606 -20.989532 1.256096 0.086141 -18.477676 -5.139310 0.176025 39.221684 4.137331 3.030545 -21.049606 -1.801260 -0.012272 +-0.014220 39.430023 0.375119 0.000000 0.000000 0.000000 1.379720 -0.058167 -0.048668 3.956980 -0.096067 -0.039212 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 -1.520100 0.280711 -0.079193 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -39.795300 29.057301 20.590500 -61.377300 -4.961130 -13.466700 3.512730 16.985100 -3.976380 -2.021920 5.690310 -0.063351 40.389801 -25.345600 19.328501 51.469826 19.179800 -8.803940 1.976780 -7.063970 -5.298480 -20.580112 5.044665 0.088184 43.811947 -4.179464 -3.719604 -23.424221 1.276742 0.264553 -20.595350 -5.286973 0.212114 43.778599 4.187866 3.535518 -23.477573 -1.832180 -0.224473 +-0.019074 39.870884 0.332559 0.000000 0.000000 0.000000 -2.395458 -0.082339 -0.163457 2.077727 0.143276 -0.207912 0.000000 0.000000 0.000000 5.898341 -1.105529 -0.035608 -4.366530 0.310297 -0.153359 0.000000 0.000000 0.000000 2.989475 -7.572152 -0.063315 -42.364014 26.925434 19.786909 -59.878757 -5.372922 -14.483195 3.823878 17.032614 -5.193772 -0.968049 8.412091 -0.489194 40.927189 -22.265930 18.942612 51.690372 19.375071 -10.858658 3.461437 -8.509402 -3.017130 -18.994699 4.932830 0.103248 40.302353 -4.158970 -3.339857 -21.497404 1.271591 0.104611 -19.001810 -5.151322 0.181703 40.271679 4.138422 3.136489 -21.578358 -1.808326 -0.071003 +-0.001657 40.869717 0.228113 0.000000 0.000000 0.000000 -7.835074 -0.083321 -0.274060 -1.313731 0.445341 -0.427666 0.000000 0.000000 0.000000 5.736419 -1.075180 -0.034630 -7.362792 0.301779 -0.184247 0.000000 0.000000 0.000000 4.030186 -10.170990 -0.103771 -51.128189 20.101238 17.849096 -51.309570 -6.500994 -12.151805 6.289315 14.339257 -6.109611 0.529554 11.990705 -1.065363 46.866146 -14.988771 17.709290 46.986889 17.572186 -9.669486 2.321472 -9.767118 0.878633 -14.744857 4.579631 0.140008 30.988152 -3.976104 -2.327360 -16.481709 1.190176 -0.257446 -14.736386 -4.871478 0.124428 30.946112 3.964018 2.155460 -16.533148 -1.731927 0.334577 +0.063452 41.756557 0.077363 0.000000 0.000000 0.000000 -12.816797 -0.031647 -0.284030 -4.815021 0.623053 -0.611727 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 -8.520100 0.280711 -0.079193 0.000000 0.000000 0.000000 4.314043 -12.537759 -0.231623 -60.289238 11.810699 15.826021 -42.405220 -7.269185 -6.366794 12.252100 11.636600 -6.665910 1.988242 14.844906 -1.563295 53.623539 -6.911429 16.180277 41.508293 14.704120 -2.650972 -3.122504 -11.754798 4.199219 -9.768288 4.067308 0.158032 20.025101 -3.543511 -1.225340 -10.519890 1.095845 -0.621800 -9.787580 -4.586547 0.097928 20.023888 3.533732 1.019439 -10.585788 -1.589599 0.878372 +0.190781 42.032425 -0.115652 0.000000 0.000000 0.000000 -15.738819 0.076852 -0.144894 -7.304046 0.537788 -0.692671 0.000000 0.000000 0.000000 5.091331 -0.954271 -0.030736 -6.380908 0.267842 0.208008 0.000000 0.000000 0.000000 3.246287 -13.919806 -0.475354 -65.239822 4.722684 14.554306 -38.515999 -6.848300 2.635280 22.526268 11.072767 -6.833986 3.015871 15.759265 -1.804252 57.529629 -0.795689 14.813597 38.580833 11.569360 11.738563 -13.901322 -15.131921 5.249050 -7.871446 3.695417 0.149934 15.376431 -3.312588 -0.765725 -7.782899 1.039315 -0.593528 -7.919963 -4.634352 0.089621 15.462440 3.313399 0.586696 -7.897211 -1.497805 1.234668 +0.351282 41.882240 -0.393059 0.000000 0.000000 0.000000 -17.081444 0.145161 -0.000072 -8.779832 0.244714 -0.680379 0.000000 0.000000 0.000000 5.031478 -0.943053 -0.030374 -1.612644 0.264693 0.537713 0.000000 0.000000 0.000000 1.173175 -14.350142 -0.789760 -66.137634 -0.722431 14.021228 -39.451355 -5.397014 13.248735 35.699112 12.462098 -6.702373 3.582324 14.981649 -1.808807 58.568256 3.138798 13.692354 38.240055 8.428392 30.865757 -28.305101 -19.525196 4.308610 -9.394735 3.517340 0.194201 17.653378 -3.432544 -0.985120 -8.535607 1.082860 -0.241460 -9.501078 -4.984668 0.085425 17.817183 3.439740 0.822327 -8.665739 -1.472809 1.402163 +0.505013 41.661896 -0.808527 0.000000 0.000000 0.000000 -17.845501 0.050966 -0.040955 -9.521678 -0.152548 -0.604052 0.000000 0.000000 0.000000 5.093934 -0.954759 -0.030751 4.586026 0.267979 0.723818 0.000000 0.000000 0.000000 -1.323781 -14.058190 -1.111217 -64.331612 -4.641374 14.001732 -43.635521 -3.320968 23.525591 50.022617 15.035484 -6.388905 3.747990 13.125747 -1.647365 57.636646 5.307903 12.805930 39.698837 5.407210 51.053471 -44.216763 -24.303129 2.152398 -11.554763 3.391435 0.239317 20.759052 -3.600961 -1.286433 -9.482657 1.143947 0.133941 -11.642502 -5.347980 0.107796 20.895926 3.590903 1.109639 -9.580339 -1.443698 1.539163 +0.621648 41.642170 -1.382684 0.000000 0.000000 0.000000 -18.802845 -0.265661 -0.374323 -9.808887 -0.550380 -0.492896 0.000000 0.000000 0.000000 5.216243 -0.977683 -0.031490 11.016426 0.274414 0.580217 0.000000 0.000000 0.000000 -3.663066 -13.273377 -1.376100 -61.170723 -7.150879 14.270762 -49.492741 -1.025805 31.517872 63.937984 18.023821 -6.011419 3.573258 10.805248 -1.390327 55.632034 6.127502 12.143701 42.170055 2.631807 68.624550 -59.771641 -28.834229 -0.445086 -12.357143 3.195179 0.272574 20.483473 -3.591089 -1.255651 -8.408253 1.152653 0.309339 -12.455382 -5.534608 0.076107 20.650639 3.573918 1.099239 -8.516973 -1.353393 1.725405 +0.709342 41.753376 -2.004003 0.000000 0.000000 0.000000 -19.809423 -0.615122 -0.768517 -9.920762 -0.845163 -0.376113 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 16.479900 0.280711 -0.079193 0.000000 0.000000 0.000000 -5.263173 -12.225127 -1.520783 -58.003899 -8.367682 14.603264 -55.447258 1.082837 35.277607 75.406097 20.658001 -5.687750 3.118513 8.633838 -1.108096 53.451637 6.013471 11.695041 44.866581 0.228171 79.901886 -72.611542 -32.487011 -2.709344 -12.122638 2.968351 0.272076 17.905134 -3.469238 -1.007730 -6.076949 1.134993 0.362928 -12.246922 -5.583670 0.034696 18.123890 3.448002 0.844472 -6.197040 -1.234638 1.944999 +0.783028 41.866840 -2.553159 0.000000 0.000000 0.000000 -20.564121 -0.795285 -0.969069 -10.085657 -0.958504 -0.277567 0.000000 0.000000 0.000000 5.403718 -1.012822 -0.032622 20.041548 0.284276 -1.323804 0.000000 0.000000 0.000000 -5.687039 -11.107864 -1.499056 -55.914989 -8.429913 14.816586 -60.228893 2.675910 33.610607 75.423676 22.329575 -5.508943 2.444547 7.098298 -0.858274 51.828247 5.332490 11.444719 47.151299 -1.701649 82.344681 -72.676979 -34.778358 -4.029438 -11.641778 2.759345 0.258004 15.051002 -3.340250 -0.737296 -3.710738 1.089599 0.376910 -11.796193 -5.594633 -0.004078 15.337096 3.291938 0.575628 -3.875156 -1.118837 2.149803 +0.846277 41.958378 -3.011806 0.000000 0.000000 0.000000 -21.053482 -0.803421 -0.968705 -10.328142 -0.912916 -0.199762 0.000000 0.000000 0.000000 5.422694 -1.016378 -0.032736 21.821569 0.285274 -2.756147 0.000000 0.000000 0.000000 -5.075415 -9.975988 -1.334370 -54.927399 -7.561300 14.897696 -63.789726 3.730748 28.337828 75.441254 23.072725 -5.458877 1.613750 6.177766 -0.647263 50.836830 4.254469 11.359059 48.987053 -3.151389 77.957497 -72.742416 -35.818642 -4.448681 -10.944053 2.538132 0.222398 12.077358 -3.140171 -0.459812 -1.446764 1.065774 0.345460 -11.133385 -5.586823 -0.037105 12.466691 3.138342 0.309922 -1.654657 -1.019342 2.329103 +0.899820 42.029938 -3.386842 0.000000 0.000000 0.000000 -21.335964 -0.686654 -0.821954 -10.621842 -0.756139 -0.139860 0.000000 0.000000 0.000000 5.409140 -1.013838 -0.032654 22.203945 0.284561 -3.862039 0.000000 0.000000 0.000000 -3.713504 -8.848899 -1.067591 -54.799435 -6.006971 14.875963 -66.387421 4.301282 22.034021 75.458832 23.082300 -5.494638 0.688914 5.724474 -0.468664 50.387913 2.900128 11.399775 50.486683 -4.138728 69.881264 -72.807861 -35.866619 -4.173951 -10.646250 2.311741 0.204497 10.062571 -2.989644 -0.278163 0.257621 1.042874 0.407701 -10.632916 -5.637139 -0.054043 10.098088 2.993294 0.095660 0.197990 -0.926348 2.540776 +0.944387 42.083462 -3.685165 0.000000 0.000000 0.000000 -21.470026 -0.492108 -0.583345 -10.940384 -0.535912 -0.095026 0.000000 0.000000 0.000000 5.379322 -1.008249 -0.032474 21.572651 0.282993 -4.127299 0.000000 0.000000 0.000000 -1.886507 -7.745990 -0.739584 -55.289398 -4.012050 14.780756 -68.279640 4.441444 17.273916 75.476410 22.553144 -5.573313 -0.267172 5.590647 -0.316078 50.392010 1.390181 11.528579 51.763023 -4.681349 61.256882 -72.873299 -35.181042 -3.412121 -11.099010 2.244096 0.220648 9.990908 -2.990761 -0.273807 0.770619 1.045546 0.481234 -10.977972 -5.548414 -0.034879 9.984129 2.965119 0.086208 0.662668 -0.942768 2.485943 +0.980709 42.120895 -3.913672 0.000000 0.000000 0.000000 -21.514118 -0.266904 -0.307407 -11.257387 -0.299975 -0.062422 0.000000 0.000000 0.000000 5.349504 -1.002660 -0.032294 20.311665 0.281424 -3.037744 0.000000 0.000000 0.000000 0.120367 -6.686663 -0.391216 -56.155586 -1.821669 14.641445 -69.724014 4.205164 16.632267 75.493988 21.680096 -5.651988 -1.191713 5.628516 -0.183106 50.759636 -0.154650 11.707184 52.928913 -4.796932 55.225296 -72.938736 -34.020653 -2.370069 -11.248100 2.293012 0.226812 9.895164 -3.003968 -0.268458 1.016982 1.027028 0.449719 -11.286947 -5.608764 -0.030773 9.920803 2.972461 0.082394 1.034845 -0.923136 2.527872 +1.009516 42.144188 -4.079264 0.000000 0.000000 0.000000 -21.526697 -0.058167 -0.048668 -11.546480 -0.096067 -0.039212 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 18.804956 0.280711 -0.079193 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -57.156300 0.319050 14.487400 -70.978210 3.646372 22.683800 75.511566 20.658001 -5.687750 -2.021920 5.690310 -0.063351 51.401299 -1.613650 11.897300 54.097187 -4.503160 54.927399 -73.004181 -32.644199 -1.254670 -11.480216 2.224017 0.241394 9.698562 -3.013215 -0.246733 1.449094 1.029224 0.523985 -11.517940 -5.714243 -0.031714 9.757286 2.939417 0.070059 1.425668 -0.888256 2.667301 +1.031539 42.155273 -4.188837 0.000000 0.000000 0.000000 -21.554464 0.096406 0.149133 -11.786451 0.038180 -0.022934 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 17.371590 0.280711 5.034460 0.000000 0.000000 0.000000 3.588840 -4.773105 0.211167 -58.091228 2.210386 14.342970 -72.250893 2.819701 36.948471 75.529144 19.648962 -5.687750 -2.708651 5.656941 0.048404 52.234360 -2.889386 12.067354 55.355286 -3.828197 62.426048 -73.069626 -31.267097 -0.237404 -11.461226 2.171978 0.232602 9.296545 -2.990704 -0.199482 1.835853 1.018998 0.550077 -11.619644 -5.752836 -0.023064 9.606977 2.931235 0.049875 1.680527 -0.874819 2.708277 +1.047510 42.156086 -4.249288 0.000000 0.000000 0.000000 -21.597113 0.196810 0.285406 -11.976748 0.105559 -0.012625 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 16.069910 0.280711 11.676955 0.000000 0.000000 0.000000 4.815366 -3.938340 0.431583 -58.925625 3.834222 14.212427 -73.554741 1.782595 56.726921 75.546722 18.683746 -5.687750 -3.257356 5.524058 0.152639 53.203522 -3.977553 12.212629 56.689072 -2.842159 75.471817 -73.135063 -29.931023 0.652820 -11.487365 2.138235 0.235146 9.150023 -2.966581 -0.198334 2.010347 1.023640 0.558186 -11.702713 -5.783033 -0.023171 9.583891 2.938934 0.058837 1.789290 -0.876076 2.728638 +1.058158 42.148540 -4.267513 0.000000 0.000000 0.000000 -21.642580 0.252469 0.370352 -12.121985 0.118974 -0.007696 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 14.893179 0.280711 18.993977 0.000000 0.000000 0.000000 5.751633 -3.186079 0.605163 -59.666134 5.217855 14.095024 -74.853432 0.593200 78.265045 75.564301 17.760315 -5.687750 -3.687135 5.315993 0.248650 54.260323 -4.897132 12.335121 58.059017 -1.625642 90.737259 -73.200500 -28.634232 1.422643 -11.530880 2.117082 0.238440 9.182247 -2.962119 -0.200471 2.009287 1.025718 0.577671 -11.737325 -5.801158 -0.023723 9.592756 2.943372 0.059743 1.803866 -0.868428 2.748083 +1.064214 42.134567 -4.250411 0.000000 0.000000 0.000000 -21.678808 0.272803 0.414170 -12.226782 0.091324 -0.007558 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 13.834817 0.280711 26.131210 0.000000 0.000000 0.000000 6.447775 -2.516387 0.739176 -60.319408 6.388579 13.990013 -76.110664 -0.690343 97.808746 75.581879 16.876688 -5.687750 -4.017089 5.057078 0.335735 55.356312 -5.667108 12.436827 59.425594 -0.259242 104.894936 -73.265945 -27.375040 2.078557 -11.589218 2.122914 0.241333 9.365378 -2.999033 -0.214668 1.877876 1.023659 0.608097 -11.774894 -5.793068 -0.014921 9.720354 2.927540 0.057049 1.719577 -0.862791 2.757221 +1.066410 42.116081 -4.204875 0.000000 0.000000 0.000000 -21.693733 0.267234 0.427059 -12.295750 0.035512 -0.011623 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 12.888394 0.280711 32.234306 0.000000 0.000000 0.000000 6.953921 -1.929331 0.840889 -60.892086 7.373684 13.896646 -77.290100 -2.009883 111.603821 75.599457 16.030930 -5.687750 -4.266317 4.771645 0.413191 56.443016 -6.306457 12.519739 60.749252 1.176437 114.617325 -73.331390 -26.151800 2.626903 -11.696416 2.132252 0.246687 9.719210 -3.012564 -0.247964 1.642323 1.039094 0.609960 -11.734365 -5.807189 -0.023119 9.813614 2.955719 0.074376 1.594719 -0.869715 2.727051 +1.065477 42.095009 -4.137803 0.000000 0.000000 0.000000 -21.675289 0.245182 0.419219 -12.333503 -0.035561 -0.019301 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 12.047641 0.280711 36.448948 0.000000 0.000000 0.000000 7.320205 -1.424976 0.917568 -61.390808 8.200464 13.814171 -78.355415 -3.307280 115.896187 75.617035 15.221163 -5.687750 -4.453918 4.484026 0.480315 57.471973 -6.834161 12.585854 61.990459 2.600801 116.576981 -73.396828 -24.962923 3.073873 -11.692476 2.099233 0.247636 9.878020 -2.993101 -0.266488 1.479834 1.053410 0.630841 -11.628485 -5.734806 -0.023866 9.912525 2.964937 0.091521 1.372566 -0.898831 2.657314 +1.062145 42.073273 -4.056093 0.000000 0.000000 0.000000 -21.611420 0.216071 0.400851 -12.344656 -0.108994 -0.030005 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 11.306445 0.280711 37.920807 0.000000 0.000000 0.000000 7.596758 -1.003390 0.976481 -61.822227 8.896212 13.741846 -79.270317 -4.524384 106.931694 75.634613 14.445565 -5.687750 -4.598993 4.218555 0.536402 58.394730 -7.269203 12.637166 63.109684 3.933249 107.446442 -73.462265 -23.806873 3.425509 -11.481243 2.170951 0.233721 9.900875 -3.019935 -0.259868 1.250728 1.046689 0.584113 -11.529840 -5.736286 -0.021550 9.943067 2.966142 0.083749 1.246825 -0.892352 2.656240 +1.057039 42.052464 -3.965571 0.000000 0.000000 0.000000 -21.492643 0.187726 0.380456 -12.333246 -0.174146 -0.043193 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 10.658843 0.280711 36.057652 0.000000 0.000000 0.000000 7.825623 -0.663836 1.023769 -62.192272 9.484540 13.678993 -80.006157 -5.613531 83.040710 75.652191 13.702356 -5.687750 -4.717636 3.995034 0.580990 59.172321 -7.628049 12.675479 64.075241 5.107770 85.756775 -73.527710 -22.682150 3.687703 -11.572085 2.057659 0.233250 9.993114 -2.983310 -0.273318 1.239219 1.075252 0.662181 -11.406127 -5.720028 -0.029562 9.957099 2.952042 0.093211 1.114984 -0.904277 2.645644 +1.050375 42.032848 -3.867851 0.000000 0.000000 0.000000 -21.319798 0.161592 0.359748 -12.300985 -0.229423 -0.058514 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 10.099039 0.280711 31.315573 0.000000 0.000000 0.000000 8.016469 -0.402367 1.061060 -62.503944 9.974342 13.625215 -80.564972 -6.568969 50.891396 75.669769 12.989823 -5.687750 -4.813915 3.815156 0.614567 59.803772 -7.917108 12.701810 64.886795 6.116704 57.473003 -73.593155 -21.587326 3.866199 -11.422311 2.065311 0.224759 10.013497 -2.983302 -0.274584 1.074313 1.080208 0.643986 -11.286693 -5.718713 -0.026750 10.004434 2.965364 0.087485 0.945755 -0.904465 2.644204 +1.042262 42.014351 -3.763482 0.000000 0.000000 0.000000 -21.096302 0.137519 0.338746 -12.249004 -0.275493 -0.075665 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 9.621389 0.280711 24.412775 0.000000 0.000000 0.000000 8.170875 -0.214236 1.088858 -62.759533 10.370831 13.580185 -80.956490 -7.395422 19.236538 75.687355 12.306302 -5.687750 -4.888893 3.676081 0.637859 60.297600 -8.140276 12.716986 65.551865 6.966972 30.418791 -73.658592 -20.521015 3.966585 -11.271390 2.078650 0.215970 10.031225 -2.992287 -0.276441 0.902858 1.078185 0.645700 -11.141235 -5.701494 -0.034044 10.025321 2.963605 0.088637 0.780164 -0.913359 2.623420 +1.032807 41.996906 -3.652997 0.000000 0.000000 0.000000 -20.825577 0.115357 0.317466 -12.178433 -0.313025 -0.094342 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 9.220411 0.280711 16.067442 0.000000 0.000000 0.000000 8.290419 -0.094696 1.107665 -62.961323 10.679217 13.543579 -81.190422 -8.097614 -3.171250 75.704941 11.650187 -5.687750 -4.943633 3.574974 0.651595 60.662327 -8.301450 12.721831 66.077965 7.665501 12.417651 -73.724030 -19.481895 3.994303 -11.100560 2.087380 0.216420 10.040183 -2.995381 -0.287023 0.718425 1.082073 0.637667 -11.062395 -5.850107 -0.046693 10.094947 3.003951 0.095855 0.638668 -0.875882 2.739345 +1.022115 41.980450 -3.536921 0.000000 0.000000 0.000000 -20.511045 0.094956 0.295926 -12.090405 -0.342685 -0.114241 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 8.890780 0.280711 6.997760 0.000000 0.000000 0.000000 8.376680 -0.038998 1.117986 -63.111603 10.904716 13.515073 -81.276497 -8.680274 -7.579302 75.722519 11.019927 -5.687750 -4.979196 3.508996 0.656501 60.906475 -8.404526 12.717174 66.472618 8.219215 11.293159 -73.789474 -18.468699 3.954642 -10.803932 2.224873 0.215493 10.076163 -3.011573 -0.290116 0.400870 1.049075 0.523503 -10.892092 -5.756381 -0.035999 10.184278 2.977061 0.099630 0.385221 -0.918599 2.678955 +1.010289 41.964924 -3.415763 0.000000 0.000000 0.000000 -20.156128 0.076166 0.274142 -11.986047 -0.365141 -0.135059 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 8.627332 0.280711 -2.078106 0.000000 0.000000 0.000000 8.431240 -0.042394 1.120322 -63.212666 11.052543 13.494341 -81.224442 -9.148129 11.453605 75.740097 10.414029 -5.687750 -4.996646 3.475310 0.653305 61.038570 -8.453401 12.703837 66.743340 8.635043 31.790518 -73.854919 -17.480204 3.852738 -10.715137 2.176933 0.202515 10.228693 -2.978470 -0.288039 0.157983 1.072412 0.525714 -10.965322 -5.784906 -0.037121 10.736565 3.034877 0.149453 -0.101066 -0.922224 2.645722 +0.997425 41.950260 -3.290021 0.000000 0.000000 0.000000 -19.764242 0.058837 0.252132 -11.866491 -0.381061 -0.156492 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 8.425063 0.280711 -10.441907 0.000000 0.000000 0.000000 8.455674 -0.100136 1.115176 -63.266785 11.127905 13.481055 -81.043961 -9.505902 46.122265 75.757683 9.831062 -5.687750 -4.997046 3.471078 0.642735 61.067127 -8.451968 12.682648 66.897636 8.919904 66.340797 -73.920357 -16.515263 3.693578 -10.763491 2.232095 0.203313 10.731777 -3.030291 -0.333747 -0.288382 1.085393 0.529977 -11.282845 -5.810635 -0.032731 11.838208 3.112787 0.256838 -0.879408 -0.955866 2.580562 +0.983622 41.936405 -3.160180 0.000000 0.000000 0.000000 -19.338810 0.042819 0.229914 -11.732870 -0.391113 -0.178237 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 8.279131 0.280711 -17.375481 0.000000 0.000000 0.000000 8.451563 -0.207477 1.103051 -63.276264 11.136019 13.474894 -80.744789 -9.758321 85.310112 75.775269 9.269651 -5.687750 -4.981457 3.493464 0.625518 61.000675 -8.404126 12.654433 66.943039 9.080727 104.296783 -73.985794 -15.572782 3.481996 -11.174755 2.311346 0.222162 12.059752 -3.130114 -0.457673 -1.200906 1.103497 0.568022 -11.394887 -5.807710 -0.025903 12.468336 3.131700 0.309339 -1.392277 -0.974234 2.546844 +0.968971 41.923298 -3.026714 0.000000 0.000000 0.000000 -18.883251 0.027961 0.207504 -11.586314 -0.395964 -0.199991 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 8.184856 0.280711 -22.160639 0.000000 0.000000 0.000000 8.420486 -0.359668 1.084450 -63.243385 11.082096 13.475529 -80.336647 -9.910111 117.900543 75.792847 8.728485 -5.687750 -4.950944 3.539630 0.602380 60.847733 -8.313772 12.620020 66.887062 9.124436 135.011246 -74.051239 -14.651735 3.222676 -11.283802 2.361093 0.226080 12.694036 -3.171211 -0.512931 -1.725075 1.109140 0.563450 -11.497407 -5.823267 -0.017201 13.135139 3.201374 0.370087 -1.958602 -0.996132 2.492824 +0.953565 41.910892 -2.890085 0.000000 0.000000 0.000000 -18.400980 0.014115 0.184920 -11.427952 -0.396282 -0.221448 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 8.137721 0.280711 -24.079193 0.000000 0.000000 0.000000 8.364022 -0.551961 1.059877 -63.170425 10.971350 13.482635 -79.829239 -9.966000 132.776947 75.810425 8.206316 -5.687750 -4.906568 3.606738 0.574050 60.616814 -8.184801 12.580231 66.737206 9.057956 147.836929 -74.116684 -13.751163 2.920152 -11.333325 2.405683 0.236790 13.297147 -3.211026 -0.576338 -2.277096 1.123538 0.559404 -11.526469 -5.810888 -0.008488 13.652446 3.220814 0.416199 -2.449708 -1.027261 2.468413 +0.937491 41.899136 -2.750744 0.000000 0.000000 0.000000 -17.895414 0.001128 0.162179 -11.258913 -0.392735 -0.242307 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 8.133371 0.280711 -22.646431 0.000000 0.000000 0.000000 8.283748 -0.779608 1.029832 -63.059666 10.808991 13.495886 -79.232285 -9.930711 122.488243 75.828011 7.701962 -5.687750 -4.849391 3.691950 0.541255 60.316433 -8.021108 12.535889 66.500977 8.888209 135.700241 -74.182121 -12.870178 2.578812 -11.401390 2.460109 0.238231 13.869352 -3.253809 -0.619054 -2.781458 1.119269 0.564124 -11.590367 -5.814054 -0.010256 14.253758 3.261509 0.489552 -2.982605 -1.056610 2.413963 +0.920836 41.887974 -2.609133 0.000000 0.000000 0.000000 -17.369976 -0.011148 0.139298 -11.080328 -0.385990 -0.262264 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 8.167614 0.280711 -18.311543 0.000000 0.000000 0.000000 8.181242 -1.037862 0.994820 -62.913403 10.600234 13.514956 -78.555511 -9.808970 94.245224 75.845596 7.214309 -5.687750 -4.780475 3.792429 0.504721 59.955112 -7.826589 12.487821 66.185890 8.622121 105.822021 -74.247559 -12.007961 2.202889 -11.449656 2.509510 0.248556 14.451900 -3.289697 -0.681083 -3.309859 1.126463 0.559711 -11.598775 -5.799158 -0.001092 14.742434 3.269793 0.523252 -3.461432 -1.070708 2.379826 +0.903681 41.877361 -2.465684 0.000000 0.000000 0.000000 -16.828089 -0.022863 0.116294 -10.893331 -0.376715 -0.281014 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 8.236419 0.280711 -11.757246 0.000000 0.000000 0.000000 8.058085 -1.321973 0.955344 -62.733917 10.350291 13.539520 -77.808647 -9.605506 58.924500 75.863174 6.742315 -5.687750 -4.700884 3.905339 0.465177 59.541382 -7.605141 12.436853 65.799477 8.266616 68.997063 -74.313004 -11.163783 1.796478 -11.451406 2.546882 0.247323 14.928498 -3.305471 -0.724813 -3.787753 1.139063 0.545309 -11.597344 -5.782073 0.008194 15.217825 3.289071 0.567369 -3.940713 -1.102522 2.354734 +0.886109 41.867264 -2.320819 0.000000 0.000000 0.000000 -16.273169 -0.034168 0.093186 -10.699052 -0.365578 -0.298255 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 8.335921 0.280711 -3.666220 0.000000 0.000000 0.000000 7.915856 -1.627195 0.911907 -62.523502 10.064376 13.569254 -77.001411 -9.325042 27.402363 75.880753 6.285009 -5.687750 -4.611681 4.027840 0.423350 59.083755 -7.360660 12.383813 65.349251 7.828619 36.019855 -74.378448 -10.336990 1.363526 -11.401352 2.588371 0.253003 15.322155 -3.334616 -0.754612 -4.225925 1.133363 0.539720 -11.547707 -5.774317 0.018825 15.639995 3.323890 0.599871 -4.411446 -1.118609 2.300792 +0.868198 41.857628 -2.174953 0.000000 0.000000 0.000000 -15.708636 -0.045213 0.069989 -10.498622 -0.353246 -0.313682 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 8.462417 0.280711 5.278851 0.000000 0.000000 0.000000 7.756131 -1.948780 0.865010 -62.284435 9.747700 13.603830 -76.143524 -8.972304 10.555206 75.898338 5.841499 -5.687750 -4.513928 4.157096 0.379966 58.590755 -7.097041 12.329524 64.842728 7.315057 17.684967 -74.443886 -9.527024 0.907840 -11.360734 2.631287 0.259119 15.747180 -3.352884 -0.805397 -4.688728 1.136574 0.525021 -11.553981 -5.761656 0.018553 16.116022 3.334880 0.653148 -4.878325 -1.141452 2.265919 +0.850024 41.848423 -2.028497 0.000000 0.000000 0.000000 -15.137914 -0.056147 0.046721 -10.293172 -0.340387 -0.326993 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 8.612362 0.280711 14.395278 0.000000 0.000000 0.000000 7.580491 -2.281978 0.815158 -62.019005 9.405477 13.642923 -75.244698 -8.552019 15.874070 75.915924 5.410973 -5.687750 -4.408688 4.290269 0.335754 58.070896 -6.818181 12.274813 64.287415 6.732852 21.458866 -74.509323 -8.733425 0.433090 -11.339501 2.679448 0.256239 16.179729 -3.383291 -0.848176 -5.139416 1.138476 0.519792 -11.531921 -5.744235 0.037196 16.549364 3.361320 0.685761 -5.341311 -1.175445 2.220739 +0.831663 41.839615 -1.881853 0.000000 0.000000 0.000000 -14.564417 -0.067121 0.023400 -10.083832 -0.327669 -0.337884 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 8.782373 0.280711 23.000401 0.000000 0.000000 0.000000 7.390513 -2.622044 0.762852 -61.729507 9.042918 13.686209 -74.314667 -8.068912 37.308685 75.933502 4.992705 -5.687750 -4.297024 4.424523 0.291440 57.532707 -6.527976 12.220505 63.690834 6.088930 41.495598 -74.574768 -7.955839 -0.057184 -11.319334 2.722201 0.253670 16.634907 -3.400803 -0.881781 -5.616345 1.149593 0.505586 -11.430655 -5.728688 0.039189 16.834682 3.379668 0.707502 -5.726814 -1.194276 2.186441 +0.813187 41.831165 -1.735425 0.000000 0.000000 0.000000 -13.991568 -0.078286 0.000042 -9.871733 -0.315759 -0.346051 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 8.969225 0.280711 30.411474 0.000000 0.000000 0.000000 7.187779 -2.964228 0.708597 -61.418221 8.665239 13.733360 -73.363144 -7.527710 65.423187 75.951080 4.586071 -5.687750 -4.179997 4.557019 0.247752 56.984703 -6.230322 12.167425 63.060497 5.390218 68.620857 -74.640213 -7.194044 -0.559561 -11.257494 2.767110 0.259162 16.988264 -3.426367 -0.919007 -6.035226 1.145501 0.480307 -11.384509 -5.713866 0.049171 17.217546 3.406302 0.747466 -6.160225 -1.219429 2.151328 +0.794670 41.823051 -1.589620 0.000000 0.000000 0.000000 -13.422781 -0.089790 -0.023335 -9.658005 -0.305326 -0.351190 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 9.169843 0.280711 35.945839 0.000000 0.000000 0.000000 6.973866 -3.303782 0.652894 -61.087425 8.277651 13.784053 -72.399834 -6.933138 90.781921 75.968666 4.190545 -5.687750 -4.058671 4.684919 0.205418 56.435402 -5.929114 12.116398 62.403908 4.643640 93.660507 -74.705650 -6.447953 -1.070735 -11.147503 2.805950 0.252426 17.263830 -3.443369 -0.940133 -6.412454 1.146235 0.464476 -11.300026 -5.688401 0.060522 17.555124 3.408567 0.780403 -6.572922 -1.245930 2.115953 +0.776182 41.815243 -1.444846 0.000000 0.000000 0.000000 -12.861479 -0.101784 -0.046713 -9.443778 -0.297036 -0.352998 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 9.381301 0.280711 38.920807 0.000000 0.000000 0.000000 6.750352 -3.635958 0.596246 -60.739410 7.885365 13.837959 -71.434471 -6.289922 103.949188 75.986252 3.805721 -5.687750 -3.934108 4.805387 0.165164 55.893322 -5.628249 12.068251 61.728592 3.856121 107.440399 -74.771088 -5.717649 -1.587491 -11.066749 2.843658 0.256945 17.589962 -3.452251 -0.983707 -6.819008 1.145248 0.449037 -11.205841 -5.680215 0.061998 17.836874 3.440804 0.823825 -6.954199 -1.279267 2.070714 +0.757796 41.807720 -1.301529 0.000000 0.000000 0.000000 -12.310825 -0.114362 -0.070054 -9.230215 -0.291376 -0.351324 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 9.600812 0.280711 38.855896 0.000000 0.000000 0.000000 6.519031 -3.956773 0.539149 -60.376888 7.493150 13.894665 -70.475998 -5.603960 98.295967 76.003830 3.431328 -5.687750 -3.807395 4.916215 0.127562 55.365719 -5.331188 12.023619 61.041878 3.035271 103.490265 -74.836533 -5.003412 -2.106691 -10.955760 2.883597 0.250704 17.844954 -3.471880 -1.004010 -7.194607 1.148067 0.433363 -11.110666 -5.654149 0.072761 18.115448 3.439844 0.843254 -7.337477 -1.300263 2.035835 +0.739585 41.800468 -1.160113 0.000000 0.000000 0.000000 -11.772005 -0.127395 -0.093257 -9.018311 -0.288037 -0.346696 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 9.825714 0.280711 36.149323 0.000000 0.000000 0.000000 6.282412 -4.265990 0.481997 -60.004139 7.103456 13.953421 -69.528900 -4.885880 78.419975 76.021408 3.067257 -5.687750 -3.679588 5.018080 0.092449 54.853767 -5.039172 11.982244 60.349701 2.191094 86.155380 -74.901978 -4.305768 -2.625234 -10.864950 2.922007 0.245064 18.130983 -3.482973 -1.035005 -7.560136 1.149236 0.407931 -11.004855 -5.627404 0.083874 18.372049 3.449640 0.862261 -7.700850 -1.320073 2.010880 +0.721626 41.793476 -1.021082 0.000000 0.000000 0.000000 -11.245881 -0.140703 -0.116207 -8.809041 -0.286547 -0.339773 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 10.053450 0.280711 31.380388 0.000000 0.000000 0.000000 6.043107 -4.564137 0.425161 -59.625687 6.718192 14.013424 -68.596710 -4.147029 51.725834 76.038994 2.713594 -5.687750 -3.551722 5.112251 0.059516 54.357349 -4.752959 11.943695 59.657574 1.333854 62.485104 -74.967415 -3.625564 -3.140007 -10.774095 2.959335 0.239512 18.406771 -3.497012 -1.056069 -7.923855 1.160245 0.392779 -10.903072 -5.614143 0.095967 18.636433 3.469160 0.893126 -8.062872 -1.346691 1.965770 +0.704002 41.786732 -0.884975 0.000000 0.000000 0.000000 -10.733617 -0.154115 -0.138780 -8.603445 -0.286476 -0.331157 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 10.281530 0.280711 25.078176 0.000000 0.000000 0.000000 5.803661 -4.851476 0.369018 -59.245899 6.339370 14.073899 -67.683289 -3.398232 25.617941 76.056580 2.370677 -5.687750 -3.424830 5.199811 0.028506 53.876717 -4.473446 11.907605 58.970993 0.473485 39.528614 -75.032852 -2.964060 -3.647809 -10.672854 2.993339 0.243892 18.644728 -3.498184 -1.082953 -8.269635 1.156898 0.366677 -10.803550 -5.594307 0.097796 18.882118 3.483789 0.912293 -8.406134 -1.366092 1.931031 +0.686808 41.780247 -0.752423 0.000000 0.000000 0.000000 -10.236819 -0.167464 -0.160843 -8.402678 -0.287443 -0.321395 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 10.507481 0.280711 17.722795 0.000000 0.000000 0.000000 5.566613 -5.127926 0.313968 -58.869102 5.969206 14.134088 -66.793106 -2.649998 7.500778 76.074158 2.039185 -5.687750 -3.299973 5.281631 -0.000776 53.412628 -4.201743 11.873686 58.295631 -0.380181 24.335159 -75.098297 -2.323115 -4.145218 -10.561984 3.027426 0.237621 18.870464 -3.511643 -1.110360 -8.604058 1.162423 0.351107 -10.693117 -5.576148 0.108925 19.097656 3.498315 0.939190 -8.737773 -1.395528 1.895500 +0.670154 41.774025 -0.624215 0.000000 0.000000 0.000000 -9.757773 -0.180577 -0.182239 -8.208106 -0.289109 -0.310984 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 10.728732 0.280711 9.748298 0.000000 0.000000 0.000000 5.334610 -5.392929 0.260457 -58.499752 5.610299 14.193216 -65.931664 -1.912865 2.741249 67.381119 1.720296 -5.687750 -3.178304 5.358330 -0.028452 52.966557 -3.939300 11.841744 57.637650 -1.217013 21.996048 -67.849709 -1.705487 -4.628358 -10.450992 3.060638 0.231427 19.078041 -3.519021 -1.116101 -8.919491 1.161105 0.334633 -10.573088 -5.555069 0.121148 19.293594 3.513147 0.955092 -9.052128 -1.408550 1.861370 +0.654188 41.768105 -0.501420 0.000000 0.000000 0.000000 -9.299914 -0.193268 -0.202769 -8.021501 -0.291181 -0.300381 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 10.942407 0.280711 1.549663 0.000000 0.000000 0.000000 5.110626 -5.645186 0.209033 -58.142803 5.265975 14.250444 -65.106316 -1.198106 8.015506 50.059090 1.416007 -5.687750 -3.061182 5.430202 -0.054536 52.541157 -3.688173 11.811718 57.004360 -2.025777 29.262079 -53.361572 -1.115446 -5.092423 -10.350139 3.092659 0.226327 19.275366 -3.524204 -1.140321 -9.214911 1.160792 0.308272 -10.463972 -5.532027 0.123213 19.471731 3.514140 0.977323 -9.334943 -1.433218 1.836318 +0.639132 41.762543 -0.385681 0.000000 0.000000 0.000000 -8.868917 -0.205306 -0.222140 -7.845476 -0.293408 -0.290027 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 11.144811 0.280711 -6.498878 0.000000 0.000000 0.000000 4.898497 -5.882055 0.160466 -57.804543 4.941113 14.304726 -64.328232 -0.519413 18.615625 29.696156 1.129854 -5.687750 -2.950454 5.497033 -0.078879 52.141251 -3.451611 11.783741 56.405693 -2.792221 41.552631 -36.318134 -0.560176 -5.530578 -10.249703 3.122179 0.220870 19.462349 -3.533430 -1.154759 -9.499161 1.170211 0.292400 -10.364842 -5.512748 0.134952 19.658541 3.522111 1.001906 -9.628102 -1.454548 1.811305 +0.625396 41.757481 -0.280121 0.000000 0.000000 0.000000 -8.476070 -0.216318 -0.239816 -7.684869 -0.295560 -0.280421 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 11.329863 0.280711 -13.982878 0.000000 0.000000 0.000000 4.704571 -6.097694 0.116125 -57.495216 4.644675 14.354384 -63.618507 0.101826 30.796021 9.322645 0.869158 -5.687750 -2.849314 5.557580 -0.100974 51.776985 -3.235913 11.758369 55.858891 -3.493115 55.191376 -19.261585 -0.054127 -5.930536 -10.149719 3.149197 0.215572 19.609488 -3.541401 -1.176621 -9.754741 1.172011 0.275618 -10.265499 -5.491796 0.136906 19.816296 3.527753 1.013774 -9.882777 -1.468649 1.777553 +0.614267 41.753380 -0.194593 0.000000 0.000000 0.000000 -8.157831 -0.225249 -0.254140 -7.554726 -0.297331 -0.272602 0.000000 0.000000 0.000000 5.335950 -1.000120 -0.032212 11.479900 0.280711 -20.079193 0.000000 0.000000 0.000000 4.547343 -6.272320 0.080190 -57.244408 4.404460 14.394654 -63.043453 0.605680 41.235840 -7.593903 0.658001 -5.687750 -2.767334 5.606545 -0.118851 51.481953 -3.061163 11.737844 55.415676 -4.061421 66.793831 -5.098297 0.355801 -6.254670 -10.081352 3.172135 0.211947 19.757627 -3.547404 -1.178144 -9.971728 1.166701 0.267781 -10.191556 -5.485282 0.138123 19.933298 3.539629 1.023882 -10.079520 -1.473459 1.754848 diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_sad.bvh b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_sad.bvh new file mode 100644 index 00000000..090f5bdd --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_sad.bvh @@ -0,0 +1,179 @@ +HIERARCHY +ROOT hip +{ + OFFSET 0.00 0.00 0.00 + CHANNELS 6 Xposition Yposition Zposition Xrotation Zrotation Yrotation + JOINT abdomen + { + OFFSET 0.000000 0.000000 0.000000 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT chest + { + OFFSET 0.000000 5.018152 -1.882228 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT neckDummy + { + OFFSET 0.000000 8.316447 0.784897 + CHANNELS 3 Xrotation Yrotation Zrotation + JOINT neck + { + OFFSET 0.000000 2.280413 -0.392801 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT head + { + OFFSET 0.000000 3.496879 0.529469 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT figureHair + { + OFFSET 0.000000 4.699570 0.720622 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 0.000000 -6.419331 0.000000 + } + } + } + } + } + JOINT lCollar + { + OFFSET 0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lShldr + { + OFFSET 6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT lForeArm + { + OFFSET 10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lHand + { + OFFSET 11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 10.353753 0.000000 0.000000 + } + } + } + } + } + JOINT rCollar + { + OFFSET -0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rShldr + { + OFFSET -6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT rForeArm + { + OFFSET -10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rHand + { + OFFSET -11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET -10.353753 0.000000 0.000000 + } + } + } + } + } + } + } + JOINT lThigh + { + OFFSET 4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lShin + { + OFFSET -1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lFoot + { + OFFSET -0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } + JOINT rThigh + { + OFFSET -4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rShin + { + OFFSET 1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rFoot + { + OFFSET 0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } +} +MOTION +Frames: 50 +Frame Time: 0.125000 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -70.104897 9.959680 15.983900 -22.552299 -9.319900 0.134635 5.975360 -0.119941 0.169518 -2.021920 5.690310 -0.063351 70.083900 -9.978520 15.970600 22.553400 9.316290 0.143662 -5.965430 0.128090 0.169127 -7.548709 4.016634 0.126881 15.890360 -3.336124 -0.813312 -8.628910 1.044381 -0.888102 -7.530616 -4.334307 0.100752 15.830232 3.319340 0.622262 -8.660608 -1.559428 0.936809 +0.641969 42.187958 0.250649 0.000000 0.000000 0.000000 0.386418 0.078759 -0.012004 -0.256704 -0.012910 -0.115113 0.000000 0.000000 0.000000 -2.574532 -1.362167 0.260832 -1.055014 -1.024317 0.002206 0.000000 0.000000 0.000000 0.295707 3.706243 0.649559 -80.090179 10.094073 15.989038 -22.536488 -9.349968 0.132058 8.138763 -0.329497 -1.243013 -0.517056 -4.196613 0.602215 80.501709 -6.418766 15.630506 13.994238 6.363006 0.983108 -2.811463 5.622548 -1.475455 -5.816685 2.857898 0.108097 12.279718 -3.136223 -0.482662 -6.778389 1.091077 0.006004 -5.908698 -5.241153 0.117082 12.480851 3.120473 0.319266 -6.905432 -1.427760 2.081830 +1.269360 42.340870 0.191726 0.000000 0.000000 0.000000 0.749627 0.139974 -0.031803 -0.592310 -0.037000 -0.225312 0.000000 0.000000 0.000000 -5.757330 -3.019660 0.596156 -2.324980 -2.214530 0.013376 0.000000 0.000000 0.000000 -1.775930 13.037988 1.463990 -90.060165 9.885670 16.048800 -22.485201 -9.328300 0.136879 9.403810 -0.441501 -3.112450 1.251720 -12.876521 1.364910 88.761009 -4.713940 15.561700 10.837900 5.264130 1.291640 -0.422692 8.045620 -3.437540 -4.953509 1.805527 0.066840 10.038667 -3.001580 -0.277177 -5.416463 1.151286 0.874642 -4.954569 -6.111100 0.105531 10.071378 2.980199 0.092888 -5.431526 -1.306272 3.111904 +1.492495 42.296371 -0.015384 0.000000 0.000000 0.000000 0.884192 0.141326 -0.054702 -0.915613 -0.066177 -0.270157 0.000000 0.000000 0.000000 -8.525320 -4.413720 0.907541 -3.376780 -3.130960 0.036118 0.000000 0.000000 0.000000 -3.456830 16.808372 2.076040 -94.244217 8.898510 16.206600 -22.299601 -9.233840 0.165409 7.769730 -0.241183 -4.987080 2.642710 -12.990220 1.938550 86.410835 -8.283970 16.194901 22.515400 9.331130 0.152796 -1.354590 1.474210 -5.066080 -5.309512 1.461003 0.071584 10.076133 -3.012745 -0.280449 -5.111109 1.175269 1.224248 -5.303191 -6.456789 0.103633 10.100794 2.984084 0.095041 -5.092728 -1.252769 3.459993 +1.425502 41.964611 -0.097891 0.000000 0.000000 0.000000 1.090547 0.230181 -0.034370 -0.841079 -0.030438 -0.326604 0.000000 0.000000 0.000000 -8.126865 -4.233254 0.835160 -3.300905 -3.153265 0.015010 0.000000 0.000000 0.000000 -3.261812 16.100510 2.151296 -93.723564 8.382042 16.215948 -21.772697 -9.286470 0.228527 7.636019 -0.298559 -4.900937 2.612767 -8.928617 1.992323 82.246780 -7.836957 16.303064 23.705919 9.983288 0.082367 -2.200259 -0.118637 -5.158311 -8.032195 1.726786 0.200959 15.765966 -3.358582 -0.807401 -8.066228 1.264318 1.407285 -8.308896 -6.647347 0.195305 16.304905 3.335968 0.675667 -8.301224 -1.341765 3.203392 +1.247182 41.524879 -0.052641 0.000000 0.000000 0.000000 1.513670 0.371094 0.000000 -0.390622 0.009750 -0.439450 0.000000 0.000000 0.000000 -5.212830 -2.835280 0.446754 -2.368080 -2.537750 -0.048768 0.000000 0.000000 0.000000 -1.923930 12.503065 1.766250 -90.609795 7.866410 16.111099 -20.529200 -8.611710 0.390751 9.327760 -1.348270 -3.694140 1.593150 -3.749084 1.643850 78.681366 -4.970130 16.068001 17.497900 7.591150 0.737828 -2.962360 3.005060 -4.061910 -11.258701 2.253158 0.316695 22.702023 -3.703945 -1.482624 -11.743346 1.321290 1.424811 -11.495235 -6.626107 0.297698 23.126839 3.680140 1.343994 -11.935324 -1.447342 2.680725 +1.090265 41.176437 0.040430 0.000000 0.000000 0.000000 2.192844 0.487800 0.007642 0.294025 -0.022269 -0.628110 0.000000 0.000000 0.000000 -1.242403 -0.954841 -0.083175 -1.111793 -1.714710 -0.136940 0.000000 0.000000 0.000000 -0.578352 7.201646 1.097222 -86.540321 6.570697 15.999683 -18.328629 -6.377296 0.700914 11.766952 -3.897783 -2.743282 0.313745 1.000715 1.104604 75.293381 -4.030032 16.032784 14.534869 5.155734 1.026005 -4.679783 6.322100 -2.472486 -13.207054 2.656173 0.367862 27.131054 -3.870112 -1.920796 -14.206977 1.327346 1.376169 -13.409876 -6.527894 0.352952 27.456129 3.839204 1.782611 -14.353964 -1.530246 2.268439 +0.969900 40.936550 0.156784 0.000000 0.000000 0.000000 3.047432 0.587965 -0.006098 1.112284 -0.110650 -0.881865 0.000000 0.000000 0.000000 3.238587 1.168217 -0.685745 0.289281 -0.811768 -0.239527 0.000000 0.000000 0.000000 0.629159 0.990879 0.263999 -81.985199 4.784874 15.900991 -15.623709 -3.156224 1.085751 14.399264 -7.588593 -2.131535 -1.005247 5.144381 0.462227 71.934288 -5.183747 16.215521 15.609814 3.308869 0.864464 -7.238639 9.038823 -0.647002 -14.383659 2.945528 0.378068 30.016134 -3.956086 -2.227710 -15.901606 1.346309 1.311009 -14.480732 -6.431494 0.378607 30.094677 3.926870 2.051624 -15.920162 -1.577364 1.976702 +0.871840 40.776966 0.285733 0.000000 0.000000 0.000000 3.966815 0.700242 -0.024348 1.973860 -0.216430 -1.182464 0.000000 0.000000 0.000000 7.912644 3.417845 -1.318481 1.745166 0.119120 -0.348622 0.000000 0.000000 0.000000 1.800190 -5.432335 -0.627759 -77.122673 3.066635 15.812227 -13.040476 0.127191 1.441474 16.801283 -11.845697 -1.618718 -2.271046 8.848314 -0.226594 68.523727 -7.553497 16.503088 19.053091 2.090090 0.423454 -10.236835 11.293948 1.267234 -14.939320 3.158005 0.360104 31.624527 -4.004773 -2.393735 -16.940283 1.347027 1.216051 -15.086019 -6.336557 0.381801 31.810137 3.981495 2.236960 -17.034452 -1.623735 1.758821 +0.781840 40.669456 0.416591 0.000000 0.000000 0.000000 4.840377 0.853280 -0.030236 2.788463 -0.300640 -1.511656 0.000000 0.000000 0.000000 12.462280 5.677999 -1.938908 3.165891 1.025998 -0.456318 0.000000 0.000000 0.000000 3.036332 -11.371113 -1.472398 -72.130966 1.973672 15.730595 -11.204962 2.548641 1.664293 18.549603 -16.094101 -0.964649 -3.390873 12.278931 -0.905172 64.981323 -10.261508 16.782356 23.195068 1.538929 -0.126775 -13.272285 13.226200 3.122920 -15.319125 3.347793 0.343932 32.890526 -4.028674 -2.527718 -17.813042 1.334270 1.117279 -15.447868 -6.228734 0.387252 33.045925 4.010084 2.369825 -17.904531 -1.656762 1.565249 +0.685654 40.585773 0.538671 0.000000 0.000000 0.000000 5.557500 1.075730 -0.006888 3.465800 -0.324315 -1.851190 0.000000 0.000000 0.000000 16.570000 7.832630 -2.504550 4.461480 1.856910 -0.554711 0.000000 0.000000 0.000000 4.439170 -16.128555 -2.164260 -67.188301 2.063680 15.653300 -10.743200 3.183810 1.650420 19.220800 -19.758801 0.070852 -4.271950 15.602634 -1.516820 61.226700 -12.430000 16.940201 26.366100 1.694920 -0.615973 -15.942900 14.974300 4.772750 -15.490177 3.530274 0.318185 33.684605 -4.048974 -2.615730 -18.430218 1.331182 0.987380 -15.622291 -6.104184 0.374970 33.838058 4.048211 2.462842 -18.529295 -1.690087 1.364994 +0.575010 40.503349 0.642947 0.000000 0.000000 0.000000 6.040849 1.381966 0.055815 3.943056 -0.260997 -2.181542 0.000000 0.000000 0.000000 19.983200 9.769304 -2.980160 5.552519 2.567053 -0.636898 0.000000 0.000000 0.000000 6.041467 -19.213709 -2.631029 -62.507984 3.635891 15.576022 -12.002980 1.481946 1.342375 18.574919 -22.413488 1.621076 -4.853456 18.894865 -2.019579 57.281002 -13.421769 16.898312 27.375523 2.528308 -0.915717 -17.941408 16.631817 6.100765 -15.753591 3.740916 0.293695 34.616737 -4.060863 -2.721731 -19.096600 1.322360 0.847332 -15.848134 -5.947701 0.358526 34.701698 4.062977 2.544936 -19.165358 -1.705863 1.147658 +0.465538 40.422314 0.727052 0.000000 0.000000 0.000000 6.346214 1.729258 0.140984 4.267333 -0.134259 -2.478098 0.000000 0.000000 0.000000 22.708847 11.390048 -3.359403 6.401832 3.140239 -0.699996 0.000000 0.000000 0.000000 7.600691 -20.959377 -2.933753 -58.443451 5.955706 15.488337 -14.219121 -1.613475 0.867916 17.105764 -24.226635 3.391750 -5.202415 21.867195 -2.430397 53.571381 -13.561912 16.717672 26.948578 3.732185 -1.064892 -19.339828 18.111713 7.116391 -15.948458 3.943050 0.256535 35.323589 -4.068510 -2.790365 -19.606213 1.313555 0.695566 -16.040663 -5.785796 0.332417 35.408783 4.068208 2.612227 -19.672771 -1.734818 0.949300 +0.378842 40.348457 0.790279 0.000000 0.000000 0.000000 6.562670 2.060600 0.224980 4.513210 0.019815 -2.714970 0.000000 0.000000 0.000000 24.818800 12.600500 -3.643170 6.982800 3.567430 -0.742126 0.000000 0.000000 0.000000 8.805480 -21.904303 -3.166820 -55.383202 8.030060 15.378300 -16.348200 -4.785410 0.401107 15.490600 -25.515400 4.981710 -5.417810 24.140232 -2.780947 50.626499 -13.416100 16.494101 26.289499 4.930350 -1.144210 -20.305000 19.281799 7.860400 -16.220432 4.113298 0.224610 36.097771 -4.086332 -2.876875 -20.105625 1.309840 0.583587 -16.289013 -5.666212 0.316962 36.163948 4.079218 2.695860 -20.190239 -1.760706 0.770599 +0.331053 40.286331 0.832545 0.000000 0.000000 0.000000 6.761315 2.328961 0.288885 4.739429 0.170544 -2.871800 0.000000 0.000000 0.000000 26.369043 13.342568 -3.834527 7.285092 3.845599 -0.763005 0.000000 0.000000 0.000000 9.426753 -22.507460 -3.402529 -53.593075 9.103127 15.243454 -17.586367 -6.983904 0.080202 14.276221 -26.526947 6.076746 -5.585442 25.000000 -3.093467 48.847836 -13.445465 16.308849 26.340582 5.821304 -1.217155 -20.976408 20.044792 8.369830 -16.436218 4.222002 0.203459 36.723541 -4.120615 -2.937779 -20.507240 1.304002 0.528653 -16.503155 -5.611922 0.307645 36.771019 4.096009 2.769168 -20.581478 -1.771737 0.664759 +0.316417 40.235466 0.856253 0.000000 0.000000 0.000000 6.941342 2.527204 0.332679 4.941383 0.308842 -2.950330 0.000000 0.000000 0.000000 27.352053 13.703218 -3.945224 7.363521 3.995754 -0.768736 0.000000 0.000000 0.000000 9.564528 -22.908758 -3.624813 -52.848339 9.367995 15.119306 -18.088057 -8.227312 -0.099799 13.487617 -27.228416 6.710447 -5.738375 25.000000 -3.352441 48.128159 -13.692987 16.184944 26.996407 6.402341 -1.278305 -21.384096 20.443043 8.666779 -16.559032 4.253620 0.205618 37.057968 -4.110407 -2.980865 -20.722218 1.309242 0.522371 -16.633507 -5.593906 0.313471 37.125259 4.094742 2.787480 -20.796974 -1.773775 0.631666 +0.323708 40.194145 0.864431 0.000000 0.000000 0.000000 7.083969 2.658169 0.361068 5.098628 0.431027 -2.957829 0.000000 0.000000 0.000000 27.744434 13.805683 -3.989188 7.289186 4.044910 -0.767022 0.000000 0.000000 0.000000 9.401105 -23.168343 -3.795516 -52.801609 9.254993 15.050852 -18.247278 -8.801077 -0.179711 13.019313 -27.516951 7.003361 -5.896489 25.000000 -3.532914 48.233059 -14.097110 16.130852 27.889629 6.745458 -1.305007 -21.530760 20.553814 8.769609 -16.749826 4.258231 0.201834 37.488445 -4.130776 -3.022148 -20.947176 1.311155 0.554662 -16.808939 -5.623295 0.311905 37.526932 4.096485 2.849533 -21.022285 -1.775565 0.627758 +0.341700 40.160652 0.860107 0.000000 0.000000 0.000000 7.170412 2.724694 0.378756 5.190719 0.533415 -2.901568 0.000000 0.000000 0.000000 27.522783 13.773196 -3.980342 7.133184 4.020082 -0.765561 0.000000 0.000000 0.000000 9.118778 -23.346354 -3.876481 -53.105503 9.194444 15.083087 -18.458038 -8.990637 -0.200346 12.765839 -27.289684 7.076034 -6.079664 25.000000 -3.609931 48.928127 -14.596275 16.155039 28.652901 6.922646 -1.274612 -21.419086 20.454359 8.696686 -16.894785 4.237669 0.218327 37.802975 -4.122283 -3.064958 -21.123262 1.311977 0.605945 -16.961451 -5.665370 0.330897 37.839432 4.117184 2.881522 -21.188419 -1.781765 0.643473 +0.359167 40.133274 0.846307 0.000000 0.000000 0.000000 7.181887 2.729619 0.390447 5.197211 0.612321 -2.788816 0.000000 0.000000 0.000000 26.663704 13.728991 -3.932611 6.966616 3.948287 -0.772055 0.000000 0.000000 0.000000 8.899845 -23.502934 -3.829552 -53.412628 9.616672 15.261005 -19.114344 -9.081429 -0.202517 12.621725 -26.443756 7.049008 -6.307781 25.000000 -3.558538 49.978947 -15.128925 16.265968 28.918873 7.005899 -1.164469 -21.051769 20.221935 8.466372 -17.041224 4.213775 0.225559 38.058247 -4.120376 -3.094716 -21.230448 1.319658 0.637732 -17.123096 -5.705431 0.331164 38.123798 4.115724 2.923508 -21.306086 -1.781155 0.661246 +0.364883 40.110291 0.826058 0.000000 0.000000 0.000000 7.099610 2.675780 0.400847 5.097660 0.664063 -2.626840 0.000000 0.000000 0.000000 25.143801 13.796300 -3.859920 6.860580 3.856540 -0.794203 0.000000 0.000000 0.000000 8.926600 -23.698219 -3.616570 -53.375599 10.952000 15.629600 -20.610201 -9.358890 -0.227040 12.481500 -24.876301 7.042830 -6.600720 25.000000 -3.353780 51.151100 -15.633500 16.472099 28.320200 7.067210 -0.951928 -20.431499 19.933800 8.097030 -17.172676 4.213181 0.220853 38.253849 -4.133966 -3.105358 -21.299143 1.316338 0.657676 -17.252075 -5.722309 0.339304 38.320473 4.117300 2.930954 -21.384758 -1.777810 0.660629 +0.350355 40.091457 0.802271 0.000000 0.000000 0.000000 6.912773 2.568542 0.413222 4.881210 0.686543 -2.425230 0.000000 0.000000 0.000000 22.981331 14.060561 -3.780132 6.902361 3.764157 -0.835178 0.000000 0.000000 0.000000 9.314610 -23.966534 -3.218904 -52.791359 13.380938 16.197437 -23.085381 -9.994895 -0.296910 12.239673 -22.570749 7.141056 -6.960027 25.000000 -2.986506 52.259624 -16.053856 16.769274 26.637606 7.164229 -0.628416 -19.573666 19.643301 7.611111 -17.296011 4.242717 0.222341 38.440235 -4.133112 -3.129944 -21.357561 1.321275 0.649542 -17.371016 -5.703638 0.334768 38.496166 4.129867 2.949421 -21.443476 -1.778928 0.630183 +0.318023 40.082417 0.777393 0.000000 0.000000 0.000000 6.642469 2.423365 0.425089 4.575359 0.684011 -2.202847 0.000000 0.000000 0.000000 20.361212 14.456029 -3.726866 7.243994 3.659653 -0.880038 0.000000 0.000000 0.000000 9.912504 -24.238894 -2.696019 -52.034153 16.084702 16.827356 -25.662682 -10.707035 -0.363857 11.790669 -19.855717 7.279279 -7.313912 25.000000 -2.510779 53.317307 -16.355503 17.102812 24.244125 7.297220 -0.241683 -18.544464 19.308155 7.047422 -17.392956 4.301947 0.210624 38.548191 -4.134252 -3.139110 -21.367718 1.314935 0.599632 -17.378267 -5.645905 0.319901 38.408653 4.119884 2.938972 -21.346157 -1.770193 0.584575 +0.273060 40.090286 0.753756 0.000000 0.000000 0.000000 6.317765 2.258235 0.432524 4.217191 0.662304 -1.980873 0.000000 0.000000 0.000000 17.510019 14.879169 -3.737685 8.053699 3.523846 -0.909312 0.000000 0.000000 0.000000 10.502186 -24.420496 -2.126906 -51.622566 17.994701 17.345770 -27.210674 -11.099336 -0.361794 11.028897 -17.146101 7.356107 -7.572253 25.000000 -1.996465 54.386383 -16.509365 17.405405 21.660864 7.452099 0.146445 -17.422789 18.862171 6.448854 -17.395309 4.377931 0.194308 38.458900 -4.144055 -3.135110 -21.279663 1.314774 0.520436 -17.451773 -5.572127 0.302185 38.497643 4.113389 2.944029 -21.355564 -1.775187 0.505346 +0.220642 40.122173 0.733688 0.000000 0.000000 0.000000 5.967726 2.091138 0.431607 3.843789 0.627259 -1.780487 0.000000 0.000000 0.000000 14.654322 15.226438 -3.850146 9.499695 3.337549 -0.903530 0.000000 0.000000 0.000000 10.865551 -24.416525 -1.590552 -52.075157 18.042334 17.579082 -26.597921 -10.775819 -0.224633 9.848757 -14.856791 7.270143 -7.644924 25.000000 -1.513430 55.529072 -16.486357 17.609739 19.408916 7.614783 0.474143 -16.287533 18.239149 5.858295 -17.286663 4.454045 0.173991 38.174679 -4.140252 -3.101021 -21.104357 1.300755 0.408311 -17.343876 -5.485541 0.277514 38.201488 4.129388 2.924609 -21.158594 -1.786965 0.418356 +0.165940 40.185200 0.719522 0.000000 0.000000 0.000000 5.621420 1.940060 0.418416 3.492240 0.584712 -1.622870 0.000000 0.000000 0.000000 12.020700 15.394300 -4.101810 11.750200 3.081580 -0.843222 0.000000 0.000000 0.000000 10.784500 -24.132179 -1.165950 -53.910500 15.159000 17.353701 -22.693001 -9.340510 0.113711 8.144660 -13.402700 6.919990 -7.441800 25.000000 -1.131540 56.807598 -16.257401 17.648500 18.009399 7.771190 0.679582 -15.217600 17.372900 5.318640 -17.036413 4.526378 0.159652 37.577015 -4.125679 -3.037374 -20.752834 1.288198 0.294463 -17.080515 -5.369598 0.244514 37.594513 4.109412 2.859189 -20.815342 -1.788942 0.355117 +0.112851 40.288204 0.712724 0.000000 0.000000 0.000000 5.307079 1.819185 0.391475 3.190581 0.538992 -1.526044 0.000000 0.000000 0.000000 9.764724 15.085043 -4.469843 14.785184 2.757278 -0.734877 0.000000 0.000000 0.000000 10.150491 -23.487434 -0.906855 -57.336952 9.036460 16.604456 -15.215108 -6.693749 0.666733 5.986724 -13.031652 6.268255 -6.933756 23.127861 -0.897401 58.265560 -15.807424 17.484438 17.816498 7.917415 0.721836 -14.269826 16.223961 4.875776 -16.658178 4.582153 0.142818 36.744213 -4.106324 -2.944625 -20.303635 1.272561 0.179027 -16.687483 -5.246403 0.223974 36.752136 4.087901 2.765075 -20.383694 -1.792126 0.302863 +0.060156 40.446953 0.711313 0.000000 0.000000 0.000000 5.049602 1.727493 0.359094 2.930668 0.488389 -1.495389 0.000000 0.000000 0.000000 7.757948 13.224239 -4.689834 17.831587 2.448078 -0.688829 0.000000 0.000000 0.000000 9.293200 -22.461380 -0.766091 -61.321999 2.407839 15.699847 -7.285934 -3.921122 1.237554 4.147914 -13.323170 5.533541 -6.335641 20.632030 -0.764577 59.871971 -15.177347 17.200527 18.516705 8.090249 0.643583 -13.412811 14.859772 4.587570 -15.913192 4.599987 0.126979 35.168339 -4.047858 -2.771796 -19.482512 1.257607 0.001064 -15.918473 -5.110083 0.195470 35.133091 4.075587 2.582875 -19.531765 -1.777976 0.270139 +0.005358 40.678947 0.712443 0.000000 0.000000 0.000000 4.873050 1.660160 0.332031 2.695310 0.429688 -1.533130 0.000000 0.000000 0.000000 5.800930 8.543290 -4.436980 19.928101 2.257940 -0.841370 0.000000 0.000000 0.000000 8.651860 -21.047899 -0.671249 -64.522903 -1.233390 15.116800 -2.877800 -2.404530 1.576700 3.576910 -13.689700 4.998450 -5.923300 17.982800 -0.663372 61.577202 -14.422100 16.909800 19.629601 8.336660 0.508398 -12.593100 13.374500 4.514890 -14.914725 4.633420 0.112050 33.057182 -4.031233 -2.551847 -18.377634 1.239856 -0.170703 -14.921168 -4.945498 0.162268 33.025394 4.018061 2.370488 -18.433397 -1.774147 0.259141 +-0.047667 40.958740 0.710464 0.000000 0.000000 0.000000 4.789203 1.610265 0.311925 2.481924 0.359446 -1.624835 0.000000 0.000000 0.000000 3.965812 0.683171 -3.466973 20.362661 2.244793 -1.189440 0.000000 0.000000 0.000000 8.530806 -19.348545 -0.567267 -65.990120 0.362171 15.175092 -4.545782 -3.027608 1.523196 4.822812 -13.687481 4.854286 -5.882018 15.523208 -0.542537 63.296432 -13.612172 16.701387 20.734823 8.674776 0.372060 -11.786927 11.885411 4.677032 -13.514303 4.613746 0.098561 30.076254 -3.947519 -2.230090 -16.803822 1.204630 -0.378850 -13.497585 -4.753647 0.134972 30.025068 3.929608 2.056772 -16.864035 -1.761516 0.295758 +-0.069555 41.089100 0.688511 0.000000 0.000000 0.000000 4.760690 1.562490 0.263942 2.346360 0.273323 -1.689460 0.000000 0.000000 0.000000 3.411130 -7.076660 -1.857520 19.420200 2.282440 -1.172560 0.000000 0.000000 0.000000 8.694780 -17.895599 -0.468477 -66.346802 4.467560 15.565900 -9.175900 -4.680900 1.270050 6.836360 -13.447900 4.927160 -6.034830 13.087300 -0.424609 64.804001 -12.880300 16.568800 21.652201 9.007340 0.259150 -11.089300 10.602200 4.927000 -12.877205 4.597680 0.108244 28.674175 -3.895868 -2.091653 -16.040916 1.192015 -0.476671 -12.873507 -4.669855 0.130282 28.631384 3.895708 1.903377 -16.089514 -1.747491 0.319557 +-0.023956 40.909977 0.638674 0.000000 0.000000 0.000000 4.748466 1.508401 0.166625 2.338025 0.176342 -1.658777 0.000000 0.000000 0.000000 5.181490 -11.747730 0.294793 17.479019 2.236912 -0.552468 0.000000 0.000000 0.000000 8.839161 -17.157475 -0.400062 -66.441803 7.812075 15.903572 -13.021851 -6.037336 1.051039 8.427768 -13.203826 4.999090 -6.162859 10.606241 -0.341767 65.882317 -12.348351 16.485928 22.277214 9.230963 0.183871 -10.592193 9.712322 5.109981 -13.891641 4.591877 0.111585 30.645491 -3.961747 -2.287609 -16.999388 1.208353 -0.317608 -13.892447 -4.811054 0.145433 30.594234 3.944263 2.113632 -17.030657 -1.764640 0.312211 +0.127927 40.581734 0.600075 0.000000 0.000000 0.000000 4.755920 1.475510 0.088480 2.422130 0.111867 -1.582430 0.000000 0.000000 0.000000 8.779500 -15.143600 3.139840 14.293900 2.127270 -0.937177 0.000000 0.000000 0.000000 8.921440 -16.916401 -0.361227 -66.453903 9.926340 16.123699 -15.477000 -6.892460 0.909013 9.443420 -13.018900 5.040930 -6.241810 8.908755 -0.290974 66.486702 -12.032500 16.443800 22.567699 9.333080 0.150106 -10.256700 9.221920 5.206150 -15.496912 4.449320 0.154215 33.883545 -4.027825 -2.625183 -18.621609 1.251197 0.058476 -15.535826 -5.181251 0.200858 33.907772 4.040051 2.465936 -18.699316 -1.763173 0.432564 +0.403859 40.302921 0.609093 0.000000 0.000000 0.000000 4.792616 1.488717 0.096682 2.547854 0.117313 -1.524599 0.000000 0.000000 0.000000 13.370456 -19.515623 6.645450 9.826855 2.002933 -3.711358 0.000000 0.000000 0.000000 8.961298 -16.860044 -0.346025 -66.388107 11.058475 16.245506 -16.762644 -7.336146 0.834866 10.003957 -12.909315 5.068311 -6.289170 8.766785 -0.264333 66.606819 -11.910312 16.437141 22.516996 9.324960 0.156788 -10.003796 9.110929 5.223889 -16.718586 4.088380 0.244809 36.509769 -4.091301 -2.921075 -20.016960 1.319012 0.642771 -16.805405 -5.727473 0.320224 36.605137 4.087131 2.743333 -20.113991 -1.734453 0.796066 +0.735026 40.104351 0.644104 0.000000 0.000000 0.000000 4.850379 1.526524 0.163095 2.684443 0.167952 -1.489729 0.000000 0.000000 0.000000 18.312405 -24.064270 9.804822 5.492299 1.881724 -7.520029 0.000000 0.000000 0.000000 8.965043 -16.983990 -0.353892 -66.224342 11.525274 16.301523 -17.272123 -7.512990 0.802577 10.290854 -12.870689 5.087147 -6.294985 9.827599 -0.269729 66.196732 -11.910601 16.458267 22.198092 9.222357 0.193359 -9.724855 9.435774 5.149395 -17.451744 3.599755 0.363827 38.204571 -4.135691 -3.101924 -20.973129 1.366957 1.288013 -17.587669 -6.341434 0.476264 38.339516 4.124000 2.934030 -21.056488 -1.714959 1.292629 +1.030969 39.974918 0.668983 0.000000 0.000000 0.000000 4.916600 1.555830 0.235760 2.806160 0.223521 -1.467330 0.000000 0.000000 0.000000 23.011600 -27.227301 11.367500 3.067748 1.773570 -10.323300 0.000000 0.000000 0.000000 8.935640 -17.360800 -0.385610 -65.936302 11.660700 16.327600 -17.441799 -7.581270 0.781898 10.500800 -12.893500 5.100920 -6.242440 11.457300 -0.318992 65.201599 -11.950000 16.498899 21.703899 9.042150 0.246889 -9.303850 10.272000 4.963320 -17.831064 3.134051 0.491513 39.106632 -4.142962 -3.207015 -21.508369 1.416132 1.850897 -18.023167 -6.860489 0.616798 39.330631 4.126951 3.035908 -21.606903 -1.692465 1.766983 +1.221632 39.902897 0.656171 0.000000 0.000000 0.000000 4.980435 1.551193 0.273417 2.893027 0.251809 -1.448687 0.000000 0.000000 0.000000 26.984324 -27.860264 10.456958 3.810380 1.690729 -10.587337 0.000000 0.000000 0.000000 8.877600 -18.027388 -0.440052 -65.512344 11.742332 16.353397 -17.627476 -7.664188 0.748960 10.788912 -12.966343 5.112531 -6.123133 13.117739 -0.418043 63.624805 -11.962183 16.550888 21.118977 8.806036 0.306088 -8.663513 11.638939 4.659264 -18.133619 2.834599 0.572777 39.704178 -4.157012 -3.270516 -21.800434 1.441254 2.191509 -18.361946 -7.200822 0.715088 39.967796 4.136359 3.101069 -21.902140 -1.674181 2.068817 +1.318586 39.874172 0.612383 0.000000 0.000000 0.000000 5.038110 1.517790 0.277613 2.948103 0.252808 -1.432184 0.000000 0.000000 0.000000 30.187185 -26.490021 7.692459 6.895916 1.654792 -8.802658 0.000000 0.000000 0.000000 8.801609 -18.878059 -0.508461 -64.999596 11.822218 16.383801 -17.862734 -7.744652 0.705407 11.144033 -13.070274 5.122539 -5.962318 14.653807 -0.549164 61.702606 -11.948999 16.606619 20.494453 8.554992 0.366238 -7.881598 13.331082 4.282609 -18.293287 2.678608 0.614725 39.900196 -4.161623 -3.288237 -21.828819 1.456773 2.380420 -18.546055 -7.384380 0.761365 40.190739 4.162541 3.147999 -21.932522 -1.660480 2.207696 +1.353804 39.874016 0.552898 0.000000 0.000000 0.000000 5.087618 1.468455 0.260596 2.980208 0.234562 -1.417979 0.000000 0.000000 0.000000 32.686855 -24.061245 4.067204 10.979731 1.689684 -5.965856 0.000000 0.000000 0.000000 8.719902 -19.771477 -0.580171 -64.459885 11.896021 16.417503 -18.100601 -7.770495 0.659263 11.513439 -13.184469 5.130920 -5.793665 16.006147 -0.688724 59.729485 -11.929342 16.658617 19.873104 8.334812 0.424261 -7.074617 15.086710 3.891685 -18.389013 2.623088 0.634510 39.890293 -4.162572 -3.287751 -21.720821 1.461857 2.438570 -18.641165 -7.439620 0.775087 40.172047 4.155416 3.134244 -21.825718 -1.647404 2.280195 +1.359261 39.887699 0.492999 0.000000 0.000000 0.000000 5.126950 1.416020 0.234616 2.998160 0.205114 -1.406230 0.000000 0.000000 0.000000 34.549999 -21.518600 0.574393 14.717200 1.819330 -3.073520 0.000000 0.000000 0.000000 8.644710 -20.566299 -0.644518 -63.955002 11.959400 16.453199 -18.294100 -7.689550 0.618552 11.844400 -13.288100 5.137650 -5.650840 17.115400 -0.813096 57.999901 -11.922100 16.699400 19.297701 8.191290 0.477080 -6.359080 16.644100 3.544820 -18.431114 2.603531 0.638666 39.754486 -4.143071 -3.269823 -21.544634 1.461639 2.426434 -18.682398 -7.439226 0.765971 40.045765 4.139349 3.118232 -21.659260 -1.646509 2.302447 +1.361547 39.902969 0.445095 0.000000 0.000000 0.000000 5.154711 1.370979 0.209821 3.009430 0.171278 -1.397013 0.000000 0.000000 0.000000 35.845131 -19.630428 -1.983890 17.027641 2.060499 -0.934754 0.000000 0.000000 0.000000 8.585813 -21.150160 -0.693016 -63.534458 12.009060 16.489746 -18.406250 -7.462498 0.589653 12.095012 -13.364519 5.142746 -5.560507 17.938850 -0.903468 56.747055 -11.942225 16.723175 18.802143 8.159578 0.522295 -5.827406 17.795507 3.288317 -18.442303 2.599427 0.629956 39.606258 -4.157547 -3.252947 -21.397121 1.471833 2.436259 -18.693888 -7.436690 0.765385 39.888855 4.140911 3.096166 -21.493359 -1.637954 2.306544 +1.365662 39.917442 0.409758 0.000000 0.000000 0.000000 5.172224 1.334227 0.187865 3.016216 0.134967 -1.390011 0.000000 0.000000 0.000000 36.660934 -18.441078 -3.595342 17.922503 2.399235 0.412447 0.000000 0.000000 0.000000 8.542753 -21.532028 -0.726317 -63.196095 12.046229 16.526695 -18.441992 -7.104342 0.572064 12.268744 -13.414508 5.146427 -5.520022 18.507301 -0.961179 55.946896 -11.988284 16.731306 18.382509 8.229776 0.560428 -5.470912 18.559551 3.118043 -18.423326 2.588801 0.639816 39.439327 -4.153319 -3.247503 -21.250380 1.470194 2.434005 -18.697447 -7.452199 0.756761 39.768967 4.160600 3.102867 -21.366991 -1.624717 2.301093 +1.371234 39.931194 0.384749 0.000000 0.000000 0.000000 5.181373 1.304355 0.168314 3.019348 0.096841 -1.384832 0.000000 0.000000 0.000000 37.085499 -17.822111 -4.433981 17.669640 2.815045 1.113565 0.000000 0.000000 0.000000 8.512703 -21.748835 -0.747174 -62.925816 12.073124 16.563784 -18.415846 -6.642127 0.563700 12.379508 -13.442899 5.148947 -5.519997 18.866940 -0.992222 55.516373 -12.055053 16.726761 18.026320 8.381919 0.592648 -5.257699 19.006895 3.018270 -18.405140 2.578072 0.640030 39.312248 -4.150334 -3.226359 -21.142591 1.471707 2.432854 -18.665237 -7.453974 0.757532 39.612560 4.156205 3.078769 -21.239651 -1.624732 2.322471 +1.377918 39.944298 0.368027 0.000000 0.000000 0.000000 5.183879 1.280086 0.150778 3.019583 0.057527 -1.381120 0.000000 0.000000 0.000000 37.199444 -17.655994 -4.659057 16.514946 3.288917 1.301734 0.000000 0.000000 0.000000 8.493080 -21.834354 -0.758107 -62.710823 12.091763 16.600750 -18.341150 -6.100899 0.562649 12.440015 -13.454112 5.150537 -5.551820 19.059959 -1.002077 55.379501 -12.137705 16.712267 17.722301 8.597610 0.620012 -5.158602 19.202148 2.974614 -18.367762 2.563814 0.639643 39.164532 -4.154701 -3.215743 -21.034805 1.473032 2.441185 -18.631456 -7.457324 0.747696 39.476105 4.140250 3.071805 -21.151243 -1.627983 2.342759 +1.385396 39.956799 0.357751 0.000000 0.000000 0.000000 5.181306 1.260278 0.134917 3.017609 0.017619 -1.378557 0.000000 0.000000 0.000000 37.075829 -17.836208 -4.414887 14.682370 3.803251 1.097607 0.000000 0.000000 0.000000 8.481559 -21.819168 -0.761392 -62.539654 12.103962 16.637327 -18.230059 -5.503784 0.567177 12.461750 -13.452148 5.151405 -5.607654 19.124500 -0.995713 55.467438 -12.231798 16.690308 17.460449 8.859997 0.643459 -5.147235 19.203789 2.974061 -18.341463 2.540468 0.640302 39.077293 -4.141503 -3.204128 -20.965796 1.480117 2.451347 -18.586941 -7.463614 0.749346 39.358624 4.139854 3.052331 -21.063873 -1.617331 2.365488 +1.393375 39.968731 0.352286 0.000000 0.000000 0.000000 5.175052 1.243933 0.120444 3.014043 -0.022304 -1.376857 0.000000 0.000000 0.000000 36.780132 -18.267294 -3.830809 12.374211 4.341741 0.609311 0.000000 0.000000 0.000000 8.476069 -21.730644 -0.759060 -62.402252 12.111332 16.673239 -18.093565 -4.872119 0.575730 12.454961 -13.440588 5.151739 -5.680427 19.094599 -0.977577 55.718521 -12.333259 16.663130 17.232105 9.153722 0.663801 -5.200014 19.064110 3.004970 -18.284538 2.525249 0.639004 38.930283 -4.141728 -3.182473 -20.878447 1.468687 2.448059 -18.541403 -7.472457 0.750147 39.240906 4.138284 3.042165 -20.995304 -1.617268 2.376258 +1.401584 39.980099 0.350211 0.000000 0.000000 0.000000 5.166355 1.230204 0.107134 3.009433 -0.061667 -1.375777 0.000000 0.000000 0.000000 36.370304 -18.864771 -3.021283 9.771967 4.889137 -0.067461 0.000000 0.000000 0.000000 8.474808 -21.592941 -0.752899 -62.290047 12.115275 16.708179 -17.941553 -4.225733 0.586929 12.428650 -13.422593 5.151699 -5.763810 19.000164 -0.951605 56.078232 -12.438335 16.632753 17.030079 9.464799 0.681718 -5.296160 18.829226 3.057078 -18.236837 2.508745 0.647983 38.832321 -4.134888 -3.181897 -20.829069 1.474981 2.458333 -18.494621 -7.484362 0.751421 39.123035 4.138355 3.032553 -20.936438 -1.618387 2.396517 +1.409767 39.990879 0.350315 0.000000 0.000000 0.000000 5.156300 1.218411 0.094833 3.004262 -0.099855 -1.375109 0.000000 0.000000 0.000000 35.897049 -19.554726 -2.086460 7.038520 5.430736 -0.848986 0.000000 0.000000 0.000000 8.476238 -21.427095 -0.744450 -62.196075 12.116977 16.741779 -17.782925 -3.583542 0.599564 12.390575 -13.400915 5.151424 -5.852147 18.866999 -0.921231 56.498947 -12.543501 16.600992 16.848864 9.780333 0.697730 -5.417651 18.539194 3.121469 -18.180403 2.489866 0.647052 38.715107 -4.131279 -3.161420 -20.770660 1.469989 2.466397 -18.449652 -7.491565 0.753223 39.034912 4.139119 3.015891 -20.887671 -1.615491 2.417290 +1.417664 40.000973 0.351611 0.000000 0.000000 0.000000 5.145835 1.208072 0.083497 2.998955 -0.136127 -1.374690 0.000000 0.000000 0.000000 35.404778 -20.272408 -1.114070 4.324171 5.951118 -1.661917 0.000000 0.000000 0.000000 8.479097 -21.251343 -0.735030 -62.115234 12.117393 16.773523 -17.625952 -2.965039 0.612564 12.347319 -13.377940 5.151031 -5.940257 18.717031 -0.889457 56.939106 -12.645213 16.569530 16.685093 10.087801 0.712165 -5.548993 18.228586 3.190450 -18.142708 2.477791 0.646354 38.616276 -4.138038 -3.155631 -20.711266 1.479485 2.477120 -18.393482 -7.500366 0.754157 38.917400 4.138953 2.996517 -20.829533 -1.606835 2.439276 +1.424948 40.010151 0.353327 0.000000 0.000000 0.000000 5.135850 1.198990 0.073272 2.993922 -0.169334 -1.374402 0.000000 0.000000 0.000000 34.935173 -20.957050 -0.186447 1.786937 6.430161 -2.437422 0.000000 0.000000 0.000000 8.482380 -21.082375 -0.725787 -62.044960 12.117242 16.802509 -17.479454 -2.395030 0.624909 12.304578 -13.355854 5.150613 -6.022783 18.569342 -0.859072 57.360031 -12.739138 16.540155 16.538866 10.372725 0.725038 -5.676297 17.928673 3.257066 -18.095676 2.462046 0.645553 38.527576 -4.141245 -3.149485 -20.672400 1.475102 2.485563 -18.358585 -7.508589 0.754658 38.849407 4.130366 2.988073 -20.800013 -1.608638 2.449128 +1.430868 40.017582 0.354840 0.000000 0.000000 0.000000 5.127660 1.191710 0.065013 2.989800 -0.196268 -1.374190 0.000000 0.000000 0.000000 34.549999 -21.518600 0.574400 -0.282800 6.819300 -3.073500 0.000000 0.000000 0.000000 8.485190 -20.943501 -0.718150 -61.988800 12.117000 16.826000 -17.360001 -1.931850 0.635022 12.269200 -13.337700 5.150260 -6.090140 18.447201 -0.834134 57.705502 -12.815500 16.516199 16.421101 10.604600 0.735401 -5.781150 17.681900 3.311880 -18.057911 2.450426 0.644380 38.469261 -4.141885 -3.125520 -20.652758 1.475893 2.495271 -18.324558 -7.514577 0.756113 38.780899 4.127595 2.981552 -20.760529 -1.612682 2.458710 diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_shrug.bvh b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_shrug.bvh new file mode 100644 index 00000000..9f72b23a --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_shrug.bvh @@ -0,0 +1,169 @@ +HIERARCHY +ROOT hip +{ + OFFSET 0.00 0.00 0.00 + CHANNELS 6 Xposition Yposition Zposition Xrotation Zrotation Yrotation + JOINT abdomen + { + OFFSET 0.000000 0.000000 0.000000 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT chest + { + OFFSET 0.000000 5.018152 -1.882228 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT neckDummy + { + OFFSET 0.000000 8.316447 0.784897 + CHANNELS 3 Xrotation Yrotation Zrotation + JOINT neck + { + OFFSET 0.000000 2.280413 -0.392801 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT head + { + OFFSET 0.000000 3.496879 0.529469 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT figureHair + { + OFFSET 0.000000 4.699570 0.720622 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 0.000000 -6.419331 0.000000 + } + } + } + } + } + JOINT lCollar + { + OFFSET 0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lShldr + { + OFFSET 6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT lForeArm + { + OFFSET 10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lHand + { + OFFSET 11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 10.353753 0.000000 0.000000 + } + } + } + } + } + JOINT rCollar + { + OFFSET -0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rShldr + { + OFFSET -6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT rForeArm + { + OFFSET -10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rHand + { + OFFSET -11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET -10.353753 0.000000 0.000000 + } + } + } + } + } + } + } + JOINT lThigh + { + OFFSET 4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lShin + { + OFFSET -1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lFoot + { + OFFSET -0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } + JOINT rThigh + { + OFFSET -4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rShin + { + OFFSET 1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rFoot + { + OFFSET 0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } +} +MOTION +Frames: 40 +Frame Time: 0.050000 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -0.002399 -0.001844 0.000279 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -70.100700 9.978770 15.991600 -22.515600 -9.303740 0.147736 5.969490 -0.173112 0.175734 -2.021920 5.690310 -0.063351 70.100700 -9.978770 15.991600 22.515600 9.303740 0.147736 -5.969490 0.173112 0.175734 -7.548020 3.866529 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099455 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589841 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.367328 -0.122586 0.003688 -1.910388 0.052142 -0.064158 0.000000 0.000000 0.000000 2.359324 -2.316271 -0.063351 -73.643448 5.713897 15.991600 -31.462919 -0.620898 -13.161567 13.054979 -0.173112 -0.354671 -1.684516 2.874621 -0.063351 74.344635 -6.450793 15.991600 32.183846 -1.833764 -11.741384 -13.516831 0.386068 -2.803593 -7.548020 3.866529 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099455 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589841 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.802014 -0.270401 0.008877 -4.214870 0.120828 -0.142668 0.000000 0.000000 0.000000 2.771035 1.800837 -0.063351 -77.966408 0.495712 15.991600 -42.308048 9.897460 -29.674206 21.700916 -0.173112 -0.908918 -1.272805 -0.561171 -0.063351 79.531059 -2.181052 15.991600 43.955574 -15.324852 -26.557936 -22.663103 0.709155 -6.522226 -7.548020 3.866529 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099454 -0.807164 -7.531943 -4.331994 0.100592 15.676721 3.192008 0.586786 -8.565729 -1.589838 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.294754 -0.414935 0.010116 -6.597465 0.169684 -0.219563 0.000000 0.000000 0.000000 3.178673 5.877219 -0.063351 -82.246605 -4.617686 15.991600 -53.320869 20.602043 -44.993542 30.261320 -0.173112 -1.809449 -0.865167 -3.962975 -0.063351 84.636528 2.179665 15.991600 55.708366 -29.057991 -40.058472 -31.958145 0.789797 -9.889403 -7.548020 3.866528 0.146894 15.728039 -3.219703 -0.973204 -8.495323 1.089980 -0.807879 -7.531943 -4.331992 0.100592 15.676721 3.192009 0.586786 -8.565728 -1.589839 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.888061 -0.531434 0.000000 -8.892377 0.156028 -0.281915 0.000000 0.000000 0.000000 3.521920 9.309690 -0.063351 -85.850700 -8.771230 15.991600 -63.380901 30.446301 -54.945900 37.469501 -0.173112 -3.574270 -0.521920 -6.827420 -0.063351 88.850700 6.232730 15.991600 65.883698 -41.696301 -48.080200 -40.469501 0.173112 -11.824300 -7.548020 3.866529 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099455 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589841 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.617826 -0.601891 -0.026184 -10.977924 0.063093 -0.320327 0.000000 0.000000 0.000000 3.755250 11.642985 -0.063351 -88.300667 -11.331834 15.991601 -71.600525 38.568550 -56.591438 42.369392 -0.173112 -6.534157 -0.288592 -8.774579 -0.063351 91.538361 9.650799 15.991601 73.279678 -52.135441 -47.718956 -47.438057 -1.428900 -11.636526 -7.548020 3.866529 0.146894 15.727672 -3.219887 -0.982961 -8.494112 1.099454 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192005 0.586786 -8.565728 -1.589840 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 3.493444 -0.635294 -0.062400 -12.908875 -0.022234 -0.339544 0.000000 0.000000 0.000000 3.892303 13.013525 -0.063351 -89.739738 -12.554363 15.991600 -78.023590 44.846653 -51.925694 45.247482 -0.173112 -10.270973 -0.151540 -9.918302 -0.063351 92.764786 12.391685 15.991600 78.121010 -60.201313 -41.105148 -52.798084 -3.636732 -10.197443 -7.548021 3.866528 0.146894 15.727672 -3.219887 -0.982961 -8.494112 1.099455 -0.807164 -7.531943 -4.331993 0.100592 15.676721 3.192006 0.586786 -8.565728 -1.589839 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.517685 -0.647382 -0.099923 -14.784105 0.012851 -0.347845 0.000000 0.000000 0.000000 3.961515 13.705649 -0.063351 -90.466461 -12.915668 15.991599 -82.926804 49.343353 -44.178059 46.700909 -0.173112 -14.179343 -0.082329 -10.495878 -0.063351 92.770393 14.484486 15.991599 80.989067 -65.952377 -31.627846 -56.657192 -5.903994 -8.768854 -7.548021 3.866528 0.146894 15.727672 -3.219887 -0.982961 -8.494112 1.099455 -0.807164 -7.531943 -4.331993 0.100592 15.676721 3.192006 0.586786 -8.565728 -1.589839 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 5.693322 -0.653890 -0.130028 -16.702492 0.281149 -0.353507 0.000000 0.000000 0.000000 3.991320 14.003700 -0.063351 -90.779404 -12.892600 15.991600 -86.586899 52.121399 -36.577900 47.326801 -0.173112 -17.653900 -0.052524 -10.744600 -0.063351 91.795601 15.958300 15.991600 82.465202 -69.447098 -22.676100 -59.123001 -7.684300 -8.612560 -7.548020 3.866529 0.146894 15.728039 -3.219704 -0.973204 -8.495323 1.089983 -0.807879 -7.531943 -4.331994 0.100592 15.676721 3.192006 0.586786 -8.565729 -1.589838 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 7.029864 -0.663024 -0.145994 -18.730682 0.853877 -0.362281 0.000000 0.000000 0.000000 4.006039 14.150888 -0.063351 -90.933952 -12.876501 15.991601 -89.279846 53.334583 -31.626671 47.635910 -0.173112 -20.241110 -0.037805 -10.867435 -0.063351 90.101753 16.870184 15.991601 83.083412 -70.870247 -16.854788 -60.361923 -8.584677 -10.597831 -7.548020 3.866528 0.146894 15.727672 -3.219887 -0.982961 -8.494112 1.099454 -0.807164 -7.531943 -4.331992 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589840 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 8.563777 -0.652868 -0.149114 -20.806406 1.635916 -0.369801 0.000000 0.000000 0.000000 4.014042 14.230927 -0.063351 -91.017990 -12.913266 15.991602 -91.333221 53.569221 -28.756451 47.804020 -0.173112 -22.151218 -0.029800 -10.934238 -0.063351 88.047791 17.416925 15.991602 83.221794 -71.001053 -13.448692 -60.830833 -8.869468 -13.948006 -7.548020 3.866528 0.146894 15.727672 -3.219887 -0.982961 -8.494112 1.099454 -0.807164 -7.531943 -4.331992 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589840 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 10.338261 -0.593974 -0.142684 -22.835161 2.490559 -0.369172 0.000000 0.000000 0.000000 4.018723 14.277731 -0.063351 -91.067131 -12.969981 15.991601 -92.989616 53.377563 -26.940516 47.902340 -0.173112 -23.657480 -0.025118 -10.973310 -0.063351 85.970261 17.775993 15.991601 83.149681 -70.580009 -11.270866 -60.946587 -8.877538 -17.663719 -7.548020 3.866528 0.146894 15.727672 -3.219887 -0.982961 -8.494112 1.099454 -0.807164 -7.531943 -4.331992 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589840 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 12.396518 -0.456893 -0.130000 -24.722448 3.281100 -0.353500 0.000000 0.000000 0.000000 4.021920 14.309700 -0.063351 -91.100700 -13.021200 15.991600 -94.282501 53.130100 -25.651400 47.969501 -0.173112 -24.824301 -0.021920 -11.000000 -0.063351 84.240601 18.035200 15.991600 83.046204 -70.116096 -9.717360 -60.969501 -8.826890 -20.824301 -7.548020 3.866528 0.146894 15.727672 -3.219887 -0.982961 -8.494112 1.099454 -0.807164 -7.531943 -4.331992 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589840 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 14.752076 -0.205694 -0.113941 -26.394047 3.899952 -0.318096 0.000000 0.000000 0.000000 2.202533 15.542357 -0.063351 -89.100700 -12.878343 12.207573 -94.951004 53.300858 -25.651400 48.381245 -0.173110 -27.125843 1.055631 -12.311872 -0.063351 83.386444 18.247986 12.921859 83.097946 -70.116096 -10.767537 -60.104145 -7.510563 -21.539415 -7.548020 3.866529 0.146894 15.728039 -3.219704 -0.973204 -8.495323 1.089983 -0.807879 -7.531943 -4.331994 0.100592 15.676721 3.192006 0.586786 -8.565729 -1.589838 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 17.299759 0.221485 -0.095720 -27.856884 4.355990 -0.267094 0.000000 0.000000 0.000000 0.383146 16.775015 -0.063351 -87.100700 -12.735485 8.423546 -95.619507 53.471615 -25.651400 48.792988 -0.173109 -29.427385 2.133183 -13.623743 -0.063351 82.532288 18.460772 9.852118 83.149689 -70.116096 -11.817715 -59.238789 -6.194236 -22.254530 -7.548020 3.866528 0.146894 15.727672 -3.219887 -0.982961 -8.494112 1.099454 -0.807164 -7.531943 -4.331992 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589840 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 19.904715 0.892986 -0.076131 -29.138176 4.687209 -0.206834 0.000000 0.000000 0.000000 -1.436241 18.007671 -0.063351 -85.100700 -12.592628 4.639519 -96.288002 53.642372 -25.651400 49.204731 -0.173107 -31.728928 3.210734 -14.935615 -0.063351 81.678131 18.673557 6.782376 83.201431 -70.116096 -12.867891 -58.373432 -4.877909 -22.969645 -7.548020 3.866529 0.146894 15.727672 -3.219887 -0.982961 -8.494112 1.099454 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192005 0.586786 -8.565728 -1.589840 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 22.432095 1.877154 -0.055970 -30.265137 4.931602 -0.143654 0.000000 0.000000 0.000000 -3.255628 19.240328 -0.063351 -83.100700 -12.449772 0.855492 -96.956497 53.813129 -25.651400 49.616474 -0.173105 -34.030472 4.288286 -16.247486 -0.063351 80.823975 18.886343 3.712635 83.253174 -70.116096 -13.918068 -57.508072 -3.561582 -23.684757 -7.548020 3.866529 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099455 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589841 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 24.747053 3.242333 -0.036031 -31.264986 5.127164 -0.083896 0.000000 0.000000 0.000000 -5.075016 20.472984 -0.063351 -81.100700 -12.306914 -2.928535 -97.625000 53.983887 -25.651400 50.028217 -0.173103 -36.332016 5.365837 -17.559357 -0.063351 79.969818 19.099129 0.642893 83.304916 -70.116096 -14.968246 -56.642715 -2.245255 -24.399872 -7.548020 3.866529 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099454 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192007 0.586786 -8.565728 -1.589839 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 26.714741 5.056868 -0.017109 -32.164932 5.311889 -0.033898 0.000000 0.000000 0.000000 -6.894403 21.705643 -0.063351 -79.100700 -12.164057 -6.712563 -98.293503 54.154644 -25.651400 50.439957 -0.173102 -38.633560 6.443388 -18.871227 -0.063351 79.115662 19.311914 -2.426848 83.356659 -70.116096 -16.018423 -55.777359 -0.928927 -25.114986 -7.548020 3.866528 0.146894 15.728041 -3.219700 -0.973204 -8.495323 1.089981 -0.807879 -7.531942 -4.331993 0.100592 15.676721 3.192007 0.586786 -8.565728 -1.589839 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 28.200300 7.389100 0.000000 -32.992199 5.523770 0.000000 0.000000 0.000000 0.000000 -8.713790 22.938299 -0.063351 -77.100700 -12.021200 -10.496590 -98.961998 54.325401 -25.651400 50.851700 -0.173100 -40.935101 7.520940 -20.183100 -0.063351 78.261497 19.524700 -5.496590 83.408401 -70.116096 -17.068600 -54.911999 0.387400 -25.830099 -7.548020 3.866529 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099454 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192007 0.586786 -8.565728 -1.589839 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 29.132229 10.186102 0.014533 -33.763954 5.779156 0.014384 0.000000 0.000000 0.000000 -10.847015 24.442463 -0.063351 -76.250778 -12.834497 -12.117180 -100.691147 55.078976 -28.941614 56.902126 -0.173099 -33.714832 8.793145 -21.771246 -0.063351 77.293358 20.022415 -6.928844 84.210358 -69.936661 -21.876369 -60.776505 0.634203 -20.937412 -7.548020 3.866529 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099455 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589841 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 29.692377 12.909827 0.025851 -34.457180 6.007813 0.017542 0.000000 0.000000 0.000000 -13.500511 26.352112 -0.063351 -76.174553 -14.489687 -12.258768 -103.462311 56.379414 -35.193104 62.851723 -0.173099 -24.935062 10.381391 -23.779522 -0.063351 76.110992 20.804386 -7.189498 85.694275 -69.595726 -30.203333 -66.911957 0.387385 -15.830128 -7.548020 3.866529 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099455 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589841 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 30.085556 15.027946 0.033567 -35.043961 6.138813 0.018821 0.000000 0.000000 0.000000 -15.432034 27.745930 -0.063351 -76.214340 -15.757030 -12.117728 -105.539734 57.361279 -39.953335 62.994576 -0.173099 -23.077925 11.538060 -25.244564 -0.063351 75.252449 21.389410 -6.998829 86.821663 -69.336113 -36.492577 -66.769104 0.387387 -15.972981 -7.548021 3.866528 0.146894 15.728039 -3.219703 -0.973204 -8.495323 1.089982 -0.807879 -7.531943 -4.331991 0.100592 15.676721 3.192007 0.586786 -8.565728 -1.589840 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 30.355068 16.516052 0.038172 -35.517025 6.185051 0.020097 0.000000 0.000000 0.000000 -16.532951 28.540516 -0.063351 -76.240692 -16.481785 -11.940782 -106.726143 57.922276 -42.674595 63.137428 -0.173099 -21.220787 12.197351 -26.079723 -0.063351 74.763191 21.723465 -6.547225 87.466057 -69.187714 -40.086025 -66.626251 0.387389 -16.115835 -7.548020 3.866529 0.146894 15.727672 -3.219887 -0.982961 -8.494112 1.099454 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192005 0.586786 -8.565728 -1.589840 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 30.503832 17.476730 0.040377 -35.874256 6.180370 0.021379 0.000000 0.000000 0.000000 -16.978012 28.861925 -0.063351 -76.256165 -16.777945 -11.737227 -107.208801 58.150845 -43.785328 63.280281 -0.173099 -19.363649 12.463904 -26.417507 -0.063351 74.565491 21.859308 -5.892597 87.728943 -69.127129 -41.550282 -66.483398 0.387391 -16.258688 -7.548019 3.866530 0.146894 15.728039 -3.219705 -0.973204 -8.495323 1.089981 -0.807879 -7.531943 -4.331992 0.100592 15.676721 3.192007 0.586786 -8.565729 -1.589839 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 30.534758 18.012556 0.040895 -36.113537 6.158617 0.022678 0.000000 0.000000 0.000000 -16.941982 28.836237 -0.063351 -76.263367 -16.759518 -11.516372 -107.175072 58.135468 -43.714027 63.423134 -0.173100 -17.506512 12.442373 -26.390442 -0.063351 74.581673 21.849712 -5.092857 87.711853 -69.131012 -41.451981 -66.340546 0.387393 -16.401541 -7.548021 3.866528 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099454 -0.807164 -7.531943 -4.331992 0.100592 15.676721 3.192008 0.586786 -8.565729 -1.589839 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 30.450769 18.226109 0.040436 -36.232754 6.153636 0.024001 0.000000 0.000000 0.000000 -16.599623 28.589523 -0.063351 -76.264893 -16.540512 -11.287520 -106.812286 57.964615 -42.889168 63.565990 -0.173100 -15.649375 12.237406 -26.131052 -0.063351 74.734039 21.747442 -4.205920 87.516289 -69.175995 -40.357746 -66.197701 0.387396 -16.544394 -7.548021 3.866528 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099454 -0.807164 -7.531943 -4.331992 0.100592 15.676721 3.192008 0.586786 -8.565729 -1.589839 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 30.254787 18.219963 0.039712 -36.229797 6.199272 0.025358 0.000000 0.000000 0.000000 -16.125692 28.247849 -0.063351 -76.263321 -16.234926 -11.059977 -106.307739 57.726734 -41.739208 63.708847 -0.173100 -13.792238 11.953648 -25.771854 -0.063351 74.944885 21.605261 -3.289697 87.243744 -69.238716 -38.834194 -66.054855 0.387398 -16.687248 -7.548020 3.866529 0.146894 15.728039 -3.219702 -0.973204 -8.495323 1.089980 -0.807879 -7.531943 -4.331993 0.100592 15.676721 3.192005 0.586786 -8.565728 -1.589840 0.974710 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 29.949728 18.096704 0.039435 -36.102551 6.329370 0.026759 0.000000 0.000000 0.000000 -15.694946 27.937286 -0.063351 -76.261261 -15.956764 -10.843045 -105.848740 57.510300 -40.692627 63.851700 -0.173100 -11.935101 11.695745 -25.445370 -0.063351 75.136513 21.475937 -2.402101 86.995728 -69.295799 -37.447941 -65.912003 0.387400 -16.830101 -7.548020 3.866529 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099455 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589841 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 29.510267 17.921049 0.040071 -35.812424 6.554089 0.028154 0.000000 0.000000 0.000000 -15.442471 27.755280 -0.063351 -76.260750 -15.794174 -10.644298 -105.580093 57.383698 -40.080715 64.651703 -0.173100 -13.135100 11.544585 -25.254032 -0.063351 75.248848 21.400255 -1.590379 86.850708 -69.329170 -36.637077 -66.312004 0.387400 -17.630100 -7.548020 3.866529 0.146894 15.728039 -3.219702 -0.973204 -8.495323 1.089980 -0.807879 -7.531943 -4.331991 0.100592 15.676721 3.192007 0.586786 -8.565729 -1.589839 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 28.798088 17.606262 0.041112 -35.174904 6.788827 0.029256 0.000000 0.000000 0.000000 -15.336067 27.678614 -0.063351 -76.261597 -15.726343 -10.462719 -105.467484 57.330734 -39.825165 65.451706 -0.173100 -14.335100 11.480889 -25.173435 -0.063351 75.296211 21.368540 -0.852133 86.790108 -69.343102 -36.297894 -66.712006 0.387400 -18.430099 -7.548021 3.866527 0.146894 15.728039 -3.219702 -0.973204 -8.495323 1.089981 -0.807879 -7.531943 -4.331993 0.100592 15.676721 3.192006 0.586786 -8.565729 -1.589839 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 27.646622 17.027754 0.041807 -33.968998 6.925295 0.029721 0.000000 0.000000 0.000000 -15.313296 27.662258 -0.063351 -76.263153 -15.712725 -10.296599 -105.444168 57.319912 -39.773510 66.251701 -0.173100 -15.535100 11.467271 -25.156239 -0.063351 75.306381 21.361988 -0.178757 86.777809 -69.345917 -36.228622 -67.112007 0.387400 -19.230101 -7.548020 3.866528 0.146894 15.728041 -3.219700 -0.973204 -8.495323 1.089981 -0.807879 -7.531942 -4.331993 0.100592 15.676721 3.192007 0.586786 -8.565728 -1.589839 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 25.889305 16.060926 0.041402 -31.973717 6.855203 0.029204 0.000000 0.000000 0.000000 -15.327130 27.672297 -0.063351 -76.264908 -15.722763 -10.147332 -105.459877 57.327492 -39.810852 67.051697 -0.173100 -16.735100 11.475569 -25.166790 -0.063351 75.300262 21.366430 0.425381 86.786613 -69.343895 -36.277222 -67.512009 0.387400 -20.030102 -7.548020 3.866529 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099454 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192007 0.586786 -8.565728 -1.589839 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 23.359577 14.581190 0.039145 -28.968073 6.470260 0.027360 0.000000 0.000000 0.000000 -15.346200 27.686100 -0.063351 -76.266403 -15.736000 -10.026900 -105.481003 57.337601 -39.860298 67.851700 -0.173100 -17.935101 11.487000 -25.181299 -0.063351 75.291801 21.372400 0.912595 86.798302 -69.341202 -36.341999 -67.912003 0.387400 -20.830101 -7.548020 3.866529 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099455 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589841 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 19.971275 12.519718 0.034541 -24.835979 5.701602 0.023987 0.000000 0.000000 0.000000 -12.451513 22.123365 -0.063351 -75.238785 -11.450205 -5.690484 -91.653435 46.230709 -33.192291 57.537998 -0.173102 -14.916628 9.235514 -20.036032 -0.063351 74.426620 16.147205 3.425762 76.084518 -56.233711 -30.260376 -57.588249 0.351685 -17.329128 -7.548020 3.866529 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099455 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589841 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 15.976519 10.042920 0.028183 -19.903925 4.648276 0.019495 0.000000 0.000000 0.000000 -9.556827 16.560631 -0.063351 -74.211166 -7.164410 -1.354067 -77.825867 35.123817 -26.524286 47.224297 -0.173104 -11.898155 6.984027 -14.890763 -0.063351 73.561440 10.922010 5.938930 65.370735 -43.126221 -24.178753 -47.264496 0.315971 -13.828156 -7.548020 3.866529 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099455 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589841 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 11.682608 7.355848 0.020851 -14.570230 3.437392 0.014390 0.000000 0.000000 0.000000 -6.662140 10.997895 -0.063351 -73.183548 -2.878615 2.982350 -63.998299 24.016928 -19.856281 36.910595 -0.173106 -8.879683 4.732540 -9.745495 -0.063351 72.696259 5.696815 8.452098 54.656952 -30.018730 -18.097130 -36.940742 0.280256 -10.327183 -7.548020 3.866529 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099455 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589841 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 7.367660 4.642965 0.013230 -9.193933 2.180442 0.009120 0.000000 0.000000 0.000000 -3.767453 5.435160 -0.063351 -72.155930 1.407180 7.318767 -50.170731 12.910039 -13.188275 26.596893 -0.173108 -5.861210 2.481053 -4.600226 -0.063351 71.831070 0.471620 10.965265 43.943169 -16.911240 -12.015508 -26.616991 0.244541 -6.826210 -7.548020 3.866529 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099455 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589841 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 3.312649 2.088214 0.005961 -4.134615 0.982410 0.004108 0.000000 0.000000 0.000000 -0.872767 -0.127575 -0.063351 -71.128311 5.692975 11.655184 -36.343166 1.803150 -6.520270 16.283192 -0.173110 -2.842738 0.229567 0.545042 -0.063351 70.965881 -4.753575 13.478433 33.229385 -3.803750 -5.933886 -16.293240 0.208827 -3.325238 -7.548020 3.866529 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099455 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589841 0.974711 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -70.100700 9.978770 15.991600 -22.515600 -9.303740 0.147736 5.969490 -0.173112 0.175734 -2.021920 5.690310 -0.063351 70.100700 -9.978770 15.991600 22.515600 9.303740 0.147736 -5.969490 0.173112 0.175734 -7.548020 3.866529 0.146894 15.727672 -3.219886 -0.982961 -8.494112 1.099455 -0.807164 -7.531943 -4.331991 0.100592 15.676721 3.192008 0.586786 -8.565728 -1.589841 0.974711 diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_surprise.bvh b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_surprise.bvh new file mode 100644 index 00000000..69a142b0 --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_surprise.bvh @@ -0,0 +1,169 @@ +HIERARCHY +ROOT hip +{ + OFFSET 0.00 0.00 0.00 + CHANNELS 6 Xposition Yposition Zposition Xrotation Zrotation Yrotation + JOINT abdomen + { + OFFSET 0.000000 0.000000 0.000000 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT chest + { + OFFSET 0.000000 5.018152 -1.882228 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT neckDummy + { + OFFSET 0.000000 8.316447 0.784897 + CHANNELS 3 Xrotation Yrotation Zrotation + JOINT neck + { + OFFSET 0.000000 2.280413 -0.392801 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT head + { + OFFSET 0.000000 3.496879 0.529469 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT figureHair + { + OFFSET 0.000000 4.699570 0.720622 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 0.000000 -6.419331 0.000000 + } + } + } + } + } + JOINT lCollar + { + OFFSET 0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lShldr + { + OFFSET 6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT lForeArm + { + OFFSET 10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lHand + { + OFFSET 11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 10.353753 0.000000 0.000000 + } + } + } + } + } + JOINT rCollar + { + OFFSET -0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rShldr + { + OFFSET -6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT rForeArm + { + OFFSET -10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rHand + { + OFFSET -11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET -10.353753 0.000000 0.000000 + } + } + } + } + } + } + } + JOINT lThigh + { + OFFSET 4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lShin + { + OFFSET -1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lFoot + { + OFFSET -0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } + JOINT rThigh + { + OFFSET -4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rShin + { + OFFSET 1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rFoot + { + OFFSET 0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } +} +MOTION +Frames: 40 +Frame Time: 0.041667 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -70.100700 9.978770 15.991600 -22.515600 -9.303740 0.147736 5.969490 -0.173112 0.175734 -2.021920 5.690310 -0.063351 70.100700 -9.978770 15.991600 22.515600 9.303740 0.147736 -5.969490 0.173112 0.175734 -7.540078 3.882017 0.146008 15.744670 -3.241251 -0.947839 -8.514585 1.093366 -0.807438 -7.531943 -4.331991 0.100592 15.702465 3.212883 0.590639 -8.576411 -1.585766 0.965128 +-0.292719 42.500225 0.894043 -1.666667 -0.333333 -0.833333 4.700394 -0.668957 -0.426130 0.803868 -0.786924 -0.315621 0.000000 0.000000 0.000000 -2.149134 0.124872 -0.048619 3.846555 1.253236 -2.232652 0.000000 0.000000 0.000000 2.485964 -6.009744 -0.047941 -66.128555 9.674990 15.288389 -30.876104 -6.317351 4.551177 4.900933 4.825302 -0.684181 -2.426141 6.970276 -0.200731 63.517384 -10.399952 15.774399 35.281979 4.849810 9.131554 -10.008048 -2.165049 0.011348 -3.554211 5.681088 0.032379 23.381083 -3.131009 -1.794263 -6.003067 4.552963 -2.320280 -1.673201 -4.237778 0.393846 9.654884 2.712913 0.204272 -6.734401 -1.118138 1.770259 +-0.900765 39.136639 -0.060342 -2.500000 -0.500000 -1.250000 10.088996 -1.450606 -0.934996 1.785540 -1.714274 -0.689683 0.000000 0.000000 0.000000 -4.662945 0.280278 -0.106858 8.238412 2.724675 -4.845828 0.000000 0.000000 0.000000 3.035456 -6.400090 -0.030064 -61.504967 9.324522 14.451381 -40.612190 -2.890040 9.613650 3.712631 10.492804 -1.622994 -2.830363 8.250243 -0.338111 56.934067 -10.821134 15.557198 48.048359 0.395880 18.115372 -14.046606 -4.503211 -0.153038 -13.891198 9.147067 -0.648781 55.816055 -3.281751 -4.979294 -14.675887 6.409758 -3.383505 -19.458065 -4.967305 0.792151 45.827076 3.480870 3.650974 -24.237238 -1.439078 0.618904 +-1.508812 35.773052 -1.014726 -3.333333 -0.666667 -1.666667 12.984676 -2.020945 -1.415780 2.938310 -2.469511 -1.015334 0.000000 0.000000 0.000000 -6.522551 0.487196 -0.163424 10.390551 3.867744 -6.795392 0.000000 0.000000 0.000000 3.509169 -6.855984 -0.018314 -58.308418 9.113690 13.687220 -47.387863 -1.011139 12.479539 3.448441 12.898082 -1.648131 -3.234584 9.530210 -0.475492 50.350750 -11.242315 15.339997 60.814739 -4.058051 27.099188 -18.085165 -6.841372 -0.317424 -17.526237 12.963726 -2.393932 76.494812 -3.083917 -7.013905 -18.390661 6.926300 -4.746644 -30.281996 -5.483248 1.097307 67.018280 3.324117 5.777417 -33.744972 -1.064265 -0.283648 +-1.791288 34.823063 -1.369879 -2.416667 -1.458333 -2.083333 10.980399 -2.134743 -1.775893 3.912389 -2.859065 -1.214413 0.000000 0.000000 0.000000 -6.964695 0.762722 -0.210062 8.566289 4.264564 -7.299421 0.000000 0.000000 0.000000 3.779055 -7.363311 -0.019886 -57.805885 9.118335 13.111905 -48.832256 -1.740446 11.446263 5.068407 9.018550 -0.051710 -3.708060 10.002029 -0.487393 45.915691 -11.941974 15.070928 73.292091 -8.150496 31.716364 -23.681023 -1.758053 -0.192127 -19.745682 15.176959 -3.955580 78.411934 -3.289745 -7.256133 -26.223724 11.334353 -6.697815 -34.265083 -5.449233 0.781949 71.670082 3.087595 6.205225 -35.261292 -0.439164 0.055795 +-2.073765 33.873074 -1.725033 -1.500000 -2.250000 -2.500000 5.551917 -1.851941 -1.898868 2.609085 -3.088631 -1.275286 0.000000 0.000000 0.000000 -6.196133 1.029757 -0.238380 6.042913 3.936524 -6.556760 0.000000 0.000000 0.000000 3.782755 -7.726855 -0.035542 -57.930721 8.939747 12.616030 -50.582470 -1.949995 10.042350 8.714964 0.822100 2.202845 -4.181535 10.473849 -0.499294 41.480633 -12.641632 14.801858 85.769440 -12.242940 36.333542 -29.276880 3.325265 -0.066829 -22.004969 16.770138 -6.080486 80.324394 -3.082322 -7.420476 -33.730991 16.998861 -9.001249 -38.165840 -5.556025 0.341288 76.114128 2.854153 6.591580 -36.619743 0.339172 0.405151 +-0.767068 36.131756 -1.766642 -3.583333 -3.041667 -2.916667 -0.854310 -1.308776 -1.662274 -2.350867 -3.463723 -1.202957 0.000000 0.000000 0.000000 -4.666123 1.187652 -0.239956 6.357864 3.014836 -5.011447 0.000000 0.000000 0.000000 3.474331 -7.706126 -0.064437 -55.782879 8.060583 12.033834 -60.277592 2.535120 13.104097 14.326142 -8.475746 3.734278 -4.655011 10.945669 -0.511196 37.045574 -13.341290 14.532789 98.246796 -16.335384 40.950718 -34.872738 8.408584 0.058469 -13.750079 15.343016 -3.328361 67.376930 -3.589897 -6.163542 -34.159210 22.577066 -7.211896 -30.044739 -7.638574 1.671524 64.153320 3.455124 5.505519 -30.902292 1.037094 4.329533 +0.539629 38.390438 -1.808251 -5.666667 -3.833333 -3.333333 -5.791828 -0.641483 -0.943677 -7.720140 -4.289855 -1.002426 0.000000 0.000000 0.000000 -2.823926 1.135757 -0.206367 9.075212 1.630712 -3.107524 0.000000 0.000000 0.000000 2.807844 -7.060632 -0.105723 -48.462292 5.963498 11.199556 -85.556702 15.889803 25.467804 21.839970 -15.659477 3.161338 -5.128487 11.417488 -0.523097 32.610516 -14.040948 14.263720 110.724144 -20.427830 45.567894 -40.468597 13.491902 0.183766 -4.487936 13.437132 -2.182448 51.982243 -3.974010 -4.579887 -33.658775 28.933132 -5.599838 -20.458042 -9.809564 1.462287 49.334400 3.854198 4.016857 -23.734125 2.593116 7.771296 +0.618462 39.565201 -2.374797 -6.833333 -5.416667 -4.166667 -7.533184 0.040859 -0.001564 -10.169692 -5.574418 -0.738569 0.000000 0.000000 0.000000 -1.118800 0.773423 -0.129189 12.765682 -0.084636 -1.289029 0.000000 0.000000 0.000000 1.901149 -5.828677 -0.151358 -35.833012 2.790301 10.132309 -125.771027 37.786728 47.128990 30.191685 -18.467316 0.095119 -3.881806 9.091841 -0.462730 29.880960 -9.205627 11.723578 115.945053 -27.373789 46.030186 -48.257034 17.292755 1.075180 -1.231968 14.831582 -2.152363 46.045444 -4.036475 -3.940492 -29.292912 30.040661 -6.237640 -15.849199 -8.748219 1.131524 40.866737 3.929649 3.141673 -18.695845 3.414722 8.638142 +0.697296 40.739964 -2.941342 -8.000000 -7.000000 -5.000000 -7.226944 0.737809 -0.618098 -10.670218 -6.132312 -0.715763 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 16.000000 -2.000000 0.000000 0.000000 0.000000 0.000000 1.527263 -5.163752 -0.164513 -28.815424 1.319412 9.590697 -147.120316 49.889675 58.720032 34.305332 -18.452423 -1.883892 -2.635126 6.766194 -0.402364 27.151405 -4.370308 9.183437 121.165955 -34.319748 46.492477 -56.045471 21.093607 1.966594 3.238062 16.343826 -1.564891 37.949352 -4.024486 -3.045332 -23.656784 30.903786 -7.174297 -9.330252 -7.533986 0.855792 28.350201 3.780839 1.846143 -11.531142 4.323492 9.596249 +1.235038 40.906448 -3.213923 -9.333333 -7.666667 -5.000000 -6.491006 1.372267 -4.132776 -10.896624 -4.986408 -1.160088 0.000000 0.000000 0.000000 0.255591 -1.070595 0.160592 17.731363 -3.923648 0.454418 0.000000 0.000000 0.000000 1.800313 -5.291774 -0.140830 -29.281757 2.020911 9.638293 -144.303528 49.347187 56.702042 34.263149 -17.664928 -1.765396 -2.614641 6.865102 -0.435272 27.186588 -3.044131 9.405931 117.912056 -32.595631 44.928631 -55.073914 19.693163 1.704413 4.693009 16.214567 -1.483818 37.341965 -4.017999 -2.964832 -23.401180 31.190874 -6.519069 -7.029481 -7.622205 0.634492 25.840677 3.679916 1.599622 -10.031932 4.806481 10.343753 +1.772780 41.072937 -3.486504 -10.666666 -8.333333 -5.000000 -5.944581 1.451864 -8.590727 -11.040908 -3.183972 -1.744924 0.000000 0.000000 0.000000 0.060593 -1.466177 0.215848 18.442846 -5.421760 0.324647 0.000000 0.000000 0.000000 2.073362 -5.419797 -0.117148 -29.748091 2.722410 9.685889 -141.486740 48.804699 54.684052 34.220966 -16.877434 -1.646901 -2.594157 6.964010 -0.468180 27.221771 -1.717954 9.628424 114.658157 -30.871513 43.364784 -54.102356 18.292719 1.442232 6.160197 16.084993 -1.306314 36.773640 -4.009575 -2.897469 -23.191568 31.427992 -5.866346 -4.597142 -7.701797 0.420253 23.073439 3.575673 1.310760 -8.377787 5.298153 11.071069 +2.310522 41.239422 -3.759085 -12.000000 -9.000000 -5.000000 -5.957206 0.380415 -11.213494 -10.924349 -2.278364 -2.005480 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 19.000000 -6.000000 0.000000 0.000000 0.000000 0.000000 2.346412 -5.547820 -0.093465 -30.214424 3.423909 9.733484 -138.669952 48.262211 52.666061 34.178787 -16.089939 -1.528405 -2.573673 7.062918 -0.501088 27.256954 -0.391777 9.850916 111.404259 -29.147396 41.800938 -53.130798 16.892275 1.180051 7.644817 15.961118 -1.089548 36.087299 -4.001315 -2.821068 -22.886948 31.651670 -5.212197 -1.944399 -7.750776 0.214887 19.762436 3.435526 0.995379 -6.424414 5.808045 11.819450 +2.310915 41.337944 -3.987860 -12.600000 -8.600000 -5.000000 -6.672896 -2.053263 -10.275426 -10.496805 -3.287963 -1.652043 0.000000 0.000000 0.000000 0.446485 3.700231 -0.536289 20.062252 -5.341701 -0.202847 0.000000 0.000000 0.000000 2.619462 -5.675842 -0.069783 -30.680758 4.125409 9.781080 -135.853165 47.719723 50.648067 34.136604 -15.302444 -1.409909 -2.553188 7.161826 -0.533997 27.292137 0.934401 10.073409 108.150360 -27.423279 40.237091 -52.159241 15.491831 0.917870 8.239739 15.443773 -0.950516 35.352943 -3.980278 -2.737305 -22.185984 31.563780 -5.193747 -1.243487 -8.159739 0.216036 18.967743 3.315233 0.981015 -4.594609 6.057672 11.736763 +2.311308 41.436466 -4.216636 -13.200001 -8.200001 -5.000000 -7.333579 -4.520347 -8.262088 -10.222483 -5.091237 -1.095218 0.000000 0.000000 0.000000 0.923438 6.748987 -0.976618 21.464546 -3.840870 -0.257763 0.000000 0.000000 0.000000 2.892511 -5.803865 -0.046100 -31.147091 4.826908 9.828676 -133.036377 47.177235 48.630074 34.094421 -14.514950 -1.291414 -2.532704 7.260734 -0.566905 27.327320 2.260578 10.295902 104.896461 -25.699162 38.673244 -51.187683 14.091387 0.655689 9.578112 14.956847 -0.638780 33.197361 -3.921134 -2.512645 -20.716969 31.406374 -5.309314 -0.553431 -8.567978 0.221859 18.085070 3.195902 0.923225 -2.662457 6.340852 11.650702 +2.311701 41.534985 -4.445411 -13.800000 -7.800001 -5.000000 -7.180381 -5.516766 -7.575040 -10.250858 -5.940855 -0.915201 0.000000 0.000000 0.000000 0.903118 6.372709 -0.921729 22.835716 -2.069190 -0.211256 0.000000 0.000000 0.000000 3.165561 -5.931888 -0.022418 -31.613424 5.528407 9.876271 -130.219589 46.634747 46.612083 34.052242 -13.727455 -1.172918 -2.512219 7.359642 -0.599813 27.362503 3.586755 10.518394 101.642563 -23.975044 37.109398 -50.216125 12.690942 0.393508 10.082387 14.495825 -0.469824 32.668312 -3.901569 -2.466453 -20.118914 31.243687 -5.326739 1.619071 -8.840971 0.115985 14.329162 2.983932 0.581905 0.669545 6.665868 11.552286 +2.312094 41.633507 -4.674186 -14.400000 -7.400001 -5.000000 -6.436975 -4.739507 -6.730057 -9.494043 -4.459696 -1.462369 0.000000 0.000000 0.000000 0.502562 3.503528 -0.506654 23.804592 -0.598340 -0.109833 0.000000 0.000000 0.000000 3.438611 -6.059911 0.001265 -32.079758 6.229906 9.923866 -127.402794 46.092255 44.594093 34.010063 -12.939960 -1.054423 -2.491735 7.458549 -0.632722 27.397686 4.912932 10.740887 98.388664 -22.250927 35.545547 -49.244568 11.290497 0.131326 10.710793 14.031775 -0.270819 31.952789 -3.877495 -2.404446 -19.458071 31.077719 -5.324698 2.934562 -9.326691 0.045280 12.075276 2.918659 0.333228 3.344529 7.064512 11.482265 +2.312487 41.732029 -4.902962 -15.000000 -7.000000 -5.000000 -5.886443 -3.543417 -5.751920 -8.564412 -2.113747 -2.250118 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 24.000000 0.000000 0.000000 0.000000 0.000000 0.000000 3.711660 -6.187934 0.024947 -32.546089 6.931405 9.971462 -124.585999 45.549767 42.576099 33.967880 -12.152465 -0.935927 -2.471250 7.557457 -0.665630 27.432869 6.239109 10.963380 95.134766 -20.526810 33.981701 -48.273010 9.890053 -0.130855 11.250330 13.585203 -0.085793 31.382336 -3.881721 -2.342709 -18.847786 30.853733 -5.330875 3.801542 -9.830099 -0.022341 10.943575 2.981177 0.168349 5.380119 7.460899 11.250388 +2.105554 41.611126 -5.190091 -15.000000 -7.000000 -5.000000 -6.167072 -3.288805 -5.195347 -8.344227 -0.692102 -2.723269 0.000000 0.000000 0.000000 -0.377036 -2.619132 0.378741 23.215105 -0.631373 0.080430 0.000000 0.000000 0.000000 3.984710 -6.315957 0.048630 -33.012421 7.632904 10.019058 -121.769203 45.007278 40.558105 33.925697 -11.364969 -0.817431 -2.450766 7.656365 -0.698538 27.468052 7.565286 11.185873 91.880859 -18.802694 32.417854 -47.301453 8.489609 -0.393036 10.160066 14.050105 -0.335624 32.771767 -3.946467 -2.486321 -18.974663 30.839533 -5.717822 2.129721 -9.575464 0.091327 13.510910 3.136997 0.407843 4.375907 7.323918 10.831884 +1.898621 41.490223 -5.477219 -15.000000 -7.000000 -5.000000 -7.003285 -3.909737 -5.089013 -8.651758 -0.342359 -2.883832 0.000000 0.000000 0.000000 -0.603804 -4.194380 0.606530 21.900423 -1.991756 0.128427 0.000000 0.000000 0.000000 4.257760 -6.443980 0.072312 -33.478756 8.334403 10.066653 -118.952408 44.464787 38.540115 33.883518 -10.577475 -0.698936 -2.430281 7.755274 -0.731447 27.503237 8.891463 11.408365 88.626961 -17.078579 30.854006 -46.329895 7.089164 -0.655217 8.998702 14.517258 -0.617266 34.287437 -4.021348 -2.655620 -19.170450 30.820351 -6.105611 0.577247 -9.297174 0.168423 15.824429 3.246066 0.632288 3.501953 7.184397 10.443554 +1.691689 41.369320 -5.764348 -15.000000 -7.000000 -5.000000 -7.891037 -4.983719 -5.330076 -9.039279 -0.801746 -2.873113 0.000000 0.000000 0.000000 -0.706261 -4.906071 0.709444 20.670805 -3.365969 0.149652 0.000000 0.000000 0.000000 4.530809 -6.572002 0.095994 -33.945091 9.035902 10.114248 -116.135612 43.922295 36.522125 33.841339 -9.789980 -0.580440 -2.409797 7.854182 -0.764355 27.538422 10.217640 11.630857 85.373062 -15.354462 29.290157 -45.358337 5.688720 -0.917398 7.956907 14.967096 -0.894217 35.520916 -4.064872 -2.795171 -19.182913 30.801432 -6.516662 -0.791628 -8.991235 0.219492 17.753653 3.296298 0.807674 2.851918 7.076733 10.066510 +1.484756 41.248413 -6.051476 -15.000000 -7.000000 -5.000000 -8.326285 -6.088256 -5.815698 -9.059058 -1.807486 -2.832422 0.000000 0.000000 0.000000 -0.710362 -4.934529 0.713559 20.141106 -4.038828 0.149771 0.000000 0.000000 0.000000 4.803859 -6.700026 0.119677 -34.411423 9.737401 10.161844 -113.318817 43.379807 34.504131 33.799156 -9.002484 -0.461944 -2.389312 7.953090 -0.797263 27.573605 11.543818 11.853351 82.119156 -13.630345 27.726307 -44.386776 4.288275 -1.179579 6.902220 15.396996 -1.211711 36.765263 -4.098877 -2.924499 -19.194958 30.806229 -6.943204 -2.080349 -8.687148 0.261427 19.507589 3.356758 0.975419 2.273878 6.953901 9.695593 +1.512174 41.311150 -6.568375 -14.883333 -7.200000 -5.000000 -7.940286 -6.855492 -6.417971 -8.439423 -3.108516 -2.859989 0.000000 0.000000 0.000000 -0.642064 -4.460081 0.644952 20.708950 -3.512307 0.134448 0.000000 0.000000 0.000000 5.056108 -6.767132 0.141113 -34.619606 10.421902 10.208002 -110.282417 43.765190 32.263973 33.871048 -7.465196 -0.400201 -2.291385 8.046245 -0.835192 27.611429 12.881763 12.080004 79.095795 -16.622873 26.907280 -43.415218 2.887830 -1.441760 5.841264 15.653364 -1.476479 36.825813 -4.082107 -2.924010 -18.280104 30.880838 -7.053785 -1.692292 -8.254029 0.152180 16.764605 3.218189 0.720979 4.390665 7.005380 9.671998 +1.539592 41.373882 -7.085273 -14.766666 -7.400000 -5.000000 -6.905502 -7.136129 -6.908729 -7.612926 -4.500627 -2.881750 0.000000 0.000000 0.000000 -0.527325 -3.663048 0.529696 21.903072 -2.156989 0.109363 0.000000 0.000000 0.000000 5.308358 -6.834238 0.162549 -34.827789 11.106402 10.254159 -107.246017 44.150574 30.023815 33.942944 -5.927908 -0.338458 -2.193457 8.139399 -0.873120 27.649254 14.219709 12.306657 76.072433 -19.615400 26.088253 -42.443661 1.487386 -1.703941 4.830899 15.884443 -1.738277 36.779369 -4.049822 -2.920449 -17.307150 30.964476 -7.185035 -1.075395 -7.825985 0.047045 13.556304 3.065907 0.423367 6.733259 7.062606 9.651711 +1.567010 41.436615 -7.602173 -14.650000 -7.599999 -5.000000 -5.529699 -6.835510 -7.034737 -7.188178 -5.791319 -2.780567 0.000000 0.000000 0.000000 -0.392105 -2.723751 0.393869 23.034985 -0.560611 0.080195 0.000000 0.000000 0.000000 5.560608 -6.901344 0.183985 -35.035973 11.790903 10.300316 -104.209618 44.535957 27.783657 34.014839 -4.390620 -0.276715 -2.095530 8.232553 -0.911048 27.687078 15.557655 12.533310 73.049072 -22.607929 25.269226 -41.472103 0.086942 -1.966122 3.827353 16.111805 -2.032971 36.714027 -4.009342 -2.912109 -16.301233 31.073662 -7.325007 0.796730 -7.288259 -0.116225 7.717543 2.735647 -0.079901 10.453835 7.174537 9.683826 +1.594428 41.499348 -8.119072 -14.533334 -7.800000 -5.000000 -4.120640 -5.858980 -6.542763 -7.773788 -6.788096 -2.439302 0.000000 0.000000 0.000000 -0.262364 -1.822510 0.263545 23.416204 0.689092 0.052625 0.000000 0.000000 0.000000 5.812857 -6.968451 0.205421 -35.244152 12.475404 10.346474 -101.173218 44.921341 25.543499 34.086731 -2.853331 -0.214972 -1.997602 8.325706 -0.948977 27.724903 16.895601 12.759963 70.025711 -25.600456 24.450199 -40.500546 -1.313503 -2.228303 2.867789 16.327290 -2.298306 36.552021 -3.955264 -2.882205 -15.243729 31.145597 -7.480915 1.049806 -6.897489 -0.164877 5.041580 2.569086 -0.298605 12.626179 7.232295 9.667349 +1.619253 41.393303 -5.934212 -14.066668 -8.599999 -5.000000 -2.781254 -4.127751 -5.269806 -9.584148 -7.252995 -1.817773 0.000000 0.000000 0.000000 -0.159101 -1.105200 0.159818 22.550982 1.153345 0.031209 0.000000 0.000000 0.000000 6.065106 -7.035557 0.226857 -35.452332 13.159904 10.392632 -98.136818 45.306725 23.303341 34.158623 -1.316043 -0.153229 -1.899675 8.418861 -0.986905 27.762728 18.233547 12.986616 67.002350 -28.592983 23.631172 -39.528988 -2.713947 -2.490484 6.598014 16.889311 -1.723331 35.768551 -3.932288 -2.803799 -18.584787 31.525900 -7.211679 -0.139128 -6.651183 -0.015327 13.957794 2.998868 0.530247 3.291530 6.633959 10.071765 +1.644079 41.287262 -3.749352 -13.600000 -9.400000 -5.000000 -0.795134 -1.626531 -3.413805 -11.256780 -6.766200 -1.183633 0.000000 0.000000 0.000000 -0.083482 -0.579914 0.083859 20.714552 0.989223 0.016008 0.000000 0.000000 0.000000 6.317356 -7.102663 0.248293 -35.660515 13.844405 10.438788 -95.100418 45.692108 21.063181 34.230518 0.221246 -0.091486 -1.801747 8.512016 -1.024834 27.800552 19.571493 13.213268 63.978992 -31.585512 22.812143 -38.557430 -4.114391 -2.752665 10.936975 17.393312 -0.846676 33.806866 -3.912482 -2.586370 -21.295422 31.771608 -6.924548 0.548558 -6.325609 -0.004134 18.754234 3.220541 0.991459 -3.797468 6.256207 10.499550 +1.433898 41.135342 -3.332195 -12.800000 -9.200000 -5.000000 2.260909 1.393764 -1.351677 -11.470407 -5.166822 -0.816904 0.000000 0.000000 0.000000 -0.031713 -0.220299 0.031856 18.374897 0.502762 0.005960 0.000000 0.000000 0.000000 6.569606 -7.169768 0.269729 -35.868698 14.528906 10.484945 -92.064018 46.077492 18.823021 34.302414 1.758534 -0.029743 -1.703820 8.605170 -1.062762 27.838377 20.909439 13.439921 60.955635 -34.578041 21.993114 -37.585873 -5.514836 -3.014846 9.763021 17.654808 -0.982899 35.796394 -3.956779 -2.794082 -22.862829 31.618240 -7.128101 -2.306610 -6.433175 0.160910 24.266954 3.484320 1.494851 -8.414369 5.743195 10.285408 +1.223716 40.983418 -2.915037 -12.000000 -9.000000 -5.000000 4.817865 3.680881 0.184675 -10.645430 -3.511542 -0.739262 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 16.000000 0.000000 0.000000 0.000000 0.000000 0.000000 6.821855 -7.236875 0.291165 -36.076878 15.213408 10.531103 -89.027618 46.462875 16.582863 34.374306 3.295822 0.032001 -1.605892 8.698324 -1.100691 27.876202 22.247385 13.666574 57.932274 -37.570568 21.174088 -36.614315 -6.915280 -3.277027 9.463217 17.892757 -0.790884 35.950565 -3.988925 -2.816150 -23.383734 31.317852 -7.424512 -3.648419 -6.484262 0.255711 26.588058 3.690929 1.675766 -11.372418 5.363389 10.123743 +1.091047 41.239967 -2.524697 -10.800000 -8.100000 -4.500000 5.347746 4.137775 0.610382 -9.504033 -2.850593 -0.875832 0.000000 0.000000 0.000000 0.015527 0.107862 -0.015597 13.962031 -0.276650 -0.002889 0.000000 0.000000 0.000000 6.035528 -6.977996 0.234181 -38.293556 13.708572 10.950327 -84.865128 41.882259 15.908444 32.495491 5.675735 0.082542 -1.507965 8.791479 -1.138619 27.914026 23.585331 13.893227 48.117245 -22.688095 19.438393 -35.642757 -8.315724 -3.539208 7.453902 17.215307 -0.866529 37.000431 -3.993048 -2.929655 -19.359762 27.577415 -7.434034 -3.461285 -6.092749 0.222240 24.724379 3.619015 1.495939 -10.849913 4.454953 9.222078 +0.958378 41.496517 -2.134357 -9.600000 -7.200000 -4.000000 4.478835 3.289583 0.283710 -8.233875 -2.990879 -1.023890 0.000000 0.000000 0.000000 0.019042 0.132277 -0.019128 12.249923 -0.339271 -0.003543 0.000000 0.000000 0.000000 4.056424 -6.341883 0.087697 -43.411438 9.809345 11.893249 -77.662659 30.827486 16.257404 27.935215 9.182797 0.134153 -1.410038 8.884634 -1.176548 27.951851 24.923279 14.119879 38.302216 -7.805623 17.702698 -34.671200 -9.716169 -3.801389 6.014193 16.354908 -0.777536 36.797684 -3.943069 -2.927531 -14.687492 23.920416 -7.237243 -3.195054 -5.714302 0.211091 22.614271 3.534758 1.290063 -10.162849 3.588599 8.316758 +0.825709 41.753063 -1.744018 -8.400001 -6.300000 -3.500000 3.378487 2.066989 -0.201296 -6.888983 -3.428472 -0.948748 0.000000 0.000000 0.000000 0.014793 0.102761 -0.014860 10.756800 -0.263566 -0.002752 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -49.600700 5.978770 12.991600 -68.515800 18.196281 16.147718 22.469496 11.826894 0.175734 -1.312110 8.977788 -1.214476 27.989676 26.261225 14.346532 28.487190 7.076849 15.967005 -33.699642 -11.116613 -4.063570 4.475524 15.615911 -0.775924 37.113693 -3.901003 -2.997294 -10.410857 20.357151 -7.061303 -2.685452 -5.341207 0.196843 20.005272 3.398756 1.035748 -9.264449 2.776148 7.441447 +0.693040 42.009613 -1.353678 -7.200000 -5.400000 -3.000000 2.914755 1.213968 -0.387771 -5.544768 -3.730962 -0.528327 0.000000 0.000000 0.000000 0.007029 0.048829 -0.007061 9.375784 -0.125240 -0.001308 0.000000 0.000000 0.000000 0.836419 -5.310861 -0.151410 -55.324730 4.159575 13.940856 -58.466293 7.993412 14.455151 17.577362 12.088758 0.198884 -1.498904 8.387300 -1.042099 34.858006 20.381371 17.726797 27.329866 6.071937 13.838099 -29.393925 -8.988767 -3.358692 2.592072 14.738912 -0.916690 38.017601 -3.874311 -3.108949 -6.416301 16.987137 -6.687294 -1.999815 -5.014076 0.170203 16.934343 3.264187 0.758161 -8.069453 2.034636 6.569139 +0.560371 42.266163 -0.963338 -6.000000 -4.500000 -2.500000 2.758508 0.727657 -0.367575 -4.362192 -3.752007 -0.090975 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 8.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.472420 -5.194354 -0.178448 -60.219810 4.213212 14.691473 -48.340271 0.651776 11.486637 13.549917 10.332541 0.205992 -1.685698 7.796813 -0.869721 41.726334 14.501515 21.107063 26.172543 5.067025 11.709194 -25.088207 -6.860920 -2.653814 0.810021 13.833354 -1.034974 38.842625 -3.847411 -3.213564 -2.392913 13.712780 -6.235668 -0.930766 -4.667134 0.160651 12.998253 3.052116 0.385702 -6.409627 1.364904 5.730629 +0.448297 42.215912 -0.722662 -4.800000 -3.600000 -2.000000 2.403974 0.445863 -0.324898 -3.462312 -3.427967 0.033419 0.000000 0.000000 0.000000 -0.003049 -0.021181 0.003063 6.541138 0.054325 0.000567 0.000000 0.000000 0.000000 0.669447 -5.257417 -0.163813 -64.215439 5.480816 15.257653 -38.909954 -4.288692 7.906907 10.381285 7.393241 0.202145 -1.872491 7.206326 -0.697344 48.594662 8.621660 24.487329 25.015219 4.062113 9.580288 -20.782490 -4.733073 -1.948936 -2.208886 12.237011 -0.847538 36.617809 -3.818663 -3.000471 -4.891715 11.368265 -5.100457 -2.629542 -4.581250 0.169972 14.401746 3.129123 0.514350 -7.305051 0.652790 4.768201 +0.336222 42.165661 -0.481986 -3.600000 -2.700000 -1.500000 1.836004 0.315910 -0.264535 -2.721037 -2.739928 -0.040775 0.000000 0.000000 0.000000 -0.002885 -0.020042 0.002898 4.985163 0.051405 0.000537 0.000000 0.000000 0.000000 1.167024 -5.416679 -0.126853 -67.241127 7.303520 15.653599 -30.947584 -7.288055 4.380694 8.065589 4.105867 0.192428 -2.059285 6.615838 -0.524966 55.462990 2.741806 27.867596 23.857895 3.057201 7.451382 -16.476770 -2.605227 -1.244058 -4.712407 10.534204 -0.576434 33.559013 -3.780187 -2.685503 -6.939662 8.888840 -4.050660 -4.233654 -4.505118 0.159666 15.548731 3.177422 0.615546 -8.076168 0.004908 3.789401 +0.224148 42.115410 -0.241311 -2.400000 -1.800000 -1.000000 1.162109 0.312500 -0.146431 -1.952988 -1.680158 -0.088123 0.000000 0.000000 0.000000 -0.001279 -0.008882 0.001284 3.336606 0.022782 0.000238 0.000000 0.000000 0.000000 1.704674 -5.588768 -0.086916 -69.226387 9.022461 15.893515 -25.225386 -8.806384 1.572726 6.596949 1.305415 0.181929 -2.246079 6.025351 -0.352588 62.331322 -3.138049 31.247862 22.700569 2.052290 5.322476 -12.171052 -0.477380 -0.539180 -6.536213 8.711938 -0.278652 29.274450 -3.685428 -2.251289 -8.316045 6.333091 -3.133450 -5.696616 -4.446831 0.142210 16.386786 3.220793 0.676884 -8.663260 -0.566859 2.828152 +0.112074 42.065159 -0.000635 -1.200000 -0.900000 -0.500000 0.500000 0.300000 0.000000 -1.000000 -0.500000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.600000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -70.100700 9.978770 15.991600 -22.515600 -9.303740 0.147736 5.969490 -0.173112 0.175734 -2.133999 5.857831 -0.207970 66.216011 -6.558410 23.619732 22.608086 5.678015 2.735106 -9.070271 -0.152134 -0.181723 -7.408154 6.783913 0.007411 23.177509 -3.525480 -1.649475 -8.747046 3.675695 -2.336393 -7.058049 -4.403312 0.116387 17.037130 3.249708 0.743435 -9.171259 -1.115574 1.863672 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -70.100700 9.978770 15.991600 -22.515600 -9.303740 0.147736 5.969490 -0.173112 0.175734 -2.021920 5.690310 -0.063351 70.100700 -9.978770 15.991600 22.515600 9.303740 0.147736 -5.969490 0.173112 0.175734 -7.540078 3.882017 0.146008 15.744670 -3.241251 -0.947839 -8.514585 1.093366 -0.807438 -7.531943 -4.331991 0.100592 15.702465 3.212883 0.590639 -8.576411 -1.585766 0.965128 diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_wink.bvh b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_wink.bvh new file mode 100644 index 00000000..05f31f08 --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_wink.bvh @@ -0,0 +1,154 @@ +HIERARCHY +ROOT hip +{ + OFFSET 0.00 0.00 0.00 + CHANNELS 6 Xposition Yposition Zposition Xrotation Zrotation Yrotation + JOINT abdomen + { + OFFSET 0.000000 0.000000 0.000000 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT chest + { + OFFSET 0.000000 5.018152 -1.882228 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT neckDummy + { + OFFSET 0.000000 8.316447 0.784897 + CHANNELS 3 Xrotation Yrotation Zrotation + JOINT neck + { + OFFSET 0.000000 2.280413 -0.392801 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT head + { + OFFSET 0.000000 3.496879 0.529469 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT figureHair + { + OFFSET 0.000000 4.699570 0.720622 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 0.000000 -6.419331 0.000000 + } + } + } + } + } + JOINT lCollar + { + OFFSET 0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lShldr + { + OFFSET 6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT lForeArm + { + OFFSET 10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lHand + { + OFFSET 11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 10.353753 0.000000 0.000000 + } + } + } + } + } + JOINT rCollar + { + OFFSET -0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rShldr + { + OFFSET -6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT rForeArm + { + OFFSET -10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rHand + { + OFFSET -11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET -10.353753 0.000000 0.000000 + } + } + } + } + } + } + } + JOINT lThigh + { + OFFSET 4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lShin + { + OFFSET -1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lFoot + { + OFFSET -0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } + JOINT rThigh + { + OFFSET -4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rShin + { + OFFSET 1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rFoot + { + OFFSET 0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } +} +MOTION +Frames: 25 +Frame Time: 0.100000 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -70.100700 9.978770 15.991600 -22.515600 -9.303740 0.147736 5.969490 -0.173112 0.175734 -2.021920 5.690310 -0.063351 70.100700 -9.978770 15.991600 22.515600 9.303740 0.147736 -5.969490 0.173112 0.175734 -7.544341 3.962285 0.126597 15.837342 -3.291070 -0.872131 -8.576491 1.070768 -0.847483 -7.531943 -4.331991 0.100592 15.780110 3.271439 0.612621 -8.616927 -1.581442 0.945399 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.166410 -0.607426 -0.718842 -0.187552 -0.629290 -4.823352 0.000000 0.000000 0.000000 2.438003 1.124354 -0.150271 -3.245063 0.720473 3.166427 0.000000 0.000000 0.000000 2.869282 -5.867068 -0.026678 -69.861618 10.841850 16.013386 -20.421913 -9.662521 0.530866 6.181673 -0.463753 0.269531 -1.876183 6.226917 -0.158701 70.395897 -9.859337 15.903342 22.722290 9.808928 0.063287 -3.943553 1.070977 0.271388 -7.551503 3.904126 0.140824 15.816932 -3.290028 -0.881313 -8.551758 1.071751 -0.791179 -7.449052 -4.197594 0.092807 15.653620 3.265182 0.600347 -8.578678 -1.586688 0.820421 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.511711 -1.867836 -2.210440 -0.576722 -1.935068 -14.831809 0.000000 0.000000 0.000000 7.496860 3.457388 -0.462083 -9.753568 2.065454 9.526761 0.000000 0.000000 0.000000 4.627557 -6.233840 0.049417 -69.365532 12.632744 16.058594 -16.077515 -10.406996 1.325860 6.621952 -1.066833 0.464161 -1.573779 7.340377 -0.356552 71.008430 -9.611513 15.720206 23.151173 10.857193 -0.111945 0.260267 2.934047 0.469871 -7.566366 3.783445 0.170346 15.774580 -3.287866 -0.900367 -8.500437 1.073791 -0.674348 -7.277054 -3.918719 0.076652 15.391151 3.252198 0.574878 -8.499311 -1.597573 0.561092 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.888215 -3.242137 -3.836821 -1.001058 -3.358837 -25.744644 0.000000 0.000000 0.000000 13.012842 6.001238 -0.802071 -16.308022 3.170525 15.955801 0.000000 0.000000 0.000000 6.544713 -6.633755 0.132389 -68.824623 14.585465 16.107883 -11.340549 -11.218743 2.192691 7.102015 -1.724409 0.676378 -1.244049 8.554450 -0.572280 71.676315 -9.341295 15.520521 23.618813 12.000183 -0.303011 4.843950 4.965467 0.686289 -7.582571 3.651860 0.202535 15.728401 -3.285508 -0.921143 -8.444478 1.076016 -0.546960 -7.089513 -3.614645 0.059037 15.104967 3.238041 0.547107 -8.412773 -1.609442 0.278330 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 1.065026 -3.887528 -4.600591 -1.200332 -4.027458 -30.869459 0.000000 0.000000 0.000000 15.603218 7.195864 -0.961733 -18.068401 2.811028 17.745127 0.000000 0.000000 0.000000 7.445036 -6.821560 0.171354 -68.570602 15.502489 16.131029 -9.116008 -11.599954 2.599766 7.327459 -2.033215 0.776037 -1.089203 9.124595 -0.673590 71.989960 -9.214398 15.426744 23.838419 12.536950 -0.392738 6.996508 5.919449 0.787922 -7.590181 3.590066 0.217651 15.706715 -3.284401 -0.930899 -8.418199 1.077060 -0.487137 -7.001441 -3.471848 0.050765 14.970571 3.231393 0.534066 -8.372132 -1.615016 0.145541 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 1.065026 -3.887528 -4.600591 -1.200332 -4.027458 -30.869465 0.000000 0.000000 0.000000 15.603215 7.195863 -0.961733 -15.068401 0.811028 14.945123 0.000000 0.000000 0.000000 7.445036 -6.821560 0.171354 -68.570602 15.502491 16.131025 -9.116008 -11.599960 2.599767 7.327459 -2.033214 0.776037 -1.089203 9.124594 -0.673590 71.989967 -9.214398 15.426737 23.838417 12.536958 -0.392738 6.996509 5.919449 0.787922 -7.590181 3.590066 0.217651 15.706715 -3.284401 -0.930899 -8.418199 1.077060 -0.487137 -7.001441 -3.471848 0.050765 14.970571 3.231393 0.534066 -8.372132 -1.615016 0.145541 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 1.065027 -3.887528 -4.600591 -1.200332 -4.027459 -30.869471 0.000000 0.000000 0.000000 15.603212 7.195863 -0.961733 -12.068401 -1.188972 12.145119 0.000000 0.000000 0.000000 7.445037 -6.821560 0.171354 -68.570602 15.502493 16.131021 -9.116008 -11.599967 2.599767 7.327459 -2.033213 0.776037 -1.089202 9.124593 -0.673590 71.989975 -9.214398 15.426730 23.838413 12.536965 -0.392738 6.996509 5.919449 0.787922 -7.590181 3.590066 0.217651 15.706715 -3.284401 -0.930899 -8.418199 1.077060 -0.487137 -7.001441 -3.471848 0.050765 14.970571 3.231393 0.534066 -8.372132 -1.615016 0.145541 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 1.065028 -3.887529 -4.600591 -1.200331 -4.027459 -30.869476 0.000000 0.000000 0.000000 15.603210 7.195862 -0.961733 -9.068401 -3.188972 9.345115 0.000000 0.000000 0.000000 7.445038 -6.821560 0.171354 -68.570602 15.502495 16.131016 -9.116009 -11.599974 2.599768 7.327459 -2.033213 0.776037 -1.089202 9.124592 -0.673590 71.989975 -9.214399 15.426723 23.838409 12.536972 -0.392738 6.996509 5.919450 0.787922 -7.590181 3.590066 0.217651 15.706715 -3.284401 -0.930899 -8.418199 1.077060 -0.487137 -7.001441 -3.471848 0.050765 14.970571 3.231393 0.534066 -8.372132 -1.615016 0.145541 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 1.065028 -3.887529 -4.600591 -1.200331 -4.027459 -30.869484 0.000000 0.000000 0.000000 15.603208 7.195861 -0.961733 -6.068401 -5.188971 6.545111 0.000000 0.000000 0.000000 7.445038 -6.821560 0.171354 -68.570602 15.502496 16.131012 -9.116009 -11.599981 2.599768 7.327460 -2.033212 0.776037 -1.089201 9.124592 -0.673590 71.989983 -9.214399 15.426717 23.838408 12.536980 -0.392738 6.996509 5.919450 0.787922 -7.590181 3.590066 0.217651 15.706715 -3.284401 -0.930899 -8.418199 1.077060 -0.487137 -7.001441 -3.471848 0.050765 14.970571 3.231393 0.534066 -8.372132 -1.615016 0.145541 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 1.065028 -3.887529 -4.600591 -1.200331 -4.027459 -30.869484 0.000000 0.000000 0.000000 15.603208 7.195861 -0.961733 -5.568401 -5.522305 6.078444 0.000000 0.000000 0.000000 7.445038 -6.821560 0.171354 -68.570602 15.502496 16.131012 -9.116009 -11.599980 2.599768 7.327460 -2.033212 0.776037 -1.089201 9.124592 -0.673590 71.989983 -9.214399 15.426718 23.838408 12.536979 -0.392738 6.996509 5.919450 0.787922 -7.590181 3.590066 0.217651 15.706715 -3.284401 -0.930899 -8.418199 1.077060 -0.487137 -7.001441 -3.471848 0.050765 14.970571 3.231393 0.534066 -8.372132 -1.615016 0.145541 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 1.065028 -3.887529 -4.600591 -1.200331 -4.027459 -30.869484 0.000000 0.000000 0.000000 15.603208 7.195861 -0.961733 -5.068401 -5.855638 5.611778 0.000000 0.000000 0.000000 7.445038 -6.821560 0.171354 -68.570602 15.502496 16.131012 -9.116009 -11.599979 2.599768 7.327460 -2.033212 0.776037 -1.089201 9.124592 -0.673590 71.989983 -9.214399 15.426719 23.838408 12.536978 -0.392738 6.996509 5.919450 0.787922 -7.590181 3.590066 0.217651 15.706715 -3.284401 -0.930899 -8.418199 1.077060 -0.487137 -7.001441 -3.471848 0.050765 14.970571 3.231393 0.534066 -8.372132 -1.615016 0.145541 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 1.065028 -3.887529 -4.600591 -1.200331 -4.027459 -30.869484 0.000000 0.000000 0.000000 15.603209 7.195861 -0.961733 -4.568401 -6.188972 5.145112 0.000000 0.000000 0.000000 7.445038 -6.821560 0.171354 -68.570602 15.502496 16.131012 -9.116009 -11.599978 2.599768 7.327460 -2.033212 0.776037 -1.089201 9.124592 -0.673590 71.989983 -9.214399 15.426720 23.838408 12.536977 -0.392738 6.996509 5.919450 0.787922 -7.590181 3.590066 0.217651 15.706715 -3.284401 -0.930899 -8.418199 1.077060 -0.487137 -7.001441 -3.471848 0.050765 14.970571 3.231393 0.534066 -8.372132 -1.615016 0.145541 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 1.065028 -3.887529 -4.600591 -1.200331 -4.027459 -30.869482 0.000000 0.000000 0.000000 15.603209 7.195861 -0.961733 -4.068401 -6.522305 4.678446 0.000000 0.000000 0.000000 7.445038 -6.821560 0.171354 -68.570602 15.502496 16.131014 -9.116009 -11.599977 2.599768 7.327460 -2.033212 0.776037 -1.089202 9.124592 -0.673590 71.989983 -9.214399 15.426721 23.838408 12.536976 -0.392738 6.996509 5.919450 0.787922 -7.590181 3.590066 0.217651 15.706715 -3.284401 -0.930899 -8.418199 1.077060 -0.487137 -7.001441 -3.471848 0.050765 14.970571 3.231393 0.534066 -8.372132 -1.615016 0.145541 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 1.065028 -3.887529 -4.600591 -1.200331 -4.027459 -30.869480 0.000000 0.000000 0.000000 15.603209 7.195862 -0.961733 -3.568401 -6.855639 4.211780 0.000000 0.000000 0.000000 7.445038 -6.821560 0.171354 -68.570602 15.502495 16.131016 -9.116009 -11.599977 2.599768 7.327460 -2.033212 0.776037 -1.089202 9.124592 -0.673590 71.989975 -9.214399 15.426722 23.838409 12.536976 -0.392738 6.996509 5.919450 0.787922 -7.590181 3.590066 0.217651 15.706715 -3.284401 -0.930899 -8.418199 1.077060 -0.487137 -7.001441 -3.471848 0.050765 14.970571 3.231393 0.534066 -8.372132 -1.615016 0.145541 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 1.065028 -3.887529 -4.600591 -1.200331 -4.027459 -30.869480 0.000000 0.000000 0.000000 15.603209 7.195862 -0.961733 -3.068401 -7.188972 3.745113 0.000000 0.000000 0.000000 7.445038 -6.821560 0.171354 -68.570602 15.502495 16.131016 -9.116009 -11.599977 2.599768 7.327460 -2.033212 0.776037 -1.089202 9.124592 -0.673590 71.989975 -9.214399 15.426722 23.838409 12.536975 -0.392738 6.996509 5.919450 0.787922 -7.590181 3.590066 0.217651 15.706715 -3.284401 -0.930899 -8.418199 1.077060 -0.487137 -7.001441 -3.471848 0.050765 14.970571 3.231393 0.534066 -8.372132 -1.615016 0.145541 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 1.035207 -3.778678 -4.471774 -1.166722 -3.914690 -30.005135 0.000000 0.000000 0.000000 15.166320 6.994378 -0.934805 -3.202440 -5.714612 4.756388 0.000000 0.000000 0.000000 7.293190 -6.789885 0.164782 -68.613449 15.347830 16.127111 -9.491198 -11.535682 2.531111 7.289436 -1.981130 0.759229 -1.115318 9.028432 -0.656503 71.937080 -9.235802 15.442538 23.801371 12.446444 -0.377605 6.633461 5.758553 0.770781 -7.588898 3.600488 0.215102 15.710373 -3.284588 -0.929254 -8.422631 1.076884 -0.497227 -7.016295 -3.495932 0.052161 14.993238 3.232514 0.536265 -8.378986 -1.614076 0.167937 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.966193 -3.526766 -4.173656 -1.088940 -3.653711 -28.004791 0.000000 0.000000 0.000000 14.155231 6.528086 -0.872484 -3.929874 -2.128881 7.335197 0.000000 0.000000 0.000000 6.941772 -6.716580 0.149573 -68.712608 14.989892 16.118076 -10.359491 -11.386885 2.372219 7.201440 -1.860595 0.720329 -1.175758 8.805890 -0.616960 71.814651 -9.285333 15.479143 23.715652 12.236929 -0.342582 5.793264 5.386190 0.731111 -7.585927 3.624608 0.209201 15.718838 -3.285020 -0.925445 -8.432889 1.076477 -0.520577 -7.050671 -3.551669 0.055389 15.045697 3.235109 0.541356 -8.394848 -1.611900 0.219768 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.870699 -3.178197 -3.761152 -0.981315 -3.292595 -25.236929 0.000000 0.000000 0.000000 12.756195 5.882881 -0.786252 -4.613680 1.562206 9.749022 0.000000 0.000000 0.000000 6.455517 -6.615149 0.128529 -68.849800 14.494616 16.105574 -11.560941 -11.180995 2.152362 7.079679 -1.693813 0.666504 -1.259389 8.497960 -0.562244 71.645233 -9.353868 15.529792 23.597044 11.947025 -0.294121 4.630690 4.870955 0.676220 -7.581816 3.657982 0.201037 15.730550 -3.285618 -0.920176 -8.447082 1.075912 -0.552887 -7.098237 -3.628792 0.059857 15.118281 3.238699 0.548399 -8.416796 -1.608890 0.291486 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.755794 -2.758773 -3.264796 -0.851811 -2.858074 -21.906429 0.000000 0.000000 0.000000 11.072769 5.106521 -0.682491 -4.748998 3.755416 10.625418 0.000000 0.000000 0.000000 5.870419 -6.493099 0.103207 -69.014885 13.898661 16.090530 -13.006617 -10.933253 1.887813 6.933167 -1.493127 0.601737 -1.360019 8.127436 -0.496405 71.441391 -9.436337 15.590737 23.454327 11.598191 -0.235810 3.231792 4.250984 0.610171 -7.576869 3.698140 0.191213 15.744643 -3.286337 -0.913835 -8.464160 1.075233 -0.591764 -7.155473 -3.721592 0.065233 15.205621 3.243020 0.556874 -8.443207 -1.605267 0.377782 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.627922 -2.292019 -2.712429 -0.707694 -2.374520 -18.200106 0.000000 0.000000 0.000000 9.199381 4.242555 -0.567021 -4.378964 4.517540 10.087522 0.000000 0.000000 0.000000 5.219296 -6.357275 0.075027 -69.198593 13.235457 16.073792 -14.615428 -10.657557 1.593412 6.770123 -1.269795 0.529662 -1.472005 7.715100 -0.423137 71.214554 -9.528111 15.658560 23.295504 11.209994 -0.170918 1.675038 3.561054 0.536669 -7.571363 3.742831 0.180281 15.760326 -3.287138 -0.906779 -8.483166 1.074478 -0.635029 -7.219167 -3.824865 0.071215 15.302817 3.247828 0.566306 -8.472598 -1.601236 0.473817 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.492962 -1.799393 -2.129444 -0.555589 -1.864162 -14.288337 0.000000 0.000000 0.000000 7.222148 3.330698 -0.445151 -3.666620 4.284371 8.584496 0.000000 0.000000 0.000000 4.532081 -6.213924 0.045285 -69.392494 12.535496 16.056129 -16.313423 -10.366581 1.282691 6.598043 -1.034084 0.453592 -1.590199 7.279911 -0.345808 70.975166 -9.624973 15.730145 23.127882 10.800282 -0.102429 0.031990 2.832881 0.459093 -7.565556 3.789999 0.168742 15.776882 -3.287983 -0.899332 -8.503226 1.073681 -0.680692 -7.286394 -3.933863 0.077529 15.405404 3.252903 0.576261 -8.503620 -1.596982 0.575174 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.356347 -1.300724 -1.539307 -0.401617 -1.347543 -10.328583 0.000000 0.000000 0.000000 5.220661 2.407655 -0.321785 -2.753251 3.428377 6.504154 0.000000 0.000000 0.000000 3.836436 -6.068814 0.015179 -69.588760 11.826946 16.038248 -18.032246 -10.072035 0.968159 6.423851 -0.795481 0.376589 -1.709843 6.839382 -0.267530 70.732834 -9.723022 15.802604 22.958202 10.385544 -0.033101 -1.631212 2.095774 0.380565 -7.559677 3.837745 0.157063 15.793638 -3.288839 -0.891794 -8.523531 1.072873 -0.726915 -7.354444 -4.044198 0.083921 15.509247 3.258040 0.586337 -8.535021 -1.592676 0.677776 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.223372 -0.815346 -0.964900 -0.251750 -0.844695 -6.474375 0.000000 0.000000 0.000000 3.272523 1.509216 -0.201708 -1.760076 2.259398 4.176546 0.000000 0.000000 0.000000 3.159332 -5.927571 -0.014125 -69.779793 11.137282 16.020840 -19.705252 -9.785338 0.662011 6.254303 -0.563238 0.301638 -1.826297 6.410595 -0.191339 70.496948 -9.818456 15.873130 22.793041 9.981858 0.034380 -3.250081 1.378315 0.304131 -7.553954 3.884218 0.145694 15.809946 -3.289671 -0.884456 -8.543294 1.072088 -0.771906 -7.420680 -4.151591 0.090142 15.610322 3.263040 0.596145 -8.565585 -1.588484 0.777642 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.100214 -0.365797 -0.432893 -0.112945 -0.378964 -2.904662 0.000000 0.000000 0.000000 1.468184 0.677094 -0.090494 -0.795194 1.031562 1.889907 0.000000 0.000000 0.000000 2.532208 -5.796755 -0.041266 -69.956726 10.498526 16.004719 -21.254766 -9.519804 0.378460 6.097269 -0.348138 0.232220 -1.934156 6.013459 -0.120771 70.278473 -9.906847 15.938450 22.640072 9.607971 0.096880 -4.749455 0.713814 0.233338 -7.548654 3.927261 0.135165 15.825050 -3.290442 -0.877660 -8.561597 1.071360 -0.813576 -7.482026 -4.251057 0.095904 15.703936 3.267671 0.605229 -8.593893 -1.584601 0.870136 +0.000000 42.014908 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -70.100700 9.978770 15.991600 -22.515600 -9.303740 0.147736 5.969490 -0.173112 0.175734 -2.021920 5.690310 -0.063351 70.100700 -9.978770 15.991600 22.515600 9.303740 0.147736 -5.969490 0.173112 0.175734 -7.544341 3.962285 0.126597 15.837342 -3.291070 -0.872131 -8.576491 1.070768 -0.847483 -7.531943 -4.331991 0.100592 15.780110 3.271439 0.612621 -8.616927 -1.581442 0.945399 diff --git a/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_worry.bvh b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_worry.bvh new file mode 100644 index 00000000..5638cacc --- /dev/null +++ b/NPC Chatbot for Opensim/NPC Chatbot for Opensim/Object/express_worry.bvh @@ -0,0 +1,184 @@ +HIERARCHY +ROOT hip +{ + OFFSET 0.00 0.00 0.00 + CHANNELS 6 Xposition Yposition Zposition Xrotation Zrotation Yrotation + JOINT abdomen + { + OFFSET 0.000000 0.000000 0.000000 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT chest + { + OFFSET 0.000000 5.018152 -1.882228 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT neckDummy + { + OFFSET 0.000000 8.316447 0.784897 + CHANNELS 3 Xrotation Yrotation Zrotation + JOINT neck + { + OFFSET 0.000000 2.280413 -0.392801 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT head + { + OFFSET 0.000000 3.496879 0.529469 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT figureHair + { + OFFSET 0.000000 4.699570 0.720622 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 0.000000 -6.419331 0.000000 + } + } + } + } + } + JOINT lCollar + { + OFFSET 0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lShldr + { + OFFSET 6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT lForeArm + { + OFFSET 10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT lHand + { + OFFSET 11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET 10.353753 0.000000 0.000000 + } + } + } + } + } + JOINT rCollar + { + OFFSET -0.599237 8.316447 0.784897 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rShldr + { + OFFSET -6.421198 0.010146 -0.332128 + CHANNELS 3 Zrotation Yrotation Xrotation + JOINT rForeArm + { + OFFSET -10.552783 0.025574 0.125508 + CHANNELS 3 Yrotation Zrotation Xrotation + JOINT rHand + { + OFFSET -11.035963 0.319619 0.041520 + CHANNELS 3 Zrotation Yrotation Xrotation + End Site + { + OFFSET -10.353753 0.000000 0.000000 + } + } + } + } + } + } + } + JOINT lThigh + { + OFFSET 4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lShin + { + OFFSET -1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT lFoot + { + OFFSET -0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } + JOINT rThigh + { + OFFSET -4.500466 -6.400484 -1.832696 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rShin + { + OFFSET 1.359117 -18.918689 1.179887 + CHANNELS 3 Xrotation Zrotation Yrotation + JOINT rFoot + { + OFFSET 0.652380 -17.215186 -0.312137 + CHANNELS 3 Xrotation Yrotation Zrotation + End Site + { + OFFSET 0.000000 0.000000 10.353752 + } + } + } + } +} +MOTION +Frames: 55 +Frame Time: 0.066667 +0.000000 42.149532 0.240040 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -5.690310 -0.063351 -70.100700 9.978770 15.991600 -22.515600 -9.303740 0.147736 5.969490 -0.173112 0.175734 -2.021920 5.690310 -0.063351 70.100700 -9.978770 15.991600 22.515600 9.303740 0.147736 -5.969490 0.173112 0.175734 -7.543725 3.942445 0.126599 15.818686 -3.281411 -0.889137 -8.564857 1.085121 -0.826948 -7.531943 -4.331991 0.100592 15.754723 3.250621 0.599017 -8.607944 -1.576235 0.955703 +-0.047876 41.365559 -0.067764 0.432586 0.000000 0.000000 2.583333 0.000000 0.000000 -0.287037 0.000000 0.000000 0.000000 0.000000 0.000000 -2.296296 0.000000 0.000000 -1.291667 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 -1.528273 -0.063351 -78.110664 5.089880 15.991600 -41.260048 -8.691972 -7.171721 0.085234 -0.917925 2.472030 -2.021920 2.685681 -0.063351 76.829346 -5.064861 15.445304 50.463062 10.183386 -5.451813 -2.565352 3.087934 -0.140079 -13.322116 3.988950 -1.544060 25.457567 -3.587919 -1.853563 -12.963426 0.374818 -0.631267 -13.201650 -4.319178 1.018988 25.345114 3.540295 1.563789 -13.027343 0.006927 0.586721 +-0.105679 40.437016 -0.436834 0.952758 0.000000 0.000000 5.702302 0.000000 0.000000 -0.633589 0.000000 0.000000 0.000000 0.000000 0.000000 -5.068714 0.000000 0.000000 -2.851151 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 3.496733 -0.063351 -87.565529 -1.020136 15.991600 -63.781467 -7.966349 -16.008816 -7.019082 -2.159139 5.244447 -2.021920 -0.986681 -0.063351 84.855576 1.068033 14.777601 83.446808 11.220440 -12.295775 1.598447 6.804264 -0.512945 -19.252275 3.687399 -3.552858 34.895874 -3.758698 -2.820457 -17.120665 -0.539468 -0.501110 -19.164904 -4.099480 2.110764 34.921043 3.692970 2.540716 -17.218472 2.028770 0.248535 +-0.166795 39.632202 -0.801910 1.482010 0.000000 0.000000 9.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -8.000000 0.000000 0.000000 -4.500000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 8.809690 -0.063351 -95.437965 -9.521230 15.991600 -86.515602 -7.326955 -25.352301 -14.530500 -6.835902 8.175730 -2.021920 -5.309690 -0.063351 92.382004 9.521230 13.991600 110.859032 12.071141 -20.352301 6.530510 12.673100 -0.824266 -23.884623 3.197276 -5.380493 41.584789 -3.870799 -3.528043 -19.828484 -1.860829 -0.461851 -23.698513 -3.758705 3.189402 41.502121 3.788871 3.230130 -19.839130 4.721101 0.015117 +-0.228300 39.124832 -1.126318 1.979191 0.000000 0.000000 12.318713 0.000000 0.000000 -1.368746 0.000000 0.000000 0.000000 0.000000 0.000000 -10.949966 0.000000 0.000000 -6.159357 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 14.156509 -0.063351 -99.657478 -21.566544 15.991599 -107.042473 -6.910847 -34.755322 -22.089788 -16.974361 11.125688 -2.021920 -10.277205 -0.063351 98.183098 21.062662 13.088415 125.444496 12.500116 -29.609936 12.399732 21.630966 -0.995789 -26.893723 2.755090 -6.776361 45.184116 -3.983866 -3.904574 -20.997335 -3.713659 -0.541868 -26.671448 -3.471279 4.148924 45.116936 3.944904 3.641485 -21.010050 8.212359 -0.135377 +-0.286234 38.810081 -1.408703 2.428386 0.000000 0.000000 15.444704 0.000000 0.000000 -1.716078 0.000000 0.000000 0.000000 0.000000 0.000000 -13.728624 0.000000 0.000000 -7.722352 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 19.192831 -0.063351 -101.052162 -34.794300 15.991598 -122.000877 -6.703512 -43.612293 -29.210098 -27.802208 13.904334 -2.021920 -14.515675 -0.063351 101.831879 31.745846 12.317785 130.160156 12.614258 -37.508888 18.416512 30.288078 -1.080899 -28.999664 2.384282 -7.870165 47.245583 -4.082120 -4.138345 -21.469425 -5.696473 -0.640893 -28.745152 -3.214999 4.934637 47.214603 4.093225 3.888779 -21.526955 11.239177 -0.220715 +-0.333591 38.588688 -1.634434 2.791370 0.000000 0.000000 18.000000 0.000000 0.000000 -2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -9.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.174728 -46.021198 15.991600 -127.794312 -6.652537 -50.852299 -35.030499 -32.847534 16.175699 -2.021920 -16.309700 -0.063351 103.100998 36.445702 11.991600 130.516006 12.606022 -40.852299 23.442301 34.173100 -1.133650 -30.493708 2.098840 -8.730701 48.534306 -4.193120 -4.248697 -21.703072 -7.396513 -0.755199 -30.217646 -2.915479 5.497854 48.436428 4.144450 4.025856 -21.642155 12.237210 -0.289348 +-0.329065 38.468784 -1.803093 3.079140 0.000000 0.000000 18.000000 0.000000 0.000000 -2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -9.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.180168 -45.914230 15.991600 -127.810440 -6.665517 -50.852299 -31.412901 -32.843208 16.175699 -2.021920 -16.309700 -0.063351 103.105644 36.445473 11.991600 130.532776 12.598991 -40.852299 18.971701 34.184456 -1.838690 -31.517317 1.801676 -9.512529 49.180000 -4.203861 -4.330221 -21.670719 -6.565930 -0.896636 -31.276728 -2.563901 6.063024 49.083641 4.124053 4.103238 -21.557659 11.549989 -0.294859 +-0.324539 38.348877 -1.971753 3.366910 0.000000 0.000000 18.000000 0.000000 0.000000 -2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -9.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.185608 -45.807266 15.991600 -127.826569 -6.678497 -50.852299 -35.030499 -32.838882 6.175700 -2.021920 -16.309700 -0.063351 103.110291 36.445244 11.991600 130.549545 12.591961 -40.852299 23.265800 34.195812 -16.155199 -32.468918 1.499646 -10.291219 49.786942 -4.200897 -4.411592 -21.671762 -5.736783 -1.059713 -32.211529 -2.216232 6.618924 49.672462 4.106166 4.156505 -21.509144 10.895816 -0.288691 +-0.320014 38.228970 -2.140412 3.654680 0.000000 0.000000 18.000000 0.000000 0.000000 -2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -9.000000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.191048 -45.700298 15.991600 -127.842697 -6.691477 -50.852299 -31.232000 -32.834557 16.175699 -2.021920 -16.309700 -0.063351 103.114937 36.445015 11.991600 130.566315 12.584930 -40.852299 19.030500 34.207169 -1.824270 -33.444542 1.192174 -11.041462 50.394234 -4.196861 -4.483042 -21.651052 -4.924406 -1.235125 -33.210190 -1.861936 7.171846 50.279854 4.098333 4.225676 -21.432674 10.224701 -0.268272 +-0.325004 38.159134 -2.249289 3.857847 0.000000 -1.614204 18.023827 0.000000 0.000000 -1.990469 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -9.019066 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.196487 -45.624924 15.991600 -127.858826 -6.704457 -50.852299 -35.030499 -32.830231 6.175680 -2.021920 -16.309700 -0.063351 103.119583 36.444786 11.991600 130.583084 12.577900 -40.852299 23.030500 34.218525 -15.824300 -33.905163 1.187754 -11.627220 50.785717 -4.206690 -4.522366 -21.802086 -2.801687 -1.389009 -34.141438 -1.486516 7.542891 50.739536 4.113885 4.273209 -21.177263 11.335146 -0.248380 +-0.337344 38.107914 -2.343874 4.000000 0.000000 -5.456710 18.092699 0.000000 0.000000 -1.962930 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -9.074150 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.201927 -45.558594 15.991600 -127.874954 -6.717437 -50.852299 -30.689301 -32.825905 16.175699 -2.021920 -16.309700 -0.063351 103.124229 36.444557 11.991600 130.599854 12.570869 -40.852299 19.030500 34.229881 -1.824300 -34.064262 1.457869 -12.235111 51.461494 -4.209280 -4.593777 -22.428879 1.407201 -1.566822 -35.018654 -0.733882 7.882010 50.887131 4.103272 4.281409 -20.546387 14.491805 -0.321035 +-0.345789 38.049515 -2.449080 4.045190 0.000000 -10.027363 18.202692 0.000000 0.000000 -1.918962 0.000000 0.000000 0.000000 0.000000 0.000000 -15.999999 0.000000 0.000000 -9.162081 0.000000 -8.511493 0.000000 0.000000 0.000000 2.021920 23.309698 -0.063351 -101.207367 -45.500763 15.991599 -127.891083 -6.730417 -50.852295 -35.030499 -32.821579 6.175700 -2.021920 -16.309700 -0.063351 103.128876 36.444328 11.991600 130.616623 12.563839 -40.852299 23.030500 34.241238 -15.824300 -33.987518 1.761497 -12.868383 52.147995 -4.188152 -4.665075 -23.159750 6.375578 -1.730022 -35.685680 0.038297 7.863154 50.926563 4.099278 4.283075 -19.826046 18.655437 -0.520628 +-0.350631 37.984493 -2.563823 4.027848 0.000000 -13.826010 18.349754 0.000000 0.000000 -1.860151 0.000000 0.000000 0.000000 0.000000 0.000000 -15.999998 0.000000 0.000000 -9.279695 0.000000 -24.499674 0.000000 0.000000 0.000000 2.021920 23.309698 -0.063351 -101.212799 -45.451000 15.991599 -127.907211 -6.743397 -50.852295 -31.051100 -32.817253 16.175699 -2.021920 -16.309700 -0.063351 103.133522 36.444099 11.991600 130.633392 12.556808 -40.852299 19.030500 34.252594 -1.824300 -33.894417 1.938024 -13.480551 52.824055 -4.183045 -4.734088 -23.822697 10.597246 -1.831520 -36.279888 0.724764 7.834577 51.024887 4.093409 4.289073 -19.121967 22.085793 -0.765999 +-0.355048 37.919971 -2.680516 4.000000 0.000000 -15.352500 18.529800 0.000000 0.000000 -1.788080 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -9.423830 0.000000 -33.645100 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.218231 -45.408901 15.991600 -127.923340 -6.756377 -50.852299 -35.030499 -32.812927 6.175700 -2.021920 -16.309700 -0.063351 103.138168 36.443871 11.991600 130.650162 12.549778 -40.852299 23.030500 34.263950 -15.824300 -34.027439 1.858261 -14.062467 53.284496 -4.171460 -4.789661 -24.079462 12.667249 -1.937641 -36.748428 1.064496 7.864789 51.416977 4.090830 4.323277 -18.959990 23.397530 -0.875176 +-0.361603 37.861721 -2.792845 4.002776 0.000000 -15.206317 18.738804 0.000000 0.000000 -1.704335 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000004 0.000000 0.000000 -9.591326 0.000000 -34.912968 0.000000 0.000000 0.000000 2.021920 23.309704 -0.063351 -101.223671 -45.374058 15.991601 -127.939476 -6.769357 -50.852306 -31.051100 -32.808601 16.175699 -2.021920 -16.309700 -0.063351 103.142822 36.443642 11.991600 130.666931 12.542747 -40.852299 19.030500 34.275307 -1.824300 -34.350956 1.627681 -14.622506 53.529663 -4.167274 -4.809908 -24.030712 13.111881 -2.091729 -37.010036 1.178187 7.973514 51.622288 4.086567 4.358893 -18.955950 23.077051 -0.891066 +-0.370406 37.810043 -2.899584 4.033733 0.000000 -15.060134 18.972939 0.000000 0.000000 -1.610497 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000006 0.000000 0.000000 -9.779014 0.000000 -36.180836 0.000000 0.000000 0.000000 2.021921 23.309706 -0.063351 -101.229111 -45.346069 15.991602 -127.955612 -6.782337 -50.852314 -35.030499 -32.804276 6.175700 -2.021920 -16.309700 -0.063351 103.147476 36.443413 11.991600 130.683701 12.535717 -40.852299 23.030500 34.286663 -15.824300 -34.689060 1.429534 -15.159804 53.715420 -4.161543 -4.843405 -23.949255 13.520027 -2.227871 -37.321125 1.301947 8.093459 51.710033 4.094346 4.370282 -18.820017 22.758057 -0.896755 +-0.380955 37.763874 -3.000774 4.079536 0.000000 -14.913950 19.228428 0.000000 0.000000 -1.508150 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000006 0.000000 0.000000 -9.983724 0.000000 -37.448700 0.000000 0.000000 0.000000 2.021921 23.309704 -0.063351 -101.234543 -45.324554 15.991602 -127.971741 -6.795317 -50.852314 -31.051100 -32.799950 16.175699 -2.021920 -16.309700 -0.063351 103.152122 36.443184 11.991600 130.700470 12.528687 -40.852299 19.030500 34.298019 -1.824300 -34.953461 1.274305 -15.663210 53.842621 -4.164706 -4.856518 -23.890228 13.876274 -2.363764 -37.611683 1.426307 8.204551 51.866577 4.098366 4.386067 -18.759068 22.429609 -0.900114 +-0.392747 37.722149 -3.096460 4.126848 0.000000 -14.767767 19.501501 0.000000 0.000000 -1.398875 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000006 0.000000 0.000000 -10.202288 0.000000 -38.716568 0.000000 0.000000 0.000000 2.021921 23.309706 -0.063351 -101.239975 -45.309128 15.991603 -127.987869 -6.808297 -50.852310 -35.030499 -32.795624 6.175700 -2.021920 -16.309700 -0.063351 103.156769 36.442955 11.991600 130.717239 12.521656 -40.852299 23.030500 34.309376 -15.824300 -35.263210 1.127186 -16.135317 53.998512 -4.174650 -4.885248 -23.837080 14.213849 -2.504822 -37.892544 1.557739 8.323728 51.993721 4.096254 4.406078 -18.697542 22.087412 -0.901489 +-0.405280 37.683804 -3.186683 4.162334 0.000000 -14.621584 19.788382 0.000000 0.000000 -1.284254 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000002 0.000000 0.000000 -10.431536 0.000000 -39.984436 0.000000 0.000000 0.000000 2.021920 23.309704 -0.063351 -101.245415 -45.299431 15.991600 -128.003998 -6.821277 -50.852303 -30.689301 -32.791298 16.175699 -2.021920 -16.309700 -0.063351 103.161423 36.442722 11.991600 130.734009 12.514626 -40.852299 19.030500 34.320732 -1.824300 -35.595253 0.998346 -16.531145 54.194283 -4.171271 -4.911170 -23.771486 14.446924 -2.637500 -38.144203 1.682998 8.446852 52.101204 4.089000 4.431632 -18.651766 21.757002 -0.909464 +-0.418049 37.647770 -3.271487 4.172660 0.000000 -14.475400 20.085300 0.000000 0.000000 -1.165870 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -10.668300 0.000000 -41.252300 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.250854 -45.295094 15.991600 -128.020126 -6.834257 -50.852299 -35.030499 -32.786972 6.175700 -2.021920 -16.309700 -0.063351 103.166077 36.442490 11.991600 130.750778 12.507595 -40.852299 23.030500 34.332088 -15.824300 -35.841770 0.884333 -16.860397 54.439804 -4.152454 -4.934066 -23.805370 14.645742 -2.757797 -38.307957 1.791742 8.572937 52.208858 4.091085 4.442233 -18.651791 21.438992 -0.914602 +-0.430634 37.613377 -3.351289 4.149244 0.000000 -9.080635 20.388269 0.000000 0.000000 -1.045306 0.000000 0.000000 0.000000 0.000000 0.000000 -15.999999 0.000000 0.000000 -10.909411 0.000000 -3.641399 0.000000 0.000000 0.000000 2.021920 23.309696 -0.063351 -101.256287 -45.295765 15.991601 -128.036255 -6.847237 -50.852299 -30.870199 -32.782646 16.175699 -2.021920 -16.309700 -0.063351 103.170723 36.442261 11.991600 130.767548 12.500565 -40.852299 19.030500 34.343445 -1.824300 -36.805782 0.053063 -17.039526 54.282944 -4.154966 -4.920985 -22.966528 9.794182 -2.821255 -38.199707 0.948795 8.938684 52.688850 4.092376 4.485690 -19.587280 16.233088 -0.521380 +-0.442934 37.581478 -3.427999 4.102530 0.000000 -3.685870 20.692432 0.000000 0.000000 -0.924146 0.000000 0.000000 0.000000 0.000000 0.000000 -15.999998 0.000000 0.000000 -11.151707 0.000000 33.969501 0.000000 0.000000 0.000000 2.021920 23.309694 -0.063351 -101.261719 -45.301117 15.991601 -128.052383 -6.860217 -50.852299 -35.030499 -32.778320 6.175700 -2.021920 -16.309700 -0.063351 103.175369 36.442032 11.991600 130.784317 12.493534 -40.852299 23.030500 34.354805 -15.824300 -37.599182 -0.834783 -17.133732 54.078091 -4.144608 -4.887481 -22.176386 4.952130 -2.828346 -37.998875 0.137436 9.321744 53.178410 4.090946 4.538610 -20.495770 10.991017 -0.166636 +-0.454929 37.553310 -3.503902 4.047717 0.000000 1.708895 20.992731 0.000000 0.000000 -0.803975 0.000000 0.000000 0.000000 0.000000 0.000000 -15.999999 0.000000 0.000000 -11.392023 0.000000 35.043350 0.000000 0.000000 0.000000 2.021920 23.309696 -0.063351 -101.267159 -45.310802 15.991600 -128.068512 -6.873197 -50.852299 -30.689301 -32.773994 16.175699 -2.021920 -16.309700 -0.063351 103.180023 36.441799 11.991600 130.801086 12.486504 -40.852299 19.030500 34.366161 -1.824300 -38.330757 -1.805935 -17.206730 53.862503 -4.152440 -4.862030 -21.357069 0.127100 -2.768968 -37.733974 -0.639033 9.687801 53.667439 4.092619 4.602857 -21.352137 5.719674 0.111890 +-0.466599 37.530121 -3.581281 4.000000 0.000000 7.103660 21.284100 0.000000 0.000000 -0.686377 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -11.627200 0.000000 36.117199 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.272598 -45.324493 15.991600 -128.084641 -6.886177 -50.852299 -35.030499 -32.769669 6.175700 -2.021920 -16.309700 -0.063351 103.184677 36.441566 11.991600 130.817856 12.479473 -40.852299 23.030500 34.377518 -15.824300 -38.956768 -2.846462 -17.237242 53.461685 -4.149258 -4.804719 -20.383410 -4.666951 -2.684958 -37.290581 -1.379184 10.052631 54.049999 4.075356 4.638682 -22.163969 0.432103 0.358021 +-0.477901 37.512802 -3.661598 3.971274 0.000000 7.107974 21.562075 0.000000 0.000000 -0.572937 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -11.854074 0.000000 37.191067 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.278030 -45.341877 15.991599 -128.100769 -6.899157 -50.852299 -30.689301 -32.765343 16.175699 -2.021920 -16.309700 -0.063351 103.189323 36.441338 11.991600 130.834625 12.472443 -40.852299 19.030500 34.388878 -1.824300 -39.198673 -2.924819 -17.361078 53.736031 -4.141958 -4.835734 -20.402718 -4.531427 -2.749214 -37.436237 -1.293546 10.230618 54.020580 4.082785 4.629950 -21.951778 0.249494 0.419440 +-0.488697 37.500858 -3.743021 3.960214 0.000000 7.112287 21.824614 0.000000 0.000000 -0.465235 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -12.069481 0.000000 38.264935 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.283463 -45.362656 15.991599 -128.116898 -6.912137 -50.852299 -35.030499 -32.761017 6.175700 -2.021920 -16.309700 -0.063351 103.193970 36.441109 11.991600 130.851395 12.465412 -40.852299 23.030500 34.400238 -15.824300 -39.361935 -2.983570 -17.469442 53.804577 -4.135991 -4.848752 -20.306366 -4.418760 -2.822629 -37.598347 -1.216234 10.381673 54.050102 4.080083 4.631292 -21.796772 0.068583 0.481941 +-0.498826 37.493443 -3.822899 3.962187 0.000000 7.116600 22.070271 0.000000 0.000000 -0.364851 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -12.270259 0.000000 39.338799 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.288902 -45.386551 15.991599 -128.133026 -6.925117 -50.852295 -31.051100 -32.756691 16.175699 -2.021920 -16.309700 -0.063351 103.198624 36.440876 11.991600 130.868164 12.458381 -40.852299 19.030500 34.411594 -1.824300 -39.477325 -3.015076 -17.571796 53.764809 -4.160427 -4.837659 -20.154140 -4.333002 -2.879143 -37.693226 -1.143963 10.547052 54.011116 4.076313 4.625951 -21.659931 -0.100812 0.547136 +-0.508127 37.489716 -3.898579 3.972564 0.000000 7.120914 22.297600 0.000000 0.000000 -0.273364 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -12.453246 0.000000 40.412666 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.294342 -45.413254 15.991599 -128.149155 -6.938097 -50.852295 -35.030499 -32.752365 6.175700 -2.021920 -16.309700 -0.063351 103.203278 36.440643 11.991600 130.884933 12.451349 -40.852299 23.030500 34.422951 -15.824300 -39.473526 -3.014976 -17.639170 53.500385 -4.165127 -4.806204 -19.883400 -4.288319 -2.949143 -37.846024 -1.073954 10.709991 54.011501 4.068685 4.622252 -21.492352 -0.284219 0.600375 +-0.516440 37.488827 -3.967408 3.986712 0.000000 7.125227 22.505157 0.000000 0.000000 -0.192353 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -12.615280 0.000000 41.486534 0.000000 0.000000 0.000000 2.021920 23.309698 -0.063351 -101.299774 -45.442486 15.991599 -128.165283 -6.951077 -50.852299 -31.051100 -32.748039 16.175699 -2.021920 -16.309700 -0.063351 103.207924 36.440414 11.991600 130.901703 12.444319 -40.852299 19.030500 34.434311 -1.824300 -39.601521 -3.036797 -17.657202 53.382542 -4.170298 -4.797989 -19.635418 -4.278325 -2.996053 -37.979408 -1.000784 10.872646 53.972431 4.066468 4.617636 -21.333115 -0.462316 0.664915 +-0.523602 37.489941 -4.026731 4.000000 0.000000 7.129540 22.691500 0.000000 0.000000 -0.123399 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -12.753200 0.000000 42.560398 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.305206 -45.473969 15.991600 -128.181412 -6.964057 -50.852299 -35.030499 -32.743713 6.175700 -2.021920 -16.309700 -0.063351 103.212570 36.440186 11.991600 130.918472 12.437288 -40.852299 23.030500 34.445671 -15.824300 -39.528214 -3.030826 -17.715485 53.039925 -4.171034 -4.757606 -19.342720 -4.242754 -3.047078 -38.093250 -0.932094 11.037381 53.854660 4.071071 4.609262 -21.103796 -0.647785 0.728935 +-0.529430 37.492981 -4.074747 4.008549 0.000000 3.716338 22.852121 0.000000 0.000000 -0.068085 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -12.863833 0.000000 43.634300 0.000000 0.000000 0.000000 2.021920 23.309702 -0.063351 -101.310646 -45.507454 15.991600 -128.197540 -6.977037 -50.852303 -31.051100 -32.739384 16.175699 -2.021920 -16.309700 -0.063351 103.217224 36.439953 11.991600 130.935242 12.430257 -40.852299 19.030500 34.457027 -1.824300 -39.329208 -2.375264 -17.800810 53.265110 -4.167644 -4.786067 -19.666199 -1.128542 -3.252024 -38.550632 -0.413212 10.862228 53.736794 4.084034 4.595242 -20.453623 2.633312 0.601910 +-0.533653 37.501007 -4.113047 4.011482 0.000000 -2.516153 22.970278 0.000000 0.000000 -0.028010 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -12.943981 0.000000 7.027906 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.316086 -45.542698 15.991600 -128.213669 -6.990017 -50.852303 -35.030499 -32.735054 6.175700 -2.021920 -16.309700 -0.063351 103.221878 36.439720 11.991600 130.952011 12.423225 -40.852299 23.030500 34.468384 -15.824300 -38.729130 -1.196397 -17.926546 53.735081 -4.167014 -4.838123 -20.490280 4.543549 -3.563205 -39.154892 0.710026 10.646173 53.247093 4.088910 4.543805 -19.186308 8.394760 0.277790 +-0.535973 37.517845 -4.144077 4.008674 0.000000 -9.143081 23.026171 0.000000 0.000000 -0.004781 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -12.990438 0.000000 -29.981199 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.321518 -45.579449 15.991601 -128.229797 -7.002997 -50.852303 -31.051100 -32.730728 16.175699 -2.021920 -16.309700 -0.063351 103.226524 36.439491 11.991600 130.968781 12.416195 -40.852299 18.971701 34.479744 -1.838690 -38.025753 -0.027225 -17.985952 54.253735 -4.171484 -4.897347 -21.297617 10.582398 -3.855877 -39.474270 1.985205 10.459132 52.463291 4.102951 4.460845 -17.722282 14.443284 -0.209091 +-0.536097 37.547329 -4.170276 4.000000 0.000000 -14.726600 23.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -13.000000 0.000000 -31.425299 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.326950 -45.617466 15.991600 -128.245941 -7.015977 -50.852299 -35.030499 -32.726402 6.175700 -2.021920 -16.309700 -0.063351 103.231171 36.439262 11.991600 130.985550 12.409164 -40.852299 23.030500 34.491104 -15.824300 -37.207775 0.920380 -17.928173 54.587303 -4.155131 -4.929496 -21.928253 15.623561 -4.094785 -39.700764 3.120475 10.298809 51.894989 4.103671 4.410468 -16.438379 19.482620 -0.685310 +-0.533863 37.594406 -4.192036 3.986021 0.000000 -14.655499 22.881231 0.000000 0.000000 -0.014599 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -12.970808 0.000000 -32.869400 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.332390 -45.656525 15.991601 -128.262070 -7.028957 -50.852303 -30.508400 -32.722073 16.175699 -2.021920 -16.309700 -0.063351 103.235825 36.439030 11.991600 131.002319 12.402133 -40.852299 18.971701 34.502460 -1.666030 -37.093460 1.026106 -17.656097 54.215290 -4.150300 -4.893110 -21.503002 15.270259 -4.146565 -39.660366 3.011105 10.200602 51.758068 4.105418 4.389371 -16.229633 19.551289 -0.664976 +-0.529652 37.668503 -4.201550 3.970045 0.000000 -14.584399 22.696375 0.000000 0.000000 -0.046813 0.000000 0.000000 0.000000 0.000000 0.000000 -15.999998 0.000000 0.000000 -12.906388 0.000000 -34.313499 0.000000 0.000000 0.000000 2.021920 23.309698 -0.063351 -101.337830 -45.696396 15.991601 -128.278198 -7.041937 -50.852303 -35.030499 -32.717743 6.175700 -2.021920 -16.309700 -0.063351 103.240479 36.438797 11.991599 131.019089 12.395102 -40.852299 23.030500 34.513817 -15.824300 -36.947285 1.179693 -17.264038 53.764965 -4.163994 -4.829717 -21.012768 14.765652 -4.152795 -39.511982 2.853824 10.081288 51.522038 4.120965 4.374905 -15.967726 19.673267 -0.641900 +-0.523977 37.780163 -4.188960 3.956065 0.000000 -14.513299 22.481213 0.000000 0.000000 -0.094204 0.000000 0.000000 0.000000 0.000000 0.000000 -15.999998 0.000000 0.000000 -12.811617 0.000000 -35.757599 0.000000 0.000000 0.000000 2.021920 23.309698 -0.063351 -101.343262 -45.736870 15.991600 -128.294342 -7.054917 -50.852303 -30.870199 -32.713417 16.175699 -2.021920 -16.309702 -0.063351 103.245125 36.438568 11.991600 131.035858 12.388071 -40.852303 18.971701 34.525177 -1.320700 -36.633423 1.384357 -16.771812 53.088760 -4.167538 -4.770008 -20.477337 14.203761 -4.132702 -39.273994 2.671086 9.941031 51.071796 4.117927 4.323833 -15.573019 19.843613 -0.611433 +-0.517353 37.939930 -4.144406 3.948076 0.000000 -14.442200 22.271523 0.000000 0.000000 -0.154334 0.000000 0.000000 0.000000 0.000000 0.000000 -15.999997 0.000000 0.000000 -12.691367 0.000000 -37.201698 0.000000 0.000000 0.000000 2.021920 23.309696 -0.063351 -101.348694 -45.777729 15.991599 -128.310486 -7.067897 -50.852299 -35.030499 -32.709091 6.175700 -2.021920 -16.309704 -0.063351 103.249771 36.438339 11.991601 131.052628 12.381041 -40.852306 23.030500 34.536537 -15.824300 -36.147385 1.615243 -16.239429 52.216869 -4.183102 -4.669598 -19.927256 13.556653 -4.063782 -38.654568 2.415678 9.793469 50.170979 4.128356 4.210197 -15.105186 20.071716 -0.575983 +-0.510295 38.158352 -4.058029 3.950073 0.000000 -14.371099 22.103086 0.000000 0.000000 -0.224764 0.000000 0.000000 0.000000 0.000000 0.000000 -15.999996 0.000000 0.000000 -12.550514 0.000000 -38.645798 0.000000 0.000000 0.000000 2.021920 23.309694 -0.063351 -101.354134 -45.818779 15.991598 -128.326614 -7.080877 -50.852295 -31.232000 -32.704762 16.175699 -2.021920 -16.309702 -0.063351 103.254425 36.438107 11.991600 131.069397 12.374009 -40.852303 19.324600 34.547894 -0.975379 -35.544853 1.945177 -15.681264 51.697109 -4.202126 -4.611627 -19.906996 12.874021 -3.982512 -37.854740 2.146652 9.608113 48.917042 4.134596 4.073888 -14.491150 20.352489 -0.552381 +-0.503318 38.445969 -3.919972 3.966050 0.000000 -14.299999 22.011686 0.000000 0.000000 -0.303056 0.000000 0.000000 0.000000 0.000000 0.000000 -15.999997 0.000000 0.000000 -12.393934 0.000000 -40.089897 0.000000 0.000000 0.000000 2.021920 23.309696 -0.063351 -101.359573 -45.859810 15.991598 -128.342743 -7.093857 -50.852295 -35.030499 -32.700432 6.175700 -2.021920 -16.309700 -0.063351 103.259079 36.437874 11.991600 131.086151 12.366978 -40.852299 23.030500 34.559250 -15.824300 -34.831940 2.067137 -15.099980 50.532230 -4.189590 -4.482365 -19.383663 12.286225 -3.745189 -37.131466 1.826012 9.375613 48.338005 4.156035 4.012556 -14.517629 20.686172 -0.551553 +-0.496935 38.813324 -3.720374 4.000000 0.000000 -14.228900 22.033100 0.000000 0.000000 -0.386773 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -12.226500 0.000000 -41.534000 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.365005 -45.900612 15.991600 -128.358887 -7.106837 -50.852299 -31.051100 -32.696106 16.175699 -2.021920 -16.309700 -0.063351 103.263725 36.437645 11.991600 131.102921 12.359947 -40.852299 19.148199 34.570610 -0.975379 -33.415985 2.366130 -14.567344 48.209400 -4.203568 -4.244123 -18.487726 11.697306 -3.549021 -35.588337 1.473246 9.216400 45.859310 4.155015 3.739181 -13.588630 21.033756 -0.475306 +-0.491672 39.260307 -3.456184 4.049739 0.000000 -13.514616 22.159166 0.000000 0.000000 -0.473673 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000002 0.000000 0.000000 -12.052690 0.000000 -36.247055 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.370438 -45.940975 15.991601 -128.375031 -7.119817 -50.852295 -35.030499 -32.691780 6.175700 -2.021920 -16.309702 -0.063351 103.268372 36.437416 11.991600 131.119690 12.352917 -40.852303 23.030500 34.581970 -15.824300 -31.542610 2.620011 -14.070089 45.033779 -4.213667 -3.895168 -17.326056 10.500475 -3.308093 -33.488045 0.948196 9.041908 42.655106 4.140577 3.384212 -12.644161 20.839430 -0.314770 +-0.488100 39.744164 -3.151573 4.088369 0.000000 -11.780152 22.205982 0.000000 0.000000 -0.562311 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000002 0.000000 0.000000 -11.875401 0.000000 -23.149633 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.375877 -45.980690 15.991601 -128.391159 -7.132797 -50.852295 -31.232000 -32.687450 16.175699 -2.021920 -16.309702 -0.063351 103.273026 36.437183 11.991599 131.136444 12.345885 -40.852303 19.501101 34.593327 -1.148040 -29.524641 2.732252 -13.629401 41.348595 -4.190515 -3.487116 -15.898114 8.420561 -3.032465 -31.087759 0.241360 8.812758 39.096336 4.118599 2.994494 -11.772866 19.783714 -0.080435 +-0.486801 40.211479 -2.837521 4.082814 0.000000 -9.478119 21.945707 0.000000 0.000000 -0.651435 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000002 0.000000 0.000000 -11.697138 0.000000 -9.636093 0.000000 0.000000 0.000000 2.021920 23.309702 -0.063351 -101.381317 -46.019508 15.991601 -128.407288 -7.145777 -50.852299 -31.865101 -32.683121 16.175699 -2.021920 -16.309700 -0.063351 103.277679 36.436951 11.991599 131.153198 12.338854 -40.852299 21.337200 34.604683 -2.095280 -27.384926 2.787398 -13.216844 37.358524 -4.139371 -3.053314 -14.287736 5.781743 -2.809912 -28.457083 -0.511713 8.536705 35.263313 4.054915 2.577194 -10.854119 18.185564 0.158798 +-0.488355 40.608852 -2.545006 4.000000 0.000000 -7.061130 21.150499 0.000000 0.000000 -0.739799 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -11.520400 0.000000 -3.100790 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.386749 -46.057159 15.991600 -128.423431 -7.158756 -50.852299 -32.498199 -32.678795 16.175699 -2.021920 -16.309700 -0.063351 103.282326 36.436722 11.991600 131.169968 12.331823 -40.852299 23.173300 34.616043 -3.042520 -25.248547 2.824629 -12.846099 33.475735 -4.060800 -2.631260 -12.729866 3.057248 -2.627893 -25.975151 -1.179280 8.215750 31.890759 3.967609 2.229653 -10.143305 16.410622 0.341495 +-0.492988 40.897942 -2.298080 3.820944 0.000000 -4.899048 19.691370 0.000000 0.000000 -0.825892 0.000000 0.000000 0.000000 0.000000 0.000000 -15.999999 0.000000 0.000000 -11.348210 0.000000 -2.325593 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.392181 -46.093292 15.991600 -128.439575 -7.171736 -50.852299 -33.131275 -32.674469 16.175699 -2.021920 -16.309700 -0.063351 103.286972 36.436493 11.991600 131.186737 12.324793 -40.852295 23.196424 34.627403 -2.953785 -23.524078 2.849262 -12.477494 30.582861 -3.983389 -2.316999 -11.647077 0.556022 -2.492176 -23.890606 -1.702400 7.844921 29.369184 3.903420 1.971266 -9.743961 14.843077 0.430481 +-0.499404 41.107273 -2.089381 3.585656 0.000000 -3.002576 17.851137 0.000000 0.000000 -0.907877 0.000000 0.000000 0.000000 0.000000 0.000000 -15.999998 0.000000 0.000000 -11.184240 0.000000 -1.550395 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.397621 -46.127384 15.991600 -128.455704 -7.184716 -50.852295 -33.764351 -32.670139 16.175699 -2.021920 -16.309700 -0.063351 103.291626 36.436260 11.991600 131.203491 12.317761 -40.852295 23.219549 34.638760 -2.865050 -21.987158 2.884241 -12.147185 28.169205 -3.910796 -2.066400 -10.763911 -1.653413 -2.411545 -22.063480 -2.100205 7.449727 27.338020 3.840055 1.764302 -9.484033 13.497201 0.440847 +-0.506171 41.270016 -1.909765 3.341367 0.000000 -1.335984 15.965198 0.000000 0.000000 -0.983027 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -11.033944 0.000000 -0.775198 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.403061 -46.158497 15.991600 -128.471832 -7.197696 -50.852299 -34.397423 -32.665810 16.175699 -2.021920 -16.309700 -0.063351 103.296280 36.436028 11.991600 131.220245 12.310730 -40.852295 23.242676 34.650116 -2.776315 -20.705233 2.923086 -11.830970 26.265942 -3.840737 -1.868835 -10.109248 -3.622790 -2.361411 -20.578699 -2.393072 7.057056 25.895140 3.791535 1.616992 -9.426872 12.320418 0.413624 +-0.511862 41.395466 -1.766672 3.136690 0.000000 0.000000 14.390000 0.000000 0.000000 -1.044000 0.000000 0.000000 0.000000 0.000000 0.000000 -16.000000 0.000000 0.000000 -10.912000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 23.309700 -0.063351 -101.408493 -46.183701 15.991600 -128.487976 -7.210675 -50.852299 -35.030499 -32.661484 16.175699 -2.021920 -16.309700 -0.063351 103.300926 36.435799 11.991600 131.237015 12.303699 -40.852299 23.265800 34.661476 -2.687580 -19.633562 2.972580 -11.591483 24.675898 -3.778486 -1.708921 -9.564678 -5.207702 -2.349644 -19.277863 -2.595720 6.723717 24.532280 3.729417 1.475191 -9.269896 11.379570 0.388031 +-0.434702 41.486183 -1.728811 2.633093 0.000000 0.000000 13.312000 0.000000 0.000000 -1.035200 0.000000 0.000000 0.000000 0.000000 0.000000 -14.400000 0.000000 0.000000 -9.629600 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 20.409698 -0.063351 -100.846931 -38.851208 15.991600 -120.093498 -7.829280 -45.752300 -30.930498 -26.863810 14.575706 -2.021920 -14.109698 -0.063351 101.117142 31.052885 12.391600 128.586411 12.703700 -36.752300 19.918743 30.263802 -2.314917 -18.544016 3.084713 -10.382330 23.936285 -3.695114 -1.658423 -9.267870 -4.564862 -2.127962 -18.209215 -2.841390 6.026090 23.802036 3.647658 1.435221 -9.082260 10.091263 0.481253 +-0.357543 41.576900 -1.690949 2.129496 0.000000 0.000000 12.234000 0.000000 0.000000 -1.026400 0.000000 0.000000 0.000000 0.000000 0.000000 -12.799999 0.000000 0.000000 -8.347199 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 17.509697 -0.063351 -100.285370 -31.518713 15.991600 -111.699020 -8.447886 -40.652302 -26.830498 -21.066135 12.975712 -2.021920 -11.909697 -0.063351 98.933357 25.669971 12.791599 125.935806 13.103701 -32.652302 16.571686 25.866127 -1.942255 -17.450476 3.187084 -9.159822 23.185040 -3.619267 -1.628673 -8.986745 -3.936708 -1.910884 -17.081184 -3.083135 5.316090 22.924122 3.564531 1.376041 -8.794599 8.835078 0.572474 +-0.280383 41.667618 -1.653088 1.625899 0.000000 0.000000 11.156000 0.000000 0.000000 -1.017600 0.000000 0.000000 0.000000 0.000000 0.000000 -11.200000 0.000000 0.000000 -7.064800 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 14.609694 -0.063351 -99.723816 -24.186218 15.991600 -103.304550 -9.066490 -35.552299 -22.730499 -15.268460 11.375718 -2.021920 -9.709694 -0.063351 96.749573 20.287058 13.191600 123.285202 13.503700 -28.552301 13.224627 21.468452 -1.569592 -16.265581 3.278226 -7.947428 22.268148 -3.536131 -1.548124 -8.604726 -3.320709 -1.704884 -15.975167 -3.315160 4.626875 22.124203 3.495193 1.297099 -8.569440 7.570908 0.674816 +-0.203224 41.758335 -1.615226 1.122302 0.000000 0.000000 10.078000 0.000000 0.000000 -1.008800 0.000000 0.000000 0.000000 0.000000 0.000000 -9.600000 0.000000 0.000000 -5.782400 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 11.709692 -0.063351 -99.162262 -16.853724 15.991600 -94.910080 -9.685095 -30.452301 -18.630501 -9.470785 9.775724 -2.021920 -7.509692 -0.063351 94.565788 14.904144 13.591600 120.634598 13.903700 -24.452301 9.877569 17.070776 -1.196929 -15.098444 3.354363 -6.749648 21.407455 -3.475082 -1.467225 -8.282315 -2.708299 -1.514426 -14.849196 -3.537049 3.952517 21.283508 3.431002 1.227148 -8.292864 6.282494 0.768201 +-0.126064 41.849052 -1.577364 0.618705 0.000000 0.000000 9.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -8.000000 0.000000 0.000000 -4.500000 0.000000 0.000000 0.000000 0.000000 0.000000 2.021920 8.809690 -0.063351 -98.600700 -9.521230 15.991600 -86.515602 -10.303700 -25.352301 -14.530500 -3.673110 8.175730 -2.021920 -5.309690 -0.063351 92.382004 9.521230 13.991600 117.984001 14.303700 -20.352301 6.530510 12.673100 -0.824266 -13.919423 3.412899 -5.567397 20.487652 -3.412928 -1.372854 -7.923543 -2.092024 -1.316636 -13.659977 -3.747651 3.284178 20.277349 3.354410 1.115687 -7.940426 5.000060 0.894035