寻找风叶 2007-8-26 09:33
有关脚本疑问
如果要设置一个脚本,在对话中出现,每一个对话选项只会出现一次,而其中预定的一句话就能结束原先给的任务,应该怎样设?还有在脚本里在==什么前那个双引号里面那个是什么?是代表哪里的?
Erodoeth 2007-8-26 10:05
可以设置个本地变量对应对话项的任务情况(比如设置在OBJECT_SELF,或者设置在模组上,亦或者设置在玩家自己身上,名字叫iDialog)
在各个对话项的“显示文字档”控制栏里填
int StartingConditional()
{
if(GetLocalInt(OBJECT_SELF, "iDialog")==0) //这里只给出了判断条件:玩家还没选择过此对话项,你还要加上任务是否接到,是否完成的判断
{
return TRUE;
}
else
{
return FALSE;
}
}
再在“采取动作”栏里填
void main()
{
SetLocalInt(OBJECT_SELF,"iDialog",1);
}
双引号的意思是,引号里的内容为字符串。
寻找风叶 2007-8-26 17:29
晕!还是不行,我不知哪错了,只是一味出第一句对话的选项,后面同等级对话选项就是不出现....我设定的是玩家和某个NPC对话,第一次对话选项结束后,第二次点击该人物时就出现另外一个,第一次那个部不会出现了,以后点击都只会出现第二个,这样应该怎么设?
Erodoeth 2007-8-26 17:50
原来是这样啊。
那你把第一项里面的脚本保留,把第二项里的“显示文字档”,“采取动作”干掉。
这样游戏进去,第一次点击NPC会先给第一项的对话,然后你点他他会一直给你第二项的
PS:”对话选项“是谁的?NPC的还是PC的?
Erodoeth 2007-8-26 17:55
以下东西来自NTRPG,翻译者忘了是谁,知情的请补充一下。
[quote]
第一部分 设置变量
(Jackyshadow)
你所做的最经常的事就是设置变量并且返回这些变量。这是决定游戏中大多数事件是否发生或者改变/保持故事发展轨道的唯一方式。
当你设置变量时最普通的语句是:
void SetLocalInt(object oObject, string sVarName, int nValue)
这个语句将会设置一个本地整形变量('local integer'),本地的意思是这个整形变量指向,或者存储于你指定的对象中。(其实他并不是真正的存储在对象本身上,但是这样说理解起来比较容易)
这里有三件重要的事情你要记住:
a.代码中的oObject必须是一个有效的对象。你将会看到很多语句在它们的开头部分会返回一个对象。(就像这个语句中void在 SetLocalInt开头部分或者说前面)这意味着这些语句将会从开头的这些对象中返回(提取)数据。不管这个对象是什么,整形变量都会指向它。如果你正在对话,使用GetPCSpeaker() 将会把正在与NPC对话的玩家作为一个对象返回。你可以使用GetModule()把得到的整形变量存储在MODULE本身上……你可以使用 OBJECT_SELF来指定任何当前正在运行的程序脚本中的对象,等等。
这非常重要,因为你选择的变量对于相对的对象来说是特殊并且唯一的。如果你以VARIABLE1的名字存储一个变量到MODULE中并且设定这个变量的值为1,那么这个变量将会是在这个MODULE存储的唯一一个以VARIABLE1命名的变量。你可以将VARIABLE1存储到不同的对象上,比如说玩家,并且使他们拥有完全不同的值。
b.代码中的'string sVarName' 是你赋予该变量的名字。保证让变量的名字足够独特,像一条绳子一样脉络分明,并且在上面加注注释。因为很多时候变量的名字并不是那么易于辨认和好记。
c.代码中的'int nValue' 是关于你存储的变量中的信息。当我们用上面给的语句把它设置为一个整形变量后,它必须是一个数字(无小数点)……像1,15或者320。如果你想在这里存储不同的信息,你需要不同的语句:
SetLocalFloat =存储一个浮点
SetLocalString =存储一个字符串(例如一个句子,单词或者对象的名字……它必须要有注释,就像变量名称一样)
SetLocalLocation =存储一个地点
SetLocalObject=存储对象数据(例如一个可确定位置的对象,一件物品,一个生物等等)
Q:我如何使用变量?
A:一旦你为一个东西设定了变量,它就会永远在这个东西上除非这个东西被取代或者毁灭。除此之外在任何时间你都可以在另外的程序脚本中(或者这个脚本中)激活这个变量并且读取这个变量中的信息。
如果我要激活刚才我为之设置变量的那个整形变量,我会使用这个语句:
int GetLocalInt(object oObject, string sVarName)
除了显示的数据的值之外,这个语句和你刚才用来设置变量的语句完全相同。而这些数据的值正是你想要的东西。
记住这不是个无用的语句……它返回一个整形变量,也就是一个实际上的信息。这意味着你不能单独的使用这个语句,你可以用这个语句来定义一些其他语句(或者其他你设定的变量)中所需要的'int' 数据……如下所示:
int nValue = GetLocalInt(OBJECT_SELF, "VARIABLE1");
上面代码的意思是你刚刚指定了一个名字为nValue的新变量,这个变量现在等于VARIABLE1——一个存储在OBJECT_SELF中的整形变量。
糊涂了?看例子……
这里有一个很好的例子,它显示了一个变量怎样被用来追踪剧情的发展。我需要拥有一个名字为STORY的变量。当玩家接受任务时,我将它设置为1。当玩家完成任务后,我将它设置为2。
1.玩家接受了任务……
当玩家在对话中选择了接受任务时,我到'Actions Taken'中写了一段代码用来设置STORY变量的值在玩家身上为1。
代码:
void main()
{
SetLocalInt(GetPCSpeaker(), "STORY", 1);
}
2.玩家完成了任务……
我们看到玩家回来了,并且完成了NPC交给的任务,NPC祝贺他并且STORY的在玩家身上的值变为2。
void main()
{
SetLocalInt(GetPCSpeaker(), "STORY", 2);
}
Q:我怎么知道玩家是否接受了任务?
A:当双方对话开始时,你只需要对各种不同的情况做一个新的节点(NODE)。计算机将会从头开始核对在'Text Appears When' 中所有的代码以确定是否为TRUE(如果在'Text Appears When'没有代码,将会自动默认为TRUE)。如果是TRUE,计算机将会开始运行你先前设置的节点。如果不是,将会忽略。
所以,根据剧情你可以从后向前的列出节点的内容:
#1. (plot done) "Thank you for doing that plot."(任务完成:谢谢)
#2. (plot accepted) "Have you finished that plot?"(已接受任务:你完成任务了吗?)
#3. (not accepted, not done) "Hello there!"(未接受任务,未完成:你好!)
所以当变量STORY的值为2的时候,计算机判断#1为TRUE;当STORY为1时,判断#2为TRUE;#3没有任何相关的代码,因为此时#1和#2全部为FALSE,那么任务既未被接受也未被完成,系统默认#3为TRUE。
那么任务是否被完成了?
代码:
int StartingConditional()
{
int nDone = GetLocalInt(GetPCSpeaker(), "STORY") == 2;
return nDone;
}
任务是否被接受了?
代码:
int StartingConditional()
{
int nAccept = GetLocalInt(GetPCSpeaker(), "STORY") == 1;
return nAccept;
}
所以你得到了:
#1.(Text Appears When中为第一段代码)谢谢你完成了任务。
#2.(Text Appears When中为第二段代码)你完成任务了吗?
#3.(无代码)你好!
在上述的代码中,我让NPC只给了1个人任务。
刚才我们将STORY变量设置在玩家身上(为1),但更好的办法是将这个值为1的变量设置到OBJECT_SELF(也就是NPC身上),并且将这个变量的名字改为PLOT_GIVEN。
然后当对话从#3开始的时候(因为现在玩家身上并没有STORY变量,因此当他们和NPC对话时对话分支总是从默认的#3开始),你可以使对话分为两部分:
|
|
-->(如果PLOT_GIVEN在OBJECT_SELF的值为1,那么Text Appears When中的代码判断为TRUE)对不起,今天没你的活儿。
|
|
-->(Text Appears When中无代码)你愿意为我做件事吗?
一个简单的任务对话
首先记住,所有你在'starting nodes' 列出的NODE(节点)都是以倒序执行的。
我们这样设计:你的NPC给出了3份工作,想象一下NODES的结构:
#1. "I don't have any more jobs for you."(我没有其他事情让你做了)
#2. "Are you finished job #3?"(你完成工作3了吗?)
#3. "Are you finished job #2?"(你完成工作2了吗?)
#4. "Are you finished job #1?"(你完成工作1了吗?)
#5. "Would you like a job?"(你愿意找份工作吗?)
#6. "Hello!"(你好)
记住,当NPC的对话被点击后,计算机将会扫描'Text Appears When' 中关于这些NODES的代码。如果代码返回结果为TRUE或者没有代码,那么这个NODE(节点,在这里也就相当于其中的一个对话分支)将会被启动,如果返回结果为FALSE,那么计算机将会忽略这个NODE,进行下一个NODE的扫描。
下面是每个NODE代码的纲要:(为了理解起来简单起见,你可以按#6—#1的顺序从下至上阅读下列代码和说明,但紧记在编写时一定要按照从上至下的顺序)
#1.当JOB变量在玩家身上的值为4的时候,'Text Appears When'中的代码返回为TRUE。如下:
int StartingConditional()
{
int nJob = GetLocalInt(GetPCSpeaker(), "Job") == 4;
return nJob;
}
#2.当JOB变量在玩家身上的值为3的时候,'Text Appears When'中的代码返回为TRUE。如果玩家已经完成了工作,让NPC给玩家报酬并且在'Text Appears When' 中将JOB变量的值设为4。如下:
void main()
{
SetLocalInt(GetPCSpeaker(), "Job", 4);
}
#3.当JOB变量在玩家身上的值为2的时候,'Text Appears When'中的代码返回为TRUE。如果玩家已经完成了工作,让NPC给玩家报酬并且在'Text Appears When' 中将JOB变量的值设为3。
#4.当JOB变量在玩家身上的值为1的时候,'Text Appears When'中的代码返回为TRUE。如果玩家已经完成了工作,让NPC给玩家报酬并且在'Text Appears When' 中将JOB变量的值设为2。
#5.当TalkedToJoe变量在玩家身上的值为1的时候,在对话中,如果玩家接受#1工作,在'Text Appears When'中将JOB变量在玩家身上的值设为1。
#6.没有代码在'Text Appears When'中(如果上述脚本全部为FALSE,那么这就是玩家第一次与这个NPC对话)。在第一行,写一段代码将TalkedToJoe变量在玩家身上的值设置为1。
这些就是设置变量的基本知识,存储和使用字符串及对象数据则是另外一种更复杂一点的东西……但是一些东西在你能够熟练操作整形变量后将会变得很容易。希望第一部分对你来说是个好的开始。
[/quote]
-mj- 2007-8-26 18:06
[quote]原帖由 [i]Erodoeth[/i] 于 2007-8-26 10:05 发表 [url=http://www.odyguild.net/bbs/redirect.php?goto=findpost&pid=57915&ptid=8728][img]http://www.odyguild.net/bbs/images/common/back.gif[/img][/url]
int StartingConditional()
{
if(GetLocalInt(OBJECT_SELF, "iDialog")==0) //这里只给出了判断条件:玩家还没选择过此对话项,你还要加上任务是否接到,是否完成的判断
{
return TRUE;
}
else
{
return FALSE;
}
}
... [/quote]
根据LZ的要求,应该是
int StartingConditional()
{
if(GetLocalInt(OBJECT_SELF, "iDialog") == 0)
{
return FALSE;
}
return TRUE;
}
第一次对话只出现到设置此脚本的这一句为止,任务改变后再对话能继续下去
Erodoeth 2007-8-26 18:17
做个四连装的(如果楼主要求的是PC对话项)
//[ques1]
int StartingConditional()
{
if(GetLocalInt(OBJECT_SELF, "iDia1")==1)
{
return FALSE;
}
else
{
return TRUE;
}
}
//[ques2]
int StartingConditional()
{
if(GetLocalInt(OBJECT_SELF, "iDia2")==1)
{
return FALSE;
}
else
{
return TRUE;
}
}
//[ques3]
int StartingConditional()
{
if(GetLocalInt(OBJECT_SELF, "iDia3")==1)
{
return FALSE;
}
else
{
return TRUE;
}
}
//[ques4]
int StartingConditional()
{
if(GetLocalInt(OBJECT_SELF, "iDia1")==1)
{
return FALSE;
}
else
{
return TRUE;
}
}
ques脚本按1,2,3,4填入4项(如果有四项对话的话)对话的“显示文字档”栏里
然后再编action1,action2,action3,action4
//[action1]
void main()
{
SetLocalInt(OBJECT_SELF,"iDia1",1);
}
//[action2]
void main()
{
SetLocalInt(OBJECT_SELF,"iDia2",1);
//[action3]
void main()
{
SetLocalInt(OBJECT_SELF,"iDia3",1);
//[action4]
void main()
{
SetLocalInt(OBJECT_SELF,"iDia4",1);
}
将action 脚本按1,2,3,4顺序填入四个对话项的”采取动作“栏位
效果是,PC选择对话项n时,下次对话时对话项n从列表上消失
-mj- 2007-8-26 18:22
改一下,ROOT下两个对话目录。第一个iDialog=0时TRUE,在后续对话中再用Action把iDialog变为1。第二个目录自然反一反。严谨点的话再设置一个iDialog=2的情况
寻找风叶 2007-8-26 22:44
是NPC的,第一次对话是给予物品的,我还设了技能检定,但不知为什么除了高级点的人物外新开的都会在检定时中断对话,接着就跟在3楼说的一样,只出现第一级的,但任务选项已移除,还有,字符串是代表NPC的标签还是对话剧本的名还是NPC的名字?感谢你教我这么多,但我觉得我还是不是很清楚,除了指令明白,但是对脚本指定对象和反回对象还是搞不清.....唉...我就是人笨没药医的最好例子....
Erodoeth 2007-8-26 23:32
这么说其实也不是办法,情况不明我也是睁眼瞎,这样吧,在toolset打开模组文件时,modules文件夹下面会新建个temp0目录,你把里面出问题的那个对话文件(.dlg结尾的),还有该对话文件所需的脚本文件(.nss结尾的)上传到论坛,让大家一起看看。
PS:编脚本这东西也不是聪不聪明的问题,你该明白时总会明白的,比如学过C或者C++之后 。
-mj- 2007-8-27 00:29
给个大致对话结构
Root——NPC对话A1(iDialog=0时出现本对话)
︱ ﹂PC对话A2
︱ ﹂NPC对话A31(作技能检定,通过出现本对话,同时设置动作给PC物品,iDialog=1)
︱ ︱ ﹂继续
︱ ︱
︱ ﹂NPC对话A32(技能不够时出现本对话,跳出)
﹂———NPC对话A2(iDialog=1时出现本对话)
iDialog是用脚本给某一对象设置的变量,名字可以自己起。用GetLocalInt返回不同的变量值就可以作条件判定。如果没此变量而直接GetLocalInt查看也会返回数值0,所以不用担心事先没设置。当然也可以在PC对话A2后添加更多对话选项,形式和A2、A3……一样
寻找风叶 2007-8-28 13:30
唉~~~~不懂上传啊!~~~我已经把对话和脚本提取出来了~
寻找风叶 2007-8-28 19:41
不过情况是这样,先建造一个人物,里面的对话是两个同等级的选项(NPC的,一点击就有)第一次点击出显的一个,到最后得到若干金币,为防止再点再有,第一次的选项就不会再出现,以后都是第二个选项,那脚本应该怎么编?
-mj- 2007-8-28 21:15
第一句同二楼
第二句反一反
int StartingConditional()
{
if(GetLocalInt(OBJECT_SELF, "iDialog")==0)
{
return FALSE;
}
else
{
return TRUE;
}
}
但如果是“选项”,那应该是PC说话。结构得改一改,出选项之前先加一句NPC打招呼,然后再出同级的两句,这样的话只需要第一句有脚本,第二句不用加了
寻找风叶 2007-8-29 12:52
我跟着你写的打下去,但下面总是出现一行字:2007-8-28 12:50:33:错误。`SC_001`没有翻译。SC_001.nns(3):错误:翻译器存在未知状态. 是什么原因?我的对话和NPC名字都是中文的,和这有没有关系?
页:
[1]