Jump to content
模组网
icedream

【Creation Kit 学习指南 36】存档说明

Recommended Posts

本章将详细讲解Papyrus脚本的游戏保存系统。此页上的信息将会随目标改变!已知问题和目标的修复和改变将会被标记。

何时可以存档?

游戏可以在任意时刻存档。这既适用于脚本中的多线任务,也适用于单线任务。在大多数情况下,你不必担心它,在你未改变任何东西的情况下,加载完毕的游戏将可以成功返回脚本并运行。但是如果你改变某些东西,那么本章将会予以具体讲解。

脚本

添加目标

如果你在存档建立后对一个目标添加脚本并保存游戏,那么当存档加载后此脚本将存在于目标之上,但是会原封不动(所有这些属性将设定它们的主文件值,只要存档完成加载,它们的初始化模块将会被运行)。

删除目标

如果在存档建立后从目标删除一个脚本,那么当存档加载后此脚本将持续存在于目标上。如果脚本被完全删除,那么可能会产生异常。

属性和脚本变量

添加

  • 有默认值的变量:当存档加载时,变量有默认值。(例如句法"int myVar = 5")
  • 无默认值的变量:当存档加载时,变量无默认值。(0,空字符串,空,假)
  • 自动属性:属性将收到由主文件给的值。(结尾为关键字"auto"的属性,例如:"ObjectReference Property MyObject Auto")
  • 非自动属性:属性将不会收到由主文件给的值,它将为空。
注意:由于显而易见的原因,如果当存档建立后目标初始化事件已运行,那么它不会再次运行。因此,如果对初始化事件设定一个新的变量,你不能肯定变量将会有一个适当值,除非你能确定目标从未在之前保存的游戏中存在过。

删除

如果你在存档建立后删除一个属性或变量,那么游戏存档中的属性或变量值将被丢弃,然后一个包含详细信息的警告将写入脚本日志。

改变

如果你改变游戏中的属性或变量,那么它将会先删除旧的再添加新的。如果你改变类别(并非名称),然后游戏存档中的任意值将被丢弃,然后包含详细信息的警告将被写入脚本日志。

改变主文件值

如果在主文件中有一个存在的属性并改变它的值,那么脚本将会收到一个存档中不存在的值。换句话说,改变值将不会写入游戏存档中已有的值。

属性范例

; Version 1
Scriptname MyScript Extends ObjectReference
 
int Property MyAutoValue Auto
 
int internalValue
int Property MyNonAutoValue
	Function Set(int value)
		internalValue = value
	EndFunction
	int Function Get()
		return internalValue
	EndFunction
EndProperty
 
int MyVariableWithInit = 1
int MyVariableWithoutInit
 
Event OnInit()
	MyVariableWithoutInit = 1
EndEvent
 
Event OnActivate(ObjectReference akActivator)
	Debug.Trace("MyAutoValue = " + MyAutoValue)
	Debug.Trace("MyNonAutoValue = " + MyNonAutoValue)
	Debug.Trace("MyVariableWithInit = " + MyVariableWithInit)
	Debug.Trace("MyVariableWithoutInit = " + MyVariableWithoutInit)
EndEvent
在主文件中:
  • MyAutoValue = 1
  • MyNonAutoValue = 1
在日志中,activation之后:

MyAutoValue = 1
MyNonAutoValue = 1
MyVariableWithInit = 1
MyVariableWithoutInit = 1
<save is made here>

; Version 2
Scriptname MyScript Extends ObjectReference
 
int Property MyAutoValue Auto
int Property MyAutoValue2 Auto
 
int internalValue
int Property MyNonAutoValue
	Function Set(int value)
		internalValue = value
	EndFunction
	int Function Get()
		return internalValue
	EndFunction
EndProperty
 
int internalValue2
int Property MyNonAutoValue2
	Function Set(int value)
		internalValue2 = value
	EndFunction
	int Function Get()
		return internalValue2
	EndFunction
EndProperty
 
int MyVariableWithInit = 2
int MyVariableWithoutInit
 
int MyVariableWithInit2 = 2
int MyVariableWithoutInit2
 
Event OnInit()
	MyVariableWithoutInit = 2
	MyVariableWithoutInit2 = 2
EndEvent
 
Event OnActivate(ObjectReference akActivator)
	Debug.Trace("MyAutoValue = " + MyAutoValue)
	Debug.Trace("MyNonAutoValue = " + MyNonAutoValue)
	Debug.Trace("MyVariableWithInit = " + MyVariableWithInit)
	Debug.Trace("MyVariableWithoutInit = " + MyVariableWithoutInit)
	Debug.Trace("MyAutoValue2 = " + MyAutoValue2)
	Debug.Trace("MyNonAutoValue2 = " + MyNonAutoValue2)
	Debug.Trace("MyVariableWithInit2 = " + MyVariableWithInit2)
	Debug.Trace("MyVariableWithoutInit2 = " + MyVariableWithoutInit2)
EndEvent
在主文件中:
  • MyAutoValue = 2
  • MyNonAutoValue = 2
  • MyAutoValue2 = 2
  • MyNonAutoValue2 = 2
在日志中,activation之后且加载先前存档:

<save is loaded here>
MyAutoValue = 1
MyNonAutoValue = 1
MyVariableWithInit = 1
MyVariableWithoutInit = 1
MyAutoValue2 = 2
MyNonAutoValue2 = 0
MyVariableWithInit2 = 2
MyVariableWithoutInit2 = 0
函数

注意

函数改变只会影响函数运行中建立的存档。然而,由于存档可以在任意时刻建立,因此这些接下来的点将会被写入。同样,假设在2010年11月29日之后建立并保存一个信息,那么一旦线程中的任意函数改变,早期建立和保存的存档(即使已加载和稍晚建立)将拒绝任何运行的堆栈。

添加

添加的新函数中没有任何问题。

删除

当存档建立后,如果在运行中删除一个函数,那么旧函数将从存档中加载并允许结束。警告将被写入脚本日志,大量对已删除函数的调用(经常由于一些其它改变或删除的函数调用它)将会失败。

改变

改变参数或返回类型

函数的差异将被注意,旧版本的函数将会从游戏存档中被加载并允许结束运行。大量对函数的调用将使用档案和零散文件中的版本,最有可能的问题错误是参数或返回类别的不匹配(经常由于一些其它改变或删除的函数调用它)。

添加/删除/改变函数变量

函数的差异将会被注意,旧版本的函数将从游戏存档中加载并允许结束运行。大量对函数的调用将使用存档/零散文件中的版本。

改变代码

函数的差异将会被注意,旧版本的函数将从游戏存档中加载并允许结束运行。大量对函数的调用将使用存档/零散文件中的版本。例外:如果一个本地函数被脚本化,堆栈将会被拒绝而非恢复。

函数范例

; Version 1
Scriptname MyScript extends ObjectReference
 
Event OnActivate(ObjectReference akActivator)
	MyFunction(1)
	MyFunction(2)
EndEvent
 
Function MyFunction(int aiMyValue)
	Debug.Trace("Entered my function version 1: aiMyValue = " + aiMyValue)
	; 存档*在此*建立
	Debug.Trace("Left my function version 1: aiMyValue = " + aiMyValue)
EndFunction


; Version 2 - 和version 1相同, 除非状态追踪
Scriptname MyScript extends ObjectReference
 
Event OnActivate(ObjectReference akActivator)
	MyFunction(1)
	MyFunction(2)
EndEvent
 
Function MyFunction(int aiMyValue)
	Debug.Trace("Entered my function version 2: aiMyValue = " + aiMyValue)
	; 存档*在此*建立
	Debug.Trace("Left my function version 2: aiMyValue = " + aiMyValue)
EndFunction


; Version 3
Scriptname MyScript extends ObjectReference
 
Event OnActivate(ObjectReference akActivator)
	Debug.Trace("OnActivate received!")
EndEvent
存档在调用version 1的OnActivate的MyFunction(1)运行期间建立。

保存之前的脚本日志:

Entered my function version 1: aiMyValue = 1
加载version 2后的脚本日志:

warning: Function MyScript..MyFunction in stack frame 2 in stack 457 differs from the in-game resource files - using version from save
...
Left my function version 1: aiMyValue = 1
Entered my function version 2: aiMyValue = 2
Left my function version 2: aiMyValue = 2
加载version 3后的脚本日志:

warning: Function Myscript..MyFunction in stack frame 2 in stack 457 doesn't exist in the in-game resource files - using version from save
warning: Function MyScript..OnActivate in stack frame 1 in stack 457 differs from the in-game resource files - using version from save
...
Left my function version 1: aiMyValue = 1
error: Method MyFunction not found on MyScript. Aborting call and returning None
... <later, after another activation>
OnActivate received!

Share this post


Link to post
Share on other sites

问下creation kit怎么加载obse?

我看外网写obse快捷方式加上editor,但是没啥用啊,打开ck还是加载不到obse

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...