查看“虚拟世界/NPC”的源代码
←
虚拟世界/NPC
跳转至:
导航
、
搜索
因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
用户
您可以查看与复制此页面的源代码。
{{VWSnav}} 开源社区提供了一组 OSSL NPC 函数,用于创建和操作机器人(NPC、BOT)。 这种方法的一个优点是,机器人不需要外部客户端,并且机器人的外观可以保存在岛屿备份中。一个缺点是可用的功能集非常有限,因为需要编写脚本方法来控制 NPC 的不同方面。此外,这样的机器人不能移动到它们被创建的岛屿之外。 ==服务器配置== *Opensim.ini <pre> [NPC] ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} false Enabled = true ;; several options to control NPCs creation ;# {AllowNotOwned} {} {allow NPCs to be created not Owned} {true false} true ;; allow NPCs to be created not Owned {true false} default: true AllowNotOwned = true ;# {AllowSenseAsAvatar} {} {allow NPCs to set to be sensed as Avatars} {true false} true ;; allow NPCs to set to be sensed as Avatars {true false} default: true AllowSenseAsAvatar = true ;# {AllowCloneOtherAvatars} {} {allow NPCs to created cloning any avatar in region} {true false} true ;; allow NPCs to created cloning any avatar in region {true false} default: true AllowCloneOtherAvatars = true ;# {NoNPCGroup} {} {if true NPCs will have no group title, if false display "- NPC -"} {true false} true ;; if true NPCs will have no group title, if false display "- NPC -" for easy identification {true false} default: true NoNPCGroup = true …… [OSSL] ;# {Include-osslEnable} {} {Include file for enabling and permissions for OSSL functions} {} ;; Optionally include file to enable OSSL functions and set permissions on who can use which. ;; If this INI file is not included, the OSSL functions are disabled. Include-osslEnable = "config-include/osslEnable.ini" </pre> *config-include/osslEnable.ini 在该文件中包含对各种os*函数的授权 ==相关API== ===osIsNpc=== 函数:integer osIsNpc(key npc)。<br> 功能:判断一个指定的key是不是一个NPC。<br> 返回值:NPC的状态 *如果提供的key是一个NPC,则返回值为TRUE (1),否则为FALSE (0); *如果提供的key是一个NPC,但不存在于场景中,返回FALSE (0); ===osNpcCreate=== 函数: *key osNpcCreate(string firstname, string lastname, vector position, string cloneFrom) *key osNpcCreate(string firstname, string lastname, vector position, string cloneFrom, integer options) 功能:创建一个名为firstname lastname, 位置为position, 外观为cloneFrom的NPC。<br> 示例: <pre> // touch to create a NPC clone of the toucher in front of this emitter // NPC will move to the toucher, then will greet them. // Touch again to remove the NPC key npc; vector toucherPos; default { touch_start(integer number) { vector npcPos = llGetPos() + <1,0,0>; osAgentSaveAppearance(llDetectedKey(0), "appearance"); // coud use avatar UUID directly in osNpcCreate, but then NPC appearance is not persisted npc = osNpcCreate("ImYour", "Clone", npcPos, "appearance"); toucherPos = llDetectedPos(0); state hasNPC; } } state hasNPC { state_entry() { osNpcMoveTo(npc, toucherPos + <1,1,0>); osNpcSay(npc, "Hi there! My name is " + llKey2Name(npc)); } touch_start(integer number) { osNpcSay(npc, "Goodbye!"); osNpcRemove(npc); npc = NULL_KEY; state default; } } </pre> '''[备注]''' #您可以从保存的外观记录卡名称或UUID或从登录到相同区域中克隆外观。 #您可以使用以下函数创建和加载外观记录卡:osOwnerSaveAppearance,osAgentSaveAppearance,osNpcLoadAppearance,osNpcSaveAppearance。 #在当前的OpenSimulator开发代码中(从2012年1月12日的提交c4972e77),已经添加了osNpcCreate()的重载版本。 #关于重载函数key osNpcCreate(string firstname, string lastname, vector position, string cloneFrom, integer options) #*options字段可以是OS_NPC_CREATOR_OWNED或OS_NPC_NOT_OWNED。 #*OS_NPC_CREATOR_OWNED将创建一个“被拥有”的NPC,只会响应与创建NPC相同的所有者脚本发出的osNpc *命令。 #*OS_NPC_NOT_OWNED将创建一个“无主”的NPC,它将响应任何具有OSSL权限的脚本来调用osNpc *命令。 #*例如:key npc = osNpcCreate("ImYour", "Clone", npcPos, "appearance", OS_NPC_CREATOR_OWNED); #现有的没有options字段的osNpcCreate()函数将继续存在。 ===osGetNpcList=== 函数:list osGetNPCList( ).<br> 功能:显示该区域中每个NPC的UUID、位置和名称的列表。<br> 示例: <pre> default { touch_start(integer total_number) { list npcs = osGetNPCList(); if (npcs == []) llSay(0, "You must be the owner. There is nobody else here who could have touched me."); else llSay(0, "NPC's in this region (without avatars):" + llList2CSV(npcs)); } } </pre> ===osNpcGetOwner=== 函数:key osNpcGetOwner(key npc).<br> 功能:获取NPC的所有者的UUID。 ===osNpcGetPos=== 函数:vector osNpcGetPos(key npc).<br> 功能:返回NPC的当前位置。 ===osNpcGetRot=== 函数:rotation osNpcGetRot(key npc).<br> 功能:获取化身的旋转。欧拉旋转(水平旋转)中只有Z平面的旋转才有意义。 ===osNpcLoadAppearance=== 函数:osNpcLoadAppearance(key npc, string notecard).<br> 功能:从记事卡加载外观。此记事卡必须包含使用其中一个保存外观功能创建的外观数据。 ===osNpcMoveTo=== 函数:void osNpcMoveTo(key npc, vector position).<br> 功能:移动NPC到指定位置。 ===osNpcMoveToTarget=== 函数:osNpcMoveToTarget(key npc, vector target, integer options).<br> 功能:随着时间的推移,到达指定的地点。如何到达目的地取决于options的值。 *OS_NPC_FLY :将飞到指定的位置。NPC将不会着陆,除非OS_NPC_LAND_AT_TARGET选项也被给出。 *OS_NPC_NO_FLY : 不要飞到目标。NPC将尝试走向该地点。如果它在空中,那么NPC将一直处于无望的状态,直到另一个移动目标被提供或移动被停止。 *OS_NPC_LAND_AT_TARGET : 如果给出,NPC正在飞行,那么它会在到达目标时着陆。如果给出OS_NPC_NO_FLY,那么这个选项不起作用。<br> **OS_NPC_FLY和OS_NPC_NO_FLY是不能合并的选项 - NPC最终会做一个或另一个。如果你想让NPC飞行并落在目标上,那么OS_NPC_LAND_AT_TARGET必须与OS_NPC_FLY结合。 *OS_NPC_RUNNING : 将NPC运行到给定的位置。 ===osNpcPlayAnimation=== 函数:osNpcPlayAnimation(key npc, string animation).<br> 功能:在NPC的身份标识上播放动画。 ===osNpcRemove=== 函数:void osNpcRemove(key npc).<br> 功能:移除指定key的NPC。<br> 示例: <pre> // sim-wide NPC killer // kill all of NPCs in this SIM // Attempts to kill agents too, but it will silently fail // http://opensimulator.org/wiki/OsNpcRemove default { touch_start(integer number) { list avatars = llList2ListStrided(osGetAvatarList(), 0, -1, 3); integer i; llSay(0,"NPC Removal: No avatars will be harmed or removed in this process!"); for (i=0; i<llGetListLength(avatars); i++) { string target = llList2String(avatars, i); osNpcRemove(target); llSay(0,"NPC Removal: Target "+target); } } } </pre> '''[备注]''' 如果化身是任何其他类型的代理(即用户的常规化身,而不是NPC)的UUID,则该功能将默认失败,不会擦除已存在的化身。 ===osNpcSaveAppearance=== 函数:key osNpcSaveAppearance(key npc, string notecard).<br> 功能:将NPC的当前外表保存在资产库中的记事卡中。这包括身体部位数据,衣物和附件。如果同名的记事卡已经存在,则被替换。当这个函数被调用时,化身必须出现在该区域。化身的烘焙纹理(重现外观所必需的)被永久保存。 ===osNpcSay=== 函数: *void osNpcSay(key npc, int channel, string message). *void osNpcSay(key npc, string message). 功能:NPC在已给的通道表示信息(第二个通道为0). ===osNpcSetProfileAbout=== 函数:osNpcSetProfileAbout(LSL_Key npc, string about).<br> 功能:在创建的NPC的配置文件中设置。<br> 示例: <pre> // // osNpcSetProfileImageScript Example // key npc = NULL_KEY; string about = "I'm your Clone"; default { touch_start(integer number) { if (npc == NULL_KEY) { osOwnerSaveAppearance("MyClone"); llSetTimerEvent(2.0); } else { osNpcRemove(npc); npc = NULL_KEY; llRemoveInventory("MyClone"); } } timer() { llSetTimerEvent(0.0); npc = osNpcCreate("John", "Smith", llGetPos() + <0.0, 0.0, 2.0>, "MyClone"); osNpcSetProfileAbout(npc, about); } } </pre> ===osNpcSetProfileImage=== 函数:osNpcSetProfileImage(LSL_Key npc, string image).<br> 功能:在创建的NPC的个人资料中设置图像。可以通过名称或UUID使用包含在资产库中的纹理。<br> 示例: <pre> // // osNpcSetProfileImage Example // key npc = NULL_KEY; string image = "My Photo"; default { touch_start(integer number) { if (npc == NULL_KEY) { osOwnerSaveAppearance("MyClone"); llSetTimerEvent(2.0); } else { osNpcRemove(npc); npc = NULL_KEY; llRemoveInventory("MyClone"); } } timer() { llSetTimerEvent(0.0); npc = osNpcCreate("John", "Smith", llGetPos() + <0.0, 0.0, 2.0>, "MyClone"); osNpcSetProfileImage(npc, image); } } </pre> ===osNpcSetRot=== 函数:osNpcSetRot(key npc, rotation rot).<br> 功能:设置化身的旋转。只有在欧拉旋转中设置Z平面中的旋转将会产生任何有意义的效果(将化身指向一个方向或另一个方向)。设置X或Y欧拉值将导致化身以不确定的方式旋转。 ===osNpcShout=== 函数:void osNpcShout(key npc, int channel, string message).<br> 功能:NPC在给定的通道上呼喊信息。 ===osNpcSit=== 函数:osNpcSit(key npc,key target,integer options).<br> 功能:让一个NPC坐在一个物体上。<br> options : OS_NPC_SIT_NOW。 *让npc在可能的情况下,立即坐在prim上。这是唯一可用的选项,而且当前总是在选项字段中指定的任何内容上。 *如果prim有一个sit目标,那么无论在NPC和prim之间的距离,都要坐着。 *如果prim没有坐目标的话,如果prim在NPC的10米以内,那么坐就会成功。 ===osNpcStand=== 函数:osNpcStand(key npc).<br> 功能:让一个坐着的NPC站起来。 ===osNpcStopAnimation=== 函数:osNpcStopAnimation(key npc, string animation).<br> 功能:停止正在用指定NPC的密钥标识播放的动画。 ===osNpcStopMoveToTarget=== 函数:osNpcStopMoveToTarget(key npc).<br> 功能:停止当前移动到目标的行为。 ===osNpcTouch=== ===osNpcWhisper=== 函数:void osNpcWhisper(key npc, int channel, string message).<br> 功能:NPC在给定的通道中低语指定消息。 ===OsOwnerSaveAppearance=== 函数:key osOwnerSaveAppearance(string notecard).<br> 功能:将所有者的当前外观保存到资产库中的记事卡中。这包括身体部位数据,衣物和附件。如果同名的记事卡已经存在,则被替换。当这个函数被调用时,所有者必须在区域中。所有者的烘焙纹理(需要在NPC上重现外观)被永久保存。 示例: <pre> // // osOwnerSaveAppearance exxample. // This example creates the notecard with the user's appearance in the inventory of a prim. // You will find the notecard in the contents of the prim after the script has run. // default { state_entry() { string ownername = llKey2Name(llGetOwner()); // Retrieve the owner's key, and find out his/her name. string date = (string)llGetDate(); // Store the date in a string. string notecard_name = ownername+" "+date; // Combine the name and the date for use as a notecard name. osOwnerSaveAppearance(notecard_name); // Make the notecard. } } </pre> ==综合实例== ===综合实例1=== 在此实例中,囊括了大多数关于NPC的API,通过对话框的形式成功实现了一个NPC的建立、移动、说话、站立、坐下、显示位置等功能。 {| border="1" !功能 !菜单等级 !功能描述 |- ||触碰 ||无 ||用户化身触碰物体开始相关操作 |- ||create ||一级菜单 ||创建一个npc,可以输入npc的姓名,也可系统命名 |- ||remove ||一级菜单 ||移除该区域所有npc,并删除相应生成的外观记事卡 |- ||other ||一级菜单 ||点击可输入指定npc的key值,随后可对该npc进行相关操作 |- ||exit ||一级菜单 ||点击以退出对话框 |- ||return ||二级菜单 ||点击返回一级菜单 |- ||exit ||二级菜单 ||点击以退出对话框 |- ||get... ||二级菜单 ||返回给定npc的位置、旋转角度、拥有者 |- ||move ||二级菜单 ||输入坐标位置,将npc移动到给定位置 |- ||stopMove ||二级菜单 ||若npc在移动工程中,可停止移动 |- ||remove ||二级菜单 ||移除指定npc,并返回一级菜单 |- ||sit ||二级菜单 ||输入坐下物体的key值,npc将坐在该物体上 |- ||stand ||二级菜单 ||若npc坐在某物体上,将会站立 |- ||say ||二级菜单 ||npc将和你打招呼 |} [[文件:功能示意图.png]] <pre> // //一个关于NPC的综合案例,通过对话框的形式实现相关功能 // integer gchannel; //记录指定监听通道 integer glistener; //记录相应监听ID key toucherID; //记录触碰者ID key npc; //记录用户输入的NPC的key值 string msg; list options; //记录相关操作的列表 list choices; //记录对指定NPC进行相关操作的列表 integer num = 1; //记录已生成的NPC的数量 //删除除了脚本以外所有生成的文件 delete_all_other_contents() { string thisScript = llGetScriptName(); string inventoryItemName; integer index = llGetInventoryNumber(INVENTORY_ALL); while (index) { --index; // (faster than index--;) inventoryItemName = llGetInventoryName(INVENTORY_ALL, index); if (inventoryItemName != thisScript) llRemoveInventory(inventoryItemName); } } //移除函数:移除岛屿上所有NPC remove() { list avatars = llList2ListStrided(osGetAvatarList(),0,-1,3); //llList2ListStrided:从列表的第一个条到最后,返回第三项 integer i; llSay(0,"NPC Removal: No avatars will be harmed or removed in this process!"); for (i=0; i<llGetListLength(avatars); i++) { string target = llList2String(avatars, i); osNpcRemove(target); llSay(0,"NPC Removal: Target "+target); } delete_all_other_contents(); num = 1; //重置NPC计数 } default { state_entry() { llSay(0, "Click here to start!"); } touch_start(integer total_number) { toucherID = llDetectedKey(0); //获取触碰者ID gchannel = (integer)(llFrand(5000)+5000); //随机生成对话通道,避免对话通道冲突 state init; } } state init { state_entry() { msg = "create: create a npc. \nremove: remove all npc in the region. \n" + "other: operation to given npc."; glistener = llListen(gchannel,"","",""); options = ["create","remove","other","exit"]; llDialog(toucherID,msg,options,gchannel); } //监听函数,获取用户的操作或提交的相关信息,下同 listen(integer channel, string name, key id, string message) { if(message == "create"){ llListenRemove(glistener); state create; }else if(message == "remove"){ remove(); llDialog(toucherID,msg,options,gchannel); }else if(message == "other"){ llListenRemove(glistener); state other; }else{ llListenRemove(glistener); state default; } } } //创建事件:创建一个NPC state create { state_entry() { glistener = llListen(gchannel,"","",""); llTextBox(toucherID,"Enter the name of the npc:",gchannel); } listen(integer channel, string name, key id, string message) { if(channel == gchannel){ llListenRemove(glistener); vector npcPos = llGetPos() + <1,0,0>; string npcName = (string)message; string npcIdname = (string)("clone"+num); osAgentSaveAppearance(toucherID,npcIdname); //保存触碰者当前外观为记事卡中 key NPC = osNpcCreate(npcIdname,npcName,npcPos,npcIdname); osNpcSay(NPC, "Hi there! My name is " + llKey2Name(NPC)); num++; state init; } } } state other { state_entry() { glistener = llListen(gchannel,"","",""); llTextBox(toucherID,"The following operation are for a given NPC.\n"+ "Now,Enter a key for an npc:",gchannel); } listen(integer channel, string name, key id, string message) { llListenRemove(glistener); npc = (string)message; //确定输入key值是否为在岛上存在的NPC if(!osIsNpc(npc)) { msg = "The npc which key is " + npc + " is not existing in the region."; llSay(0,msg); state init; } state option; } } state option { state_entry() { msg = "Please select the operation you want to perform for the NPC."; choices = ["sit","stand","say","move","stopMove","remove","getPos","getRot","getOwner","return","exit"]; glistener = llListen(gchannel,"","",""); llDialog(toucherID,msg,choices,gchannel); } listen(integer channel, string name, key id, string choice) { if(choice == "sit"){ llListenRemove(glistener); state SIT; }else if(choice == "stand"){ osNpcStand(npc); osNpcSay(npc,"I'm standing."); llDialog(toucherID,msg,choices,gchannel); }else if(choice == "say"){ osNpcSay(npc,"Hello!"); llDialog(toucherID,msg,choices,gchannel); }else if(choice == "move"){ llListenRemove(glistener); state move; }else if(choice == "stopMove"){ osNpcStopMoveToTarget(npc); llSay(gchannel,"The npc has stop moving!"); llDialog(toucherID,msg,choices,gchannel); }else if(choice == "remove"){ llListenRemove(glistener); osNpcSay(npc, "Goodbye!"); osNpcRemove(npc); state init; }else if(choice == "getPos"){ vector pos = osNpcGetPos(npc); osNpcSay(npc,"The position of the npc is " + (string)pos); llDialog(toucherID,msg,choices,gchannel); }else if(choice == "getRot"){ rotation rot = osNpcGetRot(npc); osNpcSay(npc,"The rotation of the npc is " + (string)rot); llDialog(toucherID,msg,choices,gchannel); }else if(choice == "getOwner"){ key owner = osNpcGetOwner(npc); osNpcSay(npc,"The npc belongs to the user whose ID is " + (string)owner); llDialog(toucherID,msg,choices,gchannel); }else if(choice == "return"){ llListenRemove(glistener); state init; }else{ llListenRemove(glistener); state default; } } } //移动事件:将指定NPC移动到指定地点 state move { state_entry() { msg = "Please input the new vector,in sample format,<x,y,z>"; glistener = llListen(gchannel,"","",""); llTextBox(toucherID,msg,gchannel); } listen(integer channel, string name, key id, string message) { if(channel == gchannel){ llListenRemove(glistener); vector position = (vector)message; osNpcMoveTo(npc, position); osNpcSay(npc,"The npc has been moved to a given position."); state option; } } } //坐下事件:命令指定NPC坐在某物体上,最好在该物体上有相应的设置坐下的脚本 state SIT { state_entry() { msg = "Please input the key what the npc sit on."; glistener = llListen(gchannel,"","",""); llTextBox(toucherID,msg,gchannel); } listen(integer channel, string name, key id, string message) { if(channel == gchannel){ llListenRemove(glistener); key sitNpc = (string)message; osNpcSit(npc, sitNpc, OS_NPC_SIT_NOW); osNpcSay(npc,"I'm sitting."); state option; } } } </pre> ===综合实例2=== 在此实例中,囊括了大多数关于NPC的API,通过在指定通道上通讯的形式成功实现了一个乃至多个NPC的建立、移动、说话、站立、坐下等功能。<br> 操作说明: *输入“/10 help”获取命令菜单(10为给定通讯通道,可以在脚本中进行修改) *输入“/10 show”显示具体每个命令的通讯格式 *在执行针对于指定NPC的相关操作之前,利用npckey命令输入指定NPC的key值,即为其UUID {| border="1" !命令 !通讯格式 !功能描述 |- ||create ||create <notecard-name> ||Create NPC from a stored notecard |- ||create ||create <notecard-name> <firstName> <lastName> ||Create NPC from a stored notecard |- ||createm ||createm <num> ||Create a specified number of NPCS |- ||remove ||remove ||Remove the current NPC |- ||delete ||delete ||Delete all generated files except the script |- ||npckey ||npckey <npc-uuid> ||Enter a key value for an NPC |- ||say ||say ||NPCS greet you |- ||clone ||clone <notecard-name> ||Clone own appearance to a notecard |- ||load ||load <notecard-name> ||Load appearance on notecard to current npc |- ||save ||save <notecard-name> ||Save appearance of current NPC to notecard |- ||rot ||rot ||NPCS rotate in one direction |- ||rotabs ||rotabs <angles> ||NPC rotation specifies angles |- ||move ||move <x> <y> <z> ||move to absolute position |- ||movetarget ||movetarget ||Move NPCS to users nearby |- ||stop ||stop ||If the NPC is moving, it will stop moving |- ||sit ||sit <target-uuid> ||Make a NPC sit on the specified object |- ||stand ||stand ||If the NPC is sitting, it will stand |} <pre> key npc; integer listenChannel = 10; default { state_entry() { llListen(listenChannel,"",NULL_KEY,""); //监听listenChannel对话通道 llSetText("Listening on " + listenChannel, <0, 255, 0>, 1); //设置提示语显示在物体上方 llOwnerSay("Say '/" + (string)listenChannel + " help' for commands"); } listen(integer channel, string name, key id, string msg) { if (msg != "") { list commands = llParseString2List(msg, [ " " ], []); //接收用户在通道listenChannel输入的对话,并以空格分隔成多个字段 string msg0 = llList2String(commands, 0); //msg0记录用户输入的第一个字段 string msg1 = llList2String(commands, 1); string msg2 = llList2String(commands, 2); string msg3 = llList2String(commands, 3); if (msg0 == "create" && msg1 != "")//创建一个npc { osOwnerSaveAppearance("appearance"); //保存所有者的外观为记事卡appearance string notecardName = "appearance"; string firstName = "clone"; string lastName = "tom"; //判断用户输入的外观卡是否有效,若无效,则用默认记事卡 string thisScript = llGetScriptName(); string inventoryItemName; integer index = llGetInventoryNumber(INVENTORY_ALL); while (index) { --index; // (faster than index--;) inventoryItemName = llGetInventoryName(INVENTORY_ALL, index); if (inventoryItemName == msg1) notecardName = msg1; } //在用户通信格式正确且输入了npc的姓名的情况下,设置npc的姓名 if(msg2 != "" && msg3 != "") { firstName = msg2; lastName = msg3; } npc = osNpcCreate(firstName, lastName, llGetPos() + <5, 5, 0>, notecardName); //生成给定条件的npc llOwnerSay("Good morning! "); } else if (msg0 =="createm" && msg1 != "") //创建多个npc { osOwnerSaveAppearance("appearance"); vector pos = llGetPos(); integer i; for (i = 0; i < (integer)msg1; i++) { osNpcCreate("clone", (string)i, pos + <8, 0, 0>, "appearance"); llSleep(1); } } else if (msg0 == "remove" && osIsNpc(npc)) //删除指定npc { osNpcSay(npc, "You will pay for this with your liiiiiivvveeessss!!!....."); osNpcRemove(npc); } else if(msg0 == "delete") //删除除了脚本以外所有生成的外观记事卡 { string thisScript = llGetScriptName(); string inventoryItemName; integer index = llGetInventoryNumber(INVENTORY_ALL); while (index) { --index; // (faster than index--;) inventoryItemName = llGetInventoryName(INVENTORY_ALL, index); if (inventoryItemName != thisScript) llRemoveInventory(inventoryItemName); } llOwnerSay("All generated files except the script have been deleted."); } else if (msg0 == "say" && osIsNpc(npc)) //npc说话,打招呼 { osNpcSay(npc, " I am your worst Nightmare, " + (string)npc); } else if (msg0 == "move" && msg1 != "" && msg2 != "" && osIsNpc(npc)) //移动一个npc,输入的为npc移动的目标地址 { vector pos = <(integer)msg1, (integer)msg2, 0>; //z值可输入,也可不输入,最终高度取决于地形 if (msg3 != "") { pos.z = (integer)msg3; } osNpcMoveTo(npc, pos); } else if (msg0 == "movetarget" && osIsNpc(npc)) //移动npc到人物(用户)附近 { osNpcMoveToTarget(npc, llGetPos() + <9,9,5>, OS_NPC_FLY|OS_NPC_LAND_AT_TARGET); } else if (msg0 == "rot" && osIsNpc(npc)) //使npc旋转一个方向 { vector xyz_angles = <0,0,90>; // 定义一个度数改变值 vector angles_in_radians = xyz_angles * DEG_TO_RAD; //改变弧度 rotation rot_xyzq = llEuler2Rot(angles_in_radians); //改变旋转度数 rotation rot = osNpcGetRot(npc); osNpcSetRot(npc, rot * rot_xyzq); } else if (msg0 == "rotabs" && msg1 != "") //使npc旋转给定角度 { vector xyz_angles = <0, 0, (integer)msg1>; vector angles_in_radians = xyz_angles * DEG_TO_RAD; rotation rot_xyzq = llEuler2Rot(angles_in_radians); osNpcSetRot(npc, rot_xyzq); } else if (msg0 == "save" && msg1 != "" && osIsNpc(npc)) //保存npc的外观到给定名称的记事卡中 { osNpcSaveAppearance(npc, msg1); llOwnerSay("Saved appearance " + msg1 + " to " + npc); } else if (msg0 == "load" && msg1 != "" && osIsNpc(npc)) //npc加载指定外观记事卡 { osNpcLoadAppearance(npc, msg1); llOwnerSay("Loaded appearance " + msg1 + " to " + npc); } else if (msg0 == "clone" && msg1 != "") //保存拥有者外观到给定名称的记事卡中 { osOwnerSaveAppearance(msg1); llOwnerSay("Cloned your appearance to " + msg1); } else if (msg0 == "stop" && osIsNpc(npc)) //使npc停止移动,如果npc在运动中的话 { osNpcStopMoveToTarget(npc); } else if (msg0 == "sit" && msg1 != "" && osIsNpc(npc)) //使npc坐到指定物体上 { osNpcSit(npc, msg1, OS_NPC_SIT_NOW); } else if (msg0 == "stand" && osIsNpc(npc)) //使npc站立起来 { osNpcStand(npc); } else if(msg0 == "npckey" && msg1 != "") //输入npc的key值,为其他操作提供npc的key值 { npc = msg1; if(osIsNpc(npc)) llOwnerSay("The value of key is valid."); else llOwnerSay("The value of key is not valid.Please re-enter!"); } else if (msg0 == "help") //显示所有命令 { llOwnerSay("Commands are:"); llOwnerSay("create \t createm \t remove \t delete \t npckey \n" + "\t say \t clone \t load \t save \t rot \t rotabs \n" + "\t move \t movetarget \t stop \t sit \t stand \n" ); llOwnerSay("You can enter '/" + listenChannel +" instruction' to learn more about the communication rules"); } else if(msg0 == "instruction") //显示所有命令的具体说明 { llOwnerSay("In addition to creating and removing operations, you need to enter or check whether the NPC's key values are valid before the rest of the operations are performed."); llOwnerSay("create <notecard-name> - Create NPC from a stored notecard."); llOwnerSay("create <notecard-name> <firstName> <lastName> - Create NPC from a stored notecard."); llOwnerSay("createm <num> - Create a specified number of NPCS."); llOwnerSay("remove - Remove the current NPC."); llOwnerSay("delete - Delete all generated files except the script."); llOwnerSay("npckey <npc-uuid> - Enter a key value for an NPC."); llOwnerSay("say - NPCS greet you."); llOwnerSay("clone <notecard-name> - Clone own appearance to a notecard."); llOwnerSay("load <notecard-name> - Load appearance on notecard to current npc."); llOwnerSay("save <notecard-name> - Save appearance of current NPC to notecard."); llOwnerSay("rot - NPCS rotate in one direction."); llOwnerSay("rotabs <angles> - NPC rotation specifies angles."); llOwnerSay("move <x> <y> <z> - move to absolute position."); llOwnerSay("movetarget - Move NPCS to users nearby."); llOwnerSay("stop - If the NPC is moving, it will stop moving."); llOwnerSay("sit <target-uuid> - Make a NPC sit on the specified object"); llOwnerSay("stand - If the NPC is sitting, it will stand."); } else { llOwnerSay("I don't understand [" + msg + "]"); llOwnerSay("You can enter '/" + listenChannel +" help' to learn more about the communication rules"); } } } } </pre> == 专题探索与应用== ===NPC生命周期的控制=== osNpcRemove可以移除化身,但有时候发现模型无缘无故消失了。如何在岛屿启动和关闭时生成和移除化身 *移除化身工具 <pre> integer gchannel; // dialog channel integer glistener; // holds the listener handle; default { state_entry() { llSay(0, "单击我开始"); } touch_start(integer x) { if (llDetectedKey(0) == llGetOwner()) { gchannel = llCeil(llFrand(5000) + 5000); glistener = llListen(gchannel,"","",""); llTextBox(llDetectedKey(0), "输入一个NPC的KEY", gchannel); } } listen(integer channel, string name, key id, string message) { if(channel==gchannel){ llListenRemove(glistener); key npc=(key)message; osNpcSay(npc, "Goodbye!"); osNpcRemove(npc); } } } </pre> ===NPC形象如何个性化=== 目前来看,可以通过制作一个化身,然后讲将化身保存下来,然后供其他使用。 可以研究下danger上的化身 ===如何控制NPC=== 包括移动、控制动作等 ===如何与NPC对话=== 如何让NPC接收到化身或物体与他的通信
该页面使用的模板:
模板:MainNav
(
查看源代码
)
模板:VWSnav
(
查看源代码
)
返回至
虚拟世界/NPC
。
导航菜单
个人工具
登录
名字空间
页面
讨论
变种
视图
阅读
查看源代码
查看历史
更多
搜索
导航
网站首页
知识百科
编辑帮助
最近更改
工具
链入页面
相关更改
特殊页面
页面信息