问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

《上古卷轴5》Papyrus脚本语言入门指南

创作时间:
作者:
@小白创作中心

《上古卷轴5》Papyrus脚本语言入门指南

引用
1
来源
1.
https://games.sina.cn/j_uc.d.html?docid=hcffhsu8987553

《上古卷轴5》的自由性极高,并且还能通过MOD等方式来进行玩法的拓展。而Papyrus是B社的脚本工具,玩家要是掌握了Papyrus脚本语言,就能让本作的趣味性大大加强。

程序框架

Papyrus作为一种脚本语言,跟市面上其他的脚本语言类似,语法规则比较简单,程序结构跟高级语言也没有什么太大的差别。如果有朋友拥有一定程度的编程基础的话会很容易上手。

在此,我举个例子,介绍一下Papyrus的程序框架。

scriptName FirstScript extend ObjectReference //作为脚本开头必须有的一句,意思是定义继承自 //ObjectReference类的FirstScript脚本。
{Sample Script} //大括号的内容是在ck检查的时候工具框的内容,类似注释。
Message property box1 auto //定义Message类型的属性box1,并自动赋值。
{first box} //property,auto都是关键字
Message property box2 auto
{second box}
int count ;counter //定义整数型变量count。papyrus中,分号的作用类似
//高级语言的“//”,分号后面的内容是代码注释
Event OnActive(ObjectReference akAcitonRef) //主程序,类似c语言里的int main()
count=count+1
GetMessage(count).show()
endEvent //程序段结尾必须要加个end语句,如endEvent,endFunction
//区分大小写
Message function GetMessage(int counter) //函数定义,与高级语言基本类似
Message box
if (counter==1)
box==box1
else
box==box2
endif
Return box
endFunction

基本概念

Papyrus的基本概念包括变量,属性,函数,事件,状态,继承,多线程,持久化等。下面我们详细讲解各个概念,争取能通俗地让大家理解。

1、变量

(1)Papyrus中变量跟其他语言相比没有太大的不同,都是开辟一块内存存储特定类型(包括基本数据类型和类类型)的数据。声明方式也跟其他语言类似

声明:int counter Message box

Papyrus会用默认值自动为这些声明的变量初始化,这也是我们开头的程序中count不必手动初始化即可保证初始值是0的原因。当然,用户手动初始化也是可以的,具体初始化方式跟其他高级语言相同。

(2)衍生内容:语句

Papyrus的语句跟其他语言类似,也有循环语句和条件语句。用法也大同小异,只是需要注意语句结束时需要用专门的关键字结尾。

例如:(根据counter值的不同,决定用哪一个值来初始化chosenbox)

if (counter==1)
chosenbox=box1
else
chosenbox=box2
endIf

例如:(将object数组重新初始化)

while (currentElement < object.Length)
object[currentElement].Disable()
currentElement+=1
endWhile

(3)衍生内容:数组

在Papyrus中,数组也是一种特殊的变量,本质上是开辟出一块内存存储一系列相同类型的数据。因为在Papyrus中不存在指针,所以其声明方式跟C语言中数组的声明会有所区别。(貌似跟Java非常类似,不过楼主好久不接触Java有些忘记……惭愧……)

声明:int[] object(创建一个名为object的整数型数组,数组的长度为0,且初始值为空)

创建:int[] object = new int[10] (创建一个名为object的整数型数组,数组长度为10,并初始化)

数组在脚本中可以作为参数和函数返回值

例如:int Function arrayObject(int[] array)

或:

int[] Function arrayObject()
int[] array = new int[10]
Return array
endFunction

数组的赋值可以用while语句进行,与其他语言的数组赋值并无区别。长度则可以使用“数组名.Length”来计算。

此外,数组还可以像其他变量一样为其他的数组进行赋值或初始化。(在这里有必要提醒一下,Papyrus中数组的本质依旧是指向内存单元的指针,用数组进行赋值之后,会让被赋值的数组指向原数组的内存地址,此时当用户处理原数组的数据后,被赋值的数组相关数据也会发生变化)

2、属性

概念:

属性是Papyrus独有的一种变量类型。其作用是将MOD制作者制作或者游戏本身的物品对象(装备,武器,杂物甚至是随从等等)与脚本进行关联,从而可以通过脚本来控制这些物品对象(如武器发光,剑气,破法者的法术护盾,随从奥妮安会在玩家血量不足的时候释放恢复系法术等等,这些行为都要通过脚本控制)。

声明方法:

属性的声明使用property关键字

例如:Message property box1 auto(声明一个Message类型的属性box1,并自动赋值)

使用方法:

首先要在CK中制定好相关物品,然后在CK中将属性跟具体对象连接,之后就可以编写脚本了。

例如:

我在CK中创建了一把武器,名为blood_blade。

然后在脚本中定义属性:Weapon property blade auto

在CK中将blood_blade连接到blade上,这样一来,我们的blade变量就指向了blood_blade的内存地址

之后我们在脚本中编写武器发光,剑气之类的内容,就可以直接作用到blood_blade上了。

函数

Papyrus中的函数与其他高级语言的函数概念并无多大差别,都是一段用于完成特定功能的程序段。

定义方式也与其他脚本语言类似

例如:

int function count(int counter)
int count=0
counter=count+1
return counter
endFunction

事件

事件是驱动游戏进度的程序,在Papyrus中,事件就类似于C语言中的主函数,即int main()。在游戏中,几乎所有的角色行为都可以用事件管理。举个例子,盗贼公会任务中,玩家会跟随墨瑟前往雪漫密室寻找卡莱雅的下落,当你踏入最后一道门的时候会被卡莱雅的箭射中,昏厥倒地。玩家踩中陷阱到昏厥倒地这个动作,就可以用事件来管理。

事件的流程

玩家在进行游戏中触发了某一行为(脚步声过响,踩中陷阱等),相关联的对象(沉睡的尸鬼,毁灭系符文法术等)根据脚本做出相应的反应(苏醒,爆炸等),然后反馈到游戏当中去。

例子:

下面通过一个例子来帮助大家对事件有个具体的印象

scriptName DraugrResurrect extend Actor
Spell property reanimateSpell Auto
ObjectReference property trigger Auto
Event OnActive(ObjectReference akActionRef)
if (trigger==akActionRef)
reanimateSpell . Cast(self,self)
endIf
endEvent

状态

游戏运行在不断变化的环境下,而脚本运行只能有一个状态,代码的运行方式,运行结果跟特定的状态有关系。例如,当玩家举盾防御时,敌人蓄力攻击会触发一个短暂的时缓效果。这就是在“玩家举盾防御”,“敌人蓄力攻击”的状态下,触发函数造成“短暂的时缓效果”

定义方式

auto state XXX
;具体内容
endState
auto是关键字,可以让脚本在特定状态下起用

空状态:

当一个函数不存在于任何状态中的时候,称这个函数为空状态。(此时,这个函数的存在形式类似于高级语言中的全局函数)运用空状态可以将某个函数或者事件禁用。

想要在脚本中生效的函数或者事件,可以将该函数或事件先在空状态下定义,然后再放置到状态中生效。需要注意的是,放置到状态中的函数或者事件,必须要跟在空状态下定义的函数或者事件有相同的返回值和参数表

例如:

function A (int c)
;内容
endFunction
auto state XXX
function A(int c)
;内容
endFunction
function B(int c)
;内容
endFunction
function A(int b)
;内容
endFunction
endState

上面这个例子中,function B和function A(int b)都将不会运行并有警告提示

继承

Papyrus中,继承的概念跟其他高级语言类似,以某个已经存在的脚本为基础,对该脚本进行功能拓展从而得到新的脚本。

继承的方法

跟高级语言类似,Papyrus的继承方法也是用extend关键字

例如 scriptName HelloWorld extend ObjectReference

继承有什么用?

函数和事件

子脚本可以使用父脚本的全套函数和事件,而当子脚本调用自身与父脚本同类的函数时,子脚本函数拥有优先权。

状态

父类有状态,子类没有:此状态的父函数将会被使用。

子类有状态,父类没有:此状态的子函数将会被使用。

父类的函数有状态,子类的没有:父版本将会被使用。

子类的函数有状态,父类的没有:子版本将会被使用。

所有函数有相同状态:子版本将会被使用。

属性

子脚本可以使用父脚本的属性,但是不能有超出该父脚本属性定义的操作

变量

变量是私有的(相当于默认加上了private关键字),父脚本和子脚本使用各自的变量。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号